StickyTray
StickyTray
An authored viewport-persistent content tray.
StickyTray may be authored as an Element or directly as a PageSection. Its authored location establishes an anchor in document flow, while Quail Pages owns the tray markup, accessibility, viewport placement, visibility, and runtime state. The handle renders Elements; the panel renders ordinary Sections. Handle content and its disclosure button are separate interactive surfaces.
When visibilityTriggers is omitted, the tray is simply available. Within each trigger group, any trigger may satisfy the group (OR). Every group must be satisfied for the tray to be presented (AND). Responsive triggers use the canonical QP mobile, tablet, and desktop presentation-width ranges. Anchor triggers are evaluated against the tray's authored anchor: anchor-passed becomes true after the anchor crosses above the viewport start, anchor-visible is true while any part of the anchor is inside the viewport, and anchor-passed-center becomes true after the anchor crosses above the viewport center line. Authored location alone enables no visibility trigger.
Vertical and horizontal placement independently control where the active tray appears and default to top-center. Overlay placement accounts for occupied header/footer boundaries. Inset fills the top or bottom edge, independently of horizontal alignment, and reserves its measured handle in the document viewport. Multiple inset handles stack in authored order. The panel overlays the remaining viewport. Inset shells move to the document viewport; authored anchors stay put.
Three independent choices: disclosure controls panel interaction; visibilityTriggers controls when the whole tray appears; positionMode controls whether it reserves viewport space. For a permanent sticky menu, author the menu in handle.elements with no sections and omit visibilityTriggers. To show that menu only after scrolling past its authored position, add visibilityTriggers: [["anchor-passed"]]. No disclosure button is needed.
Authoring guidance
Use when
Avoid when
Properties
ariaLabel
Accessible name for the tray container.
class
Optional theme styling hook.
disclosure
Panel interaction, independent from visibilityTriggers and positionMode. none keeps any panel content visible with no disclosure control. handle makes the full handle surface toggle the panel; authored links and controls inside the handle keep their own actions. chevron uses a separate disclosure button. A tray without panel sections has no disclosure in any mode.
"none" | "handle" | "chevron"
handle
Persistent content, rendered independently from the panel disclosure button.
class — string
Optional styling hook for the handle content.
elements — Element[] [REQUIRED]
Menus, cards, images, or other ordinary Elements in the persistent handle.
horizontal
Horizontal viewport placement. Defaults to center when omitted. left aligns the tray to the available left side, center centers it, and right aligns it to the available right side.
"left" | "center" | "right"
id
Stable non-empty identifier used to associate the tray control and content panel.
min length: 1
positionMode
Overlay leaves the document viewport unchanged. Inset reserves the measured handle at the top or bottom edge; its panel overlays the remaining viewport. Inset requires top or bottom vertical placement and fills that edge.
"overlay" | "inset"
sections
Interior Sections. Omit or leave empty for a permanent handle without a disclosure.
Items — StandardSection | RegionSection
Accepted shape 1 — StandardSection
Accepted shape 2 — RegionSection
type
Identifies the StickyTray type represented by this object.
"sticky-tray"
vertical
Vertical viewport placement. Defaults to top when omitted. top anchors the tray to the top side, middle centers it vertically, and bottom anchors it to the bottom side.
"top" | "middle" | "bottom"
visibilityTriggers
Conditions controlling when the tray is presented. Trigger values within each inner group use OR; the outer groups use AND. Omit this property for an unconditionally available tray. These conditions control tray visibility, not panel expansion: use disclosure for the panel interaction. Groups and trigger values within each group must be nonempty, and values within a group must be unique.
min items: 1
Example
Required
Full
examples are generated from the schema.