Skip to contents

Button

A button component that can be rendered as another tag or focusable when disabled.

import { Button } from 'base-ui-solid/button';
import styles from './index.module.css';

export default function ExampleButton() {
  return <Button class={styles.Button}>Submit</Button>;
}

Usage guidelines

  • Submit buttons: Unlike the native button element, type="submit" must be specified on Button for it to act as a submit button.
  • Links: The Button component enforces button semantics (role="button", keyboard interaction, disabled state). It should not be used for links. See Rendering links as buttons below.

Anatomy

Import the component:

Anatomy
import { Button } from 'base-ui-solid/button';

<Button />;

Examples

Rendering as another tag

The button can remain keyboard accessible while being rendered as another tag, such as a <div>, by specifying nativeButton={false}.

Custom tag button
import { Button } from 'base-ui-solid/button';

<Button render="div" nativeButton={false}>
  Button that can contain complex children
</Button>;

The Button component enforces button semantics. nativeButton={false} signals that the rendered tag is not a <button>, but it must still be a tag that can receive button semantics (role="button", keyboard interaction handlers). Links (<a>) have their own semantics and should not be rendered as buttons through the render prop.

If a link needs to look like a button visually, style the <a> element directly with CSS rather than using the Button component.

Loading states

For buttons that enter a loading state after activation, specify focusableWhenDisabled so focus remains on the button while it is disabled. Because some browser and screen reader combinations do not reliably announce changes to a focused button’s descendant text, use aria-labelledby to make the changing text the button’s explicit accessible name.

import { createSignal, createUniqueId } from 'solid-js';
import { Button } from 'base-ui-solid/button';
import styles from './index.module.css';

export default function ExampleButton() {
  const [loading, setLoading] = createSignal(false);
  const labelId = createUniqueId();

  return (
    <Button
      class={styles.Button}
      disabled={loading()}
      focusableWhenDisabled
      aria-labelledby={labelId}
      onClick={() => {
        setLoading(true);
        setTimeout(() => {
          setLoading(false);
        }, 4000);
      }}
    >
      <span id={labelId}>{loading() ? 'Submitting' : 'Submit'}</span>
    </Button>
  );
}

API reference

Prop
Type
Default
focusableWhenDisabledbooleanfalse
Whether the button should be focusable when disabled.boolean
nativeButtonbooleantrue
Whether the component renders a native <button> element when replacing it via the render prop. Set to false if the rendered element is not a button (for example, <div>).boolean
classfunction—
CSS class applied to the element, or a function that returns a class based on the component’s state.JSX.ClassValue | ((state) => JSX.ClassValue)
stylefunction—
Style applied to the element, or a function that returns a style object based on the component’s state.JSX.CSSProperties | string | ((state) => JSX.CSSProperties | string | undefined)
renderfunction—
Replace the default element with a tag name, component, or render function.keyof JSX.IntrinsicElements | Component | ((props, state) => JSX.Element)

Data attributes

Name
Type
Default
data-disabled-—
Present when the button is disabled.-
Attribute
Description
data-disabled
Present when the button is disabled.
Button.State
type ButtonState = {
  /** Whether the button should ignore user interaction. */
  disabled: boolean;
};