SGUI / Development
Button
Trigger an action with a labelled button, optional icons and native interaction states.
Loading examples…
Component documentation
SGUI / Development
Trigger an action with a labelled button, optional icons and native interaction states.
Loading examples…
Start with text alone. Add either icon, then compare variant, tone, density and interaction states.
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
export default function ButtonPlaygroundExample() {
return (
<>
<Button variant="filled" tone="primary" density="comfortable" disabled={false} loading={false}>{"Publish course"}</Button>
</>
);
}
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
export default function ButtonExample1Example() {
return (
<>
<Button>{"Save changes"}</Button>
</>
);
}
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
export default function ButtonExample2Example() {
return (
<>
<Button variant="outlined">{"Save draft"}</Button>
</>
);
}
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
export default function ButtonExample3Example() {
return (
<>
<Button variant="text" tone="neutral">{"Cancel"}</Button>
</>
);
}
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { AddIcon, ChevronRightIcon } from '@structured-growth/sg-ui/icons';
export default function ButtonExample4Example() {
return (
<>
<Button startIcon={<AddIcon />}>{"Add course"}</Button>
</>
);
}
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { AddIcon, ChevronRightIcon } from '@structured-growth/sg-ui/icons';
export default function ButtonExample5Example() {
return (
<>
<Button endIcon={<ChevronRightIcon />}>{"Continue"}</Button>
</>
);
}
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { AddIcon, ChevronRightIcon } from '@structured-growth/sg-ui/icons';
export default function ButtonExample6Example() {
return (
<>
<Button startIcon={<AddIcon />} endIcon={<ChevronRightIcon />}>{"Create course"}</Button>
</>
);
}
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
export default function ButtonExample7Example() {
return (
<>
<Button disabled>{"Publish course"}</Button>
</>
);
}
Loading replaces the leading icon with progress; the trailing icon remains.
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { AddIcon, ChevronRightIcon } from '@structured-growth/sg-ui/icons';
export default function ButtonExample8Example() {
return (
<>
<Button loading startIcon={<AddIcon />} endIcon={<ChevronRightIcon />}>{"Publishing course"}</Button>
</>
);
}
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
export default function ButtonExample9Example() {
return (
<>
<Button tone="neutral">{"View details"}</Button>
</>
);
}
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { Stack } from '@structured-growth/sg-ui/experimental';
export default function ButtonDensitiesExample() {
return (
<>
<Stack direction="row" wrap gap={3}><Button density="compact">Save changes</Button><Button density="comfortable">Save changes</Button></Stack>
</>
);
}
'use client';
import { Button, ButtonGroup } from '@structured-growth/sg-ui/experimental';
export default function GroupedButtonsExample() {
return (
<>
<ButtonGroup label="Document actions" joined><Button>Save</Button><Button variant="outlined" tone="neutral">Save draft</Button></ButtonGroup>
</>
);
}
The host updates the label after activation. Connect persistence in your application.
'use client';
import { useState } from 'react';
import { Button } from '@structured-growth/sg-ui/components/Button';
export default function SaveButtonExample() {
const [saved,setSaved]=useState(false);
return (
<>
<Button onPress={() => setSaved(true)}>{saved ? "Saved" : "Save changes"}</Button>
</>
);
}
Submit uses browser validation. Reset restores the native field; the host handles persistence.
'use client';
import { useState } from 'react';
import { Button, Stack, TextField } from '@structured-growth/sg-ui/experimental';
export default function ButtonFormExample() {
const [submitted,setSubmitted]=useState(false);
return (
<>
<form onSubmit={event => { event.preventDefault(); setSubmitted(true); }} onReset={() => setSubmitted(false)}><Stack gap={3}><TextField label="Course name" name="course" defaultValue="Learning foundations" required/><Stack direction="row" gap={3}><Button type="submit">{submitted ? "Submitted" : "Submit course"}</Button><Button type="reset" variant="text" tone="neutral">Reset</Button></Stack></Stack></form>
</>
);
}
Both tones at both densities, independently of the playground.
'use client';
import { useState } from 'react';
import { ThemeScope } from '@structured-growth/sg-ui/theme';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { Stack, Typography } from '@structured-growth/sg-ui/primitives';
export default function FilledButtonsExample() {
const [presses, setPresses] = useState(0);
return (
<>
<Stack gap={3}>
<ThemeScope density="compact">
<Stack direction="row" wrap gap={3}>
<Button variant="filled" tone="primary" onPress={() => setPresses(value => value + 1)}>{"primary · compact"}</Button>
<Button variant="filled" tone="neutral" onPress={() => setPresses(value => value + 1)}>{"neutral · compact"}</Button>
</Stack>
</ThemeScope>
<ThemeScope density="comfortable">
<Stack direction="row" wrap gap={3}>
<Button variant="filled" tone="primary" onPress={() => setPresses(value => value + 1)}>{"primary · comfortable"}</Button>
<Button variant="filled" tone="neutral" onPress={() => setPresses(value => value + 1)}>{"neutral · comfortable"}</Button>
</Stack>
</ThemeScope>
</Stack>
</>
);
}
Both tones at both densities, independently of the playground.
'use client';
import { useState } from 'react';
import { ThemeScope } from '@structured-growth/sg-ui/theme';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { Stack, Typography } from '@structured-growth/sg-ui/primitives';
export default function OutlinedButtonsExample() {
const [presses, setPresses] = useState(0);
return (
<>
<Stack gap={3}>
<ThemeScope density="compact">
<Stack direction="row" wrap gap={3}>
<Button variant="outlined" tone="primary" onPress={() => setPresses(value => value + 1)}>{"primary · compact"}</Button>
<Button variant="outlined" tone="neutral" onPress={() => setPresses(value => value + 1)}>{"neutral · compact"}</Button>
</Stack>
</ThemeScope>
<ThemeScope density="comfortable">
<Stack direction="row" wrap gap={3}>
<Button variant="outlined" tone="primary" onPress={() => setPresses(value => value + 1)}>{"primary · comfortable"}</Button>
<Button variant="outlined" tone="neutral" onPress={() => setPresses(value => value + 1)}>{"neutral · comfortable"}</Button>
</Stack>
</ThemeScope>
</Stack>
</>
);
}
Both tones at both densities, independently of the playground.
'use client';
import { useState } from 'react';
import { ThemeScope } from '@structured-growth/sg-ui/theme';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { Stack, Typography } from '@structured-growth/sg-ui/primitives';
export default function TextButtonsExample() {
const [presses, setPresses] = useState(0);
return (
<>
<Stack gap={3}>
<ThemeScope density="compact">
<Stack direction="row" wrap gap={3}>
<Button variant="text" tone="primary" onPress={() => setPresses(value => value + 1)}>{"primary · compact"}</Button>
<Button variant="text" tone="neutral" onPress={() => setPresses(value => value + 1)}>{"neutral · compact"}</Button>
</Stack>
</ThemeScope>
<ThemeScope density="comfortable">
<Stack direction="row" wrap gap={3}>
<Button variant="text" tone="primary" onPress={() => setPresses(value => value + 1)}>{"primary · comfortable"}</Button>
<Button variant="text" tone="neutral" onPress={() => setPresses(value => value + 1)}>{"neutral · comfortable"}</Button>
</Stack>
</ThemeScope>
</Stack>
</>
);
}
'use client';
import { useState } from 'react';
import { ThemeScope } from '@structured-growth/sg-ui/theme';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { Stack, Typography } from '@structured-growth/sg-ui/primitives';
import { TextField } from '@structured-growth/sg-ui/experimental';
export default function CompactControlsExample() {
const [value, setValue] = useState("Course basics");
return (
<>
<ThemeScope density="compact">
<Stack gap={3}>
<Button>Example action</Button>
<TextField label="Compact field" value={value} onValueChange={setValue} />
</Stack>
</ThemeScope>
</>
);
}
'use client';
import { useState } from 'react';
import { ThemeScope } from '@structured-growth/sg-ui/theme';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { Stack, Typography } from '@structured-growth/sg-ui/primitives';
import { TextField } from '@structured-growth/sg-ui/experimental';
export default function ComfortableControlsExample() {
const [value, setValue] = useState("Course basics");
return (
<>
<ThemeScope density="comfortable">
<Stack gap={3}>
<Button>Example action</Button>
<TextField label="Comfortable field" value={value} onValueChange={setValue} />
</Stack>
</ThemeScope>
</>
);
}
'use client';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { Stack, Typography } from '@structured-growth/sg-ui/primitives';
export default function ButtonContentExample() {
return (
<>
<Stack direction="row" wrap gap={3}>
<Button density="compact">Compact action</Button>
<Button density="comfortable">Comfortable action</Button>
<Button variant="outlined">A longer action label to explore wrapping</Button>
<Button disabled>Unavailable</Button>
<Button loading>Saving changes</Button>
</Stack>
</>
);
}
'use client';
import { useState } from 'react';
import { Button } from '@structured-growth/sg-ui/components/Button';
import { Stack, Typography } from '@structured-growth/sg-ui/primitives';
export default function ButtonFormExample() {
const [submits, setSubmits] = useState(0);
return (
<>
<form onSubmit={event => { event.preventDefault(); setSubmits(value => value + 1); }}>
<Stack direction="row" wrap gap={3}>
<Button variant="text">Cancel</Button>
<Button type="submit">Save form</Button>
<Typography aria-live="polite">Saved {submits} times</Typography>
</Stack>
</form>
</>
);
}