UNPKG

desktop-window

Version:

A lightweight Web Components-based custom element that replicates the look and feel of native desktop application windows — resizable, movable, and styled like a traditional OS window.

1,230 lines (806 loc) 35.3 kB
# desktop-window A lightweight Web Components-based custom element that replicates the look and feel of native desktop application windows — resizable, movable, and styled like a traditional OS window. No frameworks required. ![demo](demo.png) ## NOT READY FOR PRODUCTION This package is in active development, and not yet reached the point where I can recommend using in production environment: - Its tested to some degree, but not well tested or battle proven. I'm working on this now. - Minor behaviour and API changes are still possible. ### Roadmap to v1.0 - test cases / unit tests? - accessibility ## Usage ``` import { register, DesktopWindow } from 'desktop-window'; register(); // this guards against multiple accidental registration // OR you could just do this instead: customElements.define('desktop-window', DesktopWindow); ``` Or without a build tool: Manually copy the `desktop-window.autoload.js` to your site, then: ```html <script src="desktop-window.autoload.js"></script> ``` Use the `<desktop-window>` tag in HTML code. ```html <style> desktop-window[fullscreen] #enter-fullscreen { display: none; } desktop-window:not([fullscreen]) #exit-fullscreen { display: none; } </style> <div style="position: relative; width: 100vw; height: 100vh;"> <desktop-window name="Hello world!" movable resizable minimizable maximizable closable centered> The contents of the window are placed here. <button id="enter-fullscreen">⛶ Enter fullscreen</button> <button id="exit-fullscreen">⛶ Exit fullscreen</button> </desktop-window> </div> <script> document.getElementById('enter-fullscreen').addEventListener('click', function (event) { this.dispatchEvent(new Event('request-fullscreen', { bubbles: true })); }); document.getElementById('exit-fullscreen').addEventListener('click', function (event) { this.dispatchEvent(new Event('exit-fullscreen', { bubbles: true })); }); </script> ``` ## Examples For examples see the [Github project `examples` folder](https://github.com/lionel87/desktop-window/tree/master/examples). 1. Clone repository or [download zip](https://github.com/lionel87/desktop-window/archive/refs/heads/master.zip). 2. Open `examples/index.html` in your browser. ## Notes on layout - The component positions itself **absolutely inside its immediate parent**. The parent should be `position: relative` (or `absolute`) and have a well-defined size. - Recommended: `overflow: hidden` on the parent to avoid scrollbars when moving windows out of bounds. - The window works only when there is a valid `parentElement`, so appending eg. to a shadow root directly will not work. - Appending to the `document.body` works, but don't forget to set the body height or have content that stretches the area! - When the script is asynchronously loaded and the HTML initially has windows I recommend you this CSS to prevent jumping content: ```css desktop-window:not(:defined) { display: none; } ``` ## Documentation **Contents** - [Attributes](#attributes) - [Events emitted](#events-emitted) - [Events listening for](#events-listening-for) - [Properties](#properties) - [Methods](#methods) - [Slots](#slots) - [Parts](#parts) - [CSS Variables](#css-variables) ### Attributes All boolean attributes on `<desktop-window>` follow this rule: - If the attribute is **present**, its value is considered `true`, regardless of whether the value is empty, `"true"`, or equals the attribute name. - If the attribute is **not present**, the value is `false`. **Truthy examples (evaluated as `true`):** ```html <desktop-window centered> <desktop-window centered="true"> <desktop-window centered="centered"> <desktop-window centered="1"> <desktop-window centered=""> ```` **Falsy example (evaluated as `false`):** ```html <desktop-window> ``` There is **no way to explicitly pass `false`** via the attribute. Omitting the attribute entirely is the only way to make it false. If dynamic control of booleans is needed, use JavaScript to set/remove attributes: ```js element.removeAttribute('centered'); // false element.setAttribute('centered', ''); // true ``` #### `name` Type: `string` Specifies the title displayed in the window's title bar. Example: ```html <desktop-window name="My Window"> ``` #### `movable` Type: `boolean` If present, the window can be dragged. If omitted, the window is fixed in place. Example: ```html <desktop-window movable> ``` #### `x` Type: `number` Initial horizontal coordinate of the window (in pixels, omit the `px` unit). Ignored if `centered` is set. Example: ```html <desktop-window x="100"> ``` #### `y` Type: `number` Initial vertical coordinate of the window (in pixels, omit `px` unit). Ignored if `centered` is set. Example: ```html <desktop-window y="100"> ``` #### `centered` Type: `boolean` If present, the window is centered. Overrides `x` and `y`. Example: ```html <desktop-window centered> ``` #### `resizable` Type: `boolean` If present, the window can be resized. Omitting it disables resizing. Example: ```html <desktop-window resizable> ``` #### `width` Type: `number` Default: `350`. Initial width in pixels. Example: ```html <desktop-window width="800"> ``` #### `height` Type: `number` Default: `350`. Initial height in pixels. Example: ```html <desktop-window height="600"> ``` #### `minwidth` Type: `number` Default: `150`. Minimum width allowed during resizing. Example: ```html <desktop-window minwidth="200"> ``` #### `maxwidth` Type: `number` Maximum width allowed during resizing. Example: ```html <desktop-window maxwidth="1000"> ``` #### `minheight` Type: `number` Default: `150`. Minimum height allowed during resizing. Example: ```html <desktop-window minheight="200"> ``` #### `maxheigh` Type: `number` Maximum height allowed during resizing. Example: ```html <desktop-window maxheigh="700"> ``` #### `minimizable` Type: `boolean` If present, the window shows a minimize button and allows minimizing. Example: ```html <desktop-window minimizable> ``` #### `minimized` Type: `boolean` If present, the window is minimized. Example: ```html <desktop-window minimized> ``` #### `maximizable` Type: `boolean` If present, the window shows a maximize button and allows maximizing. Example: ```html <desktop-window maximizable> ``` #### `maximized` Type: `boolean` If present, the window is maximized. Example: ```html <desktop-window maximized> ``` #### `closable` Type: `boolean` If present, the window can be closed via an UI button. Omit to disable closing from the UI. Closing via JS API is still possible when this is disabled. Example: ```html <desktop-window closable> ``` #### `fullscreen` Type: `boolean` If present, the window is displayed in fullscreen mode. In fullscreen mode there is no borders around the window, but the titlebar is still visible with the minimize, restore, close controls. Example: ```html <desktop-window fullscreen> ``` #### `hidden` Type: `boolean` If present, the window is not visible. Remove this attribute to show the window. Example: ```html <desktop-window hidden> ``` #### `autofocus` Type: `boolean` If present, the window receives focus on creation. Example: ```html <desktop-window autofocus> ``` #### `frameless` Type: `boolean` If present, the window is rendered without borders or title bar. Example: ```html <desktop-window frameless> ``` #### `modal` Type: `boolean` If present, the window becomes modal (blocks interaction with other sibling windows or the background). Example: ```html <desktop-window modal> ``` #### `aspectratio` Type: `number` Enforces a fixed aspect ratio (`width / height`) when resizing. Example: ```html <desktop-window aspectratio="1.777"> ``` #### `aspectratioextrawidth` Type: `number` Extra width in pixels added to the actual content width when maintaining the aspect ratio. Example: ```html <desktop-window aspectratioextrawidth="50"> ``` #### `aspectratioextraheight` Type: `number` Extra height in pixels added to the content height for aspect ratio calculation. Example: ```html <desktop-window aspectratioextraheight="50"> ``` ### Events emitted These events are dispatched (they bubble) on the `<desktop-window>` element when the user interact with the UI or when triggering states with events. If you toggle attributes/properties directly, no events are emitted. “*ing” events are cancelable pre-flight hooks; call `event.preventDefault()` to stop the default action/state change. These events carry no `detail`. #### `closing` (cancelable) Fired when a close is requested (via the close button or `close()`), before the element is removed. Preventing it stops the default removal. #### `closed` Fired after a close/destroy attempt. Treat it as “close flow finished”; if you need to know whether the element is still connected, check `win.isConnected` in your handler. #### `minimizing` (cancelable) Fired before the component sets `minimized = true` (typically via the minimize control). Preventing it keeps the window unminimized. #### `minimized` Fired when the window enters the minimized state (i.e. `minimized` changes from `false` to `true`). #### `maximizing` (cancelable) Fired before the component sets `maximized = true` (typically via the maximize control or titlebar double-click). Preventing it keeps the window unmaximized. #### `maximized` Fired when the window enters the maximized state (i.e. `maximized` changes from `false` to `true`). #### `restoring` (cancelable) Fired before the component restores (clears `minimized` and/or `maximized`, depending on the trigger). Preventing it keeps the current minimized/maximized state. #### `restored` Fired when the window leaves a minimized or maximized state (i.e. `minimized` or `maximized` changes from `true` to `false`). #### `requesting-fullscreen` (cancelable) Fired before the component sets `fullscreen = true` in response to a fullscreen request. Preventing it keeps fullscreen off. There are no post-state events for fullscreen. #### `exiting-fullscreen` (cancelable) Fired before the component sets `fullscreen = false` in response to an exit-fullscreen request. Preventing it keeps fullscreen on. There are no post-state events for fullscreen. ### Events listening for `<desktop-window>` listens to a small set of internal/control events. You can dispatch these on the element to trigger the same behavior as the built-in UI, or to drive the component from your own controls. Most of these are expected to be regular `Event`s. The `move` / `resize-*` events must be `CustomEvent`s with pointer coordinates in `detail`. #### `close` Requests closing the window. Internally triggers the cancelable `closing` flow and then `closed`. ```js win.dispatchEvent(new Event('close', { bubbles: true })); ``` #### `minimize` Requests minimizing the window. Internally emits cancelable `minimizing`, then sets `minimized = true`. ```js win.dispatchEvent(new Event('minimize', { bubbles: true })); ``` #### `maximize` Requests maximizing the window. Internally emits cancelable `maximizing`, then sets `maximized = true`. ```js win.dispatchEvent(new Event('maximize', { bubbles: true })); ``` #### `restore` Requests restoring from minimized and/or maximized. Internally emits cancelable `restoring`, then clears `minimized` and `maximized`. ```js win.dispatchEvent(new Event('restore', { bubbles: true })); ``` #### `request-fullscreen` Requests fullscreen mode. Internally emits cancelable `requesting-fullscreen`, then sets `fullscreen = true`. ```js win.dispatchEvent(new Event('request-fullscreen', { bubbles: true })); ``` #### `exit-fullscreen` Requests leaving fullscreen mode. Internally emits cancelable `exiting-fullscreen`, then sets `fullscreen = false`. ```js win.dispatchEvent(new Event('exit-fullscreen', { bubbles: true })); ``` #### `move` Starts a drag operation as if the user pressed the titlebar at a given pointer position. Must be dispatched as: ```js CustomEvent('move', { detail: { clientX, clientY }, bubbles: true }) ``` ```js win.dispatchEvent(new CustomEvent('move', { bubbles: true, detail: { clientX: 200, clientY: 120 }, })); ``` #### `resize-n | resize-e | resize-s | resize-w | resize-ne | resize-nw | resize-se | resize-sw` Starts a resize operation in the given direction as if the user pressed the corresponding resize handle at a given pointer position. Must be dispatched as: ```js CustomEvent('resize-<dir>', { detail: { clientX, clientY }, bubbles: true }) ``` ```js win.dispatchEvent(new CustomEvent('resize-se', { bubbles: true, detail: { clientX: 640, clientY: 480 }, })); ``` Notes: - If `movable` / `resizable` are not enabled, `move` / `resize-*` won’t start the interaction. - If the event payload is missing `detail.clientX` / `detail.clientY` (numbers), the component throws an error. ### Properties All attributes are reflected as properties (and vice versa). Boolean properties map to boolean attributes: setting `true` adds the attribute, setting `false` removes it. #### `name: string | null` Title shown in the default title UI (unless you override the `titlebar-center` slot). #### `movable: boolean` Enables dragging by the titlebar. #### `x: number` Left position in pixels (relative to the parent). Ignored while `centered` is `true`. Defaults to `DesktopWindow.defaultX`. #### `y: number` Top position in pixels (relative to the parent). Ignored while `centered` is `true`. Defaults to `DesktopWindow.defaultY`. #### `centered: boolean` Centers the window within its parent. While enabled, the effective position is computed from parent size and `width`/`height`. #### `width: number` Window width in pixels. Defaults to `DesktopWindow.defaultWidth`. #### `height: number` Window height in pixels. Defaults to `DesktopWindow.defaultHeight`. #### `minWidth: number` Minimum allowed width during resize. Defaults to `DesktopWindow.defaultMinWidth`. #### `minHeight: number` Minimum allowed height during resize. Defaults to `DesktopWindow.defaultMinHeight`. #### `maxWidth: number` Maximum allowed width during resize. Defaults to `DesktopWindow.defaultMaxWidth`, and if that is `null` it falls back to the parent element’s width. #### `maxHeight: number` Maximum allowed height during resize. Defaults to `DesktopWindow.defaultMaxHeight`, and if that is `null` it falls back to the parent element’s height. #### `resizable: boolean` Enables resizing via the resize handles. #### `minimizable: boolean` Shows the minimize control and enables minimizing from the UI. #### `minimized: boolean` Minimized state. When set to `true`, the client area is collapsed to zero height. #### `maximizable: boolean` Shows the maximize control and enables maximizing from the UI (including titlebar double-click). #### `maximized: boolean` Maximized state. When set to `true`, the window snaps to `top/left = 0` and `width/height = 100%` within the parent. #### `closable: boolean` Shows the close control in the UI. Programmatic close (`close()` / `destroy()`) is still possible even if this is `false`. #### `fullscreen: boolean` Fullscreen state. When set, the window fills the parent and hides borders, titlebar, and resize handles. #### `hidden: boolean` Standard HTML hidden behavior (not specific to this component). When present, the element is not rendered. #### `autofocus: boolean` If set, the window focuses itself when connected. If toggled on later, it also focuses immediately. #### `frameless: boolean` Hides the titlebar and removes border/shadow (transparent background). Intended for custom chrome. #### `modal: boolean` Shows an internal backdrop element that sits behind the window (within the parent) and intercepts clicks; clicking the backdrop calls `flash()`. #### `aspectRatio: number` Enables fixed aspect ratio resize (`width / height`). `0` disables the constraint. #### `aspectRatioExtraWidth: number` Extra width in pixels used by the aspect-ratio resize constraint. Conceptually, it reserves a fixed horizontal region on top of the ratio-locked client area: the ratio is maintained for the client area with this extra width subtracted, while the total client width still includes it. #### `aspectRatioExtraHeight: number` Extra height in pixels used by the aspect-ratio resize constraint. Conceptually, it reserves a fixed vertical region on top of the ratio-locked client area: the ratio is maintained for the client area with this extra height subtracted, while the total client height still includes it. ### Methods All methods are instance methods on the custom element (e.g. `const win = document.querySelector('desktop-window') as DesktopWindow;`). #### `flash()` Visually draws attention to the window by briefly playing a “border flash” animation. Useful when the window is behind others or the user clicked outside while it’s modal. - Does not change focus. - Safe to call repeatedly; it restarts the animation. ```ts win.flash(); ``` #### `isFocused()` Returns `true` if the window currently contains focus (internally checks `:focus-within` in the shadow root). ```ts if (!win.isFocused()) { win.flash(); } ``` #### `focus()` Brings the window to front (bumps its internal z-index) and focuses it. - Focus is set on the internal window element. - Triggers normal browser focus/blur behavior. ```ts win.focus(); ``` #### `blur()` Removes focus from the window (blurs the internal window element). ```ts win.blur(); ``` #### `close()` Requests closing the window with a cancelable lifecycle event. Flow: 1. Dispatches `closing` (bubbles, cancelable) on the custom element. 2. If not prevented: removes the element from DOM. 3. Dispatches `closed` (bubbles) after removal. Use when you want “user-like” close semantics and want listeners to be able to veto. ```ts win.addEventListener('closing', (e) => { e.preventDefault(); // veto close }); win.close(); // window does not closing ``` #### `destroy()` Immediate teardown: removes the element from DOM and dispatches `closed` (bubbles). No cancelation, no `closing`. Use when you want a hard close (e.g. app shutdown). ```ts win.destroy(); ``` #### `getPosition()` Returns `[x, y]` in pixels relative to the immediate parent element’s top-left corner, based on actual layout (bounding rects), not on attributes. ```ts const [x, y] = win.getPosition(); ``` #### `setPosition(x, y)` Sets `x` and `y` attributes (integer pixels). Equivalent to: ```ts win.x = x; win.y = y; ``` ```ts win.setPosition(120, 80); ``` #### `getSize()` Returns `[width, height]` in pixels based on actual rendered window size (`getBoundingClientRect()`), rounded to integers. ```ts const [w, h] = win.getSize(); ``` #### `setSize(width, height)` Sets `width` and `height` attributes (unsigned integer pixels). ```ts win.setSize(640, 480); ``` #### `getNormalBounds()` Returns the “normal” bounds from the element attributes (not accounting for visual overrides from `centered`, `fullscreen`, `maximized`, `minimized`): ```ts const normal = win.getNormalBounds(); // { x, y, width, height } from attributes (with defaults applied) ``` Useful as a persisted/restorable geometry snapshot. #### `getBounds()` Returns the actual current bounds `{ x, y, width, height }` in pixels relative to the parent element, based on layout. - Unlike `getNormalBounds()`, it reflects real geometry when `centered`, `fullscreen`, `maximized`, `minimized` are active. - Values are floored to integers. ```ts const bounds = win.getBounds(); ``` #### `setBounds({ x, y, width, height })` Sets any provided members of the bounds object by updating the corresponding attributes. ```ts win.setBounds({ x: 40, y: 40, width: 800, height: 600 }); win.setBounds({ width: 500 }); // partial update ``` #### `getContentSize()` Returns `[width, height]` in pixels of the content area (`client-area`) based on actual layout. This is the size of the default slot host region, not the outer window. ```ts const [cw, ch] = win.getContentSize(); ``` #### `setContentSize(width, height)` Sets the outer window size so the content area becomes the requested size. It computes current chrome (titlebar + borders) and adjusts `win.width` / `win.height` accordingly. ```ts win.setContentSize(640, 480); ``` #### `getContentBounds()` Returns the actual bounds `{ x, y, width, height }` of the content area relative to the parent element. ```ts const content = win.getContentBounds(); ``` #### `setContentBounds({ x, y, width, height })` Sets the outer window geometry so the content area ends up at the requested bounds. - `x`/`y` are interpreted as the desired content area position relative to parent. - `width`/`height` are interpreted as desired content area size. ```ts win.setContentBounds({ x: 100, y: 80, width: 600, height: 400 }); ``` #### `setAspectRatio(ratio, { width, height }?)` Convenience method to enforce a resize aspect ratio and optionally configure extra size offsets. - `ratio` is `width / height`. - Passing `0` removes the aspect ratio constraint. - `extraSize.width` maps to `aspectratioextrawidth` and `extraSize.height` maps to `aspectratioextraheight`. Theextravalues let you keep the client area ratio while reserving fixed pixels: the aspect-ratio lock is applied to the *adjusted* client size, i.e. `(clientWidth - aspectratioextrawidth)` relative to `(clientHeight - aspectratioextraheight)`. Use them to carve out a constant region (toolbar/HUD/etc.) while keeping the remaining area ratio-locked. ```ts win.setAspectRatio(16 / 9); // make room for a 30px height toolbar or menubar win.setAspectRatio(16 / 9, { width: 0, height: 30 }); // remove constraint win.setAspectRatio(0); ``` ### Slots `<desktop-window>` provides three named slots in the titlebar. They let you inject custom content (icons, buttons, menus, custom title UI) into the left/center/right areas. General usage: ```html <desktop-window name="My Window" movable> <span slot="titlebar-start">App</span> <span slot="titlebar-end">v1.0</span> Window content </desktop-window> ``` Notes: - The titlebar is hidden in `[frameless]` and `[fullscreen]`, so these slots won’t be visible in those modes. - The center area has a default fallback: if you don’t provide `titlebar-center`, the component renders the `name` attribute into the built-in `titlebar-text` (part) element. - If you provide your own `titlebar-center` content, you are fully replacing that default title rendering. In that case the `name` attribute still exists, but it won’t be shown unless you render it yourself. #### `titlebar-start` Left side of the titlebar. Good for an app icon, window menu button etc. ```html <desktop-window name="Editor" movable> <img slot="titlebar-start" src="icon.png" alt="" /> ... </desktop-window> ``` #### `titlebar-center` Center area of the titlebar. Default behavior (no slot): shows the `name` attribute in the built-in title element. Custom behavior (slot provided): replaces the default title UI. ```html <desktop-window name="Ignored visually" movable> <div slot="titlebar-center" style="padding: 0 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;"> Custom title </div> ... </desktop-window> ``` #### `titlebar-end` Right side of the titlebar, before the control buttons (minimize/restore/maximize/close). Useful for status text, extra actions, or a toolbar. ```html <desktop-window name="Downloads" movable minimizable> <div slot="titlebar-end"> <button type="button">Refresh</button> </div> ... </desktop-window> ``` ### Parts `<desktop-window>` exposes a set of Shadow Parts so you can style key internal elements from outside the component using `::part(...)`. This is meant for layout and visual tweaks that go beyond the provided CSS variables. Basic pattern: ```css desktop-window::part(window) { border-radius: 10px; } desktop-window::part(client-area) { padding: 12px; overflow: auto; } ``` Notes: - Parts work regardless of `shadowRoot` mode (`open` or `closed`). - `::part()` targets the element that carries `part="..."`. You cannot directly style arbitrary descendants inside that part unless they are also exposed as parts. - Some parts are conditionally visible: - Control buttons are `display: none` unless the corresponding boolean attributes are present (`minimizable`, `maximizable`, `closable`, etc.). - Titlebar is hidden in `[frameless]` and `[fullscreen]`. #### Available parts - `window` Main window container (the dialog box). Good for border, shadow, background, radius. - `titlebar` Title bar container. Hidden when `[frameless]` or `[fullscreen]`. - `titlebar-start` Wrapper for `slot[name="titlebar-start"]`. - `titlebar-center` Wrapper for `slot[name="titlebar-center"]`. Contains the default title element when you don’t provide this slot. - `titlebar-end` Wrapper for `slot[name="titlebar-end"]`. - `titlebar-text` Default title element. Only relevant if you do not override the `titlebar-center` slot content. - `minimize-button` Minimize control button. Visible only with `[minimizable]` and not `[minimized]`. - `restore-button` Restore control button. Visible when minimized or maximized (depending on enabled features). - `maximize-button` Maximize control button. Visible only with `[maximizable]` and not `[maximized]`. - `close-button` Close control button. Visible only with `[closable]`. - `client-area` Content container (hosts the default slot). Good place for padding/scroll rules. If you want to theme the control icons/colors, prefer CSS variables first (mask images and colors are driven by custom properties). Parts are primarily for structural styling (spacing, borders, shadows, typography, etc.). ### CSS Variables All variables are defined on `:host` and can be overridden from outside (e.g. `desktop-window { --desktop-window-titlebar-height: 32px; }`). “Focused” variables are used when the window is in `:focus-within`. Example: ```css desktop-window { --desktop-window-titlebar-height: 32px; --desktop-window-border-color: #555; } ``` #### Window surface - `--desktop-window-background-color` Background color of the window surface. - `--desktop-window-focused-background-color` Background color while focused. #### Window border - `--desktop-window-border-width` Border width. - `--desktop-window-border-color` Border color (unfocused). - `--desktop-window-focused-border-color` Border color while focused. #### Animations - `--desktop-window-minimize-duration` Duration used for the minimize height animation (when motion is allowed). - `--desktop-window-maximize-duration` Duration used for the maximize geometry animation (when motion is allowed). #### Titlebar layout - `--desktop-window-titlebar-height` Titlebar height. #### Titlebar typography and colors - `--desktop-window-titlebar-font-family` Font family used for the default title. - `--desktop-window-titlebar-font-size` Font size used for the default title. - `--desktop-window-titlebar-text-color` Default title text color (unfocused). - `--desktop-window-titlebar-background-color` Titlebar background (unfocused). - `--desktop-window-focused-titlebar-text-color` Default title text color while focused. - `--desktop-window-focused-titlebar-background-color` Titlebar background while focused. #### Control button icons These are used as CSS mask images for the built-in control buttons. - `--desktop-window-minimize-button-mask-image` Mask image for the minimize button icon. - `--desktop-window-maximize-button-mask-image` Mask image for the maximize button icon. - `--desktop-window-restore-button-mask-image` Mask image for the restore button icon. - `--desktop-window-close-button-mask-image` Mask image for the close button icon. #### Control button geometry Applies to the built-in titlebar buttons. - `--desktop-window-buttons-width` Button width. - `--desktop-window-buttons-height` Button height. - `--desktop-window-buttons-margin` Right margin applied to each button. #### Control buttons: base (unfocused) These are the default colors for all control buttons unless overridden per-button below. - `--desktop-window-buttons-text-color` Button “icon” color (via `currentColor`). - `--desktop-window-buttons-background-color` Button background. - `--desktop-window-buttons-hover-text-color` Button icon color on hover. - `--desktop-window-buttons-hover-background-color` Button background on hover. #### Control buttons: base (focused) Focused-state equivalents of the base button variables. - `--desktop-window-focused-buttons-text-color` Button icon color while focused. - `--desktop-window-focused-buttons-background-color` Button background while focused. - `--desktop-window-focused-buttons-hover-text-color` Button icon color on hover while focused. - `--desktop-window-focused-buttons-hover-background-color` Button background on hover while focused. #### Minimize button colors Overrides for the minimize button (unfocused). Falls back to the base button variables if you don’t override these. - `--desktop-window-minimize-text-color` Minimize icon color. - `--desktop-window-minimize-background-color` Minimize background. - `--desktop-window-minimize-hover-text-color` Minimize icon color on hover. - `--desktop-window-minimize-hover-background-color` Minimize background on hover. #### Minimize button colors (focused) Focused-state equivalents for minimize. - `--desktop-window-focused-minimize-text-color` Minimize icon color while focused. - `--desktop-window-focused-minimize-background-color` Minimize background while focused. - `--desktop-window-focused-minimize-hover-text-color` Minimize icon color on hover while focused. - `--desktop-window-focused-minimize-hover-background-color` Minimize background on hover while focused. #### Maximize button colors Overrides for the maximize button (unfocused). - `--desktop-window-maximize-text-color` Maximize icon color. - `--desktop-window-maximize-background-color` Maximize background. - `--desktop-window-maximize-hover-text-color` Maximize icon color on hover. - `--desktop-window-maximize-hover-background-color` Maximize background on hover. #### Maximize button colors (focused) Focused-state equivalents for maximize. - `--desktop-window-focused-maximize-text-color` Maximize icon color while focused. - `--desktop-window-focused-maximize-background-color` Maximize background while focused. - `--desktop-window-focused-maximize-hover-text-color` Maximize icon color on hover while focused. - `--desktop-window-focused-maximize-hover-background-color` Maximize background on hover while focused. #### Restore button colors Overrides for the restore button (unfocused). - `--desktop-window-restore-text-color` Restore icon color. - `--desktop-window-restore-background-color` Restore background. - `--desktop-window-restore-hover-text-color` Restore icon color on hover. - `--desktop-window-restore-hover-background-color` Restore background on hover. #### Restore button colors (focused) Focused-state equivalents for restore. - `--desktop-window-focused-restore-text-color` Restore icon color while focused. - `--desktop-window-focused-restore-background-color` Restore background while focused. - `--desktop-window-focused-restore-hover-text-color` Restore icon color on hover while focused. - `--desktop-window-focused-restore-hover-background-color` Restore background on hover while focused. #### Close button colors Overrides for the close button (unfocused). By default the close hover state typically uses a destructive accent. - `--desktop-window-close-text-color` Close icon color. - `--desktop-window-close-background-color` Close background. - `--desktop-window-close-hover-text-color` Close icon color on hover. - `--desktop-window-close-hover-background-color` Close background on hover. #### Close button colors (focused) Focused-state equivalents for close. - `--desktop-window-focused-close-text-color` Close icon color while focused. - `--desktop-window-focused-close-background-color` Close background while focused. - `--desktop-window-focused-close-hover-text-color` Close icon color on hover while focused. - `--desktop-window-focused-close-hover-background-color` Close background on hover while focused. #### Default options on the custom element class These are static defaults used when the corresponding attributes are missing (and can be overridden globally by setting the static variables). - `DesktopWindow.defaultX: number` Default `x` when the `x` attribute is not present. Initial: `50`. - `DesktopWindow.defaultY: number` Default `y` when the `y` attribute is not present. Initial: `50`. - `DesktopWindow.defaultWidth: number` Default `width` when the `width` attribute is not present. Initial: `350`. - `DesktopWindow.defaultHeight: number` Default `height` when the `height` attribute is not present. Initial: `350`. - `DesktopWindow.defaultMinWidth: number` Default `minWidth` when the `minwidth` attribute is not present. Initial: `150`. - `DesktopWindow.defaultMinHeight: number` Default `minHeight` when the `minheight` attribute is not present. Initial: `150`. - `DesktopWindow.defaultMaxWidth: number | null` Default `maxWidth` when the `maxwidth` attribute is not present. If `null`, `maxWidth` falls back to the parent element’s width. Initial: `null`. - `DesktopWindow.defaultMaxHeight: number | null` Default `maxHeight` when the `maxheight` attribute is not present. If `null`, `maxHeight` falls back to the parent element’s height. Initial: `null`. ## Missing a feature? Create an issue describing your needs! If it fits the scope of the project I will implement it.