@getvitops/create 0.4.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,121 @@
1
1
  # @getvitops/create
2
2
 
3
+ ## 0.5.0
4
+
5
+ ### Minor Changes
6
+
7
+ - **The framework now says out loud which patterns are foundational, and reports it when you
8
+ reach past them.** From repeated downstream reports: sites were inventing a `.wrap` class and
9
+ using it everywhere instead of `.centered`, and `.subgrid` — the class for any set of cards —
10
+ was going essentially unused. Neither failure is visible in a build: every class involved is
11
+ real, nothing errors, and the page renders.
12
+
13
+ **`.subgrid` was missing from the generated class reference entirely.** So was `.cluster`, and
14
+ so was `.region`. `vitops docs classes` is the doc an agent is told to fetch for "which class
15
+ do I apply", and the framework's answer for a set of cards was not in it — which is most of why
16
+ it never got used. All three are now documented, along with `grid-auto`, and the reference opens
17
+ with a **Foundations** section that states the six substitutions as
18
+ _temptation → what to write instead_ rather than as a vocabulary list. The same table is now in
19
+ the shipped agent skill and in the `@getvitops/create` template's `AGENTS.md`, because a pointer
20
+ to a doc only helps someone who already suspects there is something to look up. (`css`/`bricks`
21
+ and `tailwind` alike — this is documentation and the `TIERS` manifest, not emitted CSS.)
22
+
23
+ **`vitops lint` gained three reuse rules and a markup pass.** The existing `.centered` rule only
24
+ fired when the hand-written CSS already referenced `--width-measure`, which is precisely the
25
+ author who was never going to hand-roll a container. It now also catches a page-scale
26
+ `max-width` (≥ 48rem, or a `ch` reading measure) with auto margins, and a
27
+ container-shaped class name — `wrap`, `wrapper`, `container`, `inner`, `shell`, … — carrying any
28
+ width cap at all. Reading the cap out of `min()` / `clamp()` too. New rules report a
29
+ hand-written `repeat()` grid as `.subgrid` (or `.grid-auto`), and a new **markup** pass reports a
30
+ repeated card set laid out without either — a loop that renders a card, or three or more cards
31
+ written out. That last one is the only check that can see this drift at all, since a card list
32
+ built from utility classes contains no bad class and no hand-written CSS.
33
+
34
+ All of these are `suggestion` severity, so they do not fail your build unless you pass
35
+ `--strict`. They found five real instances in this repo's own docs site.
36
+
37
+ **`vitops lint [files...]`** now takes explicit paths instead of scanning `--src`, so it can be
38
+ wired into a pre-commit hook — `vp`'s `staged` key appends the staged files to whatever it runs,
39
+ and a command that refused positionals could not be put in the one place the feedback lands at
40
+ the moment the code is written. Unreadable and non-source paths are skipped rather than fatal. The
41
+ `@getvitops/create` emdash template wires it up with `--strict` and adds a `lint:design` script.
42
+
43
+ **Two answers for "the whole card is a link", because one cannot exist.** Reported downstream:
44
+ agents dislike the `<li>` wrapper when a card is a link and write `<li><a class="card">` instead.
45
+ That shape is **wrong in a way that renders fine**, which is why it survives review — the `<li>`
46
+ is the grid item, so the anchor is an ordinary block inside it and the tranches within the anchor
47
+ never reach the parent's shared row lines. The alignment `.subgrid` exists for silently does not
48
+ happen, and the anchor does not fill the cell either. Putting the anchor in the grid's place
49
+ (`<ul><a></ul>`) is invalid HTML, so there was genuinely no correct shape to reach for.
50
+
51
+ There are now two, and they trade against each other because **no CSS-only technique can make a
52
+ whole card clickable and leave its text selectable** — a transparent overlay necessarily receives
53
+ the pointer-drag:
54
+
55
+ | Want | Use |
56
+ | ---------------------------------------- | ------------------------------------------- |
57
+ | zero JS, whole card clickable | `.stretched-link` — **text not selectable** |
58
+ | selectable text **and** a clickable card | `<Cards>` / `<wc-cards>` — needs JS |
59
+
60
+ `.stretched-link` goes on a link inside the card; its `::after` covers the card.
61
+ **`<wc-cards>` is a new tier-2 element** that adds no overlay and instead tells a click apart from
62
+ the end of a drag, so text selection survives. Its fallback is the card's own link, fully usable
63
+ with no JS, and the pointer cursor is applied by the element — so the affordance never appears
64
+ without the behaviour. `<Cards>` emits it for you. They are alternatives, never layered: with an
65
+ overlay present the JS has nothing to do, and `vitops lint` reports the combination. (All formats
66
+ — pattern partials, deliberately not `utilities.css`, which the tailwind format skips on the
67
+ invariant that everything left in it is a name Tailwind ships itself.)
68
+
69
+ ### Breaking
70
+ - **`<Subgrid />` renders its slot verbatim — author the `<li>` items yourself.**
71
+
72
+ ```diff
73
+ <Subgrid>
74
+ - <article class="card">…</article>
75
+ + <li class="card subgrid-card">…</li>
76
+ </Subgrid>
77
+ ```
78
+
79
+ It used to parse the slotted HTML and rebuild each child as an `<li>`, carrying over only
80
+ `class` and `style`. That existed solely because a `<ul>` may contain nothing else, and it cost
81
+ more than it bought: the child's tag was discarded, `id`/`data-*`/`aria-*` were silently
82
+ dropped, and `href` could not survive at all. Nothing is copied now, so nothing is lost. `as`
83
+ picks the container (`ul` by default, `ol`, `div`), and all other props are forwarded — they
84
+ were previously discarded, including `role`.
85
+
86
+ - **`<Subgrid />` and `<Tree />` now emit `role="list"`,** as does the Bricks `sitenav` element.
87
+ `list-style: none` stops Safari + VoiceOver announcing a `<ul>` as a list, so every marker-less
88
+ framework list was silently losing the semantics its `<ul>` was chosen for. If you hand-write
89
+ `.subgrid`, `.list`, `.facet-list`, `.nav-items`, `.collapse-menu` or `.tree` markup, add
90
+ `role="list"` yourself — the framework cannot add it to markup it does not render, and each
91
+ partial now says so at the `list-style` reset.
92
+ - **`<Cards />` no longer adds `class="card"` to slotted children,** because it no longer parses
93
+ them. Write the class on the item. It now emits `<wc-cards>` around a `<Subgrid>`, which is what
94
+ makes the whole card clickable — and like `<Tree />`, **it emits its own element, so do not wrap
95
+ it in `<wc-cards>` yourself.** It also previously passed a `role="list"` that `<Subgrid>` silently
96
+ discarded, so that never took effect.
97
+ - **`.subgrid-card` now sets `position: relative`**, so `stretched-link` inside it needs no extra
98
+ class. If you were absolutely positioning a descendant of a `.subgrid-card` against an ancestor
99
+ _outside_ that card, it will now resolve against the card. Move the positioning context
100
+ explicitly. (`css`/`bricks`/`tailwind` — the pattern partial is inlined into all three.) Not
101
+ reachable by `vitops lint --fix`: the fix depends on which ancestor you meant, which the
102
+ linter cannot know.
103
+
104
+ ### Fixed
105
+ - **`packages/generator/src/docs.ts` contained a literal NUL byte** (`CODE_SLOT`, written as the
106
+ raw character rather than an escape). libmagic classified the file as `data` rather than text, so
107
+ grep and ripgrep treated the largest doc emitter in the repo as **binary and silently skipped
108
+ it** — every search for a string in it returned nothing, with no error. It is now written as the `\u0000` escape.
109
+ Behaviour is identical; the file is searchable.
110
+ - **`.grid-auto` is documented.** It was a real framework class for auto-fit card grids with no
111
+ entry in the class reference, so the honest alternative to `subgrid` was as invisible as
112
+ `subgrid` itself.
113
+ - **`.raised` replaces the advice to use `.relative` above a `stretched-link` overlay**, which
114
+ could not work: a positioned element at `z-index: auto` does not rise above an explicit
115
+ `z-index` regardless of DOM order, so a second link or button in the card stayed underneath and
116
+ unclickable. `.raised` sets both, against the same `--z-tier-raised` token the overlay now uses
117
+ instead of a hard-coded `1`.
118
+
3
119
  ## 0.4.0
4
120
 
5
121
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@getvitops/create",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Project templates for the Vitops design system — scaffold wired-up sites with `vp create @getvitops`.",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -20,6 +20,49 @@ styled by the Vitops design system.
20
20
  - Prefer framework CSS classes (utilities, patterns, type roles like
21
21
  `font-heading`) over bespoke CSS. Run `npx vitops agents` to append the
22
22
  full generated class-vocabulary reference to this file.
23
+ - **Layout foundations — these are the answer, not a starting point.** Six
24
+ substitutions carry the structure of nearly every page:
25
+ | About to write… | Write instead |
26
+ | --- | --- |
27
+ | a `wrap`/`wrapper`/`container`/`inner` class | **`centered`** |
28
+ | `max-width` + `margin-inline: auto` | **`centered`** |
29
+ | `padding-block` on a section | **`region`** |
30
+ | margins between headings/paragraphs/lists | **`rhythm`** |
31
+ | `display: grid` + `grid-template-columns: repeat(n, …)` | **`subgrid`** |
32
+ | `repeat(auto-fit, minmax(…))` | **`grid-auto`** |
33
+ | `display: flex` + `gap` for a row of controls | **`cluster`** |
34
+
35
+ `centered` is a grid of _named tracks_, not a max-width box — a child widens
36
+ itself with `breakout`/`spotlight`/`fullbleed` without the parent knowing, which
37
+ is the thing a bespoke `.wrap` can never do. **More than one card means
38
+ `subgrid`**: a plain grid aligns the outer boxes but not the tranches inside
39
+ them, so headings and CTAs land at different heights across the set. Write
40
+ `<ul class="subgrid subgrid-cols-3" role="list">` with
41
+ `<li class="card subgrid-card">` items, or `<Subgrid />` (which renders the slot
42
+ verbatim — author the `<li>`s yourself; it adds `role="list"` for you, and a
43
+ hand-written one needs it because a marker-less `<ul>` stops being announced as a
44
+ list in Safari).
45
+
46
+ **When the whole card is a link the card is still the item**, and pick by whether
47
+ the card's text must stay selectable: `stretched-link` on a link inside it is
48
+ zero-JS but kills text selection, while `<Cards>` (which wraps the list in
49
+ `<wc-cards>`) keeps selection and falls back to that same link with no JS. Never
50
+ both — the overlay wins and the JS never runs. Never `<li><a class="card">`: the
51
+ `li` is the grid item, so the anchor's tranches never align and it does not fill
52
+ the cell; it renders fine, which is why it keeps getting written.
53
+
54
+ `npm run lint:design` reports all of these, and the pre-commit hook fails on them
55
+ — the fix is the class, not a justification for the CSS.
56
+
57
+ - **Prerender by default.** `output: 'server'` is required (the admin, media/API
58
+ routes, preview and scheduled publishing need a server), so prerendering is
59
+ opt-in per route: put `export const prerender = true` on every page that
60
+ doesn't need per-request data, and give dynamic routes a `getStaticPaths()`
61
+ that queries the collection at build time. A route with no `prerender` export
62
+ is re-rendered for every visitor on every request. The cost is that a
63
+ prerendered page reflects the database as of the last build, so an admin
64
+ publish needs a redeploy — leave a route server-rendered only where that is
65
+ unacceptable (preview, personalised content, must-be-live-in-seconds).
23
66
  - The Worker cron trigger in `wrangler.jsonc` drives scheduled publishing —
24
67
  don't remove it.
25
68
  - Hosting (adapter + EmDash database/storage) comes from `vitopsHosting()`
@@ -1,5 +1,5 @@
1
1
  {
2
- "$schema": "https://unpkg.com/@getvitops/generator/schema.json",
2
+ "$schema": "./node_modules/@getvitops/generator/schema.json",
3
3
  "colors": {
4
4
  "palette": {
5
5
  "brand": { "seed": "#2e9b73" },
@@ -13,6 +13,7 @@
13
13
  "init:hosting": "node scripts/init-hosting.mjs",
14
14
  "typecheck": "astro check",
15
15
  "build:css": "vitops generate -i design-system.json -f tailwind -o src/styles",
16
+ "lint:design": "vitops lint -i design-system.json -f tailwind --strict",
16
17
  "prepare": "vp config"
17
18
  },
18
19
  "dependencies": {
@@ -3,6 +3,12 @@ import { defineConfig } from 'vite-plus';
3
3
  export default defineConfig({
4
4
  staged: {
5
5
  '*': 'vp check --fix',
6
+ // Design-system drift, checked on the files being committed. `--strict` makes
7
+ // the reuse hints fail here: a hand-rolled container or a card set without
8
+ // `subgrid` is the drift this catches, and it is only ever cheap to fix at the
9
+ // moment it is written. `vitops lint` takes the staged paths as positionals.
10
+ 'src/**/*.{astro,html,ts,tsx,jsx,vue,svelte,css}':
11
+ 'vitops lint -i design-system.json -f tailwind --strict',
6
12
  },
7
13
  fmt: {
8
14
  ignorePatterns: ['dist/**', 'node_modules/**', 'src/styles/**', 'public/vitops/**'],