import{type TemplateResult,type PropertyValues}from'lit';import{LyraElement}from'../../../internal/lyra-element.js';export interface LyraAppRailItemToggleDetail{open:boolean;}export interface LyraAppRailItemEventMap{'lr-toggle-request':CustomEvent;'lr-toggle':CustomEvent;} /** * `` — an explicit icon/label navigation item for * ``. The rail sets its `icon-only` attribute as the viewport * changes, keeping the label available to assistive technology while removing * it from the visual layout. `[part="base"]` resolves to a square hit target * (matching the icon-button footprint used elsewhere in this library) while * `icon-only`, instead of stretching across the rail's icon column. * A host `aria-label` is forwarded by attribute presence to the internal * focusable link or button, including an explicitly empty value. * When a focused link/button is replaced, focus follows an available replacement. If the new * owner is disabled or inert, focus returns to the available element that led into the item, or * to the stable owning rail surface when there is no return target; a newer external focus move * always wins. * * An item may own its own expandable child list -- the treeitem-with-link pattern used by * repository trees, Notion-style page trees and IDE explorers, where the row itself is a * destination and a SEPARATE disclosure expands that one item's own nested rows beneath it. * `` cannot express this: its collapsible heading IS the toggle, so nesting a * navigable link inside it would put an interactive element inside a button. Slotting one or more * ``s into `children` instead renders a built-in disclosure -- a SIBLING of * `[part="base"]`, never nested inside it, so the link keeps navigating on its own and the * disclosure keeps toggling on its own; clicking one never triggers the other. The disclosure * carries `aria-expanded`/`aria-controls` and a localized accessible name interpolating this * item's own label, mirroring ``'s collapsible contract for event name, detail * shape and cancelable request/commit semantics exactly (see `lr-toggle-request`/`lr-toggle` * below). An item with nothing slotted into `children` renders no disclosure and no extra * wrapper -- byte-identical to an item with no children slot at all. * * `icon-only` forwards onto every `` this item DIRECTLY owns through `children`, * exactly how `` forwards onto the items and nested groups it owns -- so a * nested item's own icon/label presentation tracks the rail's presentation without the rail * reaching through two hosts. The disclosure itself never changes shape between presentations: it * is always a fixed icon-button-sized square beside `[part="base"]`, the same footprint `end` and * icon-only `[part="base"]` already use, so it needs no icon-only-specific styling of its own. * There is no ancestor-current treatment: `` has no equivalent concept for a * group containing the current item, so none is invented here either -- a current descendant * stays perceivable only through its own `current` property, exactly as an unnested item would. * * @customElement lr-app-rail-item * @slot - The visible navigation label. * @slot icon - The leading decorative icon. Its flattened subtree is inert and hidden from * assistive technology; the default slot or host `aria-label` names the internal control. * @slot meta - Secondary trailing text -- an unread count, a keyboard shortcut. Rendered as a * SIBLING of the internal link/button, never inside it, so it is not part of the item's * accessible name and a pointer landing on it does not activate the item. Visually clipped in * `icon-only` mode exactly as `[part="label"]` is, staying available to assistive technology. * @slot end - Trailing controls or adornments -- an overflow menu trigger, a status badge. Also a * sibling of the internal link/button (the same shape `` uses for its * `header-actions`), so a slotted control keeps its own click, keyboard activation and focus * order instead of being swallowed by the item's own activation target. Unlike `meta` it stays * visible in `icon-only` mode, where it shares the narrow rail's width with the icon. * @slot children - Nested ``s disclosed beneath this item. Rendering anything * into this slot grows a built-in disclosure button (`[part="toggle"]`) as a sibling of * `[part="base"]`; leaving it empty renders neither the disclosure nor `[part="children"]`. * @event lr-toggle-request - Cancelable proposal emitted before `expanded` changes from the * built-in disclosure. Call `preventDefault()` to keep the current state, or assign `expanded` * from the listener to resolve it yourself -- a write during the dispatch suppresses the default * commit even when it assigns the value the property already held. Not emitted for a direct * `expanded` write. `detail: LyraAppRailItemToggleDetail` (`{ open: boolean }` -- the field is * named `open`, matching ``'s identical event name and detail shape exactly, * so a listener bound to both components' `lr-toggle-request` need not branch on which fired). * @event lr-toggle - The item finished expanding or collapsing its `children`. Non-cancelable, * emitted after `expanded` is written, and never emitted for a vetoed or listener-resolved * request. `detail: LyraAppRailItemToggleDetail`. * @csspart base - The link or button receiving focus and activation. * @csspart icon - The icon wrapper. * @csspart label - The label wrapper; visually clipped in icon-only mode. * @csspart current-indicator - A decorative inline indicator rendered only while the item is * `current`/`aria-current="page"`, mirroring ``'s shipped * `active-indicator` part. * @csspart meta - The wrapper around the `meta` slot. Hidden while nothing is slotted into it, so * an item without secondary text renders exactly as before the slot existed. * @csspart end - The wrapper around the `end` slot, following `[part="meta"]`. Hidden while empty * for the same reason. * @csspart toggle - The disclosure control, rendered only while something is slotted into * `children`. A sibling of `[part="base"]`, never nested inside it, so activating one never * triggers the other. Carries `aria-expanded` in both states and `aria-controls` pointing at * `[part="children"]`'s id; its accessible name is a localized `this.localize()` template * interpolating this item's own label, with no literal fallback. * @csspart toggle-icon - The wrapper around the disclosure chevron. Direction-aware through this * wrapper's own `transform`, never a second mirrored glyph -- mirrors * ``'s `[part="toggle-icon"]`. * @csspart children - The wrapper around the `children` slot. Rendered only while something is * slotted into `children`; hidden (but present, so `aria-controls` keeps resolving) while * `expanded` is `false`. * @csspart tooltip - The hover/focus label flyout, only rendered while `tooltip` is set, the item * is `icon-only`, and it is hovered or focused. * @cssprop [--lr-app-rail-item-current-bg=var(--lr-color-brand-quiet)] - Background of the * `current`/`aria-current="page"` item. Scoped to `[aria-current='page']` only and declared as an * inline `var()` fallback (never on `:host`), so setting it on the element or an ancestor recolors * only the current item without hijacking the library-wide `--lr-color-brand-quiet` token. * @cssprop [--lr-app-rail-item-current-color=var(--lr-color-brand)] - Text/icon color of the * `current`/`aria-current="page"` item. * @cssprop [--lr-app-rail-item-current-font-weight=var(--lr-font-weight-semibold)] - Font weight * of the `current`/`aria-current="page"` item, decoupled from the shared * `--lr-font-weight-semibold` token so retheming it does not repaint every other semibold * element on the page. Mirrors ``'s `--lr-stepper-current-font-weight` and * ``'s `--lr-segmented-selected-font-weight`. * @cssprop [--lr-app-rail-item-current-indicator-color=var(--lr-color-brand)] - Color of the * decorative `[part="current-indicator"]` while current. * @cssprop [--lr-app-rail-item-current-indicator-width=var(--lr-size-2px)] - Inline size of * `[part="current-indicator"]` while current. * @cssprop [--lr-app-rail-item-current-indicator-inset-inline=0 auto] - Logical inline-start and * inline-end insets for `[part="current-indicator"]`; set `auto 0` to place it at inline-end. * @cssprop [--lr-app-rail-item-current-indicator-display] - `[part="current-indicator"]`'s * `display` while `icon-only`. Unset (the default), the indicator is suppressed there -- a * full-height edge bar on the square icon-only tile reads as a rendering glitch. Set to `block` * (or any non-`none` display) to restore it. Full presentation is unaffected either way; its own * `[part="current-indicator"]` rule declares no `display` at all. * @cssprop [--lr-app-rail-item-current-ring] - `box-shadow` on `[part="base"]` while * `current`/`aria-current="page"`. Unset, icon-only gets an inset ring by default -- the * non-color-only signal that replaces the indicator bar suppressed there (WCAG 1.4.1); full * presentation, which already conveys current state through the indicator bar and * `--lr-app-rail-item-current-font-weight`, stays ring-free (`none`) by default. Setting this * token explicitly applies the same value in both presentations. * @cssprop [--lr-app-rail-item-hover-bg=var(--lr-color-brand-quiet)] - Hover background. * @cssprop [--lr-app-rail-item-hover-color=var(--lr-color-brand)] - Hover text/icon color. * @cssprop --lr-app-rail-item-active-bg - Pressed background; defaults to the former brand-quiet * active mix. * @cssprop [--lr-app-rail-item-active-color=var(--lr-color-brand)] - Pressed text/icon color. * @cssprop [--lr-app-rail-item-min-block-size=var(--lr-icon-button-size)] - `[part="base"]`'s row * height. Floor-clamped to `--lr-icon-button-size` regardless of the override, preserving the * WCAG 2.5.8 hit-area minimum. * @cssprop [--lr-app-rail-item-padding=var(--lr-space-s)] - `[part="base"]`'s padding. * @cssprop [--lr-app-rail-item-gap=var(--lr-space-s)] - Gap between `[part="icon"]` and * `[part="label"]`, and between the item's own control and its `[part="meta"]`/`[part="end"]` * adornments. * @cssprop [--lr-app-rail-item-meta-color=var(--lr-color-text-quiet)] - `[part="meta"]`'s text * color; quiet by default so a count reads as secondary to the label beside it. * @cssprop [--lr-app-rail-item-meta-font-size=var(--lr-font-size-sm)] - `[part="meta"]`'s * font size. * @cssprop [--lr-app-rail-item-icon-size=var(--lr-icon-button-size)] - `[part="icon"]`'s inline * size. Not floor-clamped -- the icon is decorative, not itself a pointer target. * @cssprop [--lr-app-rail-item-icon-only-size] - When set, sizes `[part="base"]`'s icon-only * square (`inline-size` and `block-size` alike) directly, independent of the row's own * `--lr-app-rail-item-min-block-size`. Unset (the default), the square is still derived via * `aspect-ratio: 1` against the row's block size, exactly as before. Still floor-clamped to * `--lr-icon-button-size` by `[part="base"]`'s shared `min-block-size` rule. * @cssprop [--lr-app-rail-item-font-size=inherit] - `[part="base"]`'s font size, set after the * `font` shorthand so it alone can be retuned while family/weight/line-height stay inherited. * @cssprop --lr-positioning-strategy - Cascading `absolute`/`fixed` override for the icon-only * flyout tooltip's `fixed` default, read from computed style when it is (re)positioned. Set it * once on `:root`, a theme, or one clipping ancestor to change every unset rail item beneath it; * an unrecognized value falls back to `fixed`. * @cssprop [--lr-app-rail-item-indent=var(--lr-space-l)] - `[part="children"]`'s * `padding-inline-start`. Applied once per nesting level -- a doubly-nested `children` list * compounds two insets automatically, since each level's own `[part="children"]` applies the * token again. Logical, so it mirrors under `dir="rtl"` with no separate rule. * @status stable * @since 4.0.0 */ export declare class LyraAppRailItem extends LyraElement{static styles:import("lit").CSSResultGroup[];static get observedAttributes():string[]; /** Optional destination. Without `href`, the item renders as a button. */ href:string; /** Optional link target. */ target:string; /** Prevents activation while retaining the item in the rail. */ disabled:boolean; /** Marks this as the destination for the current page/view. Reflects * `aria-current="page"` on `[part="base"]` and drives the active visual * treatment -- the rail has no built-in routing, so the consumer sets * this per item (e.g. by comparing `href` against the current location). */ current:boolean; /** Opt-in hover/focus flyout showing this item's label text while `icon-only` (set externally by * the parent `` as the viewport narrows) hides it from view -- an explicit, * documented property instead of an unverified cross-browser `::part()` + `::after` + `attr()` * composition. No effect outside icon-only mode, since the label is already visible there. * `false` (the default) reproduces today's exact output. */ tooltip:boolean; /** Whether this item's `children` are shown. `false` by default -- a nested list expanding * itself on first paint would be a surprising default, and it reproduces exactly what an item * with no `expanded` property rendered before this feature existed. Mirrors * ``'s `open` accessor: every write, including one that assigns the value * already held, marks the veto guard so a synchronous `lr-toggle-request` listener resolving * this itself is observed correctly (see {@link VetoWriteGuard}). */ get expanded():boolean;set expanded(next:boolean);private _expanded;private readonly toggleGuard;private showTooltip; /** `:empty` cannot see slotted light-DOM content (the wrapper always holds a `` element), * so emptiness is tracked from `slotchange` the same way `` tracks its own * `header-actions` wrapper. */ private hasEndSlot;private hasMetaSlot;private metaSlot?;private endSlot?;private stopPositioning?;private labelObserver?;private childrenObserver?;private semanticFocusRepair?;private focusReturnTarget?;private readonly childrenId; /** Reads the light-DOM `slot` attribute directly rather than a live `assignedNodes()` snapshot * -- the same WebKit-safe pattern ``'s own `onHeaderSlotChange`/`onFooterSlotChange` * use -- so the very first render (before any mutation has ever fired) already renders the * disclosure and `[part="children"]` when the item was authored with children in markup, * with no flash of the childless state. Only ELEMENT children can carry a `slot` attribute, so * reading `this.children` (not `this.childNodes`) already excludes stray text nodes. */ private get hasChildrenSlotted();connectedCallback():void;private armLabelObserver; /** Watches the light DOM for a `children`-slotted node being added, removed, or re-slotted, so * `hasChildrenSlotted` (read fresh from `render()`, never cached) triggers a re-render at the * moment the disclosure/`[part="children"]` should appear or disappear -- including the very * first time a consumer appends a nested item after construction. `childList` catches * add/remove; the `subtree`-scoped `slot`-only `attributes` filter catches an existing child * being re-slotted into or out of `children`, mirroring what a real `slotchange` listener would * see for an always-rendered slot (this slot is instead rendered on demand, so there is no * `` element to listen on while it does not exist). Also re-syncs this item's own * `icon-only` forwarding onto whatever it owns, since either kind of mutation can change which * nodes this item owns. */ private armChildrenObserver; /** Mirrors this item's own `icon-only` state onto every `` it DIRECTLY owns * through `children` -- exactly how ``'s `syncOwnedItems()` forwards onto the * items and nested groups it owns. One owner per node: ownership is resolved from the node's * PARENT, never the node itself, so a grandchild's own next sync does not immediately undo a * grandparent's write, and a nested item's own `attributeChangedCallback` cascades the same * forwarding one level further down in turn. Gated on `isConnected` so a detached item stops * claiming ownership of nodes appended to it afterwards. */ private syncOwnedChildren;private onToggleClick;private get labelText();private get tooltipText();private onFocusShow;private onBlurHide;private onEndSlotChange;private applyEndSlotPresence;private onMetaSlotChange;private applyMetaSlotPresence;attributeChangedCallback(name:string,oldValue:string|null,newValue:string|null):void;protected firstUpdated(changed:PropertyValues):void;protected willUpdate(changed:PropertyValues):void;protected updated(changed:PropertyValues):void;disconnectedCallback():void;private focusFallback; /** Activates the internal link or button. Disabled items remain inert. */ click():void;render():TemplateResult;}declare global{interface HTMLElementTagNameMap{'lr-app-rail-item':LyraAppRailItem;}}