InlineButton
InlineButton is an inline, text-flowing action trigger. It flows with surrounding text, wraps naturally across line breaks, and supports color, loading, and disabled/aria-disabled states. Use the as prop to render a different underlying element.
See Accessibility in Design Foundations for explanations of key concepts and best practices.
Accessible names and roles
The approach for accessible naming depends on whether the InlineButton is rendered as icon only, text only, or with a combination of icon and text.
Icon only
- Do provide an
aria-labelwith the button's name when the only child is aPrefixorSuffixicon slot. - Do set the SVG's role to
imgand hide it from assistive technology witharia-hidden="true". - Don't rely on
InlineButtonto enforce this. It doesn't warn or fall back when an icon-only instance has no accessible name. You're responsible for adding thearia-label.
<InlineButton aria-label="View sync details">
<InlineButton.Prefix>
<InformationIcon />
</InlineButton.Prefix>
</InlineButton>
Text only
- Don't add an
aria-label. The visible text is the accessible name.
Icon and text
- Do set the SVG's role to
imgand hide it from assistive technology witharia-hidden="true". - Don't add an
aria-labelto the button. The visible text is the accessible name. - Don't add an
aria-labelto aPrefixorSuffixicon. It would be announced separately, creating redundant announcements.
Keyboard accessibility and focus
Keyboard
- Reachable by
Tabby default, and removed from the tab order only whendisabledis set. Onlyaria-disabledkeeps it focusable. - Activated by
EnterorSpace, matching native button behavior.InlineButtonrenders a<span>by default, so it replicates this activation itself. Setas="button"to use the browser's own keyboard handling instead. - Don't wrap the built-in key handling with your own
onKeyDown/onKeyUplogic that callspreventDefault(), as doing so can break the disabled, loading, or popup trigger behavior described below.
Focus
InlineButton shows its focus ring only when focus arrives from the keyboard, not from a pointer click, so the ring never competes with the surrounding running text when a user clicks or taps it.
- Do trust the built-in focus ring. It's sized to sit inline with the surrounding text at any font size, so you don't need to adjust it when the text wraps or resizes.
- Don't wrap
InlineButtonin a container that clips overflow, as this can cut off the focus ring.
State announcements
Setting loading sets aria-busy="true" and forces aria-disabled="true", so assistive technologies announce the busy state and activation is blocked while the request is in flight. The button stays in the tab order and only disabled removes it.
<InlineButton loading color="primary">
Retrying sync
</InlineButton>
When InlineButton opens a popup or reveals more content (for example, when composed inside Menu.Trigger), set a disclosure trigger with aria-expanded, aria-haspopup, and aria-controls, so assistive technologies will announce the relationship and the current state.
When composing with Menu.Trigger or another Radix popup trigger, these ARIA attributes are injected automatically. Manual setting is only needed for a custom disclosure.
<InlineButton
aria-haspopup="menu"
aria-expanded={isOpen}
aria-controls="menu-id"
>
Apply to
</InlineButton>
Color contrast
InlineButton uses Strato design tokens for its text, underline, and focus-ring colors, so it meets contrast requirements automatically in every color and theme. You don't need to verify the contrast yourself.