@vinumcms/react
v0.21.0
Published
Public block renderer, core block components, and the inline-editor primitives.
Readme
@vinumcms/react
The block renderer and the inline editor — deliberately the same code path in two
modes. View mode is what a visitor gets; edit mode is the identical component
tree with an EditApi supplied, so text becomes editable where it sits.
<PageRenderer blocks={page.blocks} registry={getBlocks()} forms={forms} entries={entries} />What's here: PageRenderer · the thirteen core blocks · defineBlock and the
isomorphic block registry · EditContext, Editable, BlockShell · the inline
formatter (**bold** *italic* ~highlight~ [link](/path)) · form-control
primitives for settings panels · the --vinum-* theme contract.
Isomorphic; never imports @vinumcms/server.
The theme contract is nineteen --vinum-* CSS variables, set once on
:root. VINUM_TOKENS exports the names and VINUM_DEFAULT_THEME a complete
starting block — both listed in full under Theming in @vinumcms/admin.
Variants are the one styling choice an author gets. A block declares which
axes it accepts; today there is one, tone, with four values:
defineBlock({ type: "pricing", variants: ["tone"], /* … */ });| tone | renders on |
|---|---|
| default | --vinum-bg / --vinum-fg |
| muted | --vinum-bg-raised / --vinum-fg |
| accent | --vinum-accent / --vinum-on-accent |
| invert | --vinum-bg-invert / --vinum-fg-invert |
--vinum-accent-invert is the accent to use on the inverted surface. It is the
one colour a tone cannot work out for itself: an accent is chosen to contrast
with the page, and on the opposite surface it often does not — deriving one
would be the CMS picking a brand colour. It defaults to --vinum-accent-soft's
value, which is already the softer variant intended for the other end of the
theme. Set it if your accent is tuned to your page background:
:root {
--vinum-accent: #e35468; /* reads on your dark page */
--vinum-accent-invert: #a3283c; /* reads on the light band */
}A tone rebinds --vinum-fg, --vinum-fg-dim, --vinum-accent and the border
tokens inside its own scope, so a block that writes color: var(--vinum-fg) — which is what the
theming docs ask for — gets the right colour for the surface it is sitting on
rather than the page's. Setting only color would leave such a block unreadable
on an inverted band.
It exists to band a long page into sections without a developer forking a block to change one background. Every value resolves to variables you already set, so an author cannot reach a combination your theme has not styled, and background and foreground always move together — never one without the other.
The editor picks it from the block's settings panel. In the DOM it is
data-vinum-tone="invert", so your own CSS overrides the defaults without a
specificity fight:
[data-vinum-tone="accent"] { background: var(--vinum-accent-soft); }A block with no variant renders exactly the markup it always did — no wrapper,
no attribute. Of the core blocks, only the five section ones (stats, faq,
columns, imageGrid, collection) declare tone: a flow block sits inside a
shared content column, so a tone there tints the column instead of banding the
page. Values outside the vocabulary, and axes a block never declared, are
dropped on save.
Inline marks nest. **[the setup guide](/setup)** is a bold link and
[a **bold** label](/x) is a link containing bold. The exception is a mark
inside the same mark — **bold *italic*** — which needs parsing this
deliberately does not have and renders as visible asterisks. A URL is never
parsed for marks, so a * in a query string cannot rewrite the destination.
FormRenderer renders a form built in the admin: widths become a
six-column grid that collapses to full on narrow screens, sections and dividers
render as structure, conditional fields appear and disappear as the visitor
answers, and a page break turns the form into steps with Next/Back. Layout,
visibility and paging all come from @vinumcms/core, so the admin canvas and the
public page agree by construction.
Custom blocks register through the same defineBlock({ type, label, group,
create, sanitize, Render }) API the thirteen core blocks use, and are passed to
defineVinum({ blocks }). If a core block ever needs something that API cannot
express, the API is wrong — there is no private access.
