Spectre UI
`@phcdevworks/spectre-ui` is the styling contract package of the Spectre system. It translates Spectre design tokens into CSS bundles, Tailwind theme configuration, and class recipe functions for downstream adapters and apps.
This page is generated from the source repository’s README and ROADMAP on every build. Edit the source repository, not this file.
README
@phcdevworks/spectre-ui
@phcdevworks/spectre-ui is the styling contract package of the Spectre
system. It translates Spectre design tokens into CSS bundles, Tailwind theme
configuration, and class recipe functions for downstream adapters and apps.
Maintained by PHCDevworks. It sits between
@phcdevworks/spectre-tokens and the framework-specific adapter and
component packages, so no downstream repo needs to hand-roll CSS, Tailwind
config, or hardcode design values to consume Spectre’s visual language.
Repository Snapshot
| Field | Value |
|---|---|
| Project team | project-design |
| Repository role | Spectre L2 CSS, Tailwind, and recipe contract |
| Package/artifact | @phcdevworks/spectre-ui |
| Current version/status | 2.8.0 |
Standard Workflow
- Read AGENTS.md, then the agent-specific guide for the task.
- Check TODO.md and ROADMAP.md for current scope.
- Make the smallest repo-local change that satisfies the task.
- Run
npm run checkwhen validation is required or practical. - Update docs and CHANGELOG.md only when behavior, public contracts, or release-relevant metadata changed.
Documentation Map
| Guide | Path |
|---|---|
| Agent rules | AGENTS.md |
| Claude Code | CLAUDE.md |
| Codex | CODEX.md |
| Copilot | COPILOT.md |
| Jules | JULES.md |
| Roadmap | ROADMAP.md |
| Todo | TODO.md |
| Changelog | CHANGELOG.md |
| Security | SECURITY.md |
@phcdevworks/spectre-ui is Layer 2 of the Spectre design suite. It turns
@phcdevworks/spectre-tokens
into reusable CSS bundles, Tailwind tooling, and type-safe class recipes for
downstream adapters and apps.
For: adapter authors and app developers who need a stable, token-driven styling contract without re-implementing class logic themselves.
Not for: authoring design tokens (that belongs in
@phcdevworks/spectre-tokens) or building framework-specific components (that
belongs in adapter packages such as @phcdevworks/spectre-ui-astro).
Contributing | Code of Conduct | Changelog | Roadmap | Security Policy
Source of truth
@phcdevworks/spectre-tokens is the source of truth for visual values and
semantic meaning. ui-contract.manifest.json is the machine-readable contract
authority for this package’s public styling surface.
| Layer | Path | Rule |
|---|---|---|
| Token authority | Published @phcdevworks/spectre-tokens package |
Design values and semantic meaning start there |
| UI contract authority | ui-contract.manifest.json |
Governs public recipes, CSS entry points, and Tailwind exports |
| Source CSS | src/styles/ |
Token-backed CSS classes and bundle entry points |
| Source recipes | src/recipes/ |
Framework-agnostic class string APIs |
| Tailwind helpers | src/tailwind/ |
Tailwind theme and preset integration |
| Generated dist | dist/ |
Never edit directly — regenerated by npm run build |
After any contract-facing source change: run npm run check to validate the
full UI contract.
Architecture
| Layer | Package or consumer | Responsibility | Relationship to this package |
|---|---|---|---|
| 1 | @phcdevworks/spectre-tokens |
Defines design values and semantic token meaning | Upstream source of truth |
| 2 | @phcdevworks/spectre-ui |
Translates tokens into CSS bundles, Tailwind helpers, and class recipes | This package |
| 3 | Adapters and apps, such as @phcdevworks/spectre-ui-astro |
Deliver Spectre through framework-native ergonomics | Downstream consumers |
@phcdevworks/spectre-components is a separate component package that can wrap
this styling contract in Lit web components. This package owns Layer 2 only: it
does not deliver components and it does not define tokens.
Key capabilities
- Ships precompiled CSS:
index.css,base.css,components.css, andutilities.css - Provides Tailwind theme and preset helpers built from Spectre tokens
- Exports type-safe class recipes for shared UI patterns
- Keeps CSS classes and recipe APIs aligned
- Gives adapters and apps a stable styling contract instead of re-implementing classes
- Enforces a zero-hex approach so visual values stay tied to
@phcdevworks/spectre-tokens
What this package owns
- Token-backed CSS class contracts in
src/styles/ - Precompiled CSS bundles for root, base, components, and utilities
- Framework-agnostic class recipe functions in
src/recipes/ - Tailwind preset and theme helpers in
src/tailwind/ - Contract validation that keeps CSS, recipes, exports, and docs aligned
This package is the correct place to define reusable styling structure on top of Spectre tokens.
What this package does not own
- Design token values or semantic visual meaning. Those belong in
@phcdevworks/spectre-tokens. - Framework components, templates, hooks, or runtime behavior. Those belong in adapter packages.
- App-level layout, routing, data fetching, or product-specific composition.
- Local redefinition of token meaning. Downstream consumers should consume the token contract rather than recreate it.
Installation
npm install @phcdevworks/spectre-ui
Quick start
Vanilla HTML — CSS classes only
No framework needed. Import the CSS and use the sp-* classes directly:
<!doctype html>
<html>
<head>
<link
rel="stylesheet"
href="node_modules/@phcdevworks/spectre-ui/dist/index.css"
/>
</head>
<body>
<button class="sp-btn sp-btn--primary sp-btn--md">Save</button>
<button class="sp-btn sp-btn--ghost sp-btn--md">Cancel</button>
<span class="sp-badge sp-badge--success sp-badge--sm">Published</span>
<div class="sp-card sp-card--elevated">
<p>Card content</p>
</div>
<div class="sp-input-wrapper">
<label class="sp-label">Email</label>
<input class="sp-input sp-input--md" type="email" />
</div>
</body>
</html>
CSS import (bundler or framework)
Import the full stylesheet:
import '@phcdevworks/spectre-ui/index.css'
Or import the bundles separately:
import '@phcdevworks/spectre-ui/base.css'
import '@phcdevworks/spectre-ui/components.css'
import '@phcdevworks/spectre-ui/utilities.css'
Tailwind preset usage
Use Spectre tokens as the source of truth for your Tailwind theme:
// tailwind.config.ts
import type { Config } from 'tailwindcss'
import { createSpectreTailwindPreset } from '@phcdevworks/spectre-ui/tailwind'
import tokens from '@phcdevworks/spectre-tokens'
const config: Config = {
content: ['./src/**/*.{ts,tsx,js,jsx,html}'],
presets: [createSpectreTailwindPreset({ tokens })]
}
export default config
Class recipe usage
Class recipes are the stable styling API for adapters and apps. They return predictable class strings and keep behavior consistent across frameworks.
import {
getBadgeClasses,
getButtonClasses,
getPricingCardClasses
} from '@phcdevworks/spectre-ui'
const cta = getButtonClasses({ variant: 'primary', size: 'lg' })
const badge = getBadgeClasses({ variant: 'success', size: 'sm' })
const pricingCard = getPricingCardClasses({ featured: true })
When to use this package
Use @phcdevworks/spectre-ui when you need:
- precompiled, token-backed CSS ready to drop into any framework
- a Tailwind preset or theme helper built from Spectre tokens
- stable, type-safe class recipes for shared UI patterns (buttons, badges, cards, inputs, etc.) that you want to remain consistent across frameworks
- a styling contract that is enforced through tests and CI rather than conventions alone
When not to use this package
Do not use @phcdevworks/spectre-ui when you need to:
- Define new design values — add them to
@phcdevworks/spectre-tokensinstead. - Deliver framework components — use an adapter package such as
@phcdevworks/spectre-ui-astrothat wraps this package in framework-native components. - Use raw Tailwind utilities without a shared recipe contract — import Tailwind directly and use the Spectre preset; you do not need this package’s recipe layer if you are building one-off UI with utility classes.
What belongs here vs elsewhere
| What | Where it lives |
|---|---|
| Semantic color values, spacing scale, type scale | @phcdevworks/spectre-tokens |
| Token-to-CSS variable mapping | here — src/styles/ |
| Precompiled CSS bundles | here — built to dist/*.css |
| Class recipe functions (input → class string) | here — src/recipes/ |
| Tailwind preset and theme helpers | here — src/tailwind/ |
| Astro, React, Vue, Lit, Svelte components | Adapter packages (e.g. spectre-ui-astro) |
| WordPress shortcodes or PHP templates | A WordPress adapter package |
| App-level layout, routing, or data fetching | Consuming apps |
| New design decisions (new colors, new spacing) | @phcdevworks/spectre-tokens |
Golden rule: this package consumes tokens and exposes class contracts. It does not define tokens and it does not deliver framework components.
Package exports / API surface
Recipe quick reference
All recipe functions accept a plain options object and return a class string. All options are optional and fall back to sensible defaults.
| Recipe | Function | Variants | Sizes | Common boolean flags |
|---|---|---|---|---|
| Button | getButtonClasses |
primary secondary ghost danger success cta accent |
sm md lg |
disabled loading fullWidth pill iconOnly |
| Badge | getBadgeClasses |
primary secondary success warning danger neutral info ghost accent cta |
sm md lg |
interactive disabled loading fullWidth |
| Card | getCardClasses |
elevated flat outline ghost |
— | interactive padded fullHeight disabled loading |
| Input | getInputClasses |
— | sm md lg |
disabled loading fullWidth pill |
| Input state | getInputClasses |
state: default error success disabled loading |
— | — |
| IconBox | getIconBoxClasses |
primary secondary success warning danger info neutral ghost accent cta |
sm md lg |
interactive disabled loading pill fullWidth |
| PricingCard | getPricingCardClasses |
— | — | featured interactive disabled loading fullHeight |
| Rating | getRatingClasses |
— | sm md lg |
interactive disabled loading pill fullWidth |
| Testimonial | getTestimonialClasses |
elevated flat outline ghost |
— | interactive disabled loading fullHeight |
| Alert | getAlertClasses |
info success warning danger neutral |
sm md lg |
dismissed |
| Avatar | getAvatarClasses |
— | sm md lg xl |
shape: circle square |
| Tag | getTagClasses |
default primary secondary success warning danger info neutral accent cta outline ghost |
sm md lg |
dismissible selected disabled loading interactive fullWidth |
| Spinner | getSpinnerClasses |
— | sm md lg |
— |
| Nav | getNavClasses |
— | — | bordered sticky fullWidth |
| Toast | getToastClasses |
info success warning danger |
— | dismissed fullWidth |
| Tooltip | getTooltipClasses |
placement: top bottom left right |
— | visible |
| Dropdown | getDropdownClasses |
menu placement: bottom-start bottom-end top-start top-end |
— | fullWidth, item: active disabled |
| Modal | getModalClasses |
— | — | open fullWidth |
| Container | getContainerClasses |
maxWidth: prose |
— | — |
| Stack | getStackClasses |
direction: vertical horizontal, basis: sidebar, align: center stretch |
— | — |
| Section | getSectionClasses |
— | — | — |
| Grid | getGridClasses |
columns: 1 2 3 4 6 12 |
gap: sm md lg |
— |
| Sidebar | getSidebarClasses |
— | — | bordered |
| Footer | getFooterClasses |
— | — | bordered fullWidth |
| Checkbox | getCheckboxClasses |
— | — | checked disabled |
| Radio | getRadioClasses |
— | — | checked disabled |
| Select | getSelectClasses |
size: sm md lg, state: default invalid success |
— | fullWidth pill disabled focused loading |
| Textarea | getTextareaClasses |
size: sm md lg, state: default invalid success |
— | fullWidth pill disabled focused loading |
| Fieldset | getFieldsetClasses |
— | — | disabled |
| Label | getLabelClasses |
— | — | disabled required |
Each recipe family also exports sub-element helpers for its structural parts (labels, wrappers, sub-containers, text elements). See the full list below.
Semantic utility classes (no recipe wrapper)
These primitives are intentionally plain CSS classes in
src/styles/utilities.css with no recipe function — there is no variant or
size axis to validate, so a recipe wrapper would add indirection without a
type-safety benefit. Apply the class name directly.
| Class | Tokens | Usage |
|---|---|---|
.sp-link |
--sp-link-default --sp-link-hover --sp-link-active --sp-link-visited |
Inline text links (<a>). |
.sp-surface--hover |
--sp-surface-hover |
Clickable list items, menu items, table rows on hover. |
.sp-surface--selected |
--sp-surface-selected |
Selected list items, menu items, table rows. |
.sp-surface--active |
--sp-surface-active |
Pressed/active state for clickable surfaces. |
.sp-divider |
--sp-surface-divider |
<hr>, section separators, table borders. |
Root package
The root package exports CSS path constants plus the recipe functions
re-exported from src/recipes/index.ts.
Root constants:
spectreStylesspectreBaseStylesPathspectreComponentsStylesPathspectreIndexStylesPathspectreUtilitiesStylesPath
Root recipe functions:
getAlertClassesgetAvatarClassesgetBadgeClassesgetButtonClassesgetCardClassesgetCheckboxClassesgetContainerClassesgetDropdownClassesgetFieldsetClassesgetFooterClassesgetGridClassesgetIconBoxClassesgetInputClassesgetLabelClassesgetModalClassesgetNavClassesgetPricingCardClassesgetRadioClassesgetRatingClassesgetSectionClassesgetSelectClassesgetSidebarClassesgetSpinnerClassesgetStackClassesgetTagClassesgetTestimonialClassesgetTextareaClassesgetToastClassesgetTooltipClasses
Root recipe helper functions:
getDropdownItemClassesgetDropdownMenuClassesgetFieldsetLegendClassesgetInputErrorMessageClassesgetInputHelperTextClassesgetInputLabelClassesgetInputWrapperClassesgetModalOverlayClassesgetNavLinkClassesgetNavLinksClassesgetPricingCardBadgeClassesgetPricingCardDescriptionClassesgetPricingCardPriceClassesgetPricingCardPriceContainerClassesgetRatingStarClassesgetRatingStarsClassesgetRatingTextClassesgetSidebarBackdropClassesgetSidebarGroupClassesgetSidebarGroupSummaryClassesgetSidebarHeaderClassesgetSidebarLinkClassesgetSidebarToggleClassesgetTestimonialAuthorClassesgetTestimonialAuthorInfoClassesgetTestimonialAuthorNameClassesgetTestimonialAuthorTitleClassesgetTestimonialQuoteClassesgetToastIconClasses
The root package also re-exports the related recipe option, variant, size, and state TypeScript types defined by those recipes.
Tailwind entry point
@phcdevworks/spectre-ui/tailwind exports:
createSpectreTailwindPresetcreateSpectreTailwindTheme
CSS entry points
@phcdevworks/spectre-ui/index.css@phcdevworks/spectre-ui/base.css@phcdevworks/spectre-ui/components.css@phcdevworks/spectre-ui/utilities.css
Public contract guarantees
ui-contract.manifest.json defines the public styling contract for this
package.
It covers:
- CSS entry points
- root package constants and recipe function exports
- Tailwind subpath exports
- recipe families, variants, sizes, and public states
Every contract-facing surface must match that manifest. Validation fails when README documentation omits manifest-declared exports, when export snapshots drift, when Tailwind artifacts drift, or when CSS contract coverage no longer matches the declared surface.
Sidebar interactive-state contract
getSidebarClasses is the first recipe family with an interactive-state CSS
contract. Below breakpoints.md (768px), .sp-sidebar renders off-canvas
(transform: translateX(-100%)). This package owns only the CSS reaction to
that state — it does not own toggle behavior, click handlers, or open/closed
state management.
Consumers (typically a framework adapter) toggle the sidebar by setting a
data-sidebar-open="true" attribute on an ancestor element wrapping
.sp-sidebar and .sp-sidebar-backdrop (from getSidebarBackdropClasses):
[data-sidebar-open="true"] .sp-sidebarslides the sidebar into view (transform: translateX(0)).[data-sidebar-open="true"] .sp-sidebar-backdropshows the backdrop overlay (display: block).- Above
breakpoints.md, the sidebar docks inline and the backdrop is always hidden, regardless of thedata-sidebar-openvalue.
A consumer-rendered toggle button that opens/closes the sidebar must carry
getSidebarToggleClasses(). .sp-sidebar-toggle stacks above
.sp-sidebar-backdrop (--sp-component-sidebar-toggle-z-index, above
--sp-component-sidebar-backdrop-z-index) so the backdrop never intercepts
clicks meant for the toggle once the sidebar is open. The class also supplies
the token-backed button layout, color, hover, and focus-visible treatment;
adapters only supply the control markup and behavior.
Adapters own the hamburger/toggle control, click handling, and SSR-safe initial closed state.
Above breakpoints.md, .sp-sidebar stretches to height: 100% so a short
link list matches the height of a taller sibling content column when docked
inline in a Stack row (see align: 'stretch' on getStackClasses).
getSidebarLinkClasses accepts a level option ('parent' | 'child',
default 'parent') for nested link indentation — e.g. a package name with
“Overview” / “Reference” links beneath it. getSidebarHeaderClasses styles a
section label (e.g. “Tokens”, “UI”, “Guides”) as a muted eyebrow, visually
distinct from .sp-sidebar__link.
For collapsible navigation sections, apply getSidebarGroupClasses() to a
native details element and getSidebarGroupSummaryClasses() to its summary.
The CSS removes the browser marker, styles the summary as an interactive
section label, and rotates a consumer-provided .sp-sidebar__group-icon when
the group is open. Wrap the nested links in .sp-sidebar__group-content for
the standard bottom spacing. Open/closed behavior remains native to details;
this package returns class strings and does not render markup.
Downstream boundaries
Downstream packages should never redefine locally:
- Spectre design token meaning
- CSS class semantics already provided by this package
- recipe option names, variants, sizes, or states
- package CSS entry point behavior
- Tailwind helper export names
Downstream packages may:
- compose application UI with the exported classes
- wrap recipe functions in framework-specific adapters
- import CSS entry points directly in applications or adapter packages
- extend app-specific layout around Spectre contracts
Upgrade expectations for consumers
Consumers should treat this package as a SemVer-governed styling contract.
Practical guidance:
- additive recipes, variants, states, and helpers are intended to be safe for existing consumers
- semantic shifts may keep the same class or option name but still affect visual output
- renames, removals, and behavior changes to existing classes or options are breaking
- generated JS, TypeScript declarations, CSS bundles, Tailwind exports, README
docs, and
ui-contract.manifest.jsonare expected to stay aligned
If a downstream package depends on a class, recipe option, CSS entry point, or Tailwind helper:
- read
CHANGELOG.mdfor contract change classification - prefer documented public exports over internal paths
- run consuming app validation after package upgrades
Change classification
Contract-affecting changes should be classified in CHANGELOG.md [Unreleased]
before release.
| Classification | When to use | Examples |
|---|---|---|
additive |
New public styling surface that does not break existing consumers | Adding a recipe helper, variant, state, or CSS entry point |
semantic change |
Public name remains but behavior or visual meaning shifts | Adjusting an existing class or recipe option to map to different token intent |
breaking |
Existing consumers may need code changes | Renaming or removing a class, option, export, or CSS entry point |
Renames and removals are always breaking regardless of perceived scope.
Relationship to the rest of Spectre
Spectre keeps responsibilities separate:
@phcdevworks/spectre-tokensdefines design values and semantic meaning@phcdevworks/spectre-uiturns those tokens into reusable CSS, Tailwind tooling, and type-safe class recipes@phcdevworks/spectre-componentsturns those styling contracts into framework-agnostic Lit web components- Adapters and apps consume
@phcdevworks/spectre-uiinstead of re-implementing its styling layer, or wrap Spectre component contracts for a specific runtime
That separation keeps recipe behavior consistent across frameworks and reduces implementation drift.
Consumer checklist
For downstream packages and compatible apps:
- import
@phcdevworks/spectre-ui/index.cssfor the full styling contract - import split CSS entry points only when the consumer needs bundle-level control
- use recipe functions when framework adapters need stable class strings
- use
@phcdevworks/spectre-ui/tailwindfor Tailwind theme integration - consume tokens from
@phcdevworks/spectre-tokensinstead of inventing visual values locally - treat
dist/as generated package output, not an authoring surface - do not add framework runtime logic to this package
Development
Local setup
git clone https://github.com/phcdevworks/spectre-ui.git
cd spectre-ui
nvm use # picks up .nvmrc (Node 22.22.2)
npm install
npm run ci:verify
This project requires Node.js ^22.13.0 || >=24.0.0 and npm >=10.0.0. The
checked-in package manager is npm@11.17.0.
Common commands
| Command | What it does |
|---|---|
npm run check |
Full validation gate — run before every PR |
npm run ci:verify |
Underlying verification sequence used by npm run check |
npm test |
Build then run the contract and regression test suite |
npm run build |
Emit TypeScript and CSS artifacts to dist/ |
npm run lint |
ESLint with TypeScript-aware config |
npm run validate:exports |
Verify root export surface against snapshot |
npm run validate:exports:update |
Update the export snapshot after adding a public export |
npm run validate:tailwind |
Verify Tailwind exports and emitted subpath artifacts |
npm run validate:tailwind:update |
Update the Tailwind export snapshot |
npm run validate:tokens |
Check for token drift against latest published release |
Troubleshooting
validate:runtime fails — you are on the wrong Node version. Run nvm use
to switch to the version in .nvmrc, or install Node 22 or 24.
validate:tokens fails with a network error — the check requires outbound
npm registry access. In a restricted environment, run the other validators
individually; this step is the only network-dependent one in ci:verify.
Tests pass but the build shows stale output — npm test rebuilds
automatically via the pretest hook. If you ran vitest directly, run
npm run build first.
Lint fails locally but passes in CI — confirm you are on the same Node version as CI (Node 22.x or 24.x). ESLint plugin resolution can differ across runtimes.
Export snapshot out of date — run npm run validate:exports:update after
adding a public export, then commit the updated scripts/export-snapshot.json.
Key source areas
src/styles/for source CSSsrc/recipes/for class recipessrc/tailwind/for Tailwind helperstests/for contract and regression coverageexamples/for visual demos and verification fixtures
Planning artifacts for contract hardening live in ROADMAP.md and TODO.md.
All scoped roadmap phases through Phase 5 are delivered — there is no open
implementation phase right now. New recipe or CSS work opens only when a
downstream adapter surfaces a real integration gap, or when
@phcdevworks/spectre-tokens
publishes a new token group this package should consume. This package
synchronizes only against published npm releases, not in-progress upstream
work.
Examples
Use examples/examples.html as the visual index for
the package demos.
Available examples include:
vanilla.htmlfor the broad component showcaseshowroom.htmlfor a richer marketing-style compositionverification.htmland focused verification fixtures for regression checks
Validation
Run the full validation gate before any pull request:
npm run check
This runs: runtime check → lint → changelog validation → export validation → README validation → token drift check → build → Tailwind contract → CSS contract → tests. All steps must pass.
AI and automation boundaries
Claude Code (claude-sonnet-4-6) is the primary development agent for this
repository. Codex handles releases and production stabilization. Jules handles
small automated fixes and token sync passes. GitHub Copilot provides development
support.
Claude Code, Codex, and Copilot do not create git commits by default. Jules may
commit only bounded automated maintenance when the JULES.md scope and
validation gates pass. Release decisions, tags, and publishing remain with
Bradley Potts.
Protected from automated change: CSS contracts, recipe public API surface, and the zero-hex policy (no hardcoded color/spacing values). See AGENTS.md for full agent governance and boundary rules.
Contributing
PHCDevworks maintains this package as part of the Spectre suite.
When contributing:
- keep styling token-driven
- keep recipe APIs and CSS classes in sync
- avoid local visual values unless clearly intentional
- run
npm run checkbefore opening a pull request
See CONTRIBUTING.md for the full workflow.
License
MIT © PHCDevworks. See LICENSE.
Roadmap
Spectre UI Roadmap
@phcdevworks/spectre-ui is the Layer 2 styling contract in the Spectre system.
It consumes the published @phcdevworks/spectre-tokens package and turns those
token contracts into reusable CSS entry points, Tailwind helpers, and
framework-agnostic recipe APIs.
1. Phase 1 — Foundation — Delivered
All foundation work is complete. The package has a declared, validated, and documented public styling contract.
What is in place
ui-contract.manifest.jsondeclares root exports, Tailwind exports, CSS entry points, and stable recipe families.npm run checkvalidates runtime support, lint, changelog format, root exports, README parity, latest published token alignment, build output, Tailwind subpath packaging, CSS contract integrity, and tests.- CSS entry points are independently emitted, token-backed, and protected by contract tests.
- Recipe families are framework-agnostic and validated against live output.
- Built-package smoke tests exercise the emitted package instead of only source files.
- README and maintainer docs describe the public contract and validation path.
- The package consumes published
@phcdevworks/spectre-tokensas the upstream authority and does not invent design values locally.
What will not change
- Design values and semantic meaning remain in
@phcdevworks/spectre-tokens. - This package does not own framework components, templates, hooks, or runtime behavior.
- Recipe functions continue to accept plain option objects and return class strings only.
- CSS, recipes, Tailwind helpers, docs, snapshots, and the manifest must remain aligned before release.
- Missing upstream token values are blockers, not invitations to add local fallbacks.
2. Phase 2 — Mature Operations — Delivered
Phase 2 delivered release discipline, additive recipe expansion, and quality improvements without expanding package ownership beyond Layer 2.
What was delivered
- Full release gate via
npm run checkincluding changelog validation and latest-token drift checks. - Recipe expansion: Alert, Avatar, Tag, and Spinner added with token-backed CSS and full contract test coverage.
- Dark mode verification fixtures for new recipe families.
- Node 24 promoted as the primary CI target.
- Recipe composition patterns documented in
CONTRIBUTING.md. - Multi-agent governance (Claude Code, Codex, Copilot, Jules) with documented authority boundaries, PR creation requirements, and CodeRabbit integration.
3. Phase 3 — Semantic Primitive Expansion
P0: Release Baseline — Delivered
- v1.7.0 released: Tag variant expansion, token alignment to
spectre-tokens@2.7.0. - v1.8.0 released: Spinner component, button focus-ring parity, token alignment
to
spectre-tokens@2.8.0, ecosystem manifest.
P1: Token Synchronization — Delivered
- Aligned to
@phcdevworks/spectre-tokens@2.8.0. buttons.danger.focusVisibleandbuttons.success.focusVisibleconsumed.- Token gap audit complete:
link.*,surface.hover/selected/active, andsurface.dividerare now published upstream — no longer blockers.
P2: Semantic UI Primitives — Delivered
All three token groups exist in @phcdevworks/spectre-tokens@3.2.0 and were
delivered in @phcdevworks/spectre-ui@2.6.0.
Delivered:
- Link styling:
link.default,link.hover,link.active,link.visitedvia.sp-link. - Interactive surface state styling:
surface.hover,surface.selected,surface.active. - Divider styling:
surface.dividervia.sp-divider.
Per-primitive standard: token-backed CSS in the narrowest relevant entry point;
recipe or utility exposure only when the public class contract is stable;
manifest declaration, README update, focused contract tests; run
npm run check.
4. Phase 4 — Component Recipe Expansion
Objective: Add the next recipe families broadly useful to adapters, each backed by explicit upstream token intent.
Why it matters: The current recipe set covers core controls and content surfaces. The practical gap is application UI: navigation, overlays, notifications, and menus. These should enter the styling contract as small, auditable recipe families rather than large framework components.
Candidate recipe families
Linkor text-link classes after upstream link tokens publish.Dividerafter upstream divider or border tokens publish.Navafter upstreamcomponent.navtokens publish.Modalafter upstreamcomponent.modaltokens publish.Toastafter upstreamcomponent.toasttokens publish.Tooltipafter upstreamcomponent.tooltiptokens publish.Dropdownafter upstreamcomponent.dropdowntokens publish.Container,Stack,Section— layout primitives. Delivered. See TODO.md “Phase 4b — Layout Recipe Expansion”.Grid(v1) — responsive multi-column layout. Delivered. First recipe family requiring@media-based responsive behavior. Scope is fixed equal-width column counts (1/2/3/4/6/12) with a baked-in responsive step-down convention — no spans, offsets, or custom track sizing in v1. See TODO.md “Phase 4c — Grid Recipe (v1)” and “Phase 4c — Grid Recipe (v2, deferred)” for what’s intentionally cut until a real downstream need justifies it.- App shell layout (
Stack/Containeroptions,Sidebar,Footer) — real downstream need confirmed indocs-phcdevworks-com.SpNavalready covers the top bar as a token-backed primitive; sidebar and footer/bottom-bar have no equivalent today, the same gap that previously existed for Container/Stack/Section. Sidebar and Footer are a new tier above plain recipes — layout patterns with their own width/collapse/positioning behavior, modeled onSpNav, not single-class wrappers. See TODO.md “Phase 4d — App Shell Layout: Stack/Container Options, Sidebar, Footer” for the scoped breakdown. Token audit confirmed a real gap, now resolved upstream: unlike every recipe added since Phase 4b (Container/Stack/ Section/Grid all consumed tokens that already existed), there was no width/sizing scale inspectre-tokensat all. The token gap was resolved, and this work shipped byspectre-ui@2.5.0: Stackbasis, ContainermaxWidth, Sidebar, and Footer recipes are delivered. Sidebar’s mobile behavior is a slide-out drawer belowbreakpoints.md, with this package owning the off-canvas CSS contract (position, transition, backdrop, data-attribute selector) and the adapter (spectre-ui-astro) owning toggle interaction.
Standard deliverables per family
- One recipe file in
src/recipes/. - Token-backed selectors in
src/styles/components.cssor the narrowest appropriate CSS surface. - Root export and recipe barrel export when public.
- Manifest declaration.
- README recipe table update.
- Focused contract, recipe, and CSS tests.
- Example fixture only when it helps visual verification.
Dependency notes: Follows Phase 3 token availability. Each recipe lands as its own scoped change unless the manifest requires a paired primitive.
Risk if skipped: Adapter packages will implement these patterns independently, which weakens cross-framework consistency.
5. Phase 5 — Integration Feedback and Deprecation Readiness
P0: Downstream Integration Feedback
Objective: Use real adapter and token integration feedback to decide which Layer 2 contracts should harden next.
Why it matters: The tokens roadmap validates against a real spectre-ui
integration fixture. This package should return the favor by keeping its own
roadmap tied to real adapter usage instead of hypothetical component coverage.
Deliverables:
- Track token integration findings that require CSS, recipe, Tailwind, or docs changes.
- Add regression tests when downstream adapters expose a contract ambiguity.
- Clarify README or CONTRIBUTING guidance when repeated adapter questions appear.
- Keep adapter-specific markup, lifecycle, slots, hooks, and templates out of this package.
Dependency notes: Can run continuously alongside Phase 3 and Phase 4.
P1: Contract Automation and Deprecation Readiness
Objective: Keep release and contract governance ahead of the growing public surface.
Why it matters: As the class and recipe contract grows, manual release and deprecation steps become easier to miss. The package already has strong checks; the next step is to keep those checks aligned with a larger, more mature public surface.
Deliverables:
- Keep
release:proposealigned with changelog classification conventions. - Add deprecation guidance for UI recipes, variants, states, and CSS classes before the first public removal is needed.
- Decide whether UI deprecations need machine-readable manifest metadata.
- Keep README, CONTRIBUTING, agent guidance, and PR templates aligned with any deprecation process.
Dependency notes: Best implemented before the package needs to remove or rename a public class or recipe option.
Risk if skipped: Public removals become ad hoc and consumers lose a clear migration window.
6. Explicitly Out of Scope
- Do not author tokens or semantic visual meaning here.
- Do not use GitHub-only token changes as synchronization authority.
- Do not invent local link, divider, nav, modal, toast, tooltip, or dropdown values while waiting for token support.
- Do not add framework components, templates, hooks, slots, or runtime behavior.
- Do not move adapter-package delivery concerns into this package.
- Do not combine token synchronization, new recipe expansion, and unrelated documentation cleanup in one change.
- Do not hand-edit
dist/or generated snapshots.
7. Recommended Execution Order
- Phase 1 — done.
- Phase 2 — done.
- Phase 3 P0 — complete the v1.7.0 release handoff.
- Phase 3 P1 — watch for the next published token release; run a sync pass.
- Phase 3 P2 — done. Link, interactive surface states, and Divider
shipped in
spectre-ui@2.6.0. - Phase 4 — done. Nav, Toast, Tooltip, Dropdown, Modal delivered.
- Phase 4b — done. Container, Stack, Section delivered.
- Phase 4c (v1) — done. Grid recipe delivered.
- Phase 4c (v2) — deferred until a real downstream need surfaces: column span, offsets, custom track sizing, per-breakpoint override.
- Phase 4d — done. Stack
basis, ContainermaxWidth, Sidebar, and Footer layout-pattern recipes delivered. - Phase 4e — done. Checkbox, Radio, Select, Textarea, Fieldset, and
Label recipes shipped in
spectre-ui@2.6.0. - Phase 5 P0 — add downstream regression coverage as adapter usage reveals gaps (continuous).
- Phase 5 P1 — define deprecation mechanics before any public class, recipe option, or variant is retired.