New Agents components for tool calls and approvals: DiffView (unified and compact file diffs), TerminalOutput (command, exit code, stdout and stderr tabs), SearchResultCard (ranked web result with relevance), ToolPermissionRow (Allow / Ask / Deny per tool with its scope), ExpiryTimer (countdown that turns amber, then red) and ScopeList (requested scopes with a countdown). ApprovalCard gains (inline, dialog-diff, permission, high-cost), a banner and a ; labels default per kind.
Changelog
Every change to , and . New features and fixes are listed as they land; they ship together with the next release on npm.
Next release
53 changes are waiting for the next release. Features raise the minor version, fixes the patch version.
27 September 2026
ApprovalCard: Approve, Reject and Edit are text-only buttons, as in Figma.
RunError: the actions match Figma. Resume from this step is the primary button, Run again is outlined (primary when it is the only retry), and Cancel run is plain, all without icons.
SearchResultCard and ToolPermissionRow wrap on narrow screens: the result path breaks instead of truncating, and the permission row puts Allow / Ask / Deny under the tool name when there is no room beside it.
25 September 2026
Accessibility follow-ups from the UI/UX audit: dark-mode focus ring (≥ 4.3:1 on every dark surface), gets for shells shown inside another page (no second , no skip link), is keyboard-scrollable, small alerts keep the title on one line and truncate the description, forwards button props (usable as a popover trigger) and is 24 px high, opens through a real button next to the checkbox instead of a around it, avatar images next to a visible name have an empty alt.
gets a prop; without it the line under the prompt names the accepted types ("Accepts images") instead of a fixed "Supports images, PDFs up to 10MB".
DurationBar: lets the bar take the free width, replaces the visible time; the over-estimate tone uses the error colour. ActivityItem: lets long labels break instead of truncating.
New agent components: PlanStep, AgentPlan, PlanSummary, ActivityItem, LogStream, AgentLane, DurationBar.
now resolves to its own token, the tinted canvas from Figma (#F9FBFC light, #17181A dark), instead of . The Button matches Figma's blue_outline: link-coloured label and an indigo tint on hover.
ChatMessage: the user bubble uses the indigo tint ( / ) instead of solid primary, matching Figma. Pass a default-size (36 px) Avatar next to messages.
DataGrid: the search row's focus ring follows the grid's rounded top corners instead of being cut square.
Removed . It loaded tiles from the OpenStreetMap servers, whose usage policy does not allow them as the default tile source of a product. and are no longer (optional) peer dependencies.
24 September 2026
Accessibility fixes from the UI/UX audit (all high findings):
- Focus: every focus ring is opaque (4.99:1 light, 3.56:1 dark) instead of ; Button and IconButton get a 2 px offset in the surface colour so the ring stays visible next to filled buttons. Accordion and Collapsible triggers, Alert close, InlineSelect, Toolbar links, Tabs panels, invalid Input/Textarea, DataGrid search, NumberField, PromptInput, Navbar search and RichTextEditor now show focus.
- ThemeProvider: the single-key “d” shortcut is off by default (WCAG 2.1.4). New prop, e.g. or .
- Selection controls: Checkbox, Radio and ChecklistTask borders use ; the Switch off-track uses (≥ 3:1 in both modes).
- Keyboard: DropZone is a labelled file input (Tab, Enter, Space); NotificationItem, AgendaEvent and RecordCard use a real button stretched over the row instead of a clickable .
- Names: Sheet close, PromptInput attach/send, ChatAttachment remove, ChatMessageActions, RichTextEditor toolbar, CellColorPicker and its swatches, UserMenu and the vertical Stepper have accessible names; Slider forwards to its thumbs; Stars and the unread dot are .
- Contrast: white on becomes ; Alert, AgentStatus, ApprovalCard, TrendChip, EmojiReactionButton and ToggleButtonGroup use the tint pairs ( + ); RunError uses the red tint pair; grey badges use a lighter surface; calendar days outside the month use .
App shell, navbar and menus rebuilt from the "App Layout, Navbar, Dropdown Menu" research — only what it marks as needed:
- : the document scrolls and navbar/sidebar/aside stick ( on purpose only); regions , , , (named, can close), ; skip link first; ; measured / and a matching on the real scroll container (WCAG 2.4.11); , ; sidebar and aside become drawers below (default 64rem). New: , , , , .
- : (sticky by default) driven by an IntersectionObserver sentinel and a frame-throttled scroll direction; hide-on-scroll freezes while the bar holds focus or a menu is open and turns off under reduced motion. + (mega menu as a disclosure, hover intent, Escape returns focus), and slots with , links that do not fit move into More, and a drawer below 36rem. without renders a button; the nav landmark is named ().
- : as wide as its longest entry (no longer the trigger's width), height clamped to ≥ 0, transitions instead of keyframes (reverse smoothly, instant for keyboard-opened submenus), logical submenu side (), focus highlight wins over the checked tint, token, hidden from assistive technology, new and props (two-line entries), , ; disabled entries stay focusable (WAI-ARIA APG).
- count scales in (duration-ambient).
BubbleChart draws its bubbles with again: the Y axis is now hidden instead of removed, so the scatter keeps its y scale.
Every rounded button-like control uses the rounded Button's radius, radius-md (8 px): sidebar rows, groups, user/workspace/notification/switch rows, search and CTA; navbar links, mega menu trigger and links, More, search field; command items, checklist tasks, chat list and chat source links; rating buttons. Pills and circles keep their shape.
FloatingToc works on its own: without it tracks its sections with a scroll spy (on the page or inside ), a click scrolls smoothly to the section and moves the marker at once, reports the choice, hovering previews the marker, and entries get a focus ring and . New export .
Table rows keep the shape of their frame: the table container inherits the parent's radius, so the hover on the header and the last row is clipped to the rounded corners instead of showing square ones. clips its rows the same way. Rule: a hover always has the radius and shape of the layer below it.
New : the WunderUI mark as a loading indicator. The three strokes drift apart and click back into the mark on a loop. Transform only, travel from / , one cycle built from , and on . With reduced motion it shows the finished mark, standing still. Props: (px), ( | ), (accessible name).
Sidebar building blocks for six modes (docked, offcanvas, icon rail, rail with flyouts, double sidebar, overlay drawer):
- : an area with pages as a disclosure (, never a menu); panel and chevron share / .
- keeps its label as visually hidden text in the collapsed rail, so icon links stay named (a tooltip is only a description); is gone, labels carry for staged fades, focus ring is inset.
- passes through props (, , ) and uses the logical .
- takes a to portal into a device frame.
- takes a for the handle's accessible name.
- The collapsed rail is 48 px (market standard, was 72 px) and the sidebar sits on (white in light mode) instead of the grey sidebar tint.
23 September 2026
Accordion now covers all eight types of the Figma "Accordion Item" set.
- gains — a chevron that flips on open — alongside the existing bordered indicator.
- gains : (default, the leading icon in its own bordered square) or (a bare glyph next to the label).
- The focused state is visible again: a card item takes an indigo border, a divider row a subtle fill, and a disabled item drops to 50 % opacity.
Breaking: is now , since "plain" no longer says which glyph is meant now that a chevron exists.
Accordion: a row without a frame no longer paints a background — a divider list now sits on whatever is behind it instead of on a white slab. Horizontal padding moves from the item to the trigger and the panel, so the hover fill reaches the full width of a row, and it covers only the row itself: opening an item no longer tints the answer along with the question.
Avatar, Avatar Group and Badge now carry the values from their Figma sets.
- Avatar initials follow the type ramp — 11, 12, 13, 14 and 15 px, semibold everywhere except the 28 px size, which is medium — and the glyph shrinks to 12 and 14 px on the two small sizes instead of staying at 16.
- The outline of a plain avatar uses the light-300 grey of the set, and the status dot is 8 px with a 1.5 px ring.
- An avatar group overlaps by 12 px rather than 8, and the count bubble is 12 px semibold on the secondary text colour, sized for every avatar size.
- A black or white badge takes the greys the set spells out (#D1D1D1 and the surface grey) instead of a colour-mix of pure black or white.
- The label on a solid badge keeps its pale tint in dark mode. It used to read from a mode-aware token, which flipped the text to a dark tone while the fill stayed bright — unreadable on pink, red, yellow and green.
Badge: a black or white badge without its own fill — the outline and ghost styles — now takes the foreground colour for its label. It used to be pure black, which disappeared on a dark card.
Card follows the Figma set: the title is semibold, the description uses the secondary text colour, and the footer is white with 12/20 px padding and right-aligned actions instead of a grey band. New is the 160 px media area of "Content=image" — flush with the top of the card, filled by an image or showing the placeholder.
Charts with (Area, Bar, Bubble, Candlestick, Composed, Line) keep a hidden X axis, so the tooltip names the point ("Apr") instead of showing its position in the data ("3").
gains the highlighted step of the Figma Checklist card: pass and the row tints indigo, shows as a line of explanation and renders an such as a Start button. A finished step keeps its muted label but is no longer struck through, matching the set.
New package: writes a block's source into your project, the way a design template hands over its files. The CLI resolves a licence key from , or , fetches the block from the registry, rewrites the shared-helper imports to your own alias, and skips files that already exist unless is passed.
confirms a copy with a "Copied to clipboard" tooltip on the button, next to the green check, and its copy morph runs on the motion tokens.
takes (default ). Pass for a palette shown inline in a page, so loading the page does not jump to it.
takes to restyle the backdrop — for instance a flat page colour on a screen that consists of nothing but the modal.
A pass over the sets that changed in Figma:
- Dropdown: menu rows are 36 px with 8 px padding and a 13 px medium label, the hovered row takes the surface grey and the selected one the indigo tint, and a disabled row greys its text rather than fading the whole row.
- Selectors: the checkbox outline is the light-300 grey of the set and turns indigo on hover, the radio does the same, and an off switch is the set's solid grey instead of the surface fill.
- Icon Button: the glyph grows with the button — 16, 18, 20, 22, 24 px.
- Button / Icon Button: a plain button is outlined in light-300.
- Card: the default and outlined styles use the border token.
- Breadcrumb: 12 px medium labels, the trail in the tertiary text colour and the current page in the foreground.
- Input: the small size sets a 13 px label, the large one pads 12 px like the rest, and focus draws the indigo border of the set instead of a soft halo.
Colour decisions where Figma and WCAG disagreed, and a softer copy confirmation.
- (light) is instead of : link, tertiary and success text on selected rows, active tabs and drop zones now pass AA.
- Solid badges on light hues label in a deep shade of their own hue instead of the pale tint (1.5–3:1 → 4.75–7.4:1). Indigo, alternative and black keep white.
- follows Figma: + , so it turns light in dark mode instead of disappearing; hover is .
- follows Figma: white with brand text, hover (was a slate fill with white text at 2.8:1).
- matches Button; follows Figma: with a icon (3.8:1) instead of a white icon (2.8:1).
- : appears at once and fades out slowly with a slight rise — used for “Copied to clipboard” in CodeBlock.
Highlights inside horizontally scrolling rows are drawn inside the element, so the scroll container no longer cuts them off at the top and bottom: the Kanban drop-target ring (now with a light indigo fill), the Tabs focus ring and the TabBar focus ring. Kanban cards take the indigo border on hover like every other card, and Carousel leaves room for card shadows and focus rings.
is one frame with hairline dividers, as in the Figma KPI Group: a StatCard inside it drops its own border, radius and shadow instead of stacking a card in a card, and the row spans its container.
Controls that looked interactive now are.
- Badge rendered as a button or link behaves like a chip: hover, a press scale and a focus ring.
- SelectorItem is the label of its control, so a click anywhere on the row toggles it. The border lights up on hover and turns indigo while the control is checked — read from the control itself, so radio groups just work.
- ChecklistTask toggles in both directions; a finished step can be unticked again, and the circle animates its tick.
- PasswordField shows the state it is in: a crossed-out eye while the password is hidden, an open one while it is visible.
- DropdownMenuLabel / ContextMenuLabel no longer crash when used outside a group. Inside , or the new they name the group; on their own they are a plain heading.
- Table cells pad 12 px between columns and 16 px at the outer edges, so a table lines up with the card it sits in.
- PressableFeedback takes to lend its press effect to a child such as a Button, instead of nesting one button in another.
- Column roots of FunnelChart, ChatListView, ChatConversation, Timeline, EmptyState and SelectorItemGroup carry a .
Motion is tokenised like colour. The scale lives in as (80–700 ms) and , exposed as the utilities and . Because the easing block is plain (not ), each utility emits , so redefining a variable on a wrapper element retimes everything inside it.
Every component now references those tokens instead of raw millisecond values, and the last hardcoded hex colours in Accordion, Table cells and the other affected components were replaced with the / tokens. No component was deliberately re-timed — the tokens consolidate values the library was already using.
New and : an × icon button, a Cancel or an Apply inside a popover or sheet can now close it without extra state, like already could.
is rebuilt. It now works in both directions ( stacks the panels), follows the pointer relative to its own container instead of the window — it used to jump when not placed at the left edge of the page — handles mouse, pen and touch, and its handle is a focusable separator: arrow keys move it 16 px (64 with Shift), Home and End go to the limits. takes "start" or "end"; "left", "right", "top" and "bottom" still work.
actions are all plain buttons: an indigo or outlined button on the red error surface clashed. Rule: inside a coloured surface only the same colour or neutral elements.
gains ("done" by default, or "all") to decide which steps react to . Clickable steps show a hover ring, and the circle and the connector fill with a transition as the step advances.
New variable: the colour of whatever an element sits on. Cards, popovers, dialogs, sheets and dropdowns set it to their own fill. The ring around avatars in an , the overflow count and the status dot use it, so the stack looks cut out of its container — as in Figma — instead of drawing a page-coloured ring on a grey card. The group ring also reaches the avatars again; it had stopped applying once each avatar was wrapped for the hover lift.
Tabs follow the Figma Tab Bar page again. The default variant is the "Tab Button" row — each tab its own bordered button, the active one filled with the indigo tint — at 42, 46 and 50 px with a of rounded or pill. The variant is "Tab Item": bare labels with an indigo underline that glides between them. The pill-in-a-grey-track control is , matching Figma's separate Segmented Control, whose large size now pads 12 px like the set.
Breaking: a with no props now renders bordered buttons instead of a grey track. Swap to for the old look.
Readable status text and a styled validation message.
- Status and brand text now uses the text tokens built for it, so it passes WCAG AA in light and dark: for the active tab, pressed toggle, calendar today, links in Markdown and the rich text editor; , and in Alert, AgentStatus, ApprovalCard, CostMeter, RunError, NumberValue, TrendChip, FieldError and the warning Dialog icon, and the medium-risk label of ApprovalCard. Fills and borders keep the brand hues.
- Grey badges (light, outline, ghost) label with the tertiary text colour instead of the pale grey fill hue, which fell to 2.5:1 on white.
- answers constraint validation (, , …) with the WunderUI Tooltip instead of the browser bubble: the first invalid field is focused and marked, and the message clears as soon as the user types or leaves the field.
- focuses like (1 px primary border and ring) and shows the error border when its input is invalid.
- accepts and .
- Chart value axes (Area, Bar, Line, Composed, Bubble, Candlestick) size to their longest tick label instead of a fixed 32–40 px, so five-digit values are no longer cut off on the left.
- A horizontal with more tabs than room scrolls sideways (scrollbar hidden) instead of making the page wider on phones.
Vertical tabs: puts the list beside the panel. The default variant stacks full-width tab buttons with the label at the start (42 / 46 / 50 px per size); the line variant draws a rail on the left with the indicator gliding along it. Arrow keys move up and down.
22 September 2026
Breadcrumb: new (underlined links) matching the Figma Style axis.
21 September 2026
Charts draw themselves in on mount (shadcn-style load animation, 800 ms ease-out) on all ten chart components; opt out per chart with , and it switches off automatically for .
Core Elements now match the Figma sets: Button sizes 36/40/44/48/56 (–), Badge 20 px semibold, Avatar 24/28/36/40/44, Checkbox and Radio 20 px with an indeterminate mark, Switch 40×20 / 32×16, Kbd 22 px, Pagination cells 40 px, Skeleton block 100 px, md Tabs 42 px, Tooltip on the neutral/dark-content token, outline Button/IconButton readable in dark mode.
First public release: 120+ React components (primitives, forms, data display, charts, AI chat and agent UI), design tokens via , Figma → React map () and for coding agents. TipTap and Leaflet are optional peer dependencies loaded lazily by / .
First public release of the WunderUI MCP server (): design tokens, component props, templates and starters for AI coding agents.
InputGroup: the inner input no longer draws its own focus ring inside the group (no more double ring on search/password fields).
Motion polish: Tabs get a gliding (pill / underline), toasts stack with depth and the takes a (top-right | bottom-right), Skeleton shows a shimmer wave, Dialog / Alert Dialog / Popover / Sheet open with a spring ease, Accordion and Progress animate more smoothly, and morphs its copy icon into a check and accepts .
Switch: the thumb no longer jumps out of the track when toggled (the bounce keyframes now animate , matching Tailwind v4).