Blocks
Several components already wired together — a login popup, a mini dashboard, a swap card, a widget — copied as one working screen.
A block is the rung between one component and a whole page section. A component is a button. A section is a landing-page band. A block is what sits in between: a login popup, a mini dashboard, a swap card, a settings panel, a widget — several catalog components already assembled and wired to real state.
Browse them at Blocks. The chips filter by what the piece is: Auth, Dashboard, Cards, Widgets, Commerce, Crypto, Chat, Forms, Media, Settings, Onboarding.
What you actually get
The point of a block is the part a component library never hands you: the
composition. Which pieces, in what order, at what spacing, sharing which bit of
state. BlkLoginPopup invents nothing — the fields are VsInput, the actions
are VsButton, the rule is VsSeparator, the toggle is VsCheckbox — and
what it adds is the working screen those four make together.
So the copy you get is the assembly plus every component it uses. Copy a
block and you get its file and the source of each Vs* inside it, in one
paste-ready bundle. Nothing is left as an import you have to go and find.
Blocks are Vue SFCs
Components, sections and animations ship as native custom elements —
one self-contained vs-*.js, zero dependencies. Blocks are Vue single-file
components instead, and deliberately so: a block’s whole value is that it
imports the catalog’s own pieces, and a “zero-dependency single file” would
have to inline them and stop being an assembly at all.
<script setup lang="ts">
import VsInput from './components/VsInput.vue';
import VsButton from './components/VsButton.vue';
</script>
If you are not on Vue, the block is still the best reference you can get for
the layout and the wiring — and every component it uses has a framework-neutral
vs-*.js port of its own in Components.
Every prop is a control
Same rule as the rest of the catalog: nothing is hardcoded. Titles, labels, which optional rows appear — all props with defaults, all editable from the control bar before you copy, all visible in the preview as you change them.
Blocks emit events rather than doing the work: BlkLoginPopup emits submit
with the form payload and social with the provider. Wiring it to your own
auth endpoint is one listener.
Responsive by container query
A block is judged inside a box — a catalog card, a phone frame, a column of
your app — not at the width of the window. Its breakpoints are therefore
@container queries, so it lays itself out from the space it is actually
given. Drop one into a 380px column and it behaves like it is on a phone,
whatever the browser window is doing.
Adding one
pnpm new:block --name SwapCard --category Finance --group crypto
That scaffolds src/blocks/BlkSwapCard/ with its meta.ts and a Vue file
already set up with the container query and the “import, do not invent” rule
in a comment at the top. If a piece the block needs does not exist yet, build
it as a real component first and import it — a one-off widget buried inside a
block is a component nobody else can find.