@lessly/ui
v0.7.2
Published
Lessly design system — shared UI primitives, tokens, and theme
Readme
@lessly/ui
The live Lessly design system — shared UI primitives, design tokens, theme, and Tailwind preset. This package is the shared singleton the Lessly workspace Module Federation host provides to federation extension remotes at runtime, and it is published to the public npm registry (npmjs.com).
Contract: the package name (
@lessly/ui), its exports (.,./tailwind-preset,./styles.css), and its peer dependencies (React 19, react-router 7, optionaltailwindcss >=3.4) are a cross-project contract. Do not change them without coordinating the workspace host and every federation remote.
What's inside
- Components: shadcn/radix primitives themed by Lessly tokens (Button,
Dialog, Select, Tabs, …) plus layout:
Grid/Col(the adaptive 4 / 8 / 12 column grid) andGridOverlay(a design-aid overlay). The full catalog lives in Storybook at ui.lessly.com. - Theme:
useThemehook +ThemeToggle(toggles thelightclass on<html>;:rootis dark,.lightis light). - Tokens: the
tailwind-presetre-exports the token vocabulary from@lessly/tokens(generated upstream inlessly-hub/design-system) withdarkMode: 'class'added, andstyles.cssbundles the package'stheme.css(CSS variables,.lightoverrides, typography classes) plus this library's fonts and base layer. Token values are never edited here — they change by bumping@lessly/tokens.
Install
Published to the public npm registry — no scope or registry configuration needed:
npm install @lessly/uiUsage
import { Button, useTheme } from '@lessly/ui';
import '@lessly/ui/styles.css';Your app's Tailwind config must use the preset so token utilities resolve. The preset needs Tailwind CSS >= 3.4 (declared as an optional peer dependency — only required if you consume the preset):
import { lesslyPreset } from '@lessly/ui/tailwind-preset';
export default {
presets: [lesslyPreset],
// Scan the library too — its components (Grid, Col, …) use literal token
// utilities (`md:col-span-5`, `gap-gutter`) that Tailwind must see to generate.
content: ['./src/**/*.{ts,tsx}', './node_modules/@lessly/ui/dist/**/*.js'],
};CSS variables use the upstream unprefixed names (--bg-primary,
--text-primary, …). The old --color-* names still resolve through a
deprecated alias layer in styles.css and will be removed in the next major —
migrate any direct var(--color-*) reads.
Storybook
pnpm storybook # dev server on http://localhost:6006
pnpm build-storybook # static build → storybook-static/The Storybook toolbar has a global Dark/Light toggle driven by the package's own
useTheme hook.
Deployment (ui.lessly.com)
The Storybook is deployed via the Lessly static-service pipeline, which runs
pnpm build-storybook and serves the resulting storybook-static/. The npm
package build is pnpm build (tsup → dist/), which the release flow uses; the
npm package published to npmjs always contains the package, never the Storybook site.
Scripts
| Script | Description |
| --- | --- |
| pnpm build | tsup package build → dist/ (+ assembles styles.css from the @lessly/tokens theme, deprecated --color-* aliases, ui-local pieces, and the animation layer) — the npm package published to npmjs |
| pnpm build-storybook | Storybook static site → storybook-static/ — what the static-service pipeline deploys to ui.lessly.com |
| pnpm storybook | Storybook dev server on http://localhost:6006 |
| pnpm test | Vitest |
| pnpm type-check | tsc --noEmit |
| pnpm lint | ESLint |
| pnpm changeset / pnpm release:version | Versioning via Changesets (describe change → apply bump + changelog) — see RELEASING.md |
| pnpm release:publish | CI-only publish wrapper (publish to npmjs if needed + changeset tag) — used by .github/workflows/version.yml |
Releasing
Add a changeset (pnpm changeset) to each significant PR; merging the
auto-generated "Release: version packages" PR publishes to the public npm
registry and tags v<version>. See RELEASING.md.
