Repository navigation
Releases: phcdevworks/spectre-base
Release list
Core block recipes and validation updates
Contract change type: additive
Added
- Core quote and pull-quote blocks follow the
spectre-uisp-quoterecipe
on the front end and in the editor, with two registered block styles:
Accent rule (thick accent leading edge) and Statement (large text
under a decorative quote mark). Bold text in the citation renders as the
name; the rest renders muted as role and organization. The accent colour
comes fromtheme.jsonsettings.custom.quote.accent
(--wp--custom--quote--accent), so a child theme re-points it without
redeclaring a--sp-*property. - Core table blocks follow the
sp-tablerecipe, including the header row,
caption, footer row, and the Stripes style. Computed styles match an
sp-tablewith the same data. - README.md "Core Block Styles" and a Child Themes table pointing at the
component options (sp-textweight/leading/variant="accent",
accent/accentOutlinebuttons,sp-steppertone,sp-quote,
sp-stat, splitsp-section-head,sp-table) that replace styling
[data-sp-text-native]or.sp-btninternals.
Fixed
- Post content inside
sp-prosenow follows thelayout.prose.flowrhythm
(wider gaps around headings, quotes, figures, and rules). The unlayered
sp-content-flow16px gap overrode it before, and core's figure and
pull-quote margins plus spectre-ui 5.5.0's.sp-prose blockquotemargin
reset would otherwise collapse quote and figure spacing. - Removed the argument-less
editor-color-paletteandeditor-font-sizes
theme supports.theme.jsonalready supplies both, and WordPress 7.1
printed aforeach()warning for them.
Changed
- ESLint ignores built JavaScript bundles copied into nested downstream child
themes. Those minified outputs are linted from source in their owning
repositories and otherwise produce false errors when validating this repo. - Updated Vite from 8.3.3 to 8.3.4.
- Raised the Node.js engine floor to
>=24.18.0to match the WordPress
Playground runtime pulled in by@wordpress/env, which otherwise emits
EBADENGINEwarnings on install. CI and the WordPress smoke test now run on
Node 24 only.
Theme shell extensibility and distribution
Contract change type: breaking
Added
- Added
spectre-theme/LICENSE.txt(full GPL-2.0-or-later text) and
spectre-theme/NOTICE.txt(MIT attribution for bundled Spectre packages)
so the deployable WordPress theme package carries its own license
independently of the MIT-licensed repository. - Added
npm run package:theme, which assembles a marketplace-ready
spectre-theme.zipfrom thespectre-theme/directory. - Added
npm run check:license(part ofnpm run check), which fails the
build if repository license metadata, theme metadata, or theme license
notices drift from the MIT repo / GPL-2.0-or-later theme package boundary. - Added
spectre_base_register_cascade_layers()infunctions.php, which
unconditionally establishes thewp-global-stylescascade-layer order
(below Spectre'scomponents/utilitieslayers) on every request via a
src-less style handle, independent of the Vite manifest, dev/prod asset
mode, and whether WordPress has global-styles content to wrap. Documented
the resulting@layer wp-global-styles { ... }contract in README.md
"Adding custom shell styles" so a child theme's own global heading CSS
(e.g. plainh1-h6rules instyle.css) can opt into the same
precedence guarantee as the parent theme's compiledtheme.jsonheading
defaults, without overriding an explicit<sp-text level="h1" size="*">
recipe or requiring the child theme to target[data-sp-text-native],
.sp-text, or another rendered implementation detail. - Added regression coverage in
scripts/check-style-precedence.ts(run via
npm run check:styles, part of thewordpress-smoke.ymlCI workflow)
confirming a child theme's own CSS wrapped in@layer wp-global-styles
still loses to an explicit Spectre text recipe even when WordPress's
global-styleshandle has no content to wrap on that request. - Redesigned
footer.phpas a marketplace-ready four-column footer: a brand
column (site logo/title, tagline, social icons, and inline contact info)
and three nav columns (newfooter-secondaryandfooter-tertiarymenu
locations alongside the existingfooterlocation, each rendered via
spectre_base_footer_nav_column()). Contact details come from the
spectre_base_footer_contact_itemsfilter, rendered inline in the brand
column viaspectre_base_footer_contact_info()rather than as their own
grid column. Columns lay out via<sp-grid columns="4">(collapsing
responsively to one column on mobile) using only existingspectre-ui
footer recipe classes (sp-footer__heading,sp-footer__text,
sp-footer__muted,sp-footer__links,sp-footer__link,
sp-footer__chip,sp-footer__divider) -- no new design values. The
copyright bar now surfaces a Privacy Policy link automatically via
WordPress core'sget_privacy_policy_url()when a privacy policy page is
configured. A nav column with no menu assigned is simply omitted. - Added filter hooks
spectre_base_footer_secondary_nav_args,
spectre_base_footer_tertiary_nav_args,spectre_base_footer_nav_heading,
andspectre_base_footer_contact_items, documented in README.md "PHP Hook
API" alongside the existing footer hooks. - Added header and footer extension seams so a child theme can drop its
header.php/footer.phpforks and keep the shell's skip link and main
landmark. Sites that use none of them render the same markup as before.spectre_base_site_brandingandspectre_base_primary_navfilters:
return a markup string to replace the branding or primary-nav contents
(for example a bundled logo, or top-level items rendered as
<sp-dropdown mega>). The region wrappers and the branding actions stay.spectre_base_header_actionsaction: a slot after the primary nav for a
header CTA.spectre_base_header_layoutfilter:inline(default) or
edge-fluid-edge, a three-region branding/nav/actions grid on
spectre-ui'ssp-grid-template--edge-fluid-edgeutility.spectre_base_header_container_classfilter: utility classes for the
header container's inner element.sp-relativemakes the container the
anchor for mega panels.spectre_base_main_startaction: fires first inside
<main id="spectre-main-content">in every public template, so a page
hero renders inside the landmark without the child opening<main>.spectre_base_footer_surface(page|card|subtle|inverse|
hero) andspectre_base_footer_appearance(dark|light|
system) filters, passed to thespectre-components1.22.0sp-footer
surfaceandappearanceoptions. The child no longer has to select
.sp-footeror[data-sp-footer-native].spectre_base_iconfilter andspectre_base_icon()helper: an icon
provider for footer social and contact icons. The spectre-icons
shortcode stays the default provider, and a child can return its own
markup (such as a bundled inline SVG) without the plugin.
npm run check:driftnow enforces the 8px layout grid (owner-confirmed
2026-10-03). It fails onsp-*padding, margin, gap, and space utilities
(including responsive prefixes) and--sp-space-*references whose step is
not 0, 4, or a multiple of 8. README.md "8px Layout Grid" documents the
rule, thexl-4xllayout steps, and thesp-sectionhero/attached
options.
Changed
-
Raised the Spectre dependency ranges to
@phcdevworks/spectre-tokens
^4.12.0,@phcdevworks/spectre-ui^5.4.0, and
@phcdevworks/spectre-components^1.22.0. -
Social icons no longer require the spectre-icons plugin: the row renders
each entry that some icon provider (the plugin shortcode or the
spectre_base_iconfilter) has markup for, and skips the rest. -
Replaced the off-grid
sp-12andsp-20block editor spacing presets in
theme.jsonwithsp-64,sp-80, andsp-96. Content that used the
removed presets loses that spacing value and needs a new preset picked in
the editor. -
Standardized the package summary against the approved PHCDevworks product
description. -
Documented the MIT (repository/framework) vs. GPL-2.0-or-later (deployable
spectre-theme/package) licensing boundary in the root and theme
README.mdfiles. -
Updated the pinned GitHub Actions major versions used by the CI, dependency
report, and WordPress smoke workflows:actions/checkoutv4 to v7 and
actions/setup-nodev4 to v7.shivammathur/setup-phpstays on v2, which is
still its current major. -
Updated
scripts/create-child-theme.tsto include a commented example of
the@layer wp-global-stylescontract in the generated child theme
style.css. -
Added block editor canvas spacing: the post title and content are
centered at the container max width with inline padding, and the title is
separated from the body by a--sp-surface-dividerrule and a
--sp-space-32gap. Rules are scoped to.editor-styles-wrapperin
src/styles/main.cssand do not affect the front end. -
Rebuilt the footer on the
spectre-components1.21.0 /spectre-ui5.3.0
footer contract:<sp-footer>is nowborderedwith a brand top accent
rail (newspectre_base_footer_accent/spectre_base_footer_accent_color
filters), the grid is sized to the columns actually rendered so missing
nav menus no longer leave empty columns, the current page's footer link
gets thesp-footer__link--activestate, and the copyright bar splits into
the copyright notice (left) and a newspectre_base_footer_legal_links
filter (right, defaulting to the privacy policy link). Social icons gain a
labelaccessible name for icon-only links, and unlinked icons render as
<sp-footer-chip>. Social and legal-link rendering moved into
spectre_base_footer_social_icons()/spectre_base_footer_legal_links()
infunctions.php. -
Added a Footer menus Customizer setting (Appearance > Customize >
Footer, 1-4, default 3) that controls how many footer menu locations the
theme registers and renders, including a new fourthfooter-quaternary
location with its ownspectre_base_footer_quaternary_nav_argsfilter.
The footer grid now puts the brand column in the first third and the menu
columns in a nested grid across the remaining two thirds, since
sp-gridhas no five-column layout for brand plus four menus. -
Footer nav column headings now default to the assigned menu's name from
Appearance > Menus instead of the theme-authored "Explore",
"Services", and "Resources" labels, so no site content ships from the
theme.spectre_base_footer_nav_headingstill overrides it, and an empty
heading omits the heading element (the nav is then labelled by its menu
location). -
Added a site-wide Color Mode Customizer setting (Appearance >
Customize > Color Mode): Light (default), Dark, or System, which follows
each visitor's device setting and updates live. The theme sets
data-spectre-themeon<html>(server-side for Light/Dark, a pre-paint
inline script for System) plus a matching<meta name="color-scheme">,
so every Spectre component switches through its published mode-aware
tokens with no theme-defined colors. -
Every page now fills at least the full viewport height, so the header
sits at the top and the footer at the bottom even on short or empty pages:
<html>getssp-h-full,<body>getssp-min-h-full sp-flex sp-flex-col(via thebody_classfilter), and<sp-footer>gets
sp-mt-auto. Longer pages scroll as before. -
Removed card framing from every page template: single posts, post-list
items (content-card.php), the front page content, comments, the
previous/next post links, the 404 page, and sidebar widgets now render on
the page surface as plain<article>/<section>/<nav>elements instead
of<sp-card>. Comments share the post's.sp-content-flowmeasure. -
Restyled the site header to match the footer: `<s...
Spectre and development dependency refresh
Contract change type: semantic change
Changed
- Updated the Spectre component, token, and UI dependency ranges to their
latest compatible releases and refreshed the resolved dependency tree. - Updated the Node type definitions, CSS processing tools, lint tooling, and
browser test runtime to their latest compatible releases.
Keyboard bypass navigation
Contract change type: additive
Added
- Added a keyboard-visible, token-backed skip link before the repeated site
header and one focusable native main-content landmark to every public theme
template. - Added static template contract coverage and a live WordPress browser check
that verifies the skip link is the first focus target, becomes visible, and
moves focus to the main landmark when activated.
Tooling checks and dependency maintenance
Contract change type: semantic change
Fixed
- Updated the locked
fast-uridependency to remove known security findings. - Required patched
qsversions in the WordPress development environment
dependency tree without downgrading the surrounding tooling. - Extended release version validation to the README, both lockfile version
fields, the theme header, and the WordPress stable tag, with regression
checks for missing and mismatched metadata.
Added
- Added strict TypeScript checking for scripts and root configuration files
to the build and full validation gate. - Added a weekly, manually runnable dependency report for npm updates, audit
counts, and workflow action releases. The workflow uses read-only
permissions and creates no branches or pull requests.
Removed
- Removed the obsolete development-container dependency update configuration.
Reliable style precedence and validation
Contract change type: semantic change
Fixed
- Established matching CSS layer order in the theme bundle and WordPress
global styles so component heading sizes win in either stylesheet order,
while default headings continue to inherit WordPress global styles. - Made design-system drift fail validation, excluding generated output and
binary files while allowing Spectre token references and component recipes. - Made asset validation reject missing files, paths outside the build
directory, non-file assets, and unresolved imported manifest entries.
Added
- Added validator regression tests to the full check gate and browser-based
computed heading precedence checks to the WordPress smoke workflow.
WordPress smoke assertion compatibility
Changed
- Relaxed content-flow smoke assertions to verify the required
wp-block-groupand alignment class tokens while allowing WordPress to add
its own layout-support classes to rendered Group blocks.
Release validation hygiene
Changed
- Updated WordPress smoke-test response assertions to read captured HTML
directly, preventing successful early matches from surfacing as pipeline
failures whengrep -qcloses its input underpipefail.
Removed
- Removed an obsolete one-off CommonJS screenshot helper that duplicated the
supported TypeScript screenshot workflow, violated the repository's
TypeScript-only tooling contract, and caused ESLint to fail in clean CI
checkouts.
Theme layout and cascade contracts
Added
-
Added
spectre_base_layer_global_styles()infunctions.php, hooked on
wp_enqueue_scripts(priority 20) andwp_footer(priority 2), both with
accepted_args = 0. It post-processes the already-enqueuedglobal-styles
inline stylesheet's queued CSS via the publicWP_Stylesdata API and
wraps it in@layer wp-global-styles, with a leading
@layer wp-global-styles, components, utilities;order statement that
slots the new layer immediately belowcomponents/utilitiesregardless
of which stylesheet the browser parses first. Fixes "Heading size
precedence": WordPress core's ownglobal-styles-inline-cssoutput for
theme.json'sstyles.elements.h1-h6compiles to plain, unlayered
selectors, which the CSS cascade-layers spec always lets win over
spectre-ui's layered@layer components/@layer utilitiessize
recipes — so an<sp-text level="h1" size="*">request was permanently
overridden by the theme's default heading scale. WordPress core has no
filter onwp_get_global_stylesheet()'s return value or on the printed
inline style tag (verified against wordpress-develop trunk and a live
WordPress 7.0 install), so this hooks the registration/print lifecycle
instead of a nonexistent filter. Regression coverage added to
.github/workflows/wordpress-smoke.yml("Verify global-styles heading
precedence layer wrap"), asserting the front page response contains both
the order statement and the wrapping@layer wp-global-styles {block.
Manually verified end-to-end against a live WordPress 7.0.2 instance
running this theme (WP's WP 6.9+ "load block assets on demand" default
routes classic-theme global styles throughwp_footerand hoists them
into<head>; confirmed the wrap survives that path) as well as directly
against WordPress core's ownWP_Styles/_WP_Dependencyclasses. -
Added a generic parent-theme content-flow contract for classic
the_content()output (page.php,front-page.php,single.phpnow wrap
it in<div class="sp-prose sp-content-flow">). New.sp-content-flow
rules insrc/styles/main.cssgive top-level blocks a token-backed prose
measure by default, honor WordPress's ownalignwide/alignfullclasses
for breakout, and space top-level block siblings by--sp-space-16--
matchingtheme.json'sstyles.spacing.blockGap-- since classic content
has no block-theme.is-layout-flowwrapper to provide that automatically.
Pairs withspectre-ui@4.2.0's.sp-proserecipe for list/blockquote
treatment. Extendedwordpress-smoke.ymlwith a page carrying
alignwide/alignfullgroup blocks to verify the wrapper renders and
Core's own block markup survives untouched. Requested by a downstream
child-theme integration on 2026-08-07; closes Phase 6.
Changed
- Bumped the Spectre runtime contract ranges to
@phcdevworks/spectre-tokens^4.5.0,@phcdevworks/spectre-ui
^4.3.0, and@phcdevworks/spectre-components^1.17.0, per Phase 7
(production layout dependency alignment). Rebuilt theme assets and
confirmednpm run checkpasses clean. - Updated
README.md"Adding custom shell styles" to demonstrate
spectre-ui's generatedsp-*layout utilities and theinner-class
contract on Spectre web components as the preferred way to style child
themes, ahead of hand-rolled descendant CSS. Added a matching hint to
scripts/create-child-theme.ts's generator output. Completes Phase 7. - Removed the local
--sp-layout-container-max-width: 80removerride from
src/styles/main.css, now that@phcdevworks/spectre-tokens@4.7.0ships
the additivelayout.container.maxWidthWidetoken and
@phcdevworks/spectre-ui@5.0.0ships the corresponding
.sp-container--max-width-wideutility. The four multi-column archive
templates that needed the wider measure (archive.php,home.php,
index.php,search.php) now opt in per-instance via
<sp-container inner-class="sp-container--max-width-wide">instead of a
sitewide token redeclaration;.sp-content-flow > .alignwidein
src/styles/main.cssnow reads
var(--sp-layout-container-max-width-wide)directly. Resolves "Container
— Remove Local Max-Width Token Override" and its duplicate
"Container width scale" entry inTODO.md. - Confirmed
spectre-ui@5.0.0moved.sp-sectioninto@layer components
(so a consumer'ssp-py-*/sp-pt-*/sp-pb-*utility now wins over the
recipe's own padding by layer precedence) and addedsp-section/sp-stack
to the base-layer custom-element hostdisplay: blockcontract. This
theme never carried a local!importantor plain-<section>workaround
for the prior defect, and has no<sp-stack>usage with a host-level
max-width, so no template or CSS change was needed here beyond
confirming the fix is present innode_modules/@phcdevworks/spectre-ui/dist.
Resolves "Section — Spacing Utility Override Of Section Padding",
"Section spacing and host display", and "sp-stackhost display contract"
inTODO.md. - Confirmed
spectre-ui@5.0.0's.sp-shadow-inset-sm/-md/-lg/-xl/-2xl
utilities are present and generated from the published
--sp-shadow-inset-*tokens. This theme has no hand-composedbox-shadow
for inset shadows to replace;theme.json'sshadow.presetsalready
reference outer-shadow tokens (var(--sp-shadow-sm|md|lg)) only. No
adjacent inset-shadow banding exists in this theme's own templates, so
there is no consumer-owned adjacency treatment to document here. Resolves
"Inset shadow delivery" inTODO.md. - Confirmed
spectre-tokens@4.7.0'ssurface.inverse/on-inverse role set is
published andspectre-ui@5.0.0/spectre-components@1.18.0consume it
(.sp-text--on-inverse/-muted,.sp-link--on-inverse,
.sp-badge--inverse,.sp-btn--inverse,.sp-surface--inverse, and the
matchingsp-text/sp-badge/sp-buttonvariantvalues). Audited this
theme's own templates (header.php,footer.php,front-page.php, and
every file undertemplate-parts/) for hand-painted on-dark treatment
(translucent badges/buttons, dark card body text/links, utility-bar or
footer link color overrides) and found none present in the current
source -- this theme carries no local on-dark styling to migrate. Resolves
"On-dark/inverse surface role" inTODO.md. - Confirmed the
component.card.padding.{sm,md,lg}token scale
(spectre-tokens@4.7.0), the correspondinggetCardClasses()size
support (spectre-ui@5.0.0), andsp-card'spaddedprop accepting
'sm'/'md'/'lg'(spectre-components@1.18.0) have all shipped --
everyRequested by Downstreamentry for card padding is gone from both
packages'TODO.md. Every<sp-card>in this theme (front-page.php,
404.php,comments.php,single.php,
template-parts/content-card.php,template-parts/content-single.php,
and the widget wrapper infunctions.php) uses the plain boolean
paddedattribute with no local padding override to simplify. The
full-bleed media workaround referenced by this item lives in a separate
downstream child theme, not this one, so evaluating it against the new size
scale is out of scope here. Resolves "Card padding
size scale" inTODO.md.
Maintenance dependency alignment
This release spans no single ROADMAP phase; it is a maintenance release.
Changed
- Updated the Spectre runtime contract ranges to
@phcdevworks/spectre-components^1.14.0,
@phcdevworks/spectre-tokens^4.1.0, and
@phcdevworks/spectre-ui^3.2.0. - Refreshed Vite, Playwright, ESLint, TypeScript ESLint, Globals, WordPress
Playground, and related transitive development dependencies. - Corrected the roadmap history for the 3.0.0 text-contract release and
clarified repository commit-completion and human-authorship policy.