Extract Keypoints into a registry block - #568
Closed
abernier wants to merge 2 commits into
Closed
Conversation
`src/lib/cn.ts` and `src/lib/utils.ts` were byte-equivalent implementations of the same helper, differing only in export style. `components.json` points its `utils` alias at the latter, so anything installed by `shadcn add` imports the named export while everything hand-written imported the default one. Keep the aliased file, drop the other. Prerequisite for extracting a block: a distributed component has to import through the alias the CLI rewrites.
abernier
marked this pull request as ready for review
August 16, 2026 11:06
This was referenced Aug 16, 2026
abernier
force-pushed
the
keypoints-block
branch
from
August 16, 2026 13:20
7e872b2 to
2f51ef1
Compare
First Tier 2 block of the pmndrs UI distribution, and the first thing to resolve a dependency across registries: `bg-surface-dim` has no shadcn equivalent, so the item declares `pmndrs/design-system/md3#v0.3.0` and the install pulls Tier 1 with it. That path is what the whole architecture rests on, and nothing else exercises it. The component moves to `registry/keypoints/`, at the root where shadcn looks for registry items, and this app imports it back through a `@/registry/*` alias — so what ships is the file the site renders, not a copy of it. Three changes were needed to make it standalone: - it pulled `ul` and `li` from this app's MDX component map. Both are trivial wrappers and no second block needs them yet, so they are inlined; the rule is to promote them to their own item at n=2. - `className` now merges after the defaults rather than before, so a consumer can override them, and `title` is optional in the type as it already was in practice. - `border-outline-variant` becomes `border-border`. The two are 1:1, and the stock token is the one a consumer who skipped Tier 1 still has. `bg-surface-dim` stays: it is the deliberate reach, and the reason for the dependency. `registry.json` is validated by `pnpm check-registry`. That validator never parses TSX, so it cannot see a missing token — an install into a scratch app outside this repo remains the only check that would.
abernier
force-pushed
the
keypoints-block
branch
from
August 16, 2026 13:54
2f51ef1 to
5a6a4c9
Compare
Member
Author
|
Collapsed into #570, which now targets |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR 3 of pmndrs/design-system#1. Stacked on #567 — review that one first.
Keypointsbecomes the first Tier 2 block of the pmndrs UI distribution:It is also the first thing anywhere to resolve a dependency across registries.
bg-surface-dimis an MD3 surface role shadcn has no equivalent for, so the item declarespmndrs/design-system/md3#v0.3.0and oneaddpulls Tier 1 down with it. That path is what the RFC's whole architecture rests on, and nothing else exercises it — which is most of why this component went first, rather than the nav.Nothing changes for authors. The same
<Keypoints>/<KeypointsItem>in the same MDX, rendering the same; only the source moved, fromsrc/components/mdx/Keypoints/toregistry/keypoints/, withregistry.jsonat the root next to it. The app imports it back through a new@/registry/*alias, so what ships to a consumer is the file this site renders rather than a copy that can drift from it.What being distributable cost
Three things in the component only worked because it lived inside this app.
import { ul as Ul, li as Li } from '../index'— which a consumer does not have. Both are trivial wrappers, and no second block needs them yet, so they are inlined. Per the plan's promotion rule that is the n=1 answer; the second block that wants them promotes them to their own registry item.cnthrough a pathcomponents.jsondoes not alias.src/lib/cn.tsandsrc/lib/utils.tswere byte-equivalent, differing only in export style, and theutilsalias — the one the CLI rewrites on install — pointed at the latter. First commit standardizes all 25 importers on it and deletes the duplicate.border-outline-variant, which isborder-borderby another name once the MD3 remap is in place. It now uses the stock token, so a consumer who installed the block but skipped Tier 1 still gets a border.bg-surface-dimstays — that one is the deliberate reach, and the reason for the dependency.Two smaller corrections while the API was becoming public:
classNamenow merges after the defaults rather than before, so a consumer can actually override them, andtitleis optional in the type as it already was in practice.Verified
The plan calls the scratch-app install a required step rather than a nicety, because nothing in-repo can catch a missing token:
registry validatenever parses TSX, Tailwind emits no rule and no error for an unknown utility, and a story runs inside this repo where every token exists by construction.So: a bare
create-next-appoutside any pmndrs repo,shadcn init --preset b5cR4Y50S, thenshadcn add pmndrs/docs/keypoints#keypoints-block. It resolved the block, followed the dependency topmndrs/design-system/md3#v0.3.0, installedmaterial-theme-builderand the seed, and rendered a correctly-themed panel with nothing mounted — v0.3.0 bakes the palette into the CSS. Every utility the block uses emits a rule in the built CSS — checked individually,bg-surface-dimincluded, which resolves tovar(--md-sys-color-surface-dim).The pin was
v0.2.0at first, and that run only rendered because<Mtb>was mounted by hand: v0.2.0 is the shared layer without its bake, so installed on its own the panel has no background at all, and since the remap points the stock variables at MD3 roles,--backgroundand--primarygo with it. Silently, as ever. Re-verified atv0.3.0, which is where the pin belongs — it was sitting one commit up the stack, which would have released a colourless block if this merged alone.Also:
pnpm check-registry(new script,shadcn registry validate),tsc,eslint,prettier --check,vitest(95 passing), and a Storybook build with the story in its new home.Chromatic will show the two Keypoints stories as removed and re-added rather than changed — the story ID follows the file path, and the file moved. The renders themselves should be identical apart from the border token, which is 1:1.
Follow-ups, unchanged
The plan's CI check for missing tokens — extract the
--color-*names a block's utilities resolve to, diff against stock shadcn ∪ what itsregistryDependenciesemit — is still worth doing once there are several blocks. Nothing native does it. Not folded in here.Separately, noticed in passing and left alone:
src/stories/Page.tsxhas two pre-existingreact/no-unescaped-entitieserrors, andvitest.config.ts'sexclude: ['node_modules']is not a glob, so a barevitestwalks intonode_modulesand tries to run its packages' tests.🤖 Generated with Claude Code
https://claude.ai/code/session_01EDvnsrory1aJsoNALn5aLB