Blocks
Several components already wired together — a login popup, a mini dashboard, a swap card, a widget — copied as one working screen.
TL;DR · the pieces, already cooked together
- A block is several catalog components assembled into one working screen.
- The copy is the assembly plus every component inside it. Nothing left to hunt down.
- Blocks emit events; you wire them to your own backend in one listener.
A block is the rung between one component and a whole page section:
- Component · a button
- Block · a login popup
- Section · a landing-page band
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:
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.
submit to your code.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.