Unstyled Button
Buttons let users take actions and make choices with a single tap.
Introduction
The Unstyled Button component replaces the native HTML <button>
element, and offers expanded options for styling and accessibility.
Component
Usage
After installation, you can start building with this component using the following basic elements:
import ButtonUnstyled from '@mui/base/ButtonUnstyled';
export default function MyApp() {
return <ButtonUnstyled>{/* button text */}</ButtonUnstyled>;
}
Basics
The Unstyled Button behaves similar to the native HTML <button>
, so it wraps around the text that will be displayed on its surface.
The following demo shows how to create and style two basic buttons.
Notice that the second button cannot be clicked due to the disabled
prop:
import * as React from 'react'; import ButtonUnstyled, { buttonUnstyledClasses } from '@mui/base/ButtonUnstyled'; import { styled } from '@mui/system'; import Stack from '@mui/material/Stack'; const blue = { 500: '#007FFF', 600: '#0072E5', 700: '#0059B2', }; const CustomButton = styled(ButtonUnstyled)` font-family: IBM Plex Sans, sans-serif; font-weight: bold; font-size: 0.875rem; background-color: ${blue[500]}; padding: 12px 24px; border-radius: 12px; color: white; transition: all 150ms ease; cursor: pointer; border: none; &:hover { background-color: ${blue[600]}; } &.${buttonUnstyledClasses.active} { background-color: ${blue[700]}; } &.${buttonUnstyledClasses.focusVisible} { box-shadow: 0 4px 20px 0 rgba(61, 71, 82, 0.1), 0 0 0 5px rgba(0, 127, 255, 0.5); outline: none; } &.${buttonUnstyledClasses.disabled} { opacity: 0.5; cursor: not-allowed; } `; export default function UnstyledButtonsSimple() { return ( <Stack spacing={2} direction="row"> <CustomButton>Button</CustomButton> <CustomButton disabled>Disabled</CustomButton> </Stack> ); }
Anatomy
The Unstyled Button component is composed of a root <button>
slot with no interior slots:
<button class="BaseButton-root">
<!-- button text goes here -->
</button>
Slot props
Use the component
prop to override the root slot with a custom element:
<ButtonUnstyled component="div" />
If you provide a non-interactive element such as a <span>
, the Unstyled Button component will automatically add the necessary accessibility attributes.
Compare the attributes on the <span>
in this demo with the Button from the previous demo—try inspecting them both with your browser's dev tools:
<CustomButton component="span">Button</CustomButton> <CustomButton component="span" disabled> Disabled </CustomButton>
Hook
import useButton from '@mui/base/useButton';
The useButton
hook lets you apply the functionality of a button to a fully custom component.
It returns props to be placed on the custom component, along with fields representing the component's internal state.
Hooks do not support slot props, but they do support customization props.
The useButton
hook requires the ref
of the element it's used on.
The following demo shows how to build the same buttons as those found in the Basics section above, but with the useButton
hook:
import * as React from 'react'; import clsx from 'clsx'; import { ButtonUnstyledProps } from '@mui/base/ButtonUnstyled'; import useButton from '@mui/base/useButton'; import { styled } from '@mui/system'; import Stack from '@mui/material/Stack'; const blue = { 500: '#007FFF', 600: '#0072E5', 700: '#0059B2', }; const CustomButtonRoot = styled('button')` font-family: IBM Plex Sans, sans-serif; font-weight: bold; font-size: 0.875rem; background-color: ${blue[500]}; padding: 12px 24px; border-radius: 12px; color: white; transition: all 150ms ease; cursor: pointer; border: none; &:hover { background-color: ${blue[600]}; } &.active { background-color: ${blue[700]}; } &.focusVisible { box-shadow: 0 4px 20px 0 rgba(61, 71, 82, 0.1), 0 0 0 5px rgba(0, 127, 255, 0.5); outline: none; } &.disabled { opacity: 0.5; cursor: not-allowed; } `; const CustomButton = React.forwardRef(function CustomButton( props: ButtonUnstyledProps, ref: React.ForwardedRef<any>, ) { const { children } = props; const { active, disabled, focusVisible, getRootProps } = useButton({ ...props, ref, }); const classes = { active, disabled, focusVisible, }; return ( <CustomButtonRoot {...getRootProps()} className={clsx(classes)}> {children} </CustomButtonRoot> ); }); export default function UseButton() { return ( <Stack spacing={2} direction="row"> <CustomButton onClick={() => console.log('click!')}>Button</CustomButton> <CustomButton disabled>Disabled</CustomButton> </Stack> ); }
Customization
Custom elements
The Unstyled Button accepts a wide range of custom elements beyond HTML elements. You can even use SVGs, as the following demo illustrates:
Focus on disabled buttons
Similarly to the native HTML <button>
element, the Unstyled Button component can't receive focus when it's disabled.
This may reduce its accessibility, as screen readers won't be able to announce the existence and state of the button.
The focusableWhenDisabled
prop lets you change this behavior.
When this prop is set, the underlying button does not set the disabled
prop.
Instead, aria-disabled
is used, which makes the button focusable.
This should be used whenever the disabled button needs to be read by screen readers.
MUI Base uses this prop internally in menu items, making it possible to use the keyboard to navigate to disabled items (in compliance with ARIA guidelines).
The following demo shows how the focusableWhenDisabled
prop works—use the Tab key to navigate within this document to see that only the second button accepts the focus:
<CustomButton disabled>focusableWhenDisabled = false</CustomButton> <CustomButton disabled focusableWhenDisabled> focusableWhenDisabled = true </CustomButton>
The focusableWhenDisabled
prop works the same when the root slot is customized, except that the aria-disabled
attribute is used no regardless of the prop's state.
The ability to receive focus is controlled internally by the tabindex
attribute.
<CustomButton component="span" disabled> focusableWhenDisabled = false </CustomButton> <CustomButton component="span" disabled focusableWhenDisabled> focusableWhenDisabled = true </CustomButton>
ButtonUnstyled API
Import
import ButtonUnstyled from '@mui/base/ButtonUnstyled';
// or
import { ButtonUnstyled } from '@mui/base';
Props
Props of the native component are also available.
Name | Type | Default | Description |
---|---|---|---|
action | func | { current?: { focusVisible: func } } | A ref for imperative actions. It currently only supports focusVisible() action. | |
component | elementType | The component used for the root node. Either a string to use a HTML element or a component. | |
disabled | bool | false | If true , the component is disabled. |
focusableWhenDisabled | bool | false | If true , allows a disabled button to receive focus. |
slotProps | { root?: func | object } | {} | The props used for each slot inside the Button. |
slots | { root?: elementType } | {} | The components used for each slot inside the Button. Either a string to use a HTML element or a component. See Slots API below for more details. |
The
ref
is forwarded to the root element.useButton API
Import
import useButton from '@mui/base/useButton';
// or
import { useButton } from '@mui/base';
Parameters
Name | Type | Default | Description |
---|---|---|---|
disabled | boolean | false | If true , the component is disabled. |
focusableWhenDisabled | boolean | false | If true , allows a disabled button to receive focus. |
href | string | ||
onFocusVisible | React.FocusEventHandler | ||
ref | React.Ref<any> | ||
tabIndex | NonNullable<React.HTMLAttributes<any>['tabIndex']> | ||
to | string | ||
type | React.ButtonHTMLAttributes<HTMLButtonElement>['type'] | 'button' | Type attribute applied when the component is button . |
Return value
Name | Type | Default | Description |
---|---|---|---|
active | boolean | false | If true , the component is active (pressed). |
disabled | boolean | false | If true , the component is disabled. |
focusVisible | boolean | false | If true , the component is being focused using keyboard. |
getRootProps | <TOther extends EventHandlers = {}>(otherHandlers?: TOther) => UseButtonRootSlotProps<TOther> | Resolver for the root slot's props. | |
setFocusVisible | React.Dispatch<React.SetStateAction<boolean>> | Callback for setting the focusVisible param. |