Introduction
What Granularity is, and the one decision that shapes everything else about it.
Granularity is a design system for Vue 3: components, foundations and the UnoCSS preset that ties them together. The name is not decoration — it describes the one decision everything else follows from.
Selection, not subdivision
Most component libraries offer granularity by splitting into sub-packages: a core,
then forms, then navigation. This one refuses to, and the reason is measurable:
most of its dependency edges cross the boundaries of its own catalogue groups —
the exact share is recomputed on every build, because it moves
with the library. GrRadio renders GrButton. GrPagination renders GrSelect.
GrDataTable renders GrCheckbox. Split along those groups and you get packages
that depend on each other in a ring.
The catalogue groups exist for readers looking for a component. They were never meant to describe who renders whom, and they do not.
So granularity comes from the other end. You name the components you render; the build resolves their dependency graph and emits exactly that CSS. One package, one version, one changelog — and a bundle that grows by what you use.
What you pay, concretely
- The first component carries tokens, both themes and the base layer.
- Every component after it costs roughly a kilobyte of CSS.
- Nothing is pulled in at run time: the core has zero runtime dependencies.
Numbers behind those three lines, measured on a real build, are on the home page — and they are the numbers, not a rounding of them.
npm i @feugene/granularitypnpm add @feugene/granularityyarn add @feugene/granularitybun add @feugene/granularitySelecting components
import granularityProvider from '@feugene/granularity/granular-provider/node'
import { granularContent, presetGranularNode } from '@feugene/unocss-preset-granular/node'
// Both calls take the same options object. Let them drift and components
// arrive without styles.
const options = {
providers: [granularityProvider],
components: [{ provider: '@feugene/granularity', names: ['GrButton', 'GrCard'] }],
themes: { names: ['light', 'dark'] },
}Where to go next
If you want it running, getting started is the shortest useful page on this site. If you want to know why the exports are shaped the way they are before you commit, read architecture first.