@feugene/granularity
v0.53.0
Published
Granularity design system package with Vue 3 components, consumed via the `@feugene/unocss-preset-granular` preset.
Maintainers
Readme
@feugene/granularity
@feugene/granularity is a Vue 3 design system package that helps you build interfaces faster, cleaner, and more
predictably: with ready-made components, a transparent styling system, granular imports, and a tidy UnoCSS
integration.
It's built for cases where a design system needs to be more than just a set of UI pieces — a working engineering tool: convenient for a product team, scalable for a large application, and flexible enough for different adoption strategies.
Why it exists
- to launch new screens and features on a single visual foundation;
- to adopt the package incrementally, without rewriting the whole application;
- to control the size of the
JSandCSSyou ship, when that actually matters; - to use the same package both as a ready-made component library and as a source of low-level package-level APIs.
What makes granularity good
- Fast start without unnecessary magic. You can simply import components and ready-made style entrypoints.
- Granular imports. Components are available both from the root API and via
subpath exports, if you need finer control over bundle size. - Sane styling. Tokens, base styles, themes, and component-level CSS are split into clear layers.
- Ready for real scale. The package works for "just plugged in a few components" as well as scenarios where dependency-aware imports, safelist, and precise CSS pipeline tuning matter.
- Integrates with
UnoCSSwithout forcing it on you. IfUnoCSSis already in the app — the package plugs into the existing pipeline. If it isn't — the basic scenario stays direct and simple. - Not just components. Alongside the UI you get directives, a file validation API, and utility entrypoints for infrastructure scenarios.
Technical highlights
- root export:
@feugene/granularity; - component subpath exports:
@feugene/granularity/components/<ComponentName>; - ready-made CSS entrypoint:
@feugene/granularity/styles.css— tokens, base layer, preflight and the built-inlight/darkthemes in one file, for consumers who do not run theUnoCSSpreset. A component's own CSS is not there and does not need to be: the component's chunk imports it itself; - low-level foundation exports:
@feugene/granularity/styles/tokens.css,@feugene/granularity/styles/base.css,@feugene/granularity/styles/preflight.css,@feugene/granularity/styles/themes/light.css,@feugene/granularity/styles/themes/dark.css; - package-level API:
@feugene/granularity/directives,@feugene/granularity/fileValidation; - design tokens as data:
@feugene/granularity/tokens(typed registry) and the raw@feugene/granularity/tokens/*.jsonsource the CSS is generated from; - two
UnoCSSintegration scenarios, both through the granular provider:@feugene/granularity/granular-provider— browser-safe registry of components;@feugene/granularity/granular-provider/node— the node-side counterpart, which reads CSS and preflight from the file system.
Limitations
RTL is not supported. Components lay themselves out with physical directions (pl-/pr-,
ml-/mr-, left-/right-), and dir="rtl" is not read anywhere: a right-to-left document will
render mirrored padding, offsets and floating panels. This is a deliberate decision for the 1.x
line — moving to logical properties changes how every component looks, which is a visual breaking
change and belongs in a major release, not a patch. See docs/styling.md.
Quick start
yarn add @feugene/granularity vue @floating-ui/dom@floating-ui/dom is a required peer dependency, not a bundled one: positioning (GrDropdown,
GrSelect, GrAutocomplete, GrTreeSelect, GrTooltip) is built on it, and keeping it external
means an application that already uses floating-ui ends up with a single copy.
The overlay components (GrModal, GrDrawer, GrDialog, GrImageViewer) need nothing else —
their focus trap, layer stack and scroll lock are the package's own primitives. @headlessui/vue
was dropped in 0.15.0 and is not a peer dependency; if it is still installed for this package alone,
it can be removed.
If the application uses UnoCSS:
yarn add -D unocssimport '@feugene/granularity/styles.css'That's enough to get a working base: the file carries the tokens, the base layer, the preflight and the
built-in light/dark themes. What it does not carry is the utility classes the components are built
from — those are generated by the UnoCSS preset for the components you actually select. Without the preset
a component renders with its own CSS but without layout utilities.
For a finer setup take the layers apart — @feugene/granularity/styles/tokens.css,
styles/base.css, styles/preflight.css, styles/themes/<name>.css — or assemble everything with the
preset. There is no per-component stylesheet to import: a component that has CSS of its own imports it
from its own chunk, so a granular import already brings everything it needs.
Granular imports, in numbers
| What you import | gzip | of the barrel |
| --- | ---: | ---: |
| the whole package from the root | 673.3 kB | 100 % |
| the lightest component — GrButtonGroup | 1.8 kB | < 1 % |
| the median component — GrSegmented | 16.3 kB | 2 % |
| the 5 heaviest together | 250.2 kB | 37 % |
These numbers do not add up: shared code is counted again in every row but paid for once, which is why
the set is shown as a union rather than a sum. They are an upper bound — the gzip of everything a subpath
pulls out of dist, before the application bundler shakes it further and minifies it again.
The weight of every component — docs/entry-sizes.md.
The rest of the family
The core ships the general-purpose components. Anything that carries a heavy dependency, belongs to a
domain of its own, or is needed by a minority of consumers lives in a companion package with a peer
on this one — the core stays lean, and you install only what you reach for.
| Package | Version | What it adds |
| --- | --- | --- |
| @feugene/granularity-charts | 0.11.0 | Charts — own SVG, zero dependencies, drawn with theme tokens. |
| @feugene/granularity-chrono | 0.10.0 | Calendar, date and time components — no third-party date widget, no date library. |
| @feugene/granularity-code | 0.2.0 | Code surfaces: view, edit and diff — the viewer and the diff carry no dependencies at all. |
| @feugene/granularity-dashboard | 0.6.0 | Widget grid — drag, resize, breakpoints and layout persistence, zero dependencies. |
| @feugene/granularity-datasource | 0.1.2 | List state: sorting, filters, paging, URL sync and race-free fetching behind one composable. |
| @feugene/granularity-devtools | 0.3.2 | Vue DevTools panel — where a prop value came from, the overlay layer stack and design-system warnings. |
| @feugene/granularity-editor | 0.4.1 | Rich-text editing: a TipTap-backed GrRichText field with a design-system toolbar. |
| @feugene/granularity-forms-schema | 0.4.0 | Schema-driven forms — zod and JSON Schema into real form fields, zero dependencies. |
| @feugene/granularity-media | 0.7.1 | Media components: image cropping, camera capture, code scanning and video playback. |
| @feugene/granularity-test-kit | 0.10.0 | Test gates for @feugene/granularity design-system packages — token, registry and defaults contracts as reusable factories. |
| @feugene/unplugin-granularity | 0.7.1 | unplugin-vue-components resolver — granular auto-import for components and directives. |
Documentation
docs/README.md— overview and documentation mapdocs/installation.md— installation, public entrypoints, and adoption strategiesdocs/styling.md— style layers, themes, and import orderdocs/tokens.md— design token reference (generated fromtokens/*.json)docs/entry-sizes.md— the weight of every component as a subpath (generated from the build)docs/theming.md— building a custom theme (roles, contrast rules, wiring)docs/keyboard.md— keyboard contract per componentdocs/overlays.md— overlay contract: portal, layer stack, Esc,inert, focusdocs/z-index.md— layering scaledocs/ssr.md— server-side rendering contractdocs/unocss.md—UnoCSSintegrationdocs/localization.md— how the package plugs into application localizationdocs/directives.md— package-level directivesdocs/file-validation.md— file validation APIdocs/components.md— catalog of published componentsdocs/ADDING_COMPONENTS.md— internal guide for adding a new component
