- Prop
variant- Type
"secondary" | "ghost" | "primary" | "link" | undefined- Default
"primary"- Requirement
- optional
- Description
- Visual style.
Docs Components Core
Button
- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
import { Button } from "@grassroot/ui-react";const buttonFixture = { id: "button", buttons: [ { id: "primary", label: "Start a project" }, { id: "secondary", label: "View work", variant: "secondary" }, { id: "ghost", label: "See the work", variant: "ghost" }, { id: "link", label: "Read the case study", variant: "link" }, { id: "small", label: "Small", size: "sm" }, { id: "large", label: "Large", size: "lg" }, { id: "disabled", label: "Disabled", disabled: true }, ],} satisfies { id: string; buttons: Array<{ id: string; label: string; variant?: "primary" | "secondary" | "ghost" | "link"; size?: "sm" | "md" | "lg"; disabled?: boolean; }>;}; export default function ButtonDemo() { return ( <div style={{ display: "flex", flexWrap: "wrap", alignItems: "center", gap: "14px" }}> {buttonFixture.buttons.map((button) => ( <Button key={button.id} variant={button.variant} size={button.size} disabled={button.disabled} > {button.label} </Button> ))} </div> );}- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
<script setup lang="ts">import { Button } from "@grassroot/ui-vue";const buttonFixture = { id: "button", buttons: [ { id: "primary", label: "Start a project" }, { id: "secondary", label: "View work", variant: "secondary" }, { id: "ghost", label: "See the work", variant: "ghost" }, { id: "link", label: "Read the case study", variant: "link" }, { id: "small", label: "Small", size: "sm" }, { id: "large", label: "Large", size: "lg" }, { id: "disabled", label: "Disabled", disabled: true }, ],} satisfies { id: string; buttons: Array<{ id: string; label: string; variant?: "primary" | "secondary" | "ghost" | "link"; size?: "sm" | "md" | "lg"; disabled?: boolean; }>;}; </script> <template> <div style="display: flex; flex-wrap: wrap; align-items: center; gap: 14px"> <Button v-for="button in buttonFixture.buttons" :key="button.id" :variant="button.variant" :size="button.size" :disabled="button.disabled" >{{ button.label }}</Button > </div></template>- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
import { Component } from "@angular/core";import { GrassrootButton } from "@grassroot/ui-angular";const buttonFixture = { id: "button", buttons: [ { id: "primary", label: "Start a project" }, { id: "secondary", label: "View work", variant: "secondary" }, { id: "ghost", label: "See the work", variant: "ghost" }, { id: "link", label: "Read the case study", variant: "link" }, { id: "small", label: "Small", size: "sm" }, { id: "large", label: "Large", size: "lg" }, { id: "disabled", label: "Disabled", disabled: true }, ],} satisfies { id: string; buttons: Array<{ id: string; label: string; variant?: "primary" | "secondary" | "ghost" | "link"; size?: "sm" | "md" | "lg"; disabled?: boolean; }>;}; @Component({ selector: "app-button-demo", standalone: true, imports: [GrassrootButton], template: ` <div style="display:flex;flex-wrap:wrap;align-items:center;gap:14px"> @for (button of fixture.buttons; track button.id) { <grassroot-button [variant]="button.variant" [size]="button.size" [disabled]="button.disabled" >{{ button.label }}</grassroot-button > } </div> `,})export class ButtonDemoComponent { protected readonly fixture = buttonFixture;} export default ButtonDemoComponent;- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
<script lang="ts"> import { Button } from "@grassroot/ui-svelte"; const buttonFixture = { id: "button", buttons: [ { id: "primary", label: "Start a project" }, { id: "secondary", label: "View work", variant: "secondary" }, { id: "ghost", label: "See the work", variant: "ghost" }, { id: "link", label: "Read the case study", variant: "link" }, { id: "small", label: "Small", size: "sm" }, { id: "large", label: "Large", size: "lg" }, { id: "disabled", label: "Disabled", disabled: true }, ], } satisfies { id: string; buttons: Array<{ id: string; label: string; variant?: "primary" | "secondary" | "ghost" | "link"; size?: "sm" | "md" | "lg"; disabled?: boolean; }>; }; </script> <div style="display:flex;flex-wrap:wrap;align-items:center;gap:14px"> {#each buttonFixture.buttons as button (button.id)} <Button variant={button.variant} size={button.size} disabled={button.disabled} >{button.label}</Button > {/each}</div>- parts
- —
- nodes
- —
- size
- —
- part
- —
ts
/** @jsxImportSource solid-js */import { Button } from "@grassroot/ui-solid";import type { JSX } from "solid-js";const buttonFixture = { id: "button", buttons: [ { id: "primary", label: "Start a project" }, { id: "secondary", label: "View work", variant: "secondary" }, { id: "ghost", label: "See the work", variant: "ghost" }, { id: "link", label: "Read the case study", variant: "link" }, { id: "small", label: "Small", size: "sm" }, { id: "large", label: "Large", size: "lg" }, { id: "disabled", label: "Disabled", disabled: true }, ],} satisfies { id: string; buttons: Array<{ id: string; label: string; variant?: "primary" | "secondary" | "ghost" | "link"; size?: "sm" | "md" | "lg"; disabled?: boolean; }>;}; export default function ButtonDemo(): JSX.Element { return ( <div style={{ display: "flex", "flex-wrap": "wrap", "align-items": "center", gap: "14px" }}> {buttonFixture.buttons.map((button) => ( <Button variant={button.variant} size={button.size} disabled={button.disabled}> {button.label} </Button> ))} </div> );}Installation
API Reference
Import
import { Button } from "@grassroot/ui-react";
Props
Prop
Type
Default
Requirement
Description
variant"secondary" | "ghost" | "primary" | "link" | undefined"primary"optional
Visual style.
size"sm" | "md" | "lg" | undefined"md"optional
—
toneTone | undefined"accent"optional
Brand colour.
as"button" | "a" | undefined"button"optional
Render as a native button or anchor while keeping Button styling.
hrefstring | undefined—
optional
Passed through when as="a" renders a native anchor.
loadingboolean | undefinedfalseoptional
In-flight state: announces `aria-busy`, swaps the leading icon for a spinner, and suspends activation — WITHOUT removing the button from the tab order (the Grassroot rule: a busy control stays findable).
- Prop
size- Type
"sm" | "md" | "lg" | undefined- Default
"md"- Requirement
- optional
- Description
- —
- Prop
tone- Type
Tone | undefined- Default
"accent"- Requirement
- optional
- Description
- Brand colour.
- Prop
as- Type
"button" | "a" | undefined- Default
"button"- Requirement
- optional
- Description
- Render as a native button or anchor while keeping Button styling.
- Prop
href- Type
string | undefined- Default
- —
- Requirement
- optional
- Description
- Passed through when as="a" renders a native anchor.
- Prop
loading- Type
boolean | undefined- Default
false- Requirement
- optional
- Description
- In-flight state: announces `aria-busy`, swaps the leading icon for a spinner, and suspends activation — WITHOUT removing the button from the tab order (the Grassroot rule: a busy control stays findable).
Content regions
childreniconLeft
Native attributes
Standard DOM and ARIA attributes not listed above spread onto the root element.
Import
import { Button } from "@grassroot/ui-vue";
Props
Prop
Type
Default
Requirement
variantButtonVariant | undefined"primary"optional
sizeButtonSize | undefined"md"optional
toneButtonTone | undefined"accent"optional
as"button" | "a" | undefined"button"optional
hrefstring | undefined—
optional
loadingboolean | undefined—
optional
disabledboolean | undefined—
optional
type"button" | "submit" | "reset" | undefined"button"optional
- Prop
variant- Type
ButtonVariant | undefined- Default
"primary"- Requirement
- optional
- Prop
size- Type
ButtonSize | undefined- Default
"md"- Requirement
- optional
- Prop
tone- Type
ButtonTone | undefined- Default
"accent"- Requirement
- optional
- Prop
as- Type
"button" | "a" | undefined- Default
"button"- Requirement
- optional
- Prop
href- Type
string | undefined- Default
- —
- Requirement
- optional
- Prop
loading- Type
boolean | undefined- Default
- —
- Requirement
- optional
- Prop
disabled- Type
boolean | undefined- Default
- —
- Requirement
- optional
- Prop
type- Type
"button" | "submit" | "reset" | undefined- Default
"button"- Requirement
- optional
Events
| Event | Payload |
|---|---|
click | [event: MouseEvent] |
Content regions
defaulticonLeft
Import
import { Component } from "@angular/core";
import { GrassrootButton } from "@grassroot/ui-angular";
Props
Prop
Type
Default
Requirement
variantButtonVariant"primary"optional
sizeButtonSize"md"optional
toneButtonTone"accent"optional
as"button" | "a""button"optional
hrefstring—
optional
loadingbooleanfalseoptional
disabledbooleanfalseoptional
type"button" | "submit" | "reset""button"optional
classNamestring—
optional
- Prop
variant- Type
ButtonVariant- Default
"primary"- Requirement
- optional
- Prop
size- Type
ButtonSize- Default
"md"- Requirement
- optional
- Prop
tone- Type
ButtonTone- Default
"accent"- Requirement
- optional
- Prop
as- Type
"button" | "a"- Default
"button"- Requirement
- optional
- Prop
href- Type
string- Default
- —
- Requirement
- optional
- Prop
loading- Type
boolean- Default
false- Requirement
- optional
- Prop
disabled- Type
boolean- Default
false- Requirement
- optional
- Prop
type- Type
"button" | "submit" | "reset"- Default
"button"- Requirement
- optional
- Prop
className- Type
string- Default
- —
- Requirement
- optional
Content regions
defaulticonLeft
Import
import { Button } from "@grassroot/ui-svelte";
Props
Prop
Type
Default
Requirement
variantButtonVariant"primary"optional
sizeButtonSize"md"optional
toneButtonTone"accent"optional
as"button" | "a""button"optional
hrefstring—
optional
loadingbooleanfalseoptional
disabledbooleanfalseoptional
type"button" | "submit" | "reset""button"optional
classNamestring—
optional
onClick(event: MouseEvent) => void—
optional
- Prop
variant- Type
ButtonVariant- Default
"primary"- Requirement
- optional
- Prop
size- Type
ButtonSize- Default
"md"- Requirement
- optional
- Prop
tone- Type
ButtonTone- Default
"accent"- Requirement
- optional
- Prop
as- Type
"button" | "a"- Default
"button"- Requirement
- optional
- Prop
href- Type
string- Default
- —
- Requirement
- optional
- Prop
loading- Type
boolean- Default
false- Requirement
- optional
- Prop
disabled- Type
boolean- Default
false- Requirement
- optional
- Prop
type- Type
"button" | "submit" | "reset"- Default
"button"- Requirement
- optional
- Prop
className- Type
string- Default
- —
- Requirement
- optional
- Prop
onClick- Type
(event: MouseEvent) => void- Default
- —
- Requirement
- optional
Events
| Event | Payload |
|---|---|
onClick | (event: MouseEvent) => void |
Content regions
childreniconLeft
Import
import { Button } from "@grassroot/ui-solid";
import type { JSX } from "solid-js";
Props
Prop
Type
Default
Requirement
variantButtonVariant"primary"optional
sizeButtonSize"md"optional
toneButtonTone"accent"optional
as"button" | "a""button"optional
hrefstring—
optional
loadingbooleanfalseoptional
disabledboolean—
optional
type"button" | "submit" | "reset""button"optional
onClick(event: MouseEvent) => void—
optional
classNamestring—
optional
- Prop
variant- Type
ButtonVariant- Default
"primary"- Requirement
- optional
- Prop
size- Type
ButtonSize- Default
"md"- Requirement
- optional
- Prop
tone- Type
ButtonTone- Default
"accent"- Requirement
- optional
- Prop
as- Type
"button" | "a"- Default
"button"- Requirement
- optional
- Prop
href- Type
string- Default
- —
- Requirement
- optional
- Prop
loading- Type
boolean- Default
false- Requirement
- optional
- Prop
disabled- Type
boolean- Default
- —
- Requirement
- optional
- Prop
type- Type
"button" | "submit" | "reset"- Default
"button"- Requirement
- optional
- Prop
onClick- Type
(event: MouseEvent) => void- Default
- —
- Requirement
- optional
- Prop
className- Type
string- Default
- —
- Requirement
- optional
Events
| Event | Payload |
|---|---|
onClick | (event: MouseEvent) => void |
Content regions
childreniconLeft