Button
wu-btn styles a <button> or a link as a button. Modifier words go after the root class: wu-btn brand sm.
| Class | Effect |
|---|---|
wu-btn |
Root. Surface background, soft border, medium control height |
brand |
Brand fill with text-on-brand text |
danger |
Danger fill with text-on-danger text, for destructive actions |
quiet |
Transparent background and border, tinted on hover |
link |
Text-only button that looks like a link: no background, border or padding, text-link color, underline on hover (see Link) |
subtle |
With brand or danger: tinted fill and role border, solid on hover (see Subtle) |
icon |
Square button for one svg and no text (see Icon) |
round |
Fully rounded pill. Empty or icon-only, it is a circle (see Round) |
sm, lg |
Small and large control height, padding and font size |
caret |
CSS-drawn caret after the label. Empty, it is a square caret-only button (see Caret) |
animated |
Spring press scale, opt-in (see Animation) |
aria-busy="true" |
Loading state: full opacity, pointer clicks blocked (see Loading) |
Default
Section titled “Default”<button class="wu-btn" type="button">Default</button><div class="flex wrap x-center gap-2"> <button class="wu-btn sm" type="button">Small</button> <button class="wu-btn" type="button">Default</button> <button class="wu-btn lg" type="button">Large</button></div><div class="flex wrap x-center gap-2"> <button class="wu-btn brand sm" type="button">Brand small</button> <button class="wu-btn brand" type="button">Brand</button> <button class="wu-btn brand lg" type="button">Brand large</button></div>Danger
Section titled “Danger”For destructive actions such as delete. The fill, hover and active colors come from the danger role tokens.
<div class="flex wrap x-center gap-2"> <button class="wu-btn danger sm" type="button">Delete small</button> <button class="wu-btn danger" type="button">Delete</button> <button class="wu-btn danger lg" type="button">Delete large</button></div>A low-emphasis button with no visible background or border until hover, for toolbars and secondary actions. Keyboard focus shows the same focus ring as every button.
<div class="flex wrap x-center gap-2"> <button class="wu-btn quiet sm" type="button">Small</button> <button class="wu-btn quiet" type="button">Cancel</button> <button class="wu-btn quiet lg" type="button">Large</button></div>quiet is the text-only button, the equivalent of the Element Plus “text” button: no background or border until hover.
Subtle
Section titled “Subtle”subtle after brand or danger gives the tinted outline style: a light role fill, a role border and role text, turning solid on hover. Use it for secondary actions that still need the role, such as a Delete in a table row.
<div class="flex wrap x-center gap-2"> <button class="wu-btn brand subtle" type="button">Edit</button> <button class="wu-btn danger subtle" type="button">Delete</button> <button class="wu-btn danger subtle sm" type="button">Delete</button> <button class="wu-btn brand subtle round" type="button">Round</button></div>icon gives a square button as wide as its height for one svg and no text. Add an aria-label. Combined with round it is a circle. Any direct child svg of a button is sized to 1em and takes the text color; in an icon button it is a little larger.
<div class="flex wrap x-center gap-2"> <button class="wu-btn icon sm" type="button" aria-label="Add small"><svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M7.25 2h1.5v5.25H14v1.5H8.75V14h-1.5V8.75H2v-1.5h5.25z"/></svg></button> <button class="wu-btn icon" type="button" aria-label="Add"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button> <button class="wu-btn icon lg" type="button" aria-label="Add large"><svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M7.25 2h1.5v5.25H14v1.5H8.75V14h-1.5V8.75H2v-1.5h5.25z"/></svg></button> <button class="wu-btn brand icon" type="button" aria-label="Add item"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg></button> <button class="wu-btn quiet icon" type="button" aria-label="Add quietly"><svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M7.25 2h1.5v5.25H14v1.5H8.75V14h-1.5V8.75H2v-1.5h5.25z"/></svg></button> <button class="wu-btn icon round" type="button" aria-label="Add round"><svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M7.25 2h1.5v5.25H14v1.5H8.75V14h-1.5V8.75H2v-1.5h5.25z"/></svg></button> <button class="wu-btn brand" type="button"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg>Add item</button></div>round gives a fully rounded pill. It combines with every variant, size and caret. With no label (and an aria-label) or with a single svg icon and no text, it becomes a circle sized to the control height.
<div class="flex wrap x-center gap-2"> <button class="wu-btn round sm" type="button">Small</button> <button class="wu-btn round" type="button">Default</button> <button class="wu-btn round lg" type="button">Large</button> <button class="wu-btn brand round" type="button">Brand</button> <button class="wu-btn danger round" type="button">Danger</button> <button class="wu-btn quiet round" type="button">Quiet</button> <button class="wu-btn round caret" type="button">Actions</button> <button class="wu-btn round caret" type="button" aria-label="Round menu"></button> <button class="wu-btn brand round" type="button" aria-label="Add"><svg width="16" height="16" viewBox="0 0 16 16" fill="currentColor" aria-hidden="true"><path d="M7.25 2h1.5v5.25H14v1.5H8.75V14h-1.5V8.75H2v-1.5h5.25z"/></svg></button></div>link is a text-only button that looks like a link. It has no background, border or horizontal padding, uses the text-link color and underlines on hover. It keeps the control height, so it lines up with other buttons in a toolbar row. It works on a <button> for actions and on an <a> for navigation, and the disabled state is the same as for every button.
<div class="flex wrap x-center gap-2"> <button class="wu-btn link sm" type="button">Small</button> <button class="wu-btn link" type="button">Default</button> <button class="wu-btn link lg" type="button">Large</button> <a class="wu-btn link" href="/components/docs/">Anchor</a> <button class="wu-btn link" type="button" disabled>Disabled</button></div>A toolbar row mixing the styles:
<div class="flex wrap x-center gap-2"> <button class="wu-btn" type="button">Default</button> <button class="wu-btn round" type="button">Round</button> <button class="wu-btn quiet" type="button">Quiet</button> <button class="wu-btn link" type="button">Link</button></div>caret draws a caret after the label. With no label (and an aria-label) it becomes a caret-only button, as wide as its height for sm, default and lg. The caret turns while the popover right after the button is open.
<div class="flex wrap x-center gap-2"> <button class="wu-btn caret" type="button" popovertarget="button-caret-menu">Actions</button> <div class="wu-dropdown" id="button-caret-menu" popover> <button class="wu-dropdown-item" type="button">Edit</button> <button class="wu-dropdown-item" type="button">Duplicate</button> </div> <button class="wu-btn sm caret" type="button" aria-label="Small menu"></button> <button class="wu-btn caret" type="button" aria-label="Default menu"></button> <button class="wu-btn lg caret" type="button" aria-label="Large menu"></button></div>As an anchor
Section titled “As an anchor”A wu-btn on an <a> looks the same as a button. Use it for navigation that should read as a button.
<a class="wu-btn" href="/components/docs/">Link button</a>States
Section titled “States”Hover darkens the default button’s border and changes its background; the brand and danger buttons also have an active color. Keyboard focus shows the focus ring from the border-focus tokens.
The disabled style applies to the disabled attribute and to aria-disabled="true", which covers links. It lowers the opacity and turns off pointer events.
<div class="flex wrap x-center gap-2"> <button class="wu-btn" type="button" disabled>Disabled</button> <button class="wu-btn brand" type="button" disabled>Brand disabled</button> <a class="wu-btn" href="/components/docs/" aria-disabled="true">Link disabled</a></div>Loading
Section titled “Loading”Set aria-busy="true" while an action runs and put a spinner in the label. The button keeps full opacity, so it does not look disabled, and pointer events are off, so a second click does not go through. Keyboard activation still reaches the button: ignore it in your handler while the attribute is set, and remove the attribute when the action ends.
<div class="flex wrap x-center gap-2"> <button class="wu-btn brand" type="button" aria-busy="true"><span class="wu-spinner sm" aria-hidden="true"></span>Saving</button> <button class="wu-btn danger" type="button" aria-busy="true"><span class="wu-spinner sm" aria-hidden="true"></span>Deleting</button></div>Animation
Section titled “Animation”Buttons are calm by default. The animated word adds a spring scale on press to one button.
<div class="flex wrap x-center gap-2"> <button class="wu-btn animated" type="button">Press me</button> <button class="wu-btn brand animated" type="button">Press me</button></div>wu-animated on an ancestor turns the same motion on for every button inside it, without the word on each button.
<section class="wu-animated"> <div class="flex wrap x-center gap-2"> <button class="wu-btn sm" type="button">Small</button> <button class="wu-btn brand" type="button">Brand</button> <button class="wu-btn lg" type="button">Large</button> </div></section>The press animation runs only under prefers-reduced-motion: no-preference. With reduced motion set in the operating system, the buttons keep the color transitions and do not scale.
Right to left
Section titled “Right to left”Buttons follow the document direction. The caret and the split-button divider mirror under dir="rtl".
<div dir="rtl" class="flex wrap x-center gap-2"> <button class="wu-btn" type="button">افتراضي</button> <button class="wu-btn round caret" type="button">إجراءات</button> <button class="wu-btn quiet" type="button">إلغاء</button> <button class="wu-btn link" type="button">رابط</button> <div class="wu-btn-group"> <button class="wu-btn brand" type="button">حفظ</button> <button class="wu-btn brand caret" type="button" aria-label="المزيد"></button> </div></div>Load only the button
Section titled “Load only the button”@use "@wovenui/components/button";Use the per-component entry or the bundle, not both. See Two ways to load components.