scrollFocus
elements man ui/behaviors/scroll-focusMakes a region that scrolls a Tab stop while it overflows, so a keyboard
user can reach it and scroll it with the arrows, PageDown and Space. Without
regions the root itself is the region; a region the author gave a
tabindex is left alone.
Signaturefunction scrollFocus(root: HTMLElement, opts?: ScrollFocusOptions): () => void;
Options
| Option | Type | Default | What it does |
|---|---|---|---|
regions |
string |
the root itself | Selector for the scrolling regions inside root. |
owns |
(el: HTMLElement) => boolean |
none | Keeps only the regions that belong to root, so a nested panel's own are skipped. |
marker |
string |
"data-scroll-stop" |
Attribute set on a region this made a stop, for styling its focus ring. |
label |
string | ((el: HTMLElement) => string | null) |
none | Accessible name for a stop that has no role and no name: the region gets role="region" and this aria-label while it is a stop, so a screen reader names what it landed on. |
A region is measured when the root's content changes and when the region or its children resize. One that stops overflowing while focused keeps its stop until focus leaves, so focus is never thrown out of a panel. The stop function puts back what the behavior added, except on a region that still has focus.
In a template of your own
app/shared/templates/log-view/index.ehtmlimport { scrollFocus } from "@elements/ui/behaviors"; interface LogViewState { stop?: () => void; } <LogView (lines: string[], private ui: LogViewState = {})> <pre class="log-view" oninsert={(e) => ui.stop = scrollFocus(e.target as HTMLElement, { label: "Log" })} onremove={() => ui.stop?.()}>{lines.join("\n")}</pre> </LogView>
app/shared/templates/log-view/style.css.log-view { max-height: 20rem; overflow: auto; } .log-view[data-scroll-stop]:focus-visible { box-shadow: var(--focus-ring); }
Writes
tabindex="0" and the marker on a region while it overflows; with label,
role="region" and aria-label on one that had no role or name. All put
back by stop.
Used by
Dialog (opens in a new tab), Message (opens in a new tab), Popover (opens in a new tab), RichText (opens in a new tab), Sheet (opens in a new tab).