Shared Vue 3 + Tailwind v4 design-system atoms and design tokens for codebar-ag applications, documented in Storybook. One source of truth so every app looks identical.
Live Storybook: https://codebar-ag.github.io/storybook.codebar.ch/ — every atom
and its variants, deployed automatically from main.
Atoms only. This package ships the basic building blocks (button, card, table, badge, form fields, dropdown, icon, list-row, metric, alert…) and the design tokens. Composite, domain-specific "organisms" (billing panels, instance rows, …) live in each consuming app — but they must be assembled only from these atoms, never from raw HTML elements.
Two ways, and the first needs no credentials.
The repository is public and prepare builds dist on install, so a git
dependency works anywhere with no setup:
npm install github:codebar-ag/storybook.codebar.ch#v1.7.0Pin a tag rather than a branch, so installs stay reproducible. npm installs this repo's devDependencies to run the build, which makes a cold install slower than a registry one — that is the trade for needing no token.
Add an .npmrc to the consuming app:
@codebar-ag:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
npm install @codebar-ag/storybookNote: GitHub's npm registry requires authentication for every read, public packages included — unlike npmjs.com. This repository being public does not change that, and neither does the package's own visibility. Set
GITHUB_TOKENto a token with theread:packagesscope (a classic PAT works, as doesgh auth token) locally, in CI, and on every deploy target.
1. Tokens + Tailwind — in your app's app.css:
@import "@codebar-ag/storybook/tokens.css"; /* @theme: colors, type scale, radius */
@import "tailwindcss";
@source "../../node_modules/@codebar-ag/storybook/dist"; /* scan atoms for classes */The @source line is required: Tailwind must scan the compiled atoms so their
utility classes are generated in your app's stylesheet.
2. Register the atoms — in your Vue entry:
import { Flows } from '@codebar-ag/storybook';
createApp(...).use(Flows); // global <Button>, <Card>, <Icon>, …Or import individually:
import { Button, Card, useToast } from '@codebar-ag/storybook';3. Toasts — mount <Toaster /> once near the root, then push() from anywhere:
import { pushToast } from '@codebar-ag/storybook';
pushToast({ message: 'Saved.', type: 'success' });Component-based consistency is the point of this package: every app should look identical because every app is built from the same atoms.
- Check Storybook first. Browse the
live Storybook (or run
npm run devin this package) and searchsrc/index.ts's barrel export before writing any markup for a new screen or feature. - Never re-implement an atom. If this package already ships a
Button,Card,Table,Badge,Modal, form field, dropdown, icon, list-row, metric, or alert, the consuming app must import and use it — not hand-roll an equivalent with raw<button>/<table>/<div>+ Tailwind classes. - Compose, don't fork. If an atom is close but not quite right, extend it via
its existing props/slots/
classoverrides. Don't copy its template into the app and tweak it. - Domain-specific "organisms" (billing panels, instance rows, resource lists, …) stay in the consuming app, but must be assembled only from these atoms, never from raw HTML elements.
Only add a component here when no existing atom (or composition of atoms) can satisfy the need. A new atom must:
- Live in
src/components/as a<script setup>Vue 3 SFC. - Be styled only with token-driven Tailwind utility classes — no
<style>blocks, no@apply, no bespoke CSS. - Ship a
*.stories.tsentry documenting its variants. - Pass
npm run typecheckandnpm run lint. - Be exported from
src/index.ts(and registered on theFlowsplugin if it's a globally-usable atom).
npm install
npm run dev # Storybook on :6006 (the styleguide)
npm run build # library build → dist/ (ESM + types + tokens.css)
npm run build-storybook # static styleguide → storybook-static/
npm run typecheck # vue-tsc
npm run lintPublishing happens in CI, on a v* tag. Never run npm publish by hand — the
registry rejects a republish, so a manual publish turns the tag's Release run
red even though the version shipped fine, and a healthy release stops being
distinguishable from a broken one (this is exactly what happened to v1.8.0).
npm version minor # bumps package.json + creates the vX.Y.Z tag
git push --follow-tags # Release workflow builds, tests, publishesThe workflow refuses to run if the tag and package.json version disagree, and
verifies the version resolves on the registry once published.
- Bump with
npm version, nevergit tagby hand.npm versionderives the tag name from the manifest, so the two cannot disagree. Writing the tag yourself is the one step where they can. - Add the
## vX.Y.Zsection to CHANGELOG.md first — the Release workflow reads the release body out of it, and falls back to commit-derived notes if the section is missing. - Push with
--follow-tags, then watch the Release run to green. A red run does not mean nothing shipped; read it. - A version number is spent the moment its tag exists. Never re-use or
re-point one.
npm run verify:versionenforces both halves of this and runs on every PR: the manifest may not match an existing tag, and may not be behind the highest one.
A tag is a release, even when the release failed. This package is documented as a git dependency, so
#v1.17.0resolves and installs straight from the tag — the registry, the Release run and the GitHub Release are not in that path at all. That is what made v1.17.0 a trap:release/v1.16.1was bumped correctly to 1.16.1 and then taggedv1.17.0by hand, the Release run failed at the mismatch guard so 1.16.1 never reached the registry, and consuming apps pinned v1.17.0 and got a build whosepackage.jsonsays 1.16.1. Nothing was broken; nothing said so either. The number 1.17.0 is now permanently unusable, which is why the next release is 1.18.0.
Release notes, migration notes and upgrade warnings live in CHANGELOG.md.
MIT © codebar Solutions AG