Components
Button
Buttons start an action. Flint has four: primary, secondary, danger and text.
CSS
For Astro, EJS and plain HTML. These rules read only component tokens.
HTML
<button type="button" class="flint-btn flint-btn--primary">Save trip</button>
<button type="button" class="flint-btn flint-btn--secondary">Add stop</button>
<button type="button" class="flint-btn flint-btn--danger">Delete trip</button>
<button type="button" class="flint-btn flint-btn--text">Skip for now</button> CSS
.flint-btn {
display: inline-flex; align-items: center; justify-content: center; gap: var(--space-8);
min-height: var(--button-height); padding: 0 var(--space-16);
border: 1px solid transparent; border-radius: var(--button-radius);
font: 700 var(--font-size-sm) / 1.2 var(--font-sans); cursor: pointer;
}
.flint-btn:focus-visible { outline: var(--focus-ring-width) solid var(--focus-ring-color); outline-offset: var(--focus-ring-offset); }
.flint-btn--primary { background: var(--button-primary-bg); color: var(--button-primary-fg); }
.flint-btn--primary:hover { background: var(--button-primary-bg-hover); }
.flint-btn--secondary { background: var(--button-secondary-bg); color: var(--button-secondary-fg); border-color: var(--button-secondary-border); }
.flint-btn--secondary:hover { background: var(--button-secondary-bg-hover); }
.flint-btn--danger { background: var(--button-danger-bg); color: var(--button-danger-fg); }
.flint-btn--danger:hover { background: var(--button-danger-bg-hover); }
.flint-btn--text { background: transparent; color: var(--button-text-fg); }
.flint-btn--text:hover { background: var(--button-text-bg-hover); }
.flint-btn:disabled { background: var(--button-disabled-bg); color: var(--button-disabled-fg); border-color: transparent; cursor: not-allowed; }
.flint-btn--secondary:disabled { border-color: var(--button-disabled-border); }
.flint-btn--text:disabled { background: transparent; } MUI
React (MUI)
import Button from '@mui/material/Button';
<Button variant="contained">Save trip</Button>
<Button variant="outlined">Add stop</Button>
<Button variant="contained" color="error">Delete trip</Button>
<Button variant="text">Skip for now</Button> Known gap
The MUI theme does not apply the secondary and disabled button tokens yet, and its buttons are 36px tall instead of 40px (ASDS-44).
shadcn/ui
The Flint version of the shadcn component. Same API as upstream; every value reads a Flint token.
components/ui/button.jsx
// shadcn/ui Button, restyled to Flint. Same API as upstream (variant, asChild); every color,
// size and focus value reads a Flint component token instead of shadcn's defaults.
// Changed from upstream: no opacity-50 disabled state (disabled has its own tokens), and the
// focus ring is Flint's solid 2px ring instead of a 50% transparent ring.
import { Slot } from '@radix-ui/react-slot';
import { cva } from 'class-variance-authority';
import { cn } from '../cn';
const buttonVariants = cva(
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-[var(--button-radius)] min-h-[var(--button-height)] px-4 text-sm font-bold transition-colors cursor-pointer border border-transparent outline-none focus-visible:[outline:var(--focus-ring-width)_solid_var(--focus-ring-color)] focus-visible:[outline-offset:var(--focus-ring-offset)] disabled:cursor-not-allowed disabled:bg-[var(--button-disabled-bg)] disabled:text-[var(--button-disabled-fg)]',
{
variants: {
variant: {
default: 'bg-[var(--button-primary-bg)] text-[var(--button-primary-fg)] hover:bg-[var(--button-primary-bg-hover)]',
secondary: 'border-[var(--button-secondary-border)] bg-[var(--button-secondary-bg)] text-[var(--button-secondary-fg)] hover:bg-[var(--button-secondary-bg-hover)] disabled:border-[var(--button-disabled-border)]',
destructive: 'bg-[var(--button-danger-bg)] text-[var(--button-danger-fg)] hover:bg-[var(--button-danger-bg-hover)]',
ghost: 'bg-transparent text-[var(--button-text-fg)] hover:bg-[var(--button-text-bg-hover)] disabled:bg-transparent',
},
},
defaultVariants: { variant: 'default' },
},
);
export function Button({ className, variant, asChild = false, ...props }) {
const Comp = asChild ? Slot : 'button';
return <Comp data-slot="button" className={cn(buttonVariants({ variant }), className)} {...props} />;
}
export { buttonVariants }; SwiftUI
SwiftUI
Button("Save trip", action: save)
.flintText(Flint.Typography.labelButton)
.foregroundStyle(Flint.Component.buttonPrimaryFg)
.padding(.horizontal, Flint.Space.s16)
.frame(minHeight: Flint.Target.touch)
.background(Flint.Component.buttonPrimaryBg,
in: RoundedRectangle(cornerRadius: Flint.Component.buttonRadius)) A ready-made SwiftUI button is moving into the Flint package (ASDS-38). Until then, build it from the component tokens as above.