Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions packages/webamp-docs/docs/06_API/02_webamp-constructor.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,21 @@ const webamp = new Webamp({

For a list of hotkeys, see the [hotkeys documentation](../05_features/01_hotkeys.md).

### `focusIndicator`

**Since** [Unreleased](../12_changelog.md#unreleased)

A boolean indicating if a focus indicator should be drawn around the focused control when the user navigates with the keyboard. **Default:** `false`.

The indicator only appears for keyboard focus (it uses [`:focus-visible`](https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible)), so mouse and touch users never see it. It is drawn entirely outside the focused control, so the skin's pixels are never covered, and is two-tone (a light ring inside a dark one) so it remains visible against any skin.

```ts
const webamp = new Webamp({
focusIndicator: true,
// ...other config options
});
```

### `zIndex`

An integer representing the zIndex that Webamp should use. **Default:** `99999`.
Expand Down
1 change: 1 addition & 0 deletions packages/webamp-docs/docs/12_changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ If you want access to the changes in this section before they are officially rel
- The Milkdrop window now has a stable id, `#milkdrop-window`, like `#main-window`, `#equalizer-window` and `#playlist-window`.
- Added a new Webamp instance method: [`webamp.onMediaError(cb)`](./06_API/03_instance-methods.md#onmediaerrorcb-error--code-number---void---void), which is called when a track fails to load or play.
- Added a new Webamp instance method: [`webamp.setTracks(tracks)`](./06_API/03_instance-methods.md#settrackstracks-track-void), which replaces the playlist without starting playback.
- Added a new [`focusIndicator`](./06_API/02_webamp-constructor.md#focusindicator) option, which draws a focus ring around the focused control for keyboard users. It is off by default, only appears for keyboard focus, and is drawn outside the control so skins render unchanged.

### Bug Fixes

Expand Down
16 changes: 16 additions & 0 deletions packages/webamp/css/webamp.css
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,22 @@
outline: 0;
}

/*
* Opt-in keyboard focus indicator, enabled by the `focusIndicator` option.
* It is drawn entirely outside the focused element so the skin's pixels are
* never covered, and is two-tone (a light ring inside a dark one) so that it
* contrasts with any skin. `z-index` keeps adjacent sprites from painting over
* it. The `input[type="range"]` selector is needed to beat the range input
* reset's specificity below.
*/
#webamp.webamp-focus-indicator :focus-visible,
#webamp.webamp-focus-indicator input[type="range"]:focus-visible {
outline: 2px solid #fff;
outline-offset: 0;
box-shadow: 0 0 0 4px #000;
z-index: 1;
}

/* Range input css reset */
#webamp input[type="range"] {
-webkit-appearance: none;
Expand Down
6 changes: 6 additions & 0 deletions packages/webamp/js/components/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ interface Props {
filePickers: FilePicker[];
media: IMedia;
parentDomNode: HTMLElement;
focusIndicator: boolean;
onMount?: () => void;
}

Expand All @@ -42,6 +43,7 @@ export default function App({
filePickers,
onMount,
parentDomNode,
focusIndicator,
}: Props) {
const closed = useTypedSelector(Selectors.getClosed);
const genWindowsInfo = useTypedSelector(Selectors.getGenWindows);
Expand All @@ -64,6 +66,10 @@ export default function App({
webampNode.style.zIndex = String(zIndex);
}, [webampNode, zIndex]);

useLayoutEffect(() => {
webampNode.classList.toggle("webamp-focus-indicator", focusIndicator);
}, [webampNode, focusIndicator]);

useLayoutEffect(() => {
parentDomNode.appendChild(webampNode);
return () => {
Expand Down
11 changes: 11 additions & 0 deletions packages/webamp/js/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -694,6 +694,17 @@ export interface Options {
*/
enableHotkeys?: boolean;

/**
* Should a focus indicator be drawn around the focused control when the user
* navigates with the keyboard?
*
* The indicator is only shown for keyboard focus (`:focus-visible`), and is
* drawn outside the focused control so the skin itself is never altered.
*
* Default: `false`
*/
focusIndicator?: boolean;

/**
* An array of additional file pickers.
*
Expand Down
1 change: 1 addition & 0 deletions packages/webamp/js/webampLazy.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@ class Webamp {
<App
media={this.media}
filePickers={this.options.filePickers || []}
focusIndicator={this.options.focusIndicator ?? false}
onMount={onMount}
parentDomNode={contained ? node : document.body}
/>
Expand Down
Loading