> ## 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_ESM_URL = 'https://esm.sh/@beeq/core/dist/beeq/beeq.esm.js';
  const BEEQ_CSS_URL = 'https://esm.sh/@beeq/core/dist/beeq/beeq.css';
  const BEEQ_ICONS_URL = 'https://esm.sh/@beeq/core/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.minHeight = height ?? '0px';
      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 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: `
        <!-- import { BqButton, BqIcon } from "@beeq/angular/standalone" -->

        <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>

### Icon-only buttons

Use icon-only 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 only-icon label="Notifications">
        <BqIcon name="bell-ringing" />
      </BqButton>
      <BqButton only-icon variant="ghost" label="Notifications">
        <BqIcon name="bell-ringing" />
      </BqButton>
      <BqButton only-icon 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** — buttons are focusable and activated with <kbd>Enter</kbd> or <kbd>Space</kbd> by default.
* **Avoid disabled states** — disabled buttons are invisible to screen readers. Where possible, keep the button discoverable and explain what is required to proceed.
* **Correct semantics** — use `<bq-button>` for actions and links for navigation.

## 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     | `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               | `0`                      |
  | `--bq-button--small-paddingX`   | Small size padding block   | `var(--bq-spacing-xs)`   |
  | `--bq-button--small-paddingY`   | Small size padding inline  | `var(--bq-spacing-xs2)`  |
  | `--bq-button--small-font-size`  | Small size font size       | `var(--bq-font-size--m)` |
  | `--bq-button--medium-paddingX`  | Medium size padding block  | `var(--bq-spacing-m)`    |
  | `--bq-button--medium-paddingY`  | Medium size padding inline | `var(--bq-spacing-s)`    |
  | `--bq-button--medium-font-size` | Medium size font size      | `var(--bq-font-size--m)` |
  | `--bq-button--large-paddingX`   | Large size padding block   | `var(--bq-spacing-l)`    |
  | `--bq-button--large-paddingY`   | Large size padding inline  | `var(--bq-spacing-m)`    |
  | `--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>
