Repository navigation
v0.2.0
Minor Changes
-
ce78068: Add
ChatBubble, a Fuji-native chat message bubble for messaging/inbox-style
UI, alongsideNotificationandList.align("incoming" | "outgoing", default"incoming") picks left-aligned
neutral styling vs. right-aligned contained/accent styling, reusing the same
tokens asButton/Badge- no new colors.avataraccepts anyReact.ReactNode(typically an<Avatar />);sender,
timestamp, andstatus("sent" | "delivered" | "read", rendered as an
icon and a text label, never color alone) round out the message metadata.groupedsuppresses the avatar/sender/timestamp/status and tightens spacing
for consecutive messages from the same sender, while still reserving the
avatar's footprint so the run stays aligned.ChatBubbleitself does not own
any list/collection state - the consumer decides which bubbles are grouped.childrenis a free-form content area (text, an attachment chip, a
typing-dots indicator, an audio-row composition, ...);ChatBubble.Attachment
(also exported asChatBubbleAttachment) is a small file/media chip
sub-component for the common case, renderable as a static chip or - with
onClick- a real, keyboard-accessible button.- Server-renderable (no
"use client"), theme/radius/elevation-aware, and
capped atmax-w-[75%]withbreak-wordsso it stays usable at 375px
widths.
-
ce78068: Add
Card.Media/Card.Overlaycomposition primitives, asizeprop to
Slider, andappearance/shapeprops toBadge; fix aBottomNavigation
underline bug, aButtonGroupdark-mode selection bleed, and aChatBubble
tail that never actually painted.Cardgained two new sub-components for image-heavy layouts (listing
cards, profile cards, full-bleed photo cards):Card.Media(position: "top" | "bottom" | "full", default"top") cancelsCard's own padding
on the relevant edge(s) so an<Image>reaches the card's outer border and
matches its corner radius, andCard.Overlayis a bottom-pinned gradient
scrim + content slot for captions baked into a photo. Both compose with
Card's existingHeader/Content/Footerslots.Card.Overlay's
gradient (from-black/85 via-black/45 to-transparent, was/75//25)
was strengthened after review found the original too light to keep body
text at an accessible contrast once an overlapping element (e.g. an
avatar pulled up with a negative margin) pushes text higher into the
scrim's lower-opacity zone.Slidergainedsize?: "sm" | "md" | "lg"(default"md"), scaling
both the track height (h-1/h-1.5/h-2.5) and thumb size
(size-3.5/size-4/size-5").Badgegainedappearance?: "soft" | "solid" | "bordered"(default
"soft", unchanged) andshape?: "rounded" | "square"(default
"rounded", unchanged) - existing usage is unaffected.BottomNavigation: its native<a>had no underline reset. This
package ships no CSS preflight, so the browser's default anchor underline
was rendering through the label text in both themes.
Added the sameno-underlinereset already applied to other native
elements elsewhere in the package.ButtonGroup: the managed (items-prop) radiogroup mode built its
shared border with-ml-pxnegative-margin overlap plus a z-index bump on
the opaque "contained" selected segment - in dark mode this let the
selected segment's own background bleed a visible sliver onto its
neighbor. Replaced with an explicit trailing border on each non-last
segment (applied after its own appearance classes, so it isn't cleared by
a selected segment'sborder-transparent) plus an outerborderand
overflow-hiddenon the container, which structurally cannot bleed since
segments no longer overlap. (An earlier pass useddivide-x/divide-y
on the container instead - that compiles to a zero-specificity:where()
selector in Tailwind v4, so it silently lost to the button's own
border-0reset and never actually drew a line; the per-button border
fixed that too.) The bare-children orientation classes (unmanaged mode)
are unchanged.ChatBubble: redesigned the bubble to a tooltip-style shape with a
small pointed tail (shown once per consecutive run, on the last message,
matching the existing sender/timestamp/status grouping rule). Went through
two implementations: the first used a rotated square tucked behind the
bubble with a negativez-index, which had two problems - the negative
z-indexresolved against whatever ancestor stacking context happened to
exist outside the component (fixable withisolate, but even once
visible, a rotated square only exposes a diamond-shaped sliver past the
bubble's rounded corner, reading as a separate floating chip rather than
part of the bubble). Replaced entirely with aclip-pathtriangle sitting
flush against the bubble's one squared-off corner (the tail-side corner's
radius is removed only on the last message of a run viarounded-b*-none),
so the tail is contiguous with the bubble instead of visually detached.
-
ce78068:
regularandfloatingelevation now use identical control heights and
panel padding - elevation changes shadow depth only, matching what
SPEC.md/README.md/docs/theming.md already claimed but the tokens didn't
actually deliver.The bug:
[data-fuji-elevation="regular"]intokens.cssoverrode
--fuji-control-h-sm(29px -> 30px),--fuji-control-h-md(38px -> 36px),
and--fuji-panel-p(16px -> 14px), whilefloatingkept the:root
defaults. So switching elevation at runtime silently resized every control
and panel by a couple of pixels - a real, visible layout shift for something
docs describe as "shadow depth only."The fix: removed the
[data-fuji-elevation="regular"]override block
entirely. Both modes now read the same:rootcontrol-height/panel-padding
values; only the[data-fuji-theme="*"][data-fuji-elevation="floating"]
shadow-token blocks still differ between the two modes, exactly as intended.This is a visible sizing change for anyone using
floating(or switching
between the two at runtime): controls and panels inregularare now
1-2px taller/more-padded than they were (matching whatfloatingalready
looked like), sinceregular's values were the ones removed, not
floating's. Docs (SPEC.md,README.md,docs/theming.md) updated to
match - all three previously described a "regular reads more compact"
distinction that no longer exists. -
ce78068: Fix an "earth" tone contrast bug and recolor
earth/forestto genuine
beige/sage tones, fix a Toast icon/title misalignment, fix a glass-theme
Toast contrast bug, and polish several components: Rating's tone type,
Spinner, Toast, FileUpload, MultiSelect, Switch, Collapsible, SearchInput,
and DatePicker.earthtone was nearly invisible as a solid fill, in bothlightand
dark(notglass) ---fuji-earthwas chosen too close in lightness to
the page background in each theme (measured 1.22:1 in light, 1.53:1 in
dark; every other tone measures 5:1+). It went through two passes: an
initial fix landed a darker/lighter tan by the numbers alone, then it was
recolored again against real references - Color Hunt's "beige" collection
forearthand "sage" collection forforest, so the two read as a
coherent, intentional warm-neutral pairing rather than two unrelated
accent colors. Final values:earthis#8b5e3cin light (5.16:1 against
the page, white foreground text),#c8a96bin dark (8.41:1, dark
foreground text), and a warm beige tint (#f3e4c9at 84% opacity, was
plain white) in glass.forestmoved from a fairly saturated true green
(#346742light /#83d292dark /#9bd8a8glass) to a muted sage
(#40513blight, 7.9:1;#a1bc98dark, 9.14:1;#b1d3b9glass) - its
-soft/-borderwashes were re-derived from the new base color in light
and dark so they stay the same hue as the accent. Also added--fuji-earth/
-foregroundto:root(the no-FujiProviderfallback) - every sibling
tone had one already;earthwas simply missing it, so a tone="earth"
component used with no provider anywhere in its ancestry had no color to
resolve at all. Consequently fixed three other places that had been using
earth-foregroundas a standalone accent color (a workaround for the
old, too-paleearth) -Rating,RadioGroup, andIcon's bare
(background="none") case now useearthdirectly like every other tone
does;Icon'sbackground="subtle"case (which has no separate
soft/tintedearthvariant to fall back to) keeps pairingearth's full
fill withearth-foregroundtext, now handled as its own explicit case so
it doesn't collide with the bare-case fix.- Toast title was visibly misaligned with its icon -
Base.Titlerenders
a native heading element, and without preflight (see SPEC.md §8) its
~0.83em native top margin (measured ~12px) was never reset, pushing the
title down and out of line with the icon beside it (measured ~11px off
center). Addedm-0toBase.Title/Base.Description, matching every
other native-element margin reset already applied elsewhere in this
package; icon and title are now vertically centered together (verified
~1px apart). - Rating used its own separate, now-stale
RatingTonetype
(warning | danger | success | info | primary) left over from before the
tone migration. It now uses the sharedComponentTone
(default | earth | fire | water | forest | sun); old values map
warning → sun,danger → fire,success → forest,info → water,
primary → default. The defaulttonevalue is now"sun"(same color as
the old default,"warning"). - Spinner replaced its rotating-arc animation with three orbiting dots
fading from a bright "lead" dot to a faint trailing one - a more distinct
loading treatment, still a single lightweight SVG +animate-spin, so it
keeps the existingprefers-reduced-motionoverride for free. - Toast: fixed a real WCAG contrast failure -
Base.Root's
bg-fuji-surface-overlaypanel composites to a medium-brightness tint only
underglass(not light/dark), and Toast is pinned to the atmosphere's
brightest corner (bottom-right), so the plaintext-fuji-foreground
title/description (white, computed ~3.5:1) and the plaintext-fuji-{tone}
status icon (bright pastel, computed as low as ~1.5:1) both fell under
WCAG AA there. Glass-only, both now use the matching-foregroundtoken
(e.g.--fuji-fire-foreground), which is dark enough to clear 4.5-5:1
against that panel; light/dark are unaffected. Also tightened Toast's
padding/gap for a more compact look, matched real toast auto-dismiss
behavior in new "Open" stories viatimeout: 0. - FileUpload: no component change - its root never set a width. The
"stretches full width" symptom wasflex-col's defaultalign-items: stretchstretching its triggerButtoninside an unconstrained Storybook
canvas. Fixed at the story level; a newFullWidthstory shows the
opposite via ordinaryw-fullwrapper composition. - MultiSelect chips now use
Badge's exact shape/padding/text recipe
(rounded-full px-2.5 py-1 text-xs font-medium, opacity-fade remove
button) instead of a bespokerounded-[6px]shape, so a selected value
reads as the same "chip" as everywhere else in Fuji. - Switch: a uniformly-colored circle rotating in place is visually
identical at any angle, so the thumb's "roll" was invisible. Added a
subtle off-center inset bevel (rotates with the thumb as one painted unit)
so the spin is now visibly perceptible; keyboard/disabled/focus/
reduced-motion behavior is unchanged. - Collapsible.Root had no surface at all (bare trigger + panel). It now
reusesCard's exact border/background/radius/padding recipe, so a
Collapsible reads as a composed card rather than plain text with a
chevron. - SearchInput: fixed two related bugs from inheriting
Input's props
unfiltered - passingendSlotsilently replaced SearchInput's own clear
button (both were assigned to the same JSX prop, and the spread was
applied last), and passingclearablerendered a second, duplicate clear
button alongside SearchInput's own.SearchInputPropsnow omitsendSlot
andclearablefromInputPropsand exposes its ownclearableboolean
(defaulttrue) controlling its single, built-in clear button instead. - DatePicker gained
interactiveHeader(defaultfalse, mirroring
Calendar's own prop of the same name and default) - previously there was
no way to reach the month/year chooser throughDatePickerat all, only
throughCalendardirectly.
Also updated
docs/theming.md, which still referenced the pre-tone-migration
token names (--fuji-primary,--fuji-success, etc.) and had no mention of
theComponentTone/StatusTonesplit at all.Genuine remaining limitation: the same glass-contrast risk that affected
Toast (a tone-colored or white-on-white-tinted-surface combination inside
bg-fuji-surface-overlay) was checked against every other component
combining a baretext-fuji-{tone}accent with that surface class, and only
Toast matched. A broader audit oftext-fuji-foreground(not just the
tone-colored accents) againstbg-fuji-surface-overlayacross every overlay
(Select, Combobox, DropdownMenu, Popover, Dialog, ...) was out of scope here
and is worth a follow-up, since those overlays are positioned relative to
their trigger rather than pinned to the atmosphere's brightest corner, so
their worst-case contrast wasn't verified. -
ce78068: Made the compiled
styles.cssfully isolated from a consumer's own Tailwind
build - no installation change (import "@fuji-ui/react/styles.css"is still
the only step), but the compiled output itself is now defensive against
collisions that were previously possible.The problem.
dist/styles.cssshipped Tailwind's own generic theme
variables (--spacing,--radius-sm,--text-xs,--font-weight-*, ...) at
:root, and every utility class Fuji's components use (flex,p-4,
text-sm,rounded-lg, and Fuji's ownbg-fuji-*/rounded-fuji-*color and
radius utilities) under Tailwind's baretheme/utilitiescascade layers. A
consumer that also uses Tailwind would generate the exact same class names
and the exact same variable names in their own build. Two concrete failure
modes followed: (1) cascade layers with the same name merge across
stylesheets, so Fuji'sutilitieslayer and the consumer's ownutilities
layer became one layer resolved by plain source order - not real isolation;
(2) a consumer who customized their own Tailwind spacing/color scale would
have that scale's--spacing/--color-*values silently apply to Fuji's own
internal utilities too (or vice versa), since both stylesheets read/wrote the
same bare variable names.The fix, in
scripts/css-entry.css:prefix(fj)on both Tailwind imports (tailwindcss/theme.css,
tailwindcss/utilities.css). Every Tailwind-generated class in Fuji's
output is nowfj:-prefixed (fj:flex,fj:bg-fuji-earth,
fj:hover:bg-fuji-surface-strong), and Tailwind's own generic theme
variables are renamed--fj-*(--spacing->--fj-spacing, etc.) -
fully independent of a consumer's identically-named--spacing/--color-*
variables in either direction.fjwas chosen specifically because it does
not collide with Fuji's own pre-existing--fuji-*token vocabulary;
tokens.css/fuji-theme.cssare untouched by the prefix; only Tailwind's
own generated names are renamed. Every component's className strings were
updated to thefj:-prefixed form (a mechanical rename across ~90
components, verified with an AST-based extraction script rather than a
blind find/replace, to avoid touching non-class strings like comparison
operands or import specifiers). Fuji's own hand-written classes
(fuji-glass-surface,fuji-theme-scope,fuji-scrollbar, and the rest of
the.fuji-*recipe classes inbase.css) are untouched - they were never
Tailwind-generated and were already uniquely namespaced.- An explicit, uniquely-named cascade layer order declared up front:
@layer fuji.theme, fuji.base, fuji.utilities, fuji.components;, with
base.css's own@layer base {}/@layer components {}blocks renamed to
match. Namespacing the layer names (not just adding layer ordering) is what
actually prevents the same-name-merges-across-stylesheets problem above. - Two hand-written selectors in
tokens.cssthat targeted Tailwind-generated
class names directly (.animate-spin/.animate-pulse/.animate-bounce
for the reduced-motion override, and.bg-fuji-backgroundfor the glass
atmosphere passthrough rule) were updated to theirfj:-prefixed selector
form so they still match what's actually in the DOM.
Verified, not assumed:
tailwind-merge(used by every component'scn())
needed no configuration change - it parses a leadingprefix:generically
as a variant and only inspects the final utility token for conflict-group
matching, sofj:p-2 fj:p-4still collapses tofj:p-4exactly asp-2 p-4
did before. Verified directly against the installedtailwind-mergeversion
rather than assumed. Three consumer fixtures underfixtures/(plain
Vite/no Tailwind, Tailwind with preflight, Tailwind with a 3x-customized
--spacingand a custom brand color) were built against a packed tarball and
checked in a real browser across light/dark/glass: Button, Input, Card, a
portaled Dialog, and a deliberately-conflicting host stylesheet all render
correctly with zero interference in both directions - including the
custom-spacing fixture, where Fuji's own Button/Input padding stayed at its
normal tuned size while the host's own identically-namedp-4utility
correctly rendered 3x larger, proving the two scales are fully independent.
These fixtures aren't published (not in thefilesallowlist) but are kept
in the repo for future regression checks.Genuine remaining limitation: Tailwind's own internal composable-
transform custom properties (--tw-translate-x/-y/-z, used by the
translate/scale/rotateutilities) are not renamed byprefix()- they
remain Tailwind's fixed internal names regardless of prefix, and Tailwind
itself sets their initial value via a universal*, ::before, ::after, ::backdrop { --tw-translate-x: 0; ... }rule. This is vendored Tailwind
output (not something this package authors), is scoped to three
narrowly-named custom properties with no visible effect on any real CSS
property by itself, and is inherent to using any transform utility with
Tailwind v4 at all - not a gap specific to this change. -
ce78068: Remove
ContextMenuandHoverCardfrom the public API.Migration notes:
ContextMenu(andContextMenuRoot/ContextMenuTrigger/ContextMenuContent/ContextMenuItem/ContextMenuSeparator)
is removed. It was a thin wrapper around Base UI's@base-ui/react/context-menu
primitive. Consumers who need custom right-click behavior can depend on
@base-ui/react/context-menudirectly - it is unaffected, it's just no
longer wrapped/exported by Fuji.HoverCard(andHoverCardRoot/HoverCardTrigger/HoverCardContent/HoverCardContentProps)
is removed. It was a thin wrapper around Base UI's@base-ui/react/preview-card
primitive. Consumers who need hover/focus preview behavior can depend on
@base-ui/react/preview-carddirectly - it is unaffected, it's just no
longer wrapped/exported by Fuji.
-
ce78068: Replace
ComponentVariantwith a warmer, more distinctive "tone" vocabulary,
and consolidateTagintoBadgeandInlineintoStack. Also fixes a
dark-theme "floating" elevation halo, adds focus rings and clear buttons to
text fields, and rounds out several components with tone support, custom
layouts, and missing stories.Migration notes:
ComponentVariantis removed and replaced by two separate types:ComponentTone(default | earth | fire | water | forest | sun) - the
decorative color prop onButton,IconButton,ButtonGroup,Badge,
Icon, and the new tone support onCheckbox,RadioGroup,Switch,
Slider,Spinner,Stepper, andAvatar. Old values map to new ones:
default/primary→default,secondary→earth,success→
forest,warning→sun,danger→fire,info→water.StatusTone(default | success | warning | danger | info) - unchanged
prop name and values on semantic components (Alert,Toast,Result,
StatusIndicator,Timeline,Progress,CircularProgress); no call-site
changes needed.- Every
variantprop on a decorative component (Button,IconButton,
ButtonGroup,Badge,Icon) is renamed totone, with the value
mapping above.
Tagis removed. UseBadgeinstead - it now acceptsonRemoveand
removeLabel(previously Tag-only) and uses the same pill shape as before.Inlineis removed. UseStackwithdirection="horizontal"instead -
Stackgaineddirection,wrap, andjustify="between", and widened
alignwith"baseline".- The
--fuji-success/-warning/-danger/-infoCSS custom property
families (and every-foreground/-soft/-border/-contained-*sibling)
are renamed to--fuji-forest/-sun/-fire/-water. Update any consumer
CSS that references these tokens directly.
Also in this release:
- Fixed a dark-theme "floating" elevation halo (shadows were tinted with the
dark theme's cream foreground color instead of black). - Added a 2px focus ring to text fields (
Input,Textarea,Select,
Combobox, ...) with no layout shift. - Added
clearabletoInputandTextarea. NumberInputis compact by default; passfullWidthfor the previous
full-width behavior.RadioGroup's selection emphasis moved to the border, with a smaller inner
dot.Switch's thumb now animates with a rolling transform (respecting
prefers-reduced-motion).Spinnerhas a new, lighter-weight arc animation.Steppersteps accept a customicon.Statisticacceptscardto render inside aCardsurface.Timelineacceptslayout(left | right | alternating), with a
responsive mobile fallback foralternating.CommandMenunow exposes proper ARIA combobox/listbox semantics for its
keyboard-navigable results.- Fixed a handful of missing overflow/underline affordances (
Tabslist
overflow,Tooltipmax-width,Breadcrumblink underlines) and missing
focus-visiblestyling onTabsandCollapsible.
Patch Changes
-
ce78068: Fix native browser chrome appearing on raw
<button>,<input>, and
<select>elements across most of the package (most visiblyDataTable's
sortable column headers,Pagination's page-number buttons, and
Combobox/MultiSelect's dropdown-toggle and clear buttons) when this
package'sstyles.cssis the only stylesheet loaded, with no Tailwind
preflight reset available to zero out the browser's default
border/background/box-sizing/margin/padding on those elements.- Added
NATIVE_CONTROL_RESET, a small shared class string applied first (so
a component's own border/background classes still win via
tailwind-merge) to every raw native control this package renders
directly, including ones rendered by a Base UI primitive with no styling
of its own:Button,IconButton,Input,Textarea,NativeSelect,
Navbar's item buttons,Tabs' tab buttons,SegmentedControl's tabs,
DataTable's sort toggle,Pagination's page-number buttons,
Combobox/MultiSelect's input, chevron-toggle, and clear/chip-remove
buttons,CommandMenu's search input and result rows,NumberInput's
input and increment/decrement buttons,OTPInput's slots,
TimePicker's AM/PM and hour/minute buttons,PasswordInput's
visibility toggle,SearchInput's clear button,Dropzone/FileUpload's
remove-file buttons, the sharedDismissButton(used byDialog,
Drawer,Toast, andImage's fullscreen preview),Tag's remove
button,Rating's stars,Calendar's header/month/year/day buttons,
Carousel's play-pause, arrow, and indicator buttons,List.Item's
clickable row,Stepper's clickable step circles,Collapsibleand
CodeBlock's triggers,NavigationMenu's trigger, andImage's
fullscreen-preview trigger. - Added
box-bordertoCard,EmptyState,Notification,Table,
Select's popup, andImage's wrapper, andm-0/p-0/list-noneto
Card.Title/Card.Description,EmptyState's andNotification's text,
andTimeline's list, so a consumer-supplied width or the browser's
default heading/paragraph/list margins can't throw off layout without
preflight'sbox-sizing: border-boxand margin/padding reset. Imagenow setsdisplay: blockon its<img>elements, matching
preflight'simg, svg, video { display: block }.
No public API, theme, radius, elevation, or accessibility behavior changed -
every component renders identically wherever preflight (or an equivalent
reset) was already present; this only restores the intended appearance where
it wasn't. - Added
-
ce78068: Fix several portaled and navigation-menu components rendering with the
browser's native default styling instead of Fuji's design tokens.- Portaled content never inherited Fuji's font.
--fuji-font-sanswas
only applied via a.fuji-theme-scopeclass onFujiProvider's own
wrapper element; every Base UI portal (Dialog,Drawer,AlertDialog,
Popover,DropdownMenu,ContextMenu,HoverCard,NavigationMenu,
Select,Combobox,MultiSelect,DatePicker,TimePicker,
CommandMenu,Toast) attaches directly todocument.body, outside that
wrapper, and only carrieddata-fuji-theme/data-fuji-radius/
data-fuji-elevationfor color-token resolution - never the font. Every
dialog title, dropdown item, and select option was silently rendering in
the browser's unset default font (serif in most browsers) instead of
Fuji's.font-familyis now also applied via the[data-fuji-theme]
attribute selector these portals already carry (color/background stay
.fuji-theme-scope-only, since painting a background there would affect
invisible floating-ui positioner wrappers). Dialog.Title/Description,Drawer.Title/Description,
AlertDialog.Title/Description, andPopover.Title/Descriptionwere
bare, unstyled re-exports of Base UI's own<h2>/<p>parts - combined
with the font-inheritance gap above, a dialog's title rendered as a large
bold serif heading with default browser margins instead of Fuji
typography. All eight now carry Fuji's heading/body text styles.NavigationMenu.List/Item(real<ul>/<li>elements) had no
list-none/margin/padding reset, so menu items showed bullet points.
NavigationMenu.Link(a real<a>) was a bare re-export with zero
styling, rendering as a default blue underlined link instead of matching
the menu's other items.
No public API, theme, radius, elevation, or accessibility behavior changed -
components render identically wherever they happened to already sit inside
a.fuji-theme-scopeelement (e.g. non-portaled content); this only fixes
the ones that didn't. - Portaled content never inherited Fuji's font.
-
ce78068: Fix several correctness, SSR, CSS-scoping, and accessibility issues found in
review:FujiProvider'spersistno longer readslocalStorageduring the initial
render (only in the existing post-mount effect), matching the documented
SSR guarantee that a persisted appearance never reaches the client's first
render ahead of the server's.Carousel's reduced-motion detection no longer readsmatchMediaduring
render; it now startsfalseon every render and is corrected in an effect.base.cssno longer appliesborder-colorand:focus-visibleglobally to
every element on the page - a required stylesheet import was silently
restyling a consumer's own non-Fuji markup. The handful of components that
relied on the global fallback (Button,Drawer,Navbar,Breadcrumb,
BottomNavigation,List) now declare their own border/focus-visible
styling directly, so nothing changes visually and noFujiProviderancestor
is required for it to keep working.Link,Breadcrumb,Navbar, andBottomNavigationnow rejecthref
values with an unrecognized URL scheme (anything other than a relative URL,
http:,https:,mailto:, ortel:) instead of passing them straight
through to a rendered anchor.Select,Combobox,MultiSelect,DatePicker, andTimePickernow set
aria-invalidon their interactive control (previously only adata-invalid
styling hook was set, which assistive technology doesn't read).TreeandDataTablenow forward a ref and accept native element props on
their root, matching every other component's convention.Calendar's month/year chooser derives its fallback year from the
already-hydration-safetodayvalue instead of a freshnew Date()read
during render.- Production source maps no longer embed the original TypeScript source
(sourcesContent); line-level maps are still published. - Corrected the README's build output list and the elevation description
(regular/floatingalso differ slightly in control sizing, not shadow
depth alone) to match actual behavior, consistently across SPEC.md,
AGENTS.md, docs/theming.md, and the review skills. isSafeHref(the new scheme guard behind thehreffix above) is
hardened against a bypass where a leading control character (e.g. a NUL
byte) made ajavascript:URL register as "no scheme, therefore safe" -
it now delegates to the platform's ownURLparser, which strips those
the same way a browser does before resolving the scheme, instead of a
hand-rolled regex.