Changelog
Plex UI changelog: release notes for every version with new components, breaking changes, bug fixes, and dependency updates by date
This changelog documents significant updates, bug fixes, and improvements to components in the Plex UI design system. Entries follow the Keep a Changelog format.
0.20.0 (2026-10-26)
Added
@plexui/vue: Plex UI for Vue 3. Every component, icon and meaningful hook has a Vue counterpart with the same names, props, defaults and rendered markup, styled by the same@plexui/stylesCSS modules and checked against the React components by parity tests. Each component page has a Vue tab, and the Vue guide covers installation, the Vite plugin and SSR. The MCP server takesframework: "vue",llms-vue.txtdescribes the Vue API, andplexui.com/r/vueis a registry for the shadcn-vue CLI.InputGroup: an input or textarea with icons, text, buttons and menus attached inside one frame.InputGroup.Addonsits before or after the control (align="inline-start"/"inline-end") or as a header or footer row ("block-start"/"block-end");InputGroup.Buttonis a ghostButtonsized from the group;InputGroup.Textholds prefixes, units and counters. EveryInputsize from3xsto3xl, both variants,pill,disabledandinvalid. Also in@plexui/vueasInputGroup,InputGroupInput,InputGroupTextarea,InputGroupAddon,InputGroupButtonandInputGroupText.Menu.Itemtakes adescription: a second line under the label, with the label going semibold on its own. Same "item + subtitle" anatomy a Select option with a description already had, so a two-line menu item no longer needs hand-written typography.- Select accepts
checkPosition="none", which removes the indicator column from the list. A menu of one-shot actions, or a list whose option view states the selection itself, no longer reserves an empty 16px column in every row. Slideracceptsaria-labelandaria-labelledby, so a slider without a visiblelabelcan be named. Range thumbs keep theirMinimumandMaximumnames.MarkdownEditoracceptsaria-labelandaria-labelledbyfor its editable region, which a<label for>cannot name.Menu.ItemActionacceptsaria-label, so its icon-only button can be named.- DatePicker and DateRangePicker calendars move focus from the keyboard: the arrow keys by a day or a week, Home and End to the start or end of the week, Page Up and Page Down by a month. The calendar turns to the next or previous month when needed, and focus stays put rather than move to a day outside
minandmax. Kbd: a key or a keyboard shortcut such as ⌘K, in text, in a tooltip or at the end of a menu item.Kbd.Groupholds keys pressed together; three sizes,softandoutline, both mixing the surrounding text color so a key reads on any surface. Also in@plexui/vueasKbdandKbdGroup.Breadcrumb: the trail of pages above a page title. Anavlandmark around an ordered list;Breadcrumb.Itemis a link (hreforto, through thelinkComponentofPlexUIProvider), a button (onClick), a plain step or thecurrentpage (aria-current="page"). Customseparator,size="sm", and long trails wrap. Also in@plexui/vueasBreadcrumbandBreadcrumbItem(the separator is a slot).Tabstakeoverflow="menu": the tabs that do not fit move into a menu at the end of the row instead of a sideways scroll. When the active tab is a hidden one, the menu button shows its name and carries the selection; badges move into the menu with their tabs.overflowLabelsets the button's text.Dialog.Body(VueDialogBody): with it, only the body scrolls and the header and footer stay in view.Dialog.Contenttakesplacement(center,top,bottom,start,end,fullscreen) for search dialogs, bottom sheets and side panels,mobilePlacementfor 640px and below (a centered dialog that becomes a bottom sheet on phones), andonOpenAutoFocus/onCloseAutoFocus.Fieldtakes alabelAction: a link or small control at the end of the label row, such as "Forgot password?".CheckboxandRadioGroup.Itemtake adescription: a second line under the label, outside it, linked througharia-describedby.Switchalready had one.Menu.ItemandMenu.Linktakedangerfor destructive actions: the label and the highlight use the danger color.EmptyMessagetakessize="sm"for an empty panel, card section or list, andalign="start"for an empty state under a section heading.Alerttakesbanner: a full-width strip with square corners and lines above and below only, for offline, read-only or new-version notices.Inputtakesvariant="ghost": no border and no fill, for a field its container already frames, such as a search line at the top of a dialog.FieldErrortakesicon={false}for a message that stands alone, such as under a centered code input.CopyButtonandCopyTooltipreport the clipboard result throughonCopy(copied)(Vue: thecopyevent).--sidebar-menu-sub-max-heightsets the height an openSidebarMenuSubanimates to (1000px by default), so long lists are not cut off.SelecttakessearchSizefor the search field in its menu, such as2xlfor 44px touch targets on phones.@plexui/ui/styles/tailwind-utilities.cssis exported, for apps that import the token files one by one instead of@plexui/ui/css.
Changed
@plexui/mcp0.2.0: every tool takesframework: "vue"for the@plexui/vuedocs, andget_componentfinds components by their exported and part names.- The CSS now ships in its own package,
@plexui/styles: design tokens, globals and the CSS module of every component.@plexui/uidepends on it and re-exports it, so@import "@plexui/ui/css", the@plexui/ui/styles/*.cssfiles,@plexui/ui/viteand@plexui/ui/typeskeep working unchanged. Rendered markup and compiled CSS are identical to 0.19. Install@plexui/styleson its own to use the same styles from another framework. - Grouped Select menus separate their sections. A group heading is now smaller and semibold in the secondary color instead of an option-sized muted row, a rule runs between sections, and the heading starts at the row's content edge instead of being indented to the option labels.
SidebarGroupno longer acceptsonOpenChange. The group has no toggle of its own and never called it; setopenfrom your own control, and a closed group hides itsSidebarGroupContent.@plexui/uirequires React 19 inpeerDependencies. The components already used React 19 APIs (use(Context),<Context value>,refas a prop) and could not run on React 18.- Published modules use fully specified imports (
./Button.js,lodash/clamp.js), so the package resolves under webpack 5's strict ESM rules, Node ESM and TypeScriptNodeNext. ThePlexUIglobal types now ship with the declarations instead of being dropped from them. Fieldtakes its label size from the child control:<Field><Input size="sm" /></Field>gets ansmlabel without repeating the size. An explicitsizeon Field still wins, and a render prop keepsmd.FloatingLabelSelectshows its error as the same plain line asFloatingLabelInput, so the two read alike on one form. It used to renderFieldErrorwith an icon.- The
Alerticon sits on the first line of the message, next to the title, instead of in the middle of a title and a description. A one-line alert looks the same.
Fixed
checkPosition="none"also drops the indicator column from a group's expand row (optionsLimit.label). The row kept a 16px slot and sat indented under options that no longer had one.- Select menus are never narrower than the field they belong to.
listWidth="auto"still grows with the content, but the menu'smin-widthnow falls back to the trigger's width instead of collapsing to nothing. - Select menus line up with their trigger's edge.
align="start"/"end"no longer apply a hidden -5px offset that pushed the menu outside the field. - Select search inputs have a default accessible name and support
searchAriaLabelindependently of the trigger label. DatePicker's year search is namedSearch year. - DatePicker and DateRangePicker use a complete attribute selector when excluding exiting calendars from their height calculation.
- Grouped Select lists expose each group to assistive technology: a
role="group"named by its heading. The arrow keys still move through the options of every group in order, and the look is unchanged. - DatePicker month and year menus use Plex UI Select, with accessible names and consistent keyboard navigation and styling across browsers.
- Select and DatePicker now forward accessible labels, descriptions and invalid state to their interactive triggers.
aria-labelledbyincludes the visible selected value or placeholder, keeping both the field name and current selection available to assistive technology. - Select checkmarks are vertically centered on the title's first line at either position, including options with multiline descriptions.
CopyButtonwithout children, the copy action in everyCodeBlock, has an accessible name:Copy, thenCopiedafter a click.Sliderthumbs take their accessible name fromlabel(range thumbs keepMinimumandMaximum, as in "Price range Minimum"). In range mode the label no longer points at a missing input, and the reset button is labelled withresetTooltip.TagInputkeeps every tag when several are pasted at once (pastinga,b,cused to keep onlyc), stops atmaxTags, and no longer throws when a tag containing a double quote is selected.Selectoption lookup escapes values the same way.- DatePicker and DateRangePicker calendars keep the
minandmaxdays selectable. Amaxat midnight or aminlater in the day used to disable that whole day. - DatePicker and DateRangePicker month navigation buttons are labelled
Previous monthandNext month. The DateRangePicker month stepper also works with Enter and Space. SidebarProviderwithonOpenChangebut noopenexpands and collapses again. Controlled mode follows theopenprop;onOpenChangeis always called.Imagerenders a newsrcafter an earlier one failed to load.Switchno longer pointsaria-describedbyat a description it does not render (a description without a label).- A
CheckboxorSwitchwith a description inside aFieldwith one: the two descriptions have their own ids (the control's ends in-label-description) and the control is described by both. They shared an id, and a Switch dropped its own description. DataTablesupports uncontrolled row selection, filtering and column visibility, also with only anon*Changecallback (row.getIsSelected()threw without arowSelectionprop). It re-paginates whenpageSizechanges, including to and from0orInfinity, and labels its pagination buttons and rows-per-page select.- Space and Enter on the clear button of
SelectControlandFloatingLabelSelectclear the value instead of opening the list, also inside aMenu.Trigger. CopyTooltipcopies with Enter or Space, not only with a pointer press.TagInputwithmaxTags={0}(no limit, as the input already treated it) no longer renders a stray0where the counter goes.InputandTextareaforwardautoCompleteand setaria-invalidwheninvalidis true.FileUploadputsaria-invalidand its error description on the visible trigger instead of the hidden file input.TextLinkkeeps an explicittarget, asButtonLinkalready did.- A
TextLinkwithouthrefbut withonClickis focusable and runs its action on Enter and Space. ButtoncolorandDatePickertriggerDateFormatare optional in the types, matching their runtime defaults.Selectreturns focus to its trigger after choosing an option or pressing Escape; it used to drop focus to the page.- With
showTime,DatePickerkeeps the chosen date and time withinminandmax, and the time fields show the adjusted time. ProgressStepswithvariant="minimal"renders adivwithrole="progressbar"instead of anav, where that role is not allowed.- The header of the primary sorted
DataTablecolumn carriesaria-sort. StatCard's info tooltip can be reached with the keyboard and is announced as "More information".TagInputkeeps a tab stop whenmaxTagsis reached, so tags can still be removed from the keyboard.MarkdownEditortoolbar toggles expose their state througharia-pressed.FloatingLabelInputwithmultilineforwards props such asrequired,maxLengthand key handlers to its textarea, and resizes when a controlledvalueorrowschanges.Fieldnames controls that its label'sforcannot reach. The label has an id, and a child without its ownaria-label,aria-labelledbyorlabelgetsaria-labelledbypointing at it, so a Select or DatePicker trigger in a Field reads "Role, Admin" instead of only its value. A render prop receivesaria-labelledbyamong the field props.CopyButton(and so everyCodeBlockcopy button) andCopyTooltipshow the copied state only after the clipboard write succeeds; a failed write used to show the check mark anyway. A second click while the write is in flight no longer copies twice.- A long
FieldErrormessage wraps inside the field, and its icon stays on the first line. Sidebar: the collapsed header no longer hides or shrinks the collapse trigger; collapsed-state rules no longer hide labels, group labels and badges in an expanded sidebar nested inside a collapsed one; in React the phone layout is used on the first render instead of one frame of the desktop sidebar.- Toasts stay inside the screen on phones instead of keeping the 400px desktop width, with the same inset on both sides.
- The opaque soft fills (
--color-background-{info,success,warning,caution,danger,discovery}-softand their hover and active states) have dark-theme values: they stayed light, under text that turned light. Checkboxplays its check animation only for the checkbox in use, not for every checked box when a list first renders or a tab with checkboxes opens.OTPInputcells narrow to fit a 320px screen, and a field cleared from outside (a wrong code wiped by the form) puts the caret back in the first cell when the focus was in the field.Select's hidden form input uses its own class instead of Tailwind utilities, so it can no longer take the trigger's width in an app whose Tailwind build ordersw-fullaftersr-onlyor does not generatesr-only.- The
Tabsthumb follows the active tab when tabs are added, removed, reordered or relabelled. Menu.Triggerforwards its props andrefto the trigger element.AnimateLayoutGroupappliesinsertMethodandpreventInitialTransition.ButtonLink,TextLinkandMenu.Linktype their props from the link component set inPlexUIConfig, as the installation guide describes. The augmentation used to reach onlyPlexUIProvider, so<ButtonLink to="/x">with a routerLinkfailed to type-check.PlexUIOverridesstill works.SidebarMenuButtonwithasChildrenders the child element as the button. The button props used to land on an innerspanwrapped around the child, so a link lost the button styles andaria-current.Sidebarno longer imports the undeclared@radix-ui/react-slot, which strict installs (pnpm without hoisting, Yarn PnP) could not resolve.Fieldmerges itsaria-describedbywith the child's own and keeps the child's explicitaria-invalid.- An
AvatarwithonClickusesnameas its accessible name instead of announcing only the initial, or nothing for icon avatars. - A sidebar item's chevron turns only when that item is expanded, not when an item it is nested under is.
Slider, theuseBreakpointhook,useDocumentThemeand theuserAgenthelpers render on the server.useBreakpointreturnsfalseon the server and on the first client render, then reads the viewport;useDocumentThemereturnslightthere, then follows the document.Slidermarks follow new values and labels when their count stays the same (changingmin,maxandmarkstogether no longer throws), range marks are positioned, thumbs show a focus ring from the keyboard, the value input accepts negative numbers, and a typed value that has not been reported yet no longer overwrites a newer change.usePreviousreturns the value before the latest change.- Select's option list is a listbox:
aria-selectedfollows the selection,aria-activedescendantthe highlighted option, and multiple selection setsaria-multiselectable. Typeahead in grouped options picks the next match, Ctrl, Cmd and Alt shortcuts no longer change the value, a multiple Select withnamesubmits every value, and a disabled Select is neither submitted nor validated. FloatingLabelSelectused as a Select or Menu trigger opens from the keyboard and gets focus back when the list closes.- Clicking the frame, an adornment or the label of an
emailornumberInputorFloatingLabelInputno longer throws. Clear buttons keep focus in the field, andFloatingLabelInputkeeps an explicitaria-invalidsuch as the oneFieldpasses. OTPInputkeeps every digit in its cell,DateInputshows its value again when it loses focus with a partly typed date, a disabledTagInputcannot remove or add tags, andInputGroupkeeps its invalid border while focused.- DatePicker and DateRangePicker accept equal
minandmax, name every day with its full date, mark the selection witharia-pressedand today witharia-current, and theiridis optional. DateRangePicker disables shortcuts outsidemin,maxormaxRangeDays, and starts a fresh selection after its value is reset tonull. DataTableenableRowSelectionrenders the checkbox column it promised, rows withonRowClickwork from the keyboard, grouped headers span their columns, the rows-per-page select shows the real page size, and pagination stays while rows overflow it.MarkdownEditorplaces the caret where you click, saves links as links instead of escaped HTML, runs Cancel and Remove on Enter, and keeps focus inside its link dialog. TheCodeBlockcopy button shows its focus ring, and expanded code taller thanmaxExpandedHeightscrolls.FileUploadwithoutmultiplereplaces its file instead of adding a second one.- Clicking the dimmed area around a
Dialogcloses it. AMenu.Itemwith onlyonClickis interactive, a disabledMenu.Linkdoes not navigate, andMenu.Labelhas its 12px text again. ImageandAvatarshow an image that loaded before hydration.ButtonandBadgekeep aTooltiptrigger or a render-prop child intact.- A collapsed
SidebarMenuSubleaves the tab order, and anonClickonSidebarTriggerorSidebarMobileMenuButtonruns before the toggle and can cancel it. ButtonGroup.Texthas its padding and gap again,ButtongutterSize="3xs"has a style, transition groups render children keyed likeconstructor, andAnimateLayoutGroupapplieshideOverflowanditemAnchor.@plexui/uiand@plexui/vuedeclarations pass a consumer type check withskipLibCheckoff, also together (oneColumnMetaaugmentation).@types/luxonand@tanstack/table-coreare dependencies of the packages that use them.- The registry
buttonandmenuitems no longer re-export types that do not exist. The registrystylesitem is imported from your stylesheet after Tailwind and carries@source, so Tailwind generates the classes the components use. - The MCP server finds components by their exported and part names (
DataTable,Toaster,Dialog.Trigger), its React setup guide includes the layer order,@sourceandlinkComponent, andllms-full.txtis generated from the docs. @plexui/vue: Vue renders what React renders with radix-ui 1.8 (Tabsradiogroup, Tooltip content,aria-controlsonly while open, Popover and Dialog dismiss on the click after an outside press, RadioGroup, Checkbox and Switch form inputs) and follows every fix above. Vue-only fixes:Card,ButtonLinkandTextLinkgive vue-router'sRouterLinkato;DialogTrigger,DialogClose,MenuTriggerandFieldwork with a child forwarded through<slot />; closed Popover, Dialog and Select render no teleport on the server; Escape closes a Dialog with a forced-open Tooltip on the page;InputandFloatingLabelInputacceptreadonly; keyed multi-root<template v-for>items in transition groups;TagInputemits plain objects; DateRangePicker follows in-place edits of its range; missing props types are exported.
0.18.1 (2026-06-20)
Fixed
Loading spinner centring in
Button. Whenloadingwas set, the spinner pinned to the top-left of the button instead of being flex-centred inside the loader'sinset:0overlay. The cause was a CSS-cascade collision:TransitionGroupapplies both.ButtonLoader(the consumer class withdisplay: flex) and its own.TransitionGroupChild(display: block) to the same wrapper<span>, andTransitionGroup.module.cssloads afterButton.module.css, soblockwon at equal specificity. Scoping the selector as.Button > .ButtonLoaderbumps specificity to (0,2,0) and restores centring.
0.18.0 (2026-05-20)
Added
Built-in password reveal toggle on
FloatingLabelInput. Atype="password"field now renders the eye show/hide toggle on its own, so no more wiring up anendAdornmentbutton and swappingtypeby hand. The newrevealableprop controls it: it defaults totruefor password inputs that don't pass their ownendAdornment, and you can setrevealabletofalseto opt out. A companiononRevealedChangecallback reports the toggle state, so custom-masked fields (e.g. an SSN input) can drive their own reveal with the same built-in button. If you already render your own visibility toggle inendAdornment, remove it (or setrevealabletofalse) to avoid a duplicate.
0.17.1 (2026-05-04)
Fixed
Text color consistency on
SelectControlandTagInput. Both components were missing a basecolorrule and inherited the page foreground (~#181818), which sat one step lighter than the--color-texttoken used byInput,Textarea, and theTagInputtag chips themselves. Side-by-side controls in a form now share the same value text color (--input-text-color). Placeholder state onSelectControl(data-selected="false") is unchanged.
0.17.0 (2026-05-02)
Added
Vite plugin: new sub-export
@plexui/ui/vite. One line invite.config.tsreplaces every install-time gotcha: pinscss.transformer = 'postcss', pinsbuild.cssMinify = 'esbuild'(so Vite 8's Lightning CSS minifier doesn't strip@layerdeclarations), and injects<style>@layer theme, base, components, utilities;</style>into<head>as a runtime failsafe. Setup becomes:import { defineConfig } from "vite"; import plexui from "@plexui/ui/vite"; export default defineConfig({ plugins: [plexui()] });Your
main.cssthen only needs the Tailwind, Plex UI, and source imports, with no manual@layerline.viteis an optional peer dependency (range: 4.x to 8.x); if you don't use Vite, you can ignore this export. Layer-order injection can be disabled with theinjectLayerOrder: falseoption. See /docs/installation → On Vite.
0.16.0 (2026-05-02)
Changed
Default pill shape on
Button,ButtonLink,Select, andSelectControlis nowfalse. The JSDoc on these props always declared@default false; the runtime now matches. Square corners are the modern Plex default and what the Plex docs and Figma kit have shown all along. To keep a pill shape on a specific control, passpillexplicitly.
0.15.3 (2026-05-02)
Fixed
@plexui/ui/css distribution: radius, font, and font-weight tokens are now declared in
:rootvia the new internalvariables-tokens-root.css, instead of being pulled in through the@theme staticblock (which is what 0.15.2 attempted). The@theme staticapproach worked for componentvar(--radius-md)lookups but reset Tailwind's own theme via--radius-*: initial, breaking consumer-side utilities likerounded-md,rounded-full, andtext-sm. The new file declares the same tokens in:rootso components see them but Tailwind's theme stays untouched. The standalone@plexui/ui/styles/variables-tailwind-theme.csssub-export is unchanged and remains opt-in for consumers who explicitly want the Plex scale to drive their Tailwind utilities.
Documentation
Installation guide (/docs/installation): added an explicit
@layer theme, base, components, utilities;declaration to the recommended snippet so cascade layer order is pinned regardless of CSS transformer. New sub-sections cover the Vite + Lightning CSS layer-reorder gotcha (with a one-line workaround to switch the transformer back to PostCSS), an optional skip-Tailwind-preflight recipe (Plex UI ships its own reset), and an opt-in Plex Tailwind theme recipe for consumers who want theirrounded-mdutilities to use the Plex radius scale.
0.15.2 (2026-05-02) RETIRED
This release is on npm but should not be used. Its @theme static import inside @plexui/ui/css resets Tailwind's radius, font, and font-weight defaults to initial, which breaks Tailwind utilities like rounded-md, rounded-full, and text-sm in consumer projects. Upgrade to 0.15.3 immediately.
0.15.1 (2026-05-01)
Changed
SelectControl: trigger value text now uses
--font-weight-normal(400) by default instead of--font-weight-medium(500), matchingInputso mixed form rows (e.g. Card Number / Month / Year / CVV) read as one cohesive set of value fields. Toolbar-style usage that wants the heavier "button" feel can opt back in via the existing--select-control-font-weighttoken.
0.15.0 (2026-04-28)
Added
TagInput: new
smsize (28 px) matchingInputandSelectControlsm. Sits flush in horizontal filter rows alongside the matching Select.TagInput: new
pillprop. Both the container and inner chips become fully-rounded so the control reads as a single rounded surface, matchingInput pillandSelectControl pill.Menu.Content: exposes
onCloseAutoFocus. Callevent.preventDefault()to keep the trigger from regaining focus (and its focus-visible ring) after a mouse pick, useful when the menu is paired with aSelectControlin filter rows.
Changed
TagInput: chip height, font-size, and gutter now scale per-size via
--tag-input-tag-{height,gutter,font-size}(defaulting to--tag-input-height/--tag-input-font-size), so a chip-filled container is exactly the same height as an empty one. Previously chip was fixed at--control-size-xs(26 px), which made md/lg/xl containers grow when chips were added.TagInput: container border-radius now scales per-size (
sm=6, md=8, lg=10, xl/2xl/3xl=12), matchingSelectControl's scale. Chip border-radius is concentric with the container (container_radius − inner_padding) at every size.TagInput: pill-mode radius is now
single_row_height / 2instead of--radius-full. Visually identical when there's one row, but no longer flares into a giant ellipse when chips wrap to a second/third row.TagInput: the X close-button inside a chip now has symmetric whitespace on top, right, and bottom (driven by chip's vertical padding), instead of being pulled to the chip edge with
margin-right: -1px.
Fixed
TagInput: added a
ResizeObserveron the container and every chip so the internalinputWidthrecomputes on any layout change (size/pill toggle, window resize, font load). Without it, a CSS-var-driven reflow didn't trigger React re-renders, which left a staleinputWidthand caused the input or last chip to wrap onto a phantom extra row right after togglingsize.
0.14.3 (2026-04-27)
Fixed
CodeBlock: mask the 8 px gap between the in-block
CopyButton's right edge and the codeblock's right edge so horizontally-scrolling code text can no longer peek past the button..CopyButtonContainernow casts an 8 pxbox-shadowin the codeblock's surface colour, which renders behind the button and on top of the scrolling<pre>, invisible against the rest of the chrome but enough to hide overflowing characters (e.g. the tail of a longraw.githubusercontent.com/…/AGENT.mdURL).
0.14.2 (2026-04-26)
Fixed
EmptyMessage: relax the container
min-widthfrom a hard20remtomin(20rem, 100%)so the component shrinks gracefully inside narrow grid columns instead of overflowing its parent. A 320px-wideEmptyMessageplaced in a 304px column was pushing 16px of horizontal overflow; now it caps at the column width and re-flows the title and description text below it.
0.14.1 (2026-04-26)
Fixed
CodeBlock: restore the ghost-secondary hover background on the in-block
CopyButton. A long-standing override inCodeBlock.module.cssforced the Button's::beforepseudo-element toopacity: 0 !important, suppressing the standard Plex ghost-button hover affordance. Removed; copy buttons now light up on hover with the same subtle gray as every other ghost-secondaryButtonon the system.Icons: fixed three previously-unrendered icons (
Education,HapticFeedback,ThumbMixed) that wrapped their paths in a<g clipPath>referencing a<rect width="1em" height="1em">. Inside theviewBox="0 0 24 24"coordinate system, "1em" collapsed to ~1 user-unit and clipped the icon out of view. Removed the broken clip wrapper.
Changed
AppStoreSquare icon: cleaner double-rounded-rect outline geometry; matches the rest of the AppStore family in stroke weight and proportions.
0.14.0 (2026-04-25)
Added
Input.AdornmentButton (Input)
New compound sub-component for in-input action buttons (voice toggle, copy, send, visibility). Picks up the same--input-clear-size/--input-clear-pill-offset/--input-clear-icon-sizetokens as the built-in clear button, so it stays perfectly aligned inside anyInputregardless of size or pill shape. Supportsaria-pressedfor toggle state and inherits all native<button>props. A newcolorprop (caution/danger/success/info/discovery) tints the pressed state with Plex's semantic palette (same tokensButtonuses), so a recording-mode mic reads as amber, a destructive retry as red, etc.ButtonGroup component (ButtonGroup)
Wraps any row of controls (Button,Input, trigger buttons) and strips the shared border so they read as one unit. Compound API withButtonGroup.SeparatorandButtonGroup.Text(muted label pill;asChildsupported). NestButtonGroupinside itself for visually separated sub-groups (gap driven by--button-group-nested-gap). Supportsorientation="horizontal" | "vertical"for toolbars, steppers, split buttons, pager + arrow nav, rich message composers, and search affordances.Accordion component (Accordion)
Compound primitive built on RadixAccordion.Root: composeAccordion.Item,Accordion.Trigger,Accordion.Content. Supportstype="single" | "multiple",collapsible, per-itemdisabled, and controlledvalue/onValueChange. Styled through--accordion-item-divider-color,--accordion-trigger-padding-block,--accordion-icon-size, and a full set of typography / transition tokens. Use it for FAQ sections, settings panels, and collapsible reference lists.Progress component (Progress)
Linear progress bar built on RadixProgress.Root. Acceptsvalue(0 tomax) ornullfor an indeterminate sweep. Styled through--progress-height,--progress-track-color,--progress-indicator-color,--progress-radius,--progress-indeterminate-duration. Use it for uploads, onboarding completion, and any determinate "X of Y" feedback; CircularProgress / LoadingIndicator stay for loading-spinner cases.
Changed
Input: the
disabledstate no longer fades the entire Container. The opacity now applies to the input text and the built-in Clear button only, so anyInput.AdornmentButtonnested viaendAdornmentstays at full opacity and remains interactive (e.g. a voice-mode toggle that puts the input into a read-only recording state while itself staying clickable).
0.10.0 (2026-04-23)
Added
Label component (Label)
Standalone accessible label built on Radix'sLabel.Root. Pairs with any form control viahtmlFor, prevents double-click text selection, and forwards clicks to the associated control. Props:htmlFor. Styled through--label-color,--label-font-size,--label-font-weight,--label-line-height. UseFieldfor stacked form rows; useLabelwhen pairing with a standalone Checkbox, Switch, or custom layout.
0.9.0 (2026-04-23)
Added
Separator component (Separator)
Thin wrapper around Radix'sSeparator.Rootfor horizontal or vertical dividers. Props:orientation="horizontal" | "vertical"anddecorative. Styled through--separator-colorand--separator-thicknesstokens so any scope can override look without subclassing.
0.8.0 (2026-04-23)
Added
Card component (Card)
New surface primitive for composing forms, pricing tiles, and showcase cards. Compound API (Card.Header,Card.Title,Card.Description,Card.Content,Card.Footer,Card.Action) withvariant="outline" | "solid" | "ghost",size="sm" | "md" | "lg", and optionalhref+interactiveprops. Whenhrefis provided the Card renders as the configuredLinkComponent(e.g.next/link) viauseLinkComponent().
0.7.98 (2026-04-23)
Added
Toast component (Toast)
New themed notification surface built onsonner.<Toaster />+toast()re-exported from@plexui/ui/components/Toast. Light/dark sync viadata-themeandMutationObserver(nonext-themesdependency). Semanticsuccess/error/warning/infovariants drive icon color from--color-text-{intent}-outlinetokens, norichColors. Defaults:top-centerposition,3000msduration, shrink-to-fit width centered within a 400px max, no close button (persistent toasts use an inline action).compacthelper export for centered-text layouts. Re-exportsAction,ExternalToast,ToastTtypes.Avatar initial renders behind image while loading (Avatar)
Initial letter (or icon / overflow count) now renders as a placeholder layer underneath the image. On slow networks the avatar is never visually empty while the image is fetching, and if the image fails the placeholder remains, andonErrorjust hides the image layer.
Changed
Select options with descriptions auto-bold title (Select)
The item + subtitle pattern is now built into the component: any option carrying adescriptionkeeps its label atfont-weight: semiboldin every state (idle, highlighted, selected). Consumers and AI-generated demos no longer need to passoptionClassName="font-semibold"..OptionDescription's ownfont-weight: normalrule protects the description line.Select option layout refactored into leading / trailing groups (Select)
Title and description now stack inside anOptionLeadingcolumn; theOptionIndicatorSlotis a dedicated start/end column at thePressableInnerlevel. Fixes a regression wherecheckPosition="end"let the description line bleed under the checkmark column. Also replaces the:last-childmatch (which was also hitting the start-position slot because text nodes don't count as element children) with an explicitdata-position="end"attribute.Avatar demos migrated to shared
data-demo-controlspattern (Avatar)
Sizing, Overflow count, Roundness, and Colors & variants now use the samedata-demo-controls/data-demo-stagelayout as every other component page, with no moremargin: 24px -24px ...+width: calc(100% + 48px)hack. Overflow count demo grew anoverflowCountslider, Colors & variants and Roundness gainedsizesliders. Colors is now a vertical 2-column grid (soft/solid× 6 colors) so it never clips at narrow widths.
Fixed
Slider hidden in docs
SliderValueControl
A:last-childrule inSliderValueControlwas hiding the slider itself when<Slider>rendered without a label (regression from 0.7.35 when Slider's label row became conditional). The only child ofSliderContainermatched both:first-childand:last-child, and the hide rule won. Added:not(:first-child)so the rule only targets the marks container when it exists. All size / roundness / overflow sliders on Avatar, Select, Alert, and Button docs are visible again.
0.7.97 (2026-04-17)
Changed
Sidebar docs rewritten (Sidebar)
Consolidated 14 examples into 7. The new App Shell demo (workspace selector, expandable sections with hover flyouts when collapsed, footer with docs link + user menu) replaces the standalone Console example, and a beefed-up Basic demo absorbs Scrollable Content, Without Icons, Collapse Modes, Footer Cards, Group Label Sizes, Badges, and Loading State via toggles (collapsible,icons,badges,footerCard,labelSize,bordered). All demos now share a 260px width, the sameDemoSidebarHeader(wordmark + tooltip-wrapped trigger with ⌘. shortcut), context-awareSidebarCollapseLeft/SidebarCollapseRighttrigger icons, and consistent group/header spacing.
Fixed
Sidebar trigger hidden when icons are disabled (Sidebar)
Thecollapsible="icon"rail no longer appears when a sidebar has no icons to collapse to, since there's nothing to click on. The Mobile Menu and App Shell demos now forcecollapsible="none"when the icons toggle is off.
Added
Installable AI skill (Skills)
Plex UI now ships as a Claude Code plugin marketplace and a Codex skill. One-step install in Claude Code via/plugin marketplace add plex-ui/ui+/plugin install plex-ui@plex-ui; one-line install in Codex vianpx degit plex-ui/ui/skills/plexui/skills/plex-ui .agents/skills/plex-ui. Shipsagents/openai.yamlwith Codex UI metadata (display name, SVG + PNG icons, brand color, default prompt, invocation policy) and.claude-plugin/marketplace.jsonwith full manifest. StandaloneSKILL.mdinstall also supported for any agent that reads the open Agent Skills format.DateInput component (DateInput)
New masked date and datetime input with Luxon-backed value parsing, configurable format, and min/max bounds.FloatingLabelSelect multi-select (Floating Label Input)
New demo pairingFloatingLabelSelectwith amultiple+clearableSelect. Trigger shows the single label when one value is picked, N skills when more, with an integrated clear button that resets the list.Skill promoted on marketing surfaces
Homepage Hero CTA Install as skill, AiFoundationSection primary CTA, expanded FAQ answer with the one-line install commands for each agent, and a Quick Start block in the repoREADME.md.
Fixed
figma-sidebar-mcp skill missing frontmatter
skills/figma-sidebar-mcp/SKILL.mdwas shipped without a YAML frontmatter block, so Claude Code never registered it as a skill. Addednameanddescriptionper the official Claude Code skill spec.Hero and /bridge pills removed, BridgePromo width balanced
Dropped the “New · Plex UI ships as…” pill above the Hero icon tiles and the “Design tokens, not just pixels” eyebrow pill on/bridge. Both were visual clutter. BridgePromoLandingSectionnow usesmaxWidth="2xl"so the card width matches its paragraph instead of stretching to a 4xl container.Luxon type conflicts (DateInput)
Aligned@types/luxonversions across workspace and fixed aDateTime/min/maxprop type mismatch in DateInput demos.
0.7.96 (2026-04-08)
Changed
Select description styling (Select)
Polished the option description treatment and rewrote EmptyMessage docs so LLMs pick the right component and props on the first try.
0.7.95 (2026-04-07)
Changed
TagInput tags restyled (TagInput)
Tags now render as soft buttons for consistency with the rest of the system. Added a new suggestions demo.
0.7.94 (2026-04-06)
Fixed
Switch label font-weight (Switch)
Switch label font-weight now matchesFieldlabel (medium). It previously rendered lighter than surrounding form labels.
0.7.93 (2026-04-05)
Added
Plain text FloatingLabelSelect example (Floating Label Input)
New example without icons: a cleaner reference for simple role / category selects.SEO blog posts (10 new) (Blog)
First push of 7 posts covering AI + design systems, Figma MCP, Bridge, design tokens, and component-library comparisons. Second push of 3 more with FAQ schema, internal linking, and updated sitemap.Comparison pages (Radix UI, MUI, Ant Design)
Three new comparison pages alongside the existing shadcn/ui and Untitled UI pages. Footer and sitemap updated.Figma AI Bridge branding
Renamed “Figma Bridge” to “Figma AI Bridge” across all pages and metadata. Landing page repositioned to lead with design tokens; ports in docs corrected (8766/8767 → 8866/8867).
Fixed
Floating label alignment (Floating Label Input)
Settransform-origin: leftso the label scales from its left edge instead of jumping horizontally when it floats up.Blog code block styling (Blog)
Unified Plex code block styles across blog and docs. Prose overrides forpre/code, defaulttextlanguage for bare fences, removed outdated Bridge demo video, and replaced placeholder/some-pathlinks in ButtonLink examples.Comparison pages polish
Left-aligned table headers across all comparison pages, fixed typography consistency.
0.7.92 (2026-04-05)
Added
FloatingLabelInput description (FloatingLabelInput)
Newdescriptionprop for helper text below the input. When botherrorMessageanddescriptionare present, error appears first (closest to input), description below, rendered as a single tight block withmargin-bottomonly under the last element. Text is left-aligned with input content viapadding-inline-start. Error uses plain text (no icon) withrole="alert"for accessibility.
0.7.87 (2026-04-03)
Added
Form examples (Form Examples)
New docs page with real-world form patterns: Field label vs section header hierarchy following Apple Settings strategy:SidebarGroupLabelfor section headers,Fieldlabels for individual controls.
Fixed
Field label-description gap
Set gap between label and description to 0px for all Field sizes (align with Figma).Switch label-description gap
Removed 4px gap between Switch label and description (align with Figma).Switch horizontal alignment
Horizontal Switch fields now align to top instead of center.
0.7.82 (2026-04-02)
Added
FileCard (FileUpload)
ExtractedFileCardas a standalone component with optional delete button.
Fixed
Control border-radius
Aligned control border-radius with Figma design tokens for sm, lg, and xl sizes.
0.7.76 (2026-04-01)
Added
FileUpload (FileUpload)
New file upload component with drag-and-drop, multi-file support, middle-truncated filenames, and form integration. CSS pixel-perfect from Figma specs.FloatingLabelInput multiline (FloatingLabelInput)
New textarea mode with auto-resize, no resize handle, 2-row default, and exact padding match with input mode.RadioGroup/Checkbox descriptions
Added description examples to RadioGroup and Checkbox docs.
Fixed
FileUpload colors
Icon color set to--input-text-color, filesize to--color-text-tertiary. All colors use CSS variables (no hardcoded values).Textarea label position
Matched textarea label position to input mode, accounting for border-box.
0.7.68 (2026-03-30)
Added
Horizontal menu (Menu)
New horizontal menu layout withsizeprop (sm/md/lg), equal-width items, andPlayicon.Icon-only tabs (Tabs)
New example showing icon-only tab items.Icons:
AlignCenterVertical,AlignStartVertical,AlignEndVertical,FoldHorizontal,UnfoldHorizontal,TextAlignCenter,TextAlignEnd,ArrowsMaximize,ArrowsMinimize,Play.
0.7.64 (2026-03-28)
Fixed
Field gap
Synced Field gap with Figma (6px). Fixed desktop preview max-width.Mobile previews
Responsive mobile previews, OG image for Twitter, Product structured data.MarkdownEditor
Fixed placeholder visibility, defaultrows=1.
0.7.61 (2026-03-28)
Added
Markdown Editor (Markdown Editor)
New compact WYSIWYG markdown editor embedded in a form field, powered by Tiptap. Supports bold, italic, ordered/unordered lists, and links. Markdown input/output format ([text](url)). Includes link dialog with URL + title fields and remove action. Toolbar buttons show active state and feature design-system tooltips. Works withFieldwrapper and supportsoutline/softvariants.Icons:
Bold,Italic,List,ListNumbers.
0.7.51 (2026-03-25)
Added
Sidebar Filtered Tree example (Sidebar)
New demo with type-based filtering viaFilter/FilterBadgeicons, expand mode toggle (row vs chevron), and search with soft Input variant.Sidebar Action Tree example (Sidebar)
Drag-and-drop sortable nested items using@dnd-kit/sortable. Hover-revealed action buttons (more, add, reorder). NewGripVerticalandParallelicons.Icons:
Filter,FilterBadge,GripVertical,Parallel.@plexui/mcp
MCP server package for AI agents, docs page, andllms.txt.
Fixed
Sidebar menu item press effect on action hover
Hovering action buttons no longer triggers scale/press animation on the parent menu item. Root cause: Tailwindscaleproperty didn't override CSS moduletransform: scale().Sidebar action tree DnD not working
ExtractedSortableNestedItemto module level (was re-created every render). RemovedonPointerDownCapturestopPropagationon drag handle that blocked dnd-kit'sonPointerDownlistener.Sidebar child item text centered instead of left-aligned
<button>defaulttext-align: centerinherited byflex-1text spans. Addedtext-left.Hydration mismatch on sidebar page
Added stableidprop toDndContextto prevent dnd-kit's auto-incrementing counter from diverging between SSR and client.- Dialog mobile buttons, Input line-height & sizing demo
0.7.45 (2026-03-18)
Added
DatePicker variants (DatePicker)
DOB dropdown, time picker, masked date/datetime inputs.
0.7.44 (2026-03-16)
Added
Dialog component (Dialog)
New modal dialog built on Radix Dialog. Compound components:Dialog.Content,Dialog.Trigger,Dialog.Header,Dialog.Title,Dialog.Description,Dialog.Footer,Dialog.Close. Supports 9-step size scale, scroll lock, and focus trapping.Form Examples page (Form Examples)
Dedicated page for complete authentication flow demos: About You, Sign up, Log in, Enter password, Verify email, Verify email (error), and Confirm phone. Each demo includes a dialog toggle to preview the form inside a modal shell.OTP input mode toggle (Form Examples)
Verify email and Confirm phone demos now toggle between per-digitOTPInputand standardFloatingLabelInputtext field modes.
Changed
Form demos consolidated (Form Examples)
Moved all authentication form demos from Float Input and OTP Input pages into the dedicated Form Examples page. Source pages now focus on individual component API and features only.Component index updated (Components)
Added Dialog, Form Examples, and OTP Input to the component card grid.
Fixed
Inline links in docs not distinguishable
Prose links in documentation pages were rendered in the same color as body text, making them invisible as links. Now use--link-primary-text-colorwith hover state, matching the TextLink component.
0.7.40 (2026-03-13)
Added
StatCard component (Stat Card)
New dashboard statistics card with 7 configurable features:size(sm/md/lg),tooltip,trendPosition(label/value),trendVariant(positive/negative/neutral),iconwith accent colors, andinvertTrend. Supports 8 accent color schemes. Icon layout usesalign-self: stretch; aspect-ratio: 1for equal padding. Includes 5 interactive demo components with live controls.DataTable component (Table)
New data table built on TanStack Table v8. Features: sorting, pagination, global filtering, column visibility, row click, row selection, and empty state handling. IncludesDataTableColumnHeaderfor sortable headers andDataTablePaginationwith rows-per-page selector.DataTable
variantprop (Table)
Addedvariantprop with"default"(borderless) and"bordered"(rounded border with tinted header background) options.DataTable column helpers (Table)
New helper functions for common cell patterns:idCell(monospace ID with CopyTooltip),dateTimeCell(formatted datetime viaIntl.DateTimeFormat),statusCell(Badge with automatic status-to-color mapping), andtooltipHeader(header with dashed underline and tooltip).DataTable
meta.align(Table)
Column definitions now supportmeta: { align: "right" }to align both header and cell content consistently. Extends TanStack Table'sColumnMetatype.Fingerprint icon
Added newFingerprinticon to the icon library.
Changed
Table
table-layout: fixed(Table)
Table primitive now usestable-layout: fixedto prevent column widths from jumping when sorting changes row order.DataTable pagination buttons (Table)
Pagination prev/next buttons no longer use pill shape (pill={false}), using standard border-radius instead.
0.7.36 (2026-03-05)
Added
Menu.Label and Menu.Group (Menu)
New compound components for organizing menu items into labeled groups.Menu.Groupwraps related items,Menu.Labelrenders a non-interactive section heading.FloatingLabelSelect component (Floating Label Input)
New select variant with floating label animation matching FloatingLabelInput. Label floats above when an option is selected.FloatingLabelInput endAdornment (Floating Label Input)
AddedendAdornmentprop for placing icons or buttons at the end of the input. Includes password toggle, SSN mask, and birthday masked input demos.FloatingLabelInput placeholder support (Floating Label Input)
Addedplaceholderprop with focus-only visibility: placeholder text appears when the input is focused and the label has floated above.Birthday masked input (Field)
Composition demo for segmented birthday input with segment highlighting, cursor positioning through separators, and live validation. Includes both masked and segmented select variants.Phone input and country selector (Select Control)
Composition demo combining SelectControl with country flag icons and phone number formatting. Flag icons use lipis/flag-icons 4:3 SVGs via jsDelivr CDN.Column configuration demo (Select)
Composition demo for table column visibility toggles using Select with checkbox items.Switch description prop (Switch)
Addeddescriptionprop to Switch for displaying secondary text below the label.Tabs scrollable demo (Tabs)
Added Scrollable example to Tabs documentation showing horizontal overflow behavior with auto-scroll to active tab. No extra prop needed: just constrain the container width.
Changed
Alert dismiss button (Alert)
Replaced raw close icon with a soft Button component for the dismiss action. Consolidated Actions and Dismissible sections into single previews for cleaner documentation.Indicator sizes unified (Indicators)
Standardized all indicator sizes to 18px across LoadingIndicator, CircularProgress, and LoadingDots. Consolidated Indicator and Dismissible demo sections into single preview cards.Checkbox alignment unified with RadioGroup (Checkbox)
Aligned Checkbox indicator size (18×18px) and label gap with RadioGroup for visual consistency. Fixed label vertical alignment to match RadioGroup first-line behavior. Added combined Checkbox + RadioGroup alignment demo to both doc pages.FloatingLabelInput focus tokens (Floating Label Input)
Replaced hardcoded blue focus ring color with neutral design tokens for consistency with the rest of the system.Birthday segment highlight token (Field)
Usesprimary/solidtoken for active segment highlight instead of hardcoded color.Removed "New" badges from component index and sidebar
Cleared allisNewbadges from the components index page and sidebar. Too many components were flagged, reducing the signal value.
Fixed
Birthday mask cursor positioning (Field)
Fixed cursor advancing past separators on complete segment and handling backspace through separator characters in the masked birthday input.Birthday inputs browser autocomplete (Field)
Fixed segmented birthday inputs triggering unwanted browser autocomplete dropdown.Flag icon aspect ratio (Select Control)
Fixed flag icons rendering as squares instead of proper 4:3 rectangles. Switched to same-height CDN endpoints and fixed alignment in dropdown lists.Input clear button styling (Input)
Fixed clear button styling inconsistencies when used alongside FloatingLabelSelect demos.Column config demo toggles (Select)
Fixed broken toggle state and removed unnecessary separator in column configuration popover.Button sizing demo height jump (Button)
Fixed preview card height jumping when switching between button sizes.FileDocument icon export (Menu)
Fixed import using non-existentFileicon export. Replaced withFileDocument.
0.6.0 (2026-02-01)
Added
Sidebar component (Sidebar)
New composable navigation sidebar for application layouts. IncludesSidebarProviderfor state management,SidebarLayoutfor layout structure, scrollableSidebarContent, stickySidebarHeader/SidebarFooter, and organized navigation withSidebarGroup,SidebarMenu,SidebarMenuItem, andSidebarMenuButton. Supports three collapse modes:offcanvas(drawer on mobile, full collapse on desktop),icon(collapses to icon rail), andnone(static). Includes keyboard shortcutCmd+B/Ctrl+Bfor toggling.Sidebar nested navigation (Sidebar)
Collapsible nested menus withSidebarMenuSubandSidebarMenuSubButton. Animated chevron toggles viaSidebarMenuChevron. Supports multi-level hierarchies for documentation and API reference navigation patterns.Sidebar footer cards (Sidebar)
SidebarCardcomponent for promotional content, upgrade CTAs, or announcements in the sidebar footer. IncludesSidebarCardTitleLinkwith dismissible close button,SidebarCardContentfor description text, andSidebarCardFooterfor action buttons. Cards animate in after sidebar expansion with delayed opacity transition.Sidebar badges (Sidebar)
SidebarMenuBadgecontainer for displaying status indicators, counts, or labels alongside menu items. Pairs with theBadgecomponent supporting all semantic colors (success,warning,danger,info,discovery,caution) and pill shape option.Sidebar mobile menu (Sidebar)
SidebarMobileMenuButtonwith animated hamburger icon that transforms to close icon. Mobile behavior is automatic viaSidebarProviderwith responsive breakpoint detection. Drawer slides in from left with backdrop overlay.Skeleton component (Skeleton)
New component for displaying loading placeholders. Supports rectangular and circular shapes viacircleprop. Uses design tokens for background color and border-radius. Includes composition examples for avatars, cards, text blocks, forms, and tables.Floating Label Input component (Floating Label Input)
New input component with animated floating label that moves above the input on focus or when filled. Supports error states witherrorMessageprop, built-in clear button viaonClear, disabled and read-only modes, browser autofill detection withonAutofillcallback, and password manager extension blocking withallowAutofillExtensions.Progress Steps component (Progress Steps)
New component for displaying progress through multi-step processes. Supports horizontal and vertical orientations, three sizes (sm, md, lg), solid and dashed connector styles, custom icons per step, and a minimal bar variant for compact layouts. Includes compound components:ProgressSteps.Step,ProgressSteps.Title, andProgressSteps.Description. Color schemes include default and success variants.ShimmerText component (ShimmerText)
New component for animated shimmer effect on text content. IncludesShimmerTextfor simple shimmer animation andShimmerableTextfor streaming-style text reveal with shimmer on the latest token. Supports customizable speed, shimmer width, and color via CSS custom properties.Field component (Field)
New form field wrapper that provides label, description, and error message with automatic accessibility linking. GenerateshtmlFor,aria-describedby, andaria-invalidattributes. Supports 9-step size scale, horizontal/vertical orientation, required indicator, and composition with Input, Textarea, Select, Slider, Checkbox, RadioGroup, and Switch controls via render prop pattern.Field optical alignment (Field)
NewopticallyAlignprop on Field that forwards to child controls viacloneElement. Compensates for pill gutter padding in form layouts, aligning labels and error messages with the visual text edge of Input, Select, and Button controls.Slider range mode (Slider)
Slider now supports dual-thumb range selection via arrayvalue/defaultValue. Also added vertical orientation, disabled state, prefix/suffix units, and step markers with labels.Icon and badge support (Tabs)
Addediconandbadgeprops toTabs.Tab. Icons automatically size based on control size. Badges support semantic colors (secondary,success,danger, etc.), style variants (soft,solid), andpillshape option.Tabs component (Tabs)
Renamed and extended SegmentedControl into Tabs. Addsvariantprop with"segmented"(default, existing behavior) and"underline"(animated line indicator with no background). Addsorientationprop with"horizontal"(default) and"vertical"support. Sub-components:Tabs.Tab(new canonical name) andTabs.Option(backward-compat alias). TheSegmentedControlimport continues to work as a backward-compatible alias.Tabs flush underline variant (Tabs)
Addedflushboolean prop for the underline variant. Removes tab padding so the indicator matches the text width exactly, uses gap-based spacing between tabs, removes the container bottom border, and renders a 1px indicator with no border-radius. Spacing scales withsizeprop.RadioGroup
orientationandblockprops (Radio Group)
Neworientationprop onRadioGroup.Itempositions the radio indicator left (default) or right of the label. Newblockprop stretches the item to full width withjustify-content: space-betweenfor menu-style layouts. Documented with Orientation, With Field, Field error, Choice card, and Card selection examples.
Changed
Sidebar variants simplified (Sidebar)
Removed unused sidebar variants (floating,inset,dual-tier) from type definitions, documentation, and CSS. The component now supports onlysidebar(default) anddocsvariants.Field horizontal orientation refactored (Field)
Restructured HTML to useLabelGroup(label + description) andContent(control + error) containers for proper horizontal layout. Added fixed-width CSS variables--field-horizontal-label-widthand--field-horizontal-control-width. Label vertical centering now usescalc((control-height - label-line-height) / 2)per size for pixel-perfect alignment.Checkbox indicator aligned to Figma (Checkbox)
Indicator size changed from hardcoded 20×20px to 18×18px using the--menu-checkbox-indicator-sizetoken, matching the Menu CheckboxItem and Figma specification. Border colors changed from solid grays (var(--gray-200)) to alpha-based tokens (var(--alpha-16)default,var(--alpha-20)hover) for consistent rendering on any background.Checkbox label layout (Checkbox)
Label changed fromdisplay: flex; align-items: centertodisplay: blockfor proper text flow in multi-line labels with descriptions. Gap tokens aligned with Menu CheckboxItem:spacing(2)(8px) for left orientation,spacing(3)(12px) for right orientation.
Fixed
Sidebar collapse animation stability (Sidebar)
Fixed jitter and layout shifts during sidebar collapse/expand animations. Stabilized flexbox rendering for menu items, improved padding transitions, and ensured footer cards animate in only after sidebar fully expands.Sidebar mobile menu label visibility (Sidebar)
Labels in mobile menu were sometimes hidden due to incorrect collapsed state detection. Fixed to ensure labels are always visible in mobile drawer mode regardless of desktop sidebar state.Month stepper sizing and alignment (Date Range Picker)
Fixed multiple issues with the month stepper trigger: stepper buttons now properly scale with control size using CSS variable overrides with correct specificity; added vertical alignment for buttons; gap between buttons and text scales with control size; month text min-width now usesemunits (9em) to scale with font size, preventing width jumps when switching between months with different name lengths (e.g., "May" vs "September"). Stepper buttons now inheritpillprop from parent, matching SelectControl's Clear button behavior. Added size and pill controls to Storybook docs for testing.Clear button sizing and consistency (Input)
Clear button overflow and border collision at various sizes. Refactored to use built-inonClearprop with dedicated sizing tokens matching SelectControl's clear-iso button. Updated gutter values and added per-size offsets for proper alignment in both standard and pill modes.FieldError semantic color tokens (Field)
Replaced hardcoded error colors with--color-text-danger-outlineand--color-border-danger-outlinesemantic tokens. Removedmargin-top: -0.1emhack from error icon, now relies on flex centering for alignment.Pill overflow and text overlap (Tabs)
In pill mode, narrow options (icons, single digits) could be narrower than the control height, causing circular hover highlights and the active thumb to overflow or clip. Added min-width to options in pill mode ensuring they're at least as wide as the control height. Also fixed a scrollable mode regression where text items overlapped, and corrected invalidwhite-space: wraptowhite-space: normal.Highlight overlay radius mismatch (Tabs)
The hover/active overlay (::before) used the sameborder-radiusas the option, but the overlay is inset by 1px. This caused the inner rounded shape to not nest correctly. Added calculated radius as option radius minus inset, so the overlay aligns flush with the container.Pill gutter scaling with opticallyAlign (Select Control, Input, Button)
When usingopticallyAlignwithpill={true}, the margin calculation used only the base gutter and ignored the pill scaling multiplier (1.33×). Controls with pills now correctly multiply the margin by--control-gutter-pill-scaling, aligning properly with Ghost controls.Inconsistent gap between Options and Actions (Select)
Options usedgap: spacing(1)(4px) while Actions used--menu-item-gap(6px). Standardized both to use--menu-item-gapfor consistency with the base Menu component.Search input icon color (Select)
The search icon hadclassName="fill-secondary"butfill="currentColor"in the SVG path inherited color from the Input container, ignoring the class. Fixed by passingfill="var(--color-text-secondary)"as a prop with!importantto overridecurrentColor.Missing caution color variant (Badge)
Badge was missing thecautioncolor option, inconsistent with Button and Alert. Addedcautionto BadgeProps, implemented CSS styles for all variants (soft, solid, outline), and added to the Colors example matrix.Tabs pill variant radius (Tabs)
Fixed incorrect border-radius in pill mode for both segmented and vertical orientations. The option radius now correctly uses--radius-fullwhen pill is active.Field label text selection (Field)
Removeduser-select: nonefrom Field label, allowing users to select and copy label text.