@smwb/ui-react
v2.3.0
Published
TypeScript React component library based on [Material Design](https://m3.material.io/), with runtime light/dark theming and LESS-based customization. Part of the `@smwb` design-system monorepo.
Readme
@smwb/ui-react
TypeScript React component library based on Material Design, with
runtime light/dark theming and LESS-based customization. Part of the @smwb design-system monorepo.
The @smwb packages
| Package | What it is |
| --- | --- |
| @smwb/ui-react | This package — React components. |
| @smwb/ui-solid | SolidJS port, same design system and class names. |
| @smwb/ui-styles | Framework-agnostic LESS source + design tokens (smwb-*). |
| @smwb/ui-css | Prebuilt aggregate stylesheet (import "@smwb/ui-css"). |
| @smwb/ui-mcp-react | MCP server exposing this catalog to AI tools. |
Component catalog
- Storybook (production): https://summerweb.ru/ui-react/
- Storybook (dev): https://summerweb.ru/ui-dev-react/
- Local:
npm run storybook→ http://localhost:6006
Installation
Published on npm as @smwb/ui-react.
Requirements: Node.js ≥ 20, React and React DOM ≥ 18 (peer dependencies).
npm install @smwb/ui-reactGetting started
import { Button } from "@smwb/ui-react";
function App() {
return <Button>Hello World</Button>;
}In ESM builds each imported component pulls in its own CSS automatically (tree-shakeable) — nothing else to import for the default theme.
Styles
Three ways to get the CSS, pick one:
- Auto-injected per-component CSS (default, ESM) — import components and their styles come along. Tree-shaken: you only ship CSS for what you use.
- Full prebuilt stylesheet — one file with every component, from
@smwb/ui-css(recommended for CJS or when you need a fixed global cascade order):
Optional CSS reset:import "@smwb/ui-css";import "@smwb/ui-styles/normalize.css";. - Custom LESS bundle compiled from
@smwb/ui-styles— see Theming.
Headless entry (compile one LESS bundle yourself)
For apps that compile a single themed LESS bundle instead of per-chunk CSS injection:
import "@smwb/ui-styles/normalize.css";
import "@smwb/ui-styles/components.less";
import { Button, TextField } from "@smwb/ui-react/headless";Selective LESS bundle (only the components you use)
Compile a minimal stylesheet from @smwb/ui-styles:
@import (less) "node_modules/@smwb/ui-styles/less/headless-base.less";
@import (less) "node_modules/@smwb/ui-styles/less/components/button/button.entry.less";
@import (less) "node_modules/@smwb/ui-styles/less/components/textField/textField.entry.less";headless-base.less= foundation tokens +:root/ dark CSS variables (import once).- One
*.entry.lessper component (each resolves LESS variables via_prelude.less). - A component's required entries and their dependencies are listed by the MCP tool
get_component_props(see@smwb/ui-mcp-react) under each component'sstylesblock. - Import
<name>.entry.less, never the barecomponents/<name>/<name>.less.
TanStack Table adapter
import { ReactTable } from "@smwb/ui-react/react-table";Targets @tanstack/react-table v8 (install it in your app). See Storybook → Connects / react-table.
Customization and theming
Pick the shallowest layer that solves the task:
| Goal | Approach | Rebuild CSS? |
| --- | --- | --- |
| Toggle light/dark, tweak a few colors live | CSS variables --smui-* + data-theme | No |
| One component instance looks different | Component props (color, size, variant, …) | No |
| New brand, density, or defaults library-wide | LESS overrides via theme.config on @smwb/ui-styles | Yes |
Full token catalogs and recipes: AI_THEMING.md (runtime + props),
AI_LESS_OVERRIDES.md (compile-time LESS).
Light and dark mode
Tokens are exposed on :root and :root[data-theme="dark"] as --smui-*.
import { useTheme, Theme } from "@smwb/ui-react";
function ThemeToggle() {
const { theme, setTheme } = useTheme(); // persists + syncs <html data-theme>
return (
<button type="button" onClick={() => setTheme(theme === Theme.dark ? Theme.light : Theme.dark)}>
{theme === Theme.dark ? "Light" : "Dark"}
</button>
);
}Or set the attribute yourself (<html data-theme="dark">). Without it, useTheme follows
prefers-color-scheme.
Runtime overrides (no rebuild)
:root {
--smui-primaryColor: #00695c;
--smui-radius-md: 2px;
}
.settings-panel { --smui-space-md: 8px; } /* scoped, cascades */Prefer --smui-* tokens over targeting internal .smwb-* classes (implementation detail).
Per-component appearance (props)
<Button variant="outlined" color="primary" size="large">Save</Button>
<FloatingButton color="success" size="large" />
<Message type="error" variant="filled" />Compile-time overrides (theme.config)
For library-wide changes, add a theme.config (see theme.config.example)
and compile @smwb/ui-styles/components.less:
// theme.config
@theme: "summer"; // or "material"
@themesFolder: "node_modules/@smwb/ui-styles/less/themes";
@primaryColor: @md-teal-600;
@smui-spacing-unit: 8px;
@smui-radius-md: 2px;lessc -rp=/ ./node_modules/@smwb/ui-styles/less/components.less ./src/app.csstheme.config is imported last, so your reassignments win. Token catalog and rules:
AI_LESS_OVERRIDES.md.
MCP server (component catalog for AI tools)
The catalog is exposed to AI assistants by a separate package, @smwb/ui-mcp-react — a stdio MCP server (no HTTP port). Tools:
| Tool | Purpose |
| --- | --- |
| search_components | Find components by name, id, description, or prop keywords |
| get_component_props | Full metadata for one component (props + required LESS imports) |
| search_customization | Global theming options and per-component customization |
| get_customization | What and how to customize a component or global topic |
Run it from npm:
npx -y @smwb/ui-mcp-reactCursor (.cursor/mcp.json) or Claude Desktop config:
{
"mcpServers": {
"smwb-ui-react": {
"command": "npx",
"args": ["-y", "@smwb/ui-mcp-react"]
}
}
}Documentation for AI assistants
| File | Topic |
| --- | --- |
| AI_THEMING.md | Runtime theming: --smui-* variables, useTheme, color / size / variant props |
| AI_LESS_OVERRIDES.md | Compile-time LESS overrides: token catalog, theme.config, custom stylesheet |
