Experimental features

FUNSTACK UI supports the latest stable Blink, WebKit and Gecko, with no fallbacks for older browsers. Features that have not shipped in all three yet are still used, but only when you ask for them.

experimental_* props

A feature inside an existing component is an experimental_<feature> prop on the part that uses it, off by default. The prefix follows React's naming for unstable APIs. It is greppable, it sits at the call site where you make the browser-support decision, and when the feature reaches every engine the prop is removed: the type error tells you exactly where to delete it.

PropPlatform featureEffect when on
Tabs.List experimental_focusgroupfocusgroupRenders focusgroup; where the browser implements it, the browser moves focus with arrow keys, Home and End and the JS handler steps aside.
Accordion.Root experimental_interpolateSizeinterpolate-sizeSets interpolate-size: allow-keywords on the root, so ::details-content can transition height to auto. Elsewhere the height jumps.
Tooltip.Trigger experimental_interestForinterestforRenders interestfor and interest-delay-*; where supported, the browser owns hover, focus, Escape and long-press and the library attaches no listeners.
Tooltip.Popup experimental_hintpopover="hint"Native light dismiss; a tooltip can open over an open menu without closing it. Engines that do not know hint treat it as manual and the JS handling stays.
Dialog.Popup experimental_closedByclosedbyRenders closedby="any" (with lightDismiss) or "closerequest"; where the browser implements it (Chromium, Firefox), the platform handles Escape and outside clicks and the JS listeners are skipped. Safari keeps the JS.
<Tabs.List experimental_focusgroup aria-label="Settings">...</Tabs.List>
<Accordion.Root experimental_interpolateSize>...</Accordion.Root>
<Tooltip.Trigger experimental_interestFor>Save</Tooltip.Trigger>
<Tooltip.Popup experimental_hint>Saves the document</Tooltip.Popup>
<Dialog.Popup lightDismiss experimental_closedBy>...</Dialog.Popup>

Rules

  • Flags never change markup between server and client. Feature detection ("focusGroup" in HTMLElement.prototype, "interestForElement" in element) runs in an effect, and only when the flag is on.
  • The baseline keeps working underneath. A flag for a feature that would silently do nothing elsewhere keeps the JavaScript path active in engines without it.
  • No provider, no global switch. The browser-support decision belongs next to the markup, and Server Components cannot create context anyway.
  • Two features with different graduation paths are two props, so each can be removed on its own.

@funstack/ui/experimental

A whole component that cannot exist without a flagged feature would ship from an @funstack/ui/experimental subpath. None does yet: every current component has a baseline that works in all engines.