This walks through a small page built from @ds-gn/ui. It assumes you
have installed both packages and imported the
token stylesheets, and that the markup below is built by a bundler — the module
imports resolve there, not in a standalone HTML file.
A page in plain HTML
Import the components you need, then use their tags. Every import registers one custom element.
<script type="module">
import '@ds-gn/ui/container';
import '@ds-gn/ui/stack';
import '@ds-gn/ui/heading';
import '@ds-gn/ui/text';
import '@ds-gn/ui/button';
import '@ds-gn/ui/badge';
</script>
<dsgn-container size="lg" padding-y="xl">
<dsgn-stack direction="vertical" gap="md">
<dsgn-badge variant="brand">Public Beta</dsgn-badge>
<dsgn-heading heading-size="h1"
>Ship a design system, not a fork</dsgn-heading
>
<dsgn-text size="lg" color="secondary">
Framework-agnostic components with a governed, documented API.
</dsgn-text>
<dsgn-stack direction="horizontal" gap="sm" wrap>
<dsgn-button appearance="solid" href="/getting-started/installation/">
Get started
</dsgn-button>
<dsgn-button appearance="outline" href="/components/button/">
Browse components
</dsgn-button>
</dsgn-stack>
</dsgn-stack>
</dsgn-container>
Two things worth noticing:
- Layout is composed, not configured.
<dsgn-container>owns the measure and padding;<dsgn-stack>owns the spacing between items. Neither paints a background. <dsgn-button>takesappearance, notvariant, and becomes an<a>as soon as you give it anhref.
Composing with slots
Larger components take their content through named slots rather than props, so your copy stays yours:
<script type="module">
import '@ds-gn/ui/card';
import '@ds-gn/ui/badge';
import '@ds-gn/ui/heading';
import '@ds-gn/ui/button';
</script>
<dsgn-card variant="elevated" padding="md">
<dsgn-badge slot="badge" variant="accent">New</dsgn-badge>
<dsgn-heading slot="heading" heading-size="h3"
>Token-driven theming</dsgn-heading
>
<dsgn-button slot="footer" appearance="ghost" href="/tokens/customization/">
Learn more
</dsgn-button>
</dsgn-card>
A card has no default slot — every child needs a slot attribute. The badge and
heading regions are omitted when empty; the media and footer regions always
reserve their spacing. Each component page lists the slots it accepts.
The same page in React
import {
Badge,
Button,
Container,
Heading,
Stack,
Text,
} from '@ds-gn/ui/react';
export function Hero() {
return (
<Container size="lg" paddingY="xl">
<Stack direction="vertical" gap="md">
<Badge variant="brand">Public Beta</Badge>
<Heading headingSize="h1">Ship a design system, not a fork</Heading>
<Text size="lg" color="secondary">
Framework-agnostic components with a governed, documented API.
</Text>
<Button appearance="solid" href="/getting-started/installation/">
Get started
</Button>
</Stack>
</Container>
);
}
The wrappers take the JavaScript property names — paddingY and headingSize
where the HTML attributes are padding-y and heading-size. Each component
page lists both.
Handling events
Components dispatch namespaced dsgn-* events that cross the shadow boundary:
import '@ds-gn/ui/input';
document.querySelector('dsgn-input').addEventListener('dsgn-input', (event) => {
const { value, name } = event.detail;
});
In React the same event is the onDsgnInput prop:
import { Input } from '@ds-gn/ui/react';
<Input
name="email"
type="email"
label="Email"
onDsgnInput={(event) => setValue(event.detail.value)}
/>;
Next
- Configuration — rebrand with tokens, switch to dark, and register icons.
- Components — the full API for every component.