> ## Documentation Index
> Fetch the complete documentation index at: https://www.beeq.design/llms.txt
> Use this file to discover all available pages before exploring further.

# Button

> Buttons trigger actions in the current context. Button labels express what action will occur when the user interacts with it.

export const CodeLivePreview = ({code, children, height, removePadding = false, mode = 'shadow'}) => {
  const previewRef = useRef(null);
  const BEEQ_VERSION = '1.16.1';
  const BEEQ_ESM_URL = `https://cdn.jsdelivr.net/npm/@beeq/core@${BEEQ_VERSION}/dist/beeq/beeq.esm.min.js`;
  const BEEQ_CSS_URL = `https://cdn.jsdelivr.net/npm/@beeq/core@${BEEQ_VERSION}/dist/beeq/beeq.css`;
  const BEEQ_ICONS_URL = `https://cdn.jsdelivr.net/npm/@beeq/core@${BEEQ_VERSION}/dist/beeq/svg`;
  const ensureParentBeeqRuntime = () => {
    if (document.querySelector('script[data-beeq-parent-runtime]')) return;
    const script = document.createElement('script');
    script.type = 'module';
    script.src = BEEQ_ESM_URL;
    script.dataset.beeqParentRuntime = BEEQ_ICONS_URL;
    document.head.appendChild(script);
  };
  const executeSnippetScripts = (root, runtimeWindow, previewRootArg, skipAttr) => {
    root.querySelectorAll('script').forEach(oldScript => {
      if (skipAttr && oldScript.hasAttribute(skipAttr)) return;
      if (oldScript.src) {
        const newScript = runtimeWindow.document.createElement('script');
        newScript.src = oldScript.src;
        oldScript.replaceWith(newScript);
        return;
      }
      runtimeWindow.Function('previewRoot', oldScript.textContent || '')(previewRootArg);
      oldScript.remove();
    });
  };
  const syncIframeMode = iframeDoc => {
    const root = document.documentElement;
    const explicitMode = root.getAttribute('bq-mode');
    const isDark = root.classList.contains('dark');
    const resolvedMode = explicitMode || (isDark ? 'dark' : 'light');
    iframeDoc.documentElement.setAttribute('bq-mode', resolvedMode);
    iframeDoc.body.setAttribute('bq-mode', resolvedMode);
  };
  useEffect(() => {
    if (mode === 'shadow') ensureParentBeeqRuntime();
  }, [mode]);
  useEffect(() => {
    const container = previewRef.current;
    if (!container) return;
    if (removePadding) container.style.padding = '0';
    container.innerHTML = '';
    if (mode === 'iframe') {
      const iframe = document.createElement('iframe');
      iframe.className = 'preview-iframe';
      iframe.style.width = '100%';
      iframe.style.border = '0';
      iframe.style.display = 'block';
      iframe.style.height = height ?? '';
      iframe.setAttribute('title', 'Live code preview');
      iframe.setAttribute('loading', 'lazy');
      iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin');
      container.appendChild(iframe);
      const iframeDoc = iframe.contentDocument;
      const iframeWin = iframe.contentWindow;
      if (!iframeDoc || !iframeWin) return;
      iframeDoc.open();
      iframeDoc.write(['<!doctype html>', '<html>', '<head>', '  <meta charset="utf-8" />', '  <meta name="viewport" content="width=device-width, initial-scale=1" />', '  <style>html,body{margin:0;padding:0;min-height:100%;}</style>', `  <link rel="stylesheet" href="${BEEQ_CSS_URL}" />`, `  <script type="module" src="${BEEQ_ESM_URL}" data-beeq-iframe-runtime="${BEEQ_ICONS_URL}"></script>`, '</head>', '<body>', code, '</body>', '</html>'].join('\n'));
      iframeDoc.close();
      syncIframeMode(iframeDoc);
      const modeObserver = new MutationObserver(() => syncIframeMode(iframeDoc));
      modeObserver.observe(document.documentElement, {
        attributes: true,
        attributeFilter: ['class', 'bq-mode']
      });
      executeSnippetScripts(iframeDoc, iframeWin, iframeDoc, 'data-beeq-iframe-runtime');
      return () => modeObserver.disconnect();
    }
    const shadowRoot = container.shadowRoot ?? container.attachShadow({
      mode: 'open'
    });
    if (!shadowRoot.adoptedStyleSheets.length) {
      const fixSheet = new CSSStyleSheet();
      fixSheet.replaceSync(`
        bq-dropdown::part(panel),
        bq-panel::part(panel),
        bq-select::part(panel),
        bq-date-picker::part(panel) { z-index: 9999; }
        bq-tooltip::part(panel) { position: absolute; }
      `);
      shadowRoot.adoptedStyleSheets = [fixSheet];
    }
    shadowRoot.innerHTML = [`<link rel="stylesheet" href="${BEEQ_CSS_URL}">`, code].join('');
    executeSnippetScripts(shadowRoot, window, shadowRoot);
    return undefined;
  }, [code, mode, height]);
  return <div className="code-live-preview not-prose">
      {}
      <div className="preview" ref={previewRef} style={{
    minHeight: height
  }} />

      {}
      {children && <div className="code">{children}</div>}
    </div>;
};

<Frame className="px-4 py-4 bq-component-overview" caption="Button component overview">
  <img className="block dark:hidden" src="https://mintcdn.com/beeq/NwMZMX-_rISftnfp/components/images/button/button-overview-light.svg?fit=max&auto=format&n=NwMZMX-_rISftnfp&q=85&s=204352dd423e44d26ed11347c16db548" alt="BEEQ Button component overview" width="572" height="320" data-path="components/images/button/button-overview-light.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/beeq/NwMZMX-_rISftnfp/components/images/button/button-overview-dark.svg?fit=max&auto=format&n=NwMZMX-_rISftnfp&q=85&s=352571bd03caf2ee0b872dad8164aa45" alt="BEEQ Button component overview" width="572" height="320" data-path="components/images/button/button-overview-dark.svg" />
</Frame>

Buttons trigger actions in the current context — saving, submitting, confirming, or moving forward in a flow.
Use emphasis to communicate priority: each view should have one clear primary action, while secondary actions should be visually lower in emphasis.

<Note>
  Use a link button for navigation when the intent is to move to another page. See the [Link](#link) variant.
</Note>

## When to use

<CardGroup cols={2}>
  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="thumbs-up" iconType="solid" size={20} color="var(--bq-stroke--success)" />

      Use buttons when
    </span>

    * The user is taking an action in the current context
    * The action changes data, state, or progress
    * The action needs clear visual priority
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="thumbs-down" iconType="solid" size={20} color="var(--bq-stroke--danger)" />

      Do not use buttons when
    </span>

    * The user is navigating to another page with no side-effect
    * Several actions compete for equal importance
    * A text link is sufficient
  </Card>
</CardGroup>

## Button patterns

Some patterns below are standalone `bq-button` usages, while others are composite interactions built from buttons and related components.

<CardGroup cols={3}>
  <Card title="Button">A standard button initiates a single action or event.</Card>
  <Card title="Menu Button">Toggles a menu of options without surfacing a primary action.</Card>
  <Card title="Split Button">Lets someone take one of several related actions. The dominant action is the label; alternatives are in a menu.</Card>
  <Card title="Icon Only">The most compact type, used for supplementary actions like "Bookmark" or "Star."</Card>
  <Card title="Segmented Button">Helps people select options, switch views, or sort elements.</Card>
  <Card title="Floating Button">Floating action buttons (FABs) help people take primary actions.</Card>
</CardGroup>

## Anatomy

<Frame caption="Button anatomy">
  <img className="block dark:hidden" src="https://mintcdn.com/beeq/NwMZMX-_rISftnfp/components/images/button/button-anatomy.svg?fit=max&auto=format&n=NwMZMX-_rISftnfp&q=85&s=5fe6406771fea0d18fdfbf3e2e6e7fd5" alt="Button anatomy: 1. Container, 2. Icon, 3. Label" width="543" height="248" data-path="components/images/button/button-anatomy.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/beeq/NwMZMX-_rISftnfp/components/images/button/button-anatomy.svg?fit=max&auto=format&n=NwMZMX-_rISftnfp&q=85&s=5fe6406771fea0d18fdfbf3e2e6e7fd5" alt="Button anatomy: 1. Container, 2. Icon, 3. Label" width="543" height="248" data-path="components/images/button/button-anatomy.svg" />
</Frame>

A button can contain a label and optional leading or trailing icons.
The label should always communicate the action clearly. Icons should reinforce meaning, not replace it — unless the action is universally understood and an accessible `label` prop is provided.

| Part | Element | Description |
| - | - | - |
| **1** | Container | The interactive surface wrapping all content |
| **2** | Icon | Optional `prefix` or `suffix` slot content |
| **3** | Label | The primary communicator of the action |

## Design guidelines

Choose the button variant based on the importance of the action. Use the strongest visual treatment for the main action in a region, keep labels short and specific, and avoid making several actions compete for the same level of emphasis.

## Usage

`appearance` defines the base style of the button. `variant` modifies supported appearances — `ghost` applies to both primary and secondary buttons, while `danger` is reserved for destructive actions on the primary appearance.

### Primary

The highest priority action in a view. Only one per screen or section.

<CodeLivePreview mode="shadow" code={`<bq-button>Primary button</bq-button>`}>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button>Primary button</bq-button>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton } from "@beeq/react";

    <BqButton>Primary button</BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton],
      template: `
        <bq-button>Primary button</bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton } from "@beeq/vue";
    </script>

    <template>
      <BqButton>Primary button</BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

<Tip>
  You don't need to specify any property that uses its default value. The default appearance is `primary` with variant `standard`.
</Tip>

Primary also supports `ghost` and `danger` variants:

* **Danger**: reserved for actions that may result in critical or irreversible consequences, such as deleting important data or confirming a high-risk operation.
* **Ghost**: a more subtle style for secondary or less prominent actions that don't require immediate attention.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-button>Primary standard</bq-button>
<bq-button variant="ghost">Primary ghost</bq-button>
<bq-button variant="danger">Primary danger</bq-button>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button>Primary standard</bq-button>
    <bq-button variant="ghost">Primary ghost</bq-button>
    <bq-button variant="danger">Primary danger</bq-button>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton } from "@beeq/react";

    <BqButton>Primary standard</BqButton>
    <BqButton variant="ghost">Primary ghost</BqButton>
    <BqButton variant="danger">Primary danger</BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton],
      template: `
        <bq-button>Primary standard</bq-button>
        <bq-button variant="ghost">Primary ghost</bq-button>
        <bq-button variant="danger">Primary danger</bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton } from "@beeq/vue";
    </script>

    <template>
      <BqButton>Primary standard</BqButton>
      <BqButton variant="ghost">Primary ghost</BqButton>
      <BqButton variant="danger">Primary danger</BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

### Secondary

Lower-emphasis actions. Can stand alone or pair with a primary button to perform secondary actions. Supports the `ghost` variant.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-button appearance="secondary">Secondary</bq-button>
<bq-button appearance="secondary" variant="ghost">Secondary ghost</bq-button>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button appearance="secondary">Secondary</bq-button>
    <bq-button appearance="secondary" variant="ghost">Secondary ghost</bq-button>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton } from "@beeq/react";

    <BqButton appearance="secondary">Secondary</BqButton>
    <BqButton appearance="secondary" variant="ghost">Secondary ghost</BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton],
      template: `
        <bq-button appearance="secondary">Secondary</bq-button>
        <bq-button appearance="secondary" variant="ghost">Secondary ghost</bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton } from "@beeq/vue";
    </script>

    <template>
      <BqButton appearance="secondary">Secondary</BqButton>
      <BqButton appearance="secondary" variant="ghost">Secondary ghost</BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

### Link

Renders as an `<a>` element under the hood when `href` is provided. Still action-oriented, not for plain navigation.

<CodeLivePreview mode="shadow" code={`<bq-button appearance="link" href="https://www.example.com" target="_blank">Link button</bq-button>`}>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button appearance="link" href="https://www.example.com" target="_blank">
      Link button
    </bq-button>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton } from "@beeq/react";

    <BqButton appearance="link" href="https://www.example.com" target="_blank">
      Link button
    </BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton],
      template: `
        <bq-button appearance="link" href="https://www.example.com" target="_blank">
          Link button
        </bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton } from "@beeq/vue";
    </script>

    <template>
      <BqButton appearance="link" href="https://www.example.com" target="_blank">
        Link button
      </BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

<Warning>
  When using the Link button, always provide a `href` value.
</Warning>

### Text

No background or border. Suitable for inline actions, subtle calls to action, or options within a form.

<CodeLivePreview mode="shadow" code={`<bq-button appearance="text">Text button</bq-button>`}>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button appearance="text">Text button</bq-button>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton } from "@beeq/react";

    <BqButton appearance="text">Text button</BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton],
      template: `
        <bq-button appearance="text">Text button</bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton } from "@beeq/vue";
    </script>

    <template>
      <BqButton appearance="text">Text button</BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

## Options

### Size and shape

### Sizes

Choose the size that best matches the context. Medium is the default and preferred size for most interfaces.

| Size | When to use |
| - | - |
| **Small** | When space is limited or the action is less significant |
| **Medium** | Default — suitable for most interfaces |
| **Large** | To increase the significance of an action; use sparingly |

<CodeLivePreview
  mode="shadow"
  code={`
<bq-button size="small">Small</bq-button>
<bq-button size="medium">Medium</bq-button>
<bq-button size="large">Large</bq-button>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button size="small">Small</bq-button>
    <bq-button size="medium">Medium</bq-button>
    <bq-button size="large">Large</bq-button>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton } from "@beeq/react";

    <BqButton size="small">Small</BqButton>
    <BqButton size="medium">Medium</BqButton>
    <BqButton size="large">Large</BqButton>
    ```

    ```ts Angular  icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton],
      template: `
        <bq-button size="small">Small</bq-button>
        <bq-button size="medium">Medium</bq-button>
        <bq-button size="large">Large</bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton } from "@beeq/vue";
    </script>

    <template>
      <BqButton size="small">Small</BqButton>
      <BqButton size="medium">Medium</BqButton>
      <BqButton size="large">Large</BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

### Full width

Use the `block` attribute to make the button stretch to its parent width.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-button block>Full width button</bq-button>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button block>Full width button</bq-button>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton } from "@beeq/react";

    <BqButton block>Full width button</BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton],
      template: `
        <bq-button block>Full width button</bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton } from "@beeq/vue";
    </script>

    <template>
      <BqButton block>Full width button</BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

### Border radius

Use the `border` property to control the corner radius.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-button border="full">Primary</bq-button>
<bq-button variant="ghost" border="full">Ghost</bq-button>
<bq-button variant="danger" border="full">Danger</bq-button>
<bq-button appearance="secondary" border="full">Secondary</bq-button>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button border="full">Primary</bq-button>
    <bq-button variant="ghost" border="full">Ghost</bq-button>
    <bq-button variant="danger" border="full">Danger</bq-button>
    <bq-button appearance="secondary" border="full">Secondary</bq-button>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton } from "@beeq/react";

    <BqButton border="full">Primary</BqButton>
    <BqButton variant="ghost" border="full">Ghost</BqButton>
    <BqButton variant="danger" border="full">Danger</BqButton>
    <BqButton appearance="secondary" border="full">Secondary</BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton],
      template: `
        <bq-button border="full">Primary</bq-button>
        <bq-button variant="ghost" border="full">Ghost</bq-button>
        <bq-button variant="danger" border="full">Danger</bq-button>
        <bq-button appearance="secondary" border="full">Secondary</bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton } from "@beeq/vue";
    </script>

    <template>
      <BqButton border="full">Primary</BqButton>
      <BqButton variant="ghost" border="full">Ghost</BqButton>
      <BqButton variant="danger" border="full">Danger</BqButton>
      <BqButton appearance="secondary" border="full">Secondary</BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

### States

For each button appearance and variant, there are five visual states: **enabled**, **hover**, **focus**, **active**, **loading** and **disabled**.

<Frame caption="Button states: enabled, hover, focus, active, loading, disabled">
  <img className="block dark:hidden" src="https://mintcdn.com/beeq/NwMZMX-_rISftnfp/components/images/button/button-states.svg?fit=max&auto=format&n=NwMZMX-_rISftnfp&q=85&s=ef9d480e3c4ffd64fd5b0901d6acda8c" alt="Button states: enabled, hover, focus, active, loading, disabled" width="796" height="248" data-path="components/images/button/button-states.svg" />

  <img className="hidden dark:block" src="https://mintcdn.com/beeq/NwMZMX-_rISftnfp/components/images/button/button-states.svg?fit=max&auto=format&n=NwMZMX-_rISftnfp&q=85&s=ef9d480e3c4ffd64fd5b0901d6acda8c" alt="Button states: enabled, hover, focus, active, loading, disabled" width="796" height="248" data-path="components/images/button/button-states.svg" />
</Frame>

### Disabled

The `disabled` attribute can be applied to any button variation. When disabled, no interaction is allowed and the `bqClick` event won't fire.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-button disabled>Primary</bq-button>
<bq-button variant="ghost" disabled>Ghost</bq-button>
<bq-button variant="danger" disabled>Danger</bq-button>
<bq-button appearance="secondary" disabled>Secondary</bq-button>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button disabled>Primary</bq-button>
    <bq-button variant="ghost" disabled>Ghost</bq-button>
    <bq-button variant="danger" disabled>Danger</bq-button>
    <bq-button appearance="secondary" disabled>Secondary</bq-button>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton } from "@beeq/react";

    <BqButton disabled>Primary</BqButton>
    <BqButton variant="ghost" disabled>Ghost</BqButton>
    <BqButton variant="danger" disabled>Danger</BqButton>
    <BqButton appearance="secondary" disabled>Secondary</BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton],
      template: `
        <bq-button disabled>Primary</bq-button>
        <bq-button variant="ghost" disabled>Ghost</bq-button>
        <bq-button variant="danger" disabled>Danger</bq-button>
        <bq-button appearance="secondary" disabled>Secondary</bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton } from "@beeq/vue";
    </script>

    <template>
      <BqButton disabled>Primary</BqButton>
      <BqButton variant="ghost" disabled>Ghost</BqButton>
      <BqButton variant="danger" disabled>Danger</BqButton>
      <BqButton appearance="secondary" disabled>Secondary</BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

<Warning>
  Avoid disabled buttons when possible. If an action is unavailable, prefer keeping the button discoverable and explain what is required to proceed.
</Warning>

### Loading

Use the `loading` attribute to indicate something is being processed. Pair with `disabled` to prevent duplicate actions.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-button loading>Loading</bq-button>
<bq-button loading disabled>Loading disabled</bq-button>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button loading>Loading</bq-button>
    <bq-button loading disabled>Loading disabled</bq-button>
    ```

    ```jsx React icon="react" theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton } from "@beeq/react";

    <BqButton loading>Loading</BqButton>
    <BqButton loading disabled>Loading disabled</BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton],
      template: `
        <bq-button loading>Loading</bq-button>
        <bq-button loading disabled>Loading disabled</bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton } from "@beeq/vue";
    </script>

    <template>
      <BqButton loading>Loading</BqButton>
      <BqButton loading disabled>Loading disabled</BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

### Icons

### Leading and trailing icons

Use the `prefix` or `suffix` slot to add icons. Icons should reinforce the label — never use them for decoration only.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-button>
<bq-icon name="arrow-circle-left" slot="prefix"></bq-icon>
Go back
</bq-button>
<bq-button>
Next step
<bq-icon name="arrow-circle-right" slot="suffix"></bq-icon>
</bq-button>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button>
      <bq-icon name="arrow-circle-left" slot="prefix"></bq-icon>
      Go back
    </bq-button>

    <bq-button>
      Next step
      <bq-icon name="arrow-circle-right" slot="suffix"></bq-icon>
    </bq-button>
    ```

    ```jsx React icon="react" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton, BqIcon } from "@beeq/react";

    <BqButton>
      <BqIcon name="arrow-circle-left" slot="prefix" />
      Go back
    </BqButton>

    <BqButton>
      Next step
      <BqIcon name="arrow-circle-right" slot="suffix" />
    </BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton, BqIcon } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton, BqIcon],
      template: `
        <bq-button>
          <bq-icon name="arrow-circle-left" slot="prefix"></bq-icon>
          Go back
        </bq-button>

        <bq-button>
          Next step
          <bq-icon name="arrow-circle-right" slot="suffix"></bq-icon>
        </bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton, BqIcon } from "@beeq/vue";
    </script>

    <template>
      <BqButton>
        <BqIcon name="arrow-circle-left" slot="prefix" />
        Go back
      </BqButton>

      <BqButton>
        Next step
        <BqIcon name="arrow-circle-right" slot="suffix" />
      </BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

### Only-icon buttons

Use `only-icon` buttons only for common, easily recognized actions.
Always provide a `label` so assistive technologies can announce the action correctly.

<CodeLivePreview
  mode="shadow"
  code={`
<bq-button only-icon label="Notifications">
<bq-icon name="bell-ringing"></bq-icon>
</bq-button>
<bq-button only-icon variant="ghost" label="Notifications">
<bq-icon name="bell-ringing"></bq-icon>
</bq-button>
<bq-button only-icon appearance="secondary" label="Notifications">
<bq-icon name="bell-ringing"></bq-icon>
</bq-button>
`}
>
  <CodeGroup>
    ```html HTML icon="html5" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <bq-button only-icon label="Notifications">
      <bq-icon name="bell-ringing"></bq-icon>
    </bq-button>
    <bq-button only-icon variant="ghost" label="Notifications">
      <bq-icon name="bell-ringing"></bq-icon>
    </bq-button>
    <bq-button only-icon appearance="secondary" label="Notifications">
      <bq-icon name="bell-ringing"></bq-icon>
    </bq-button>
    ```

    ```jsx React icon="react" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { BqButton, BqIcon } from "@beeq/react";

    <BqButton onlyIcon label="Notifications">
      <BqIcon name="bell-ringing" />
    </BqButton>
    <BqButton onlyIcon variant="ghost" label="Notifications">
      <BqIcon name="bell-ringing" />
    </BqButton>
    <BqButton onlyIcon appearance="secondary" label="Notifications">
      <BqIcon name="bell-ringing" />
    </BqButton>
    ```

    ```ts Angular icon="angular" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    import { Component } from "@angular/core";
    import { BqButton, BqIcon } from "@beeq/angular/standalone";

    @Component({
      selector: "app-root",
      standalone: true,
      imports: [BqButton, BqIcon],
      template: `
        <bq-button only-icon label="Notifications">
          <bq-icon name="bell-ringing"></bq-icon>
        </bq-button>
        <bq-button only-icon variant="ghost" label="Notifications">
          <bq-icon name="bell-ringing"></bq-icon>
        </bq-button>
        <bq-button only-icon appearance="secondary" label="Notifications">
          <bq-icon name="bell-ringing"></bq-icon>
        </bq-button>
      `,
    })
    export class AppComponent {}
    ```

    ```vue Vue icon="vuejs" expandable theme={"theme":{"light":"one-light","dark":"night-owl"}}
    <script setup lang="ts">
    import { BqButton, BqIcon } from "@beeq/vue";
    </script>

    <template>
      <BqButton onlyIcon label="Notifications">
        <BqIcon name="bell-ringing" />
      </BqButton>
      <BqButton onlyIcon variant="ghost" label="Notifications">
        <BqIcon name="bell-ringing" />
      </BqButton>
      <BqButton onlyIcon appearance="secondary" label="Notifications">
        <BqIcon name="bell-ringing" />
      </BqButton>
    </template>
    ```
  </CodeGroup>
</CodeLivePreview>

<Warning>
  Do not use `prefix` or `suffix` slots for icon-only buttons. Pass the icon as the default slot and always set the `label` prop.
</Warning>

## Content guidelines

### Label guidelines

| Guideline | Rule |
| - | - |
| **Be concise** | 1–2 words, max 4 words, under 20 characters. No punctuation. |
| **Use verbs** | Labels should describe the action: "Save", "Delete", "Submit" — not nouns or adjectives. |
| **Sentence case** | Never use ALL CAPS to emphasize a button. |
| **No wrapping** | Labels must never break to multiple lines. |
| **No emoji** | Keep labels functional and utilitarian. No emoji or exclamation points. |

***

## Best practices

<CardGroup cols={2}>
  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="check" iconType="solid" size={20} color="var(--bq-stroke--success)" />

      Do
    </span>

    Keep button labels succinct — 1 or 2 words, no longer than 4, under 20 characters.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="xmark" iconType="solid" size={20} color="var(--bq-stroke--danger)" />

      Don't
    </span>

    Never let button labels wrap to multiple lines or lose their button shape.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="check" iconType="solid" size={20} color="var(--bq-stroke--success)" />

      Do
    </span>

    Pair a primary button with a secondary button for alternative actions.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="xmark" iconType="solid" size={20} color="var(--bq-stroke--danger)" />

      Don't
    </span>

    Don't place multiple primary buttons together — it dilutes the visual hierarchy.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="check" iconType="solid" size={20} color="var(--bq-stroke--success)" />

      Do
    </span>

    Keep emphasis aligned with task priority — one primary action per view.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="xmark" iconType="solid" size={20} color="var(--bq-stroke--danger)" />

      Don't
    </span>

    Don't use icons as decoration. Every icon should reinforce the label meaning.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="check" iconType="solid" size={20} color="var(--bq-stroke--success)" />

      Do
    </span>

    Use icon-only buttons only when the action is familiar and the `label` prop provides an accessible name.
  </Card>

  <Card>
    <span className="flex items-center mr-2 text-lg font-medium" role="heading">
      <Icon className="mr-2" icon="xmark" iconType="solid" size={20} color="var(--bq-stroke--danger)" />

      Don't
    </span>

    Do not rely on an icon alone when the action is uncommon, destructive, or easy to misunderstand.
  </Card>
</CardGroup>

***

## Accessibility

* **Use descriptive labels** — labeling buttons properly lets users know what will happen, reduces errors, and increases confidence.
* **Icon-only buttons** — always set the `label` prop to provide a text alternative for assistive technologies.
* **Keyboard navigation** — enabled buttons are activated with <kbd>Enter</kbd> or <kbd>Space</kbd>. When `href` is set, the component renders a native link, activated with <kbd>Enter</kbd>; <kbd>Space</kbd> does not activate it.
* **Disabled states** — `disabled` sets `aria-disabled="true"`, removes the control from the Tab order, and prevents activation. Native buttons also receive `disabled`. Disabled controls are not necessarily hidden from screen readers; explain nearby what is required to proceed.
* **Correct semantics** — omit `href` for actions and set `href` for navigation. `appearance="link"` changes styling only; it does not turn a button into a link.

## API reference

### Properties

| Property | Attribute | Description | Type | Default |
| - | - | - | - | - |
| `appearance` | `appearance` | The appearance style to apply to the button | `'primary'` \| `'secondary'` \| `'link'` \| `'text'` | `'primary'` |
| `block` | `block` | If `true`, makes the button fit to its parent width | `boolean` | `false` |
| `border` | `border` | The corner radius of the button | `'none'` \| `'xs2'` \| `'xs'` \| `'s'` \| `'m'` \| `'l'` \| `'full'` | `'m'` |
| `disabled` | `disabled` | If `true`, the button will be disabled | `boolean` | `false` |
| `download` | `download` | Tells the browser to treat the linked URL as a download. Only used when `href` is set | `string` | `undefined` |
| `href` | `href` | When set, renders an `<a>` instead of a `<button>` | `string` | `undefined` |
| `justifyContent` | `justify-content` | How the content should be aligned | `'left'` \| `'center'` \| `'right'` | `'center'` |
| `label` | `label` | Accessible label for screen readers, especially for icon-only buttons | `string` | `undefined` |
| `loading` | `loading` | If `true`, displays the button in a loading state | `boolean` | `false` |
| `onlyIcon` | `only-icon` | If `true`, renders the button as icon-only with 1:1 aspect ratio | `boolean` | `false` |
| `size` | `size` | The size of the button | `'small'` \| `'medium'` \| `'large'` | `'medium'` |
| `target` | `target` | Where to display the linked URL | `'_blank'` \| `'_parent'` \| `'_self'` \| `'_top'` | `undefined` |
| `type` | `type` | The default behavior of the button | `'button'` \| `'submit'` \| `'reset'` | `'button'` |
| `variant` | `variant` | The variant on top of appearance (primary and secondary only) | `'standard'` \| `'ghost'` \| `'danger'` | `'standard'` |

### Events

| Event | Description | Type |
| - | - | - |
| `bqBlur` | Fires when the button loses focus | `CustomEvent<HTMLBqButtonElement>` |
| `bqFocus` | Fires when the button receives focus | `CustomEvent<HTMLBqButtonElement>` |
| `bqClick` | Fires when the button is clicked. Cancelable: on a button with `href`, calling `event.preventDefault()` stops the link navigation, so a client-side router can take over | `CustomEvent<HTMLBqButtonElement>` |

<Note>
  * In React, prefix events with `on`: `onBqClick`, `onBqFocus`, `onBqBlur`.
  * In Angular, use the event binding syntax: `(bqClick)`, `(bqFocus)`, `(bqBlur)`.
  * In Vue, use the `@` shorthand: `@bqClick`, `@bqFocus`, `@bqBlur`.
</Note>

### Slots

| Slot | Description |
| - | - |
| *(default)* | The button label content |
| `prefix` | Content displayed before the button label |
| `suffix` | Content displayed after the button label |

### Shadow parts

| Part | Description |
| - | - |
| `button` | The native `<button>` or `<a>` element |
| `label` | The `<span>` rendering the button text |
| `prefix` | The prefix container |
| `suffix` | The suffix container |

### CSS custom properties

<Expandable title="CSS variables" defaultOpen={true}>
  | Variable | Description | Default |
  | - | - | - |
  | `--bq-button--border-color` | Border color | `transparent` |
  | `--bq-button--border-radius` | Border radius | `var(--bq-radius--m)` |
  | `--bq-button--border-style` | Border style | `solid` |
  | `--bq-button--border-width` | Border width | `var(--bq-stroke-m)` |
  | `--bq-button--small-paddingX` | Small size padding inline | `var(--bq-spacing-xs)` |
  | `--bq-button--small-paddingY` | Small size padding block | `calc(var(--bq-spacing-xs2) - var(--bq-button--border-width))` |
  | `--bq-button--small-font-size` | Small size font size | `var(--bq-font-size--m)` |
  | `--bq-button--medium-paddingX` | Medium size padding inline | `var(--bq-spacing-m)` |
  | `--bq-button--medium-paddingY` | Medium size padding block | `calc(var(--bq-spacing-s) - var(--bq-button--border-width))` |
  | `--bq-button--medium-font-size` | Medium size font size | `var(--bq-font-size--m)` |
  | `--bq-button--large-paddingX` | Large size padding inline | `var(--bq-spacing-l)` |
  | `--bq-button--large-paddingY` | Large size padding block | `calc(var(--bq-spacing-m) - var(--bq-button--border-width))` |
  | `--bq-button--large-font-size` | Large size font size | `var(--bq-font-size--m)` |
</Expandable>

<Tip>
  Learn more about [styling with shadow parts](/guides/styles#component-shadow-dom-parts) and [CSS custom properties](/guides/styles#global-css-custom-properties).
</Tip>

## Resources

<CardGroup cols={2}>
  <Card horizontal title="Interactive playground" icon="code" href="https://storybook.beeq.design/?path=/story/components-button--primary">
    Explore all button configurations in Storybook
  </Card>

  <Card horizontal title="Source code" icon="github" href="https://github.com/Endava/BEEQ/tree/main/packages/beeq/src/components/button">
    View the component source on GitHub
  </Card>
</CardGroup>


## Related topics

- [Select](/components/select.md)
- [Drawer](/components/drawer.md)
- [Date Picker](/components/date-picker.md)
- [Notification](/components/notification.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.