@snowball-ui/react-web
v0.2.0
Published
React web runtime components and provider for Snowball UI.
Maintainers
Readme
@snowball-ui/react-web
React components and web runtime helpers for Snowball UI.
Use this package from React web applications. Component contracts live in
@snowball-ui/foundation, theme definitions live in @snowball-ui/themes and
@snowball-ui/tokens, and documentation/tooling metadata lives in
@snowball-ui/registry.
Install
pnpm add @snowball-ui/react-web react react-domreact and react-dom are peer dependencies. This package currently declares
React 19 peer ranges.
Styling Setup
SnowballThemeProvider supplies Snowball CSS variables. Import the packaged
runtime stylesheet once in your application entry so Snowball's compiled utility
classes are available without scanning node_modules.
import '@snowball-ui/react-web/styles.css';In this workspace, Storybook still scans packages/react-web/src directly while
developing unpublished source.
Provider Setup
Wrap the part of the app that renders Snowball components with
SnowballThemeProvider.
import { SnowballThemeProvider } from '@snowball-ui/react-web';
export function Root() {
return (
<SnowballThemeProvider>
<App />
</SnowballThemeProvider>
);
}The theme prop is optional and defaults to default. Use the exported
ThemeName type when storing a documented theme name in app state.
The provider renders a scoped wrapper with Snowball CSS variables and data attributes. Overlay components use the provider scope as their default portal container, so keep overlays under the provider.
Importing Components
Import public APIs from the package root:
import {
Button,
TextField,
Toast,
type ThemeName,
} from '@snowball-ui/react-web';For tighter app bundles, component subpaths are also published:
import { Button, type SnowballButtonProps } from '@snowball-ui/react-web/button';
import { TextField } from '@snowball-ui/react-web/text-field';Public component exports:
Agreement, AgreementV3, AgreementV4, AlertDialog, Asset, Badge, BarChart,
BoardRow, Border, BottomCTA, FixedBottomCTA, BottomInfo, BottomSheet, Bubble,
Button, Card, Checkbox, ConfirmDialog, Dialog, GridList, Highlight, IconButton,
Keypad, AlphabetKeypad, NumberKeypad, FullSecureKeypad, ListFooter, ListHeader,
ListRow, ListRowLegacy, Loader, Menu, Modal, NumericSpinner, Paragraph, Post,
ProgressBar, ProgressStepper, Rating, Result, SearchField, SegmentedControl,
Skeleton, Slider, SplitTextField, Stepper, StepperRow, Switch, TableRow, Tab,
Tabs, TextArea, TextButton, TextField, Toast, Tooltip, TopPublic provider, hook, and utility exports:
SnowballThemeProvider, ThemeName, cx, useBottomSheet, useDialog, useToast,
webSemanticStyleTokens, webPrimitiveStyleTokens, webEffectStyleTokensSome exports are compound components with static members, such as Asset,
BottomSheet, Dialog, Post, StepperRow, Toast, and Top. See the
generated TypeScript types or the Storybook stories for their member APIs.
Basic Usage
import {
Button,
SnowballThemeProvider,
TextField,
} from '@snowball-ui/react-web';
export function App() {
return (
<SnowballThemeProvider>
<form>
<TextField
label="Email"
name="email"
placeholder="[email protected]"
type="email"
/>
<Button type="submit" variant="fill" color="primary">
Continue
</Button>
</form>
</SnowballThemeProvider>
);
}Theming
SnowballThemeProvider converts the selected theme from @snowball-ui/themes
into CSS variables such as --sb-bg-surface-default,
--sb-fg-text-primary, --sb-action-primary-bg, --sb-spacing-4,
--sb-layer-overlay, and --sb-state-opacity-disabled.
Web style token helpers are exported from the public package entrypoint for custom web surfaces that need to align with component internals:
import {
webEffectStyleTokens,
webPrimitiveStyleTokens,
webSemanticStyleTokens,
} from '@snowball-ui/react-web';Use webSemanticStyleTokens for theme-aware color roles. These values are CSS
variable references, so they follow the nearest SnowballThemeProvider scope.
Use webPrimitiveStyleTokens for primitive runtime variables such as radius,
spacing, layer, interaction, state opacity, and component anatomy for controls,
rows, tabs, and dialog cards, or when a
fixed primitive value is required to match a legacy visual detail or non-role
color. Use
webEffectStyleTokens for
non-semantic effects such as glass surfaces, focus glows, masks, backdrops, and
component shadow recipes.
Use the exported ThemeName type when storing theme state:
import {
createSemanticTheme,
extendSemanticTheme,
SnowballThemeProvider,
type ThemeName,
} from '@snowball-ui/react-web';
const theme: ThemeName = 'dark';
const productTheme = createSemanticTheme('product', {
action: {
primary: {
bg: '#123456',
fg: '#ffffff',
},
},
});
const campaignTheme = extendSemanticTheme(productTheme, 'product-campaign', {
bg: {
accent: {
weak: '#eef6ff',
},
},
});
export function AppShell() {
return <SnowballThemeProvider theme={campaignTheme}>...</SnowballThemeProvider>;
}For smaller adjustments, pass themeOverrides. Overrides are merged into the
selected base theme and keep unspecified semantic roles intact.
<SnowballThemeProvider
theme={theme}
themeOverrides={{
action: {
primary: {
bg: '#123456',
fg: '#ffffff',
},
},
}}
>
<App />
</SnowballThemeProvider>Overlays and Hooks
The overlay components can be controlled directly with React state. The package also exports small state hooks that prepare props for the matching components. The hooks do not render anything by themselves; render the overlay component and spread the returned props.
import {
AlertDialog,
BottomSheet,
Button,
ConfirmDialog,
Toast,
useBottomSheet,
useDialog,
useToast,
} from '@snowball-ui/react-web';
export function Actions() {
const dialog = useDialog();
const toast = useToast();
const sheet = useBottomSheet();
return (
<>
<Button
onClick={() =>
dialog.openConfirm({
title: 'Delete item?',
description: 'This action cannot be undone.',
cancelLabel: 'Cancel',
confirmLabel: 'Delete',
})
}
>
Open dialog
</Button>
<Button onClick={() => toast.openToast('Saved')}>Show toast</Button>
<Button
onClick={() =>
sheet.open({
header: <BottomSheet.Header>Options</BottomSheet.Header>,
children: <div>Sheet content</div>,
})
}
>
Open sheet
</Button>
<AlertDialog {...dialog.alertDialogProps} />
<ConfirmDialog {...dialog.confirmDialogProps} />
<Toast {...toast.toastProps} />
<BottomSheet {...sheet.bottomSheetProps} />
</>
);
}Related overlay exports include AlertDialog, BottomSheet, ConfirmDialog,
Dialog, Menu, Modal, Toast, and Tooltip.
Storybook and Local Development
This repository uses pnpm workspaces.
pnpm install
pnpm storybookpnpm storybook runs the web Storybook app on port 6006 through
apps/storybook-web. Stories live in apps/storybook-web/src/stories and
should render examples under SnowballThemeProvider.
Build Storybook before merging docs-facing or visual changes:
pnpm build-storybookTesting and Build
Useful commands from the repository root:
pnpm --filter @snowball-ui/react-web typecheck
pnpm --filter @snowball-ui/react-web build
pnpm test
pnpm typecheck
pnpm buildpnpm test runs the Vitest suite, including tests under
packages/react-web/src. There is no package-local test script in
@snowball-ui/react-web.
For visual parity checks, use the repository's internal audit runner. Generated audit artifacts should not be committed.
Maintainer Notes
Keep the contract, runtime, metadata, and examples aligned when changing a component:
packages/foundationis the semantic component contract.packages/react-webis the React web runtime implementation and public export surface.packages/registryis the normalized documentation and automation metadata.apps/storybook-webis the rendering and review hub.
For a component change, update the foundation contract, react-web component and
tests, registry component metadata, and Storybook story together. Add or adjust
the export in packages/react-web/src/index.ts when the public API changes.
Stop and resolve any foundation/registry disagreement before continuing.
Before merging visual or docs-facing work, run focused component tests plus
pnpm --filter @snowball-ui/storybook-web build-storybook.
License
MIT
