feature/design-tokens-module - #997
Draft
d4mation wants to merge 1864 commits into
Draft
Conversation
Contributor
|
🎉 Zip build complete |
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueComment |
SOFT-4195 [4/4]: mount the token picker on Icon Size
…-update [DTM] SOFT-4212: compare metadata saves against the client's version
The stack's fifteen PRs merged bottom-up into each other rather than into this branch: the bottom one was based on SOFT-4212/metadata-write-lost-update, which had already merged here, so the chain accumulated on that branch instead of arriving. This brings the whole chain across in one commit.
…tensions-sections [DTM] SOFT-4211: reject a non-array $extensions metadata section
isBackedToken() failed open whenever the active library's resolved value map had no keys, which conflated "nothing localized" with "the library resolved and backs nothing". The PHP renderer's token_alias_is_backed() only fails open when resolution itself fails, so an empty-but-successful id map would have had PHP treat every alias as unbacked while JS treated every alias as backed. resolvedValues() now returns null when there is no map to consult -- the pickable pool is absent, or the active library is missing from it (the catalog skips a library whose stored document cannot be resolved, the same corruption PHP catches as a `\Throwable`) -- and isBackedToken() fails open only on null. A localized library that resolves to an empty map is an answer, so every alias reads as unbacked there, in both languages alike.
… blocks Adds `supports.kbPreset` to Advanced Image, Row Layout, Section, Single Icon and Advanced Text, which is what makes `early-filters.js` inject the `kbPreset` attribute, append the `kb-preset--<slug>` class to saved markup and mirror it in the canvas. Declared as a bare support with no matching block.json attribute, exactly as `kbPalette` already is on these same five blocks — the attribute comes from the registerBlockType filter. Existing content stays valid: the save filter appends nothing while `kbPreset` is empty, so saved markup is unchanged for every block already on a page. The inspector panel stays hidden too — it renders only for a block with at least one preset option, and these have none until their declarations gain a picker label.
…set in pixels A control that stores a raw number with no companion unit attribute — `kadence/single-icon`'s `size`, written straight into the SVG's geometry attributes — has its default seeded from the token by PHP's `Converts_Number_To_Px`. So a never-touched icon holds `24` while its preset resolves to `1.5rem`. Compared as strings those disagree, and the control reported as overridden before anyone had touched it. Fall back to a pixel comparison when the stored value carries NO unit and the preset literal does, converting through the same table the seeding used. A control that does carry a unit attribute keeps the strict same-unit compare, so a `rem` value against a `px` preset still reads as overridden rather than being converted into agreement. The conversion moves to `token-controls/helpers/px-from-length`, beside `parse-css-length`: the editor's `token-px` wraps it with alias resolution against the active library, and this compare needs the bare conversion with no library lookup. One table, and `kinds/dimension` does not have to import the picker's dependencies to reach it. Both scalar and per-corner compares now route through one `lengthMatches()`.
The first preset screen after the Button, and the pattern for the three that follow. Per the Style Library README's recipe it is one config plus a binding: `presets/single-icon-preset.js` describes the block (surface, preview, schema) and `SingleIconScreen`/`SingleIconSettings` bind it to the generic `PresetScreen`/`PresetSidebar`. Nothing generic changed. Declaring `label` and `style_library` on the icon's bindings is what turns it on, adding the Style Library nav entry and the editor's preset picker now that both have somewhere to go. Two shape notes. The icon binds no hover property, so the config declares no tabs and the sidebar renders its field area bare. Size uses `token-select` so a preset stores a token id and keeps following the Icon Sizes scale, which also means it carries no breakpoint switcher — one size for every device — while the binding keeps its `responsive_attrs` so a per-breakpoint override stays expressible once a responsive token picker exists. The row preview draws a neutral glyph rather than a real Kadence icon: a preset skins whichever icon a block uses, so previewing a specific one would imply the preset selects it.
…ze and color Three separate faults, all only reachable once the icon had presets to select. `resetAttrPatch` cleared every dimension to a measure control's 4-side `['', '', '', '']` array. The icon's `size` is a single number written into the SVG's geometry attributes, so selecting a preset stored an array in a scalar attribute and the control read it back as a custom value. The shape now comes from the block's own attribute schema, passed in by the one caller that has it, and the unit and per-device companions are written only where the block declares them. The editor preview resolved a cleared size to the BINDING's token rather than the selected preset's value, so every preset showed the same size in the canvas while the front end showed each preset's own — the front end reads `--kb-icon-size`, which the preset's scoped rule sets, ahead of the token. The preview and the size control's inherited-value display now resolve the preset first, then the token. Color never reached the canvas at all. The front end paints a cleared color through the block-default rule's `var(--kb-icon-color, ...)` chain on the `.kb-svg-icon-wrap` span PHP hydrates; the editor renders `GenIcon`'s own div, which carries no such class, so that rule matches nothing there. The preview resolves the preset's color and paints it inline, the same split the size has always used.
The icon's size field used `token-select`, a bare picker with nowhere to put a breakpoint switcher, so a preset could only ever give one size to every device. The block's own control is per-device — it stores `size`/`tabletSize`/`mobileSize`, all three declared on the binding — so a preset could not reproduce a look a site owner had already built with that control. Add `token-scalar`: the scalar sibling of `BoxTokenField`, wrapping `ScalarControl` (which carries the switcher) with the same responsive envelope, the same breakpoint inheritance, the same picker narrowing, and the same stored/control conversion reused rather than restated. What it drops is everything that only makes sense for four slots — the link toggle, the per-slot mapping, the slot-list unit sniffing. Nothing else was needed for it to work end to end: the responsive envelope, the per-breakpoint projection, and the editor's device-aware preset read are all generic, so a scalar dimension on a block other than the Button travels the whole path already. Covered by a wpunit case asserting an icon preset's mobile size lands in its own media block. `token-select` stays as the non-responsive single picker; the two now sit side by side in the demo schema, which is contracted to exercise every registered type.
"default" is the literal the block's `/default` sub-route uses, so the reserved-slug guard refused any write naming it. That was meant to stop someone MINTING a preset the per-preset item route could never address — but it ran over every write, and "default" is not hypothetical: every block but the Button ships its baseline look under exactly that slug. A site owner editing it got a 422, which on the Icon screen meant the one preset the block has was permanently read-only. Scope the guard to creation: a slug already present in the block's effective presets is writable, a new one under a reserved slug is still refused. The only route this forecloses for the shipped preset is DELETE, which it should refuse anyway — it is the block's built-in look, and the editor offers deletion only for user-created presets.
…paints a preset value The editor preset catalog carried only flattened literals, which is right for deciding bound-vs-overridden — a control cannot compare itself against a `var()` chain. But an editor render path that has to APPLY a preset value itself, rather than let a stylesheet do it, needs the opposite: the Icon's preview paints its color inline, and a literal had already been flattened against the default palette upstream, so an icon on an alternate per-block palette rendered the default palette's color. Carry the CSS references alongside the literals — the same `var()` chains the projected CSS uses — and paint with those. The chain resolves through the projector's `[data-kb-palette]` layer, and the editor already mirrors the block's selected palette onto its wrapper, so the icon now follows whichever palette the block is on, exactly as the front end does. Both maps stay: they answer different questions, and neither substitutes for the other.
…hite background and gray-400 border
… every side already matches
… in kb-token-control-row for spacing
…ttr so usePresetBinding can track the border indicator
…t dimension kinds
…d resetting the normal border
…etting the normal radius
The Padding and Margin sidebar fields had no "Default" hint to show, because the shipped Primary/Secondary presets never set button-padding/button-margin at all (unlike button-radius). The field rendered blank and visually shrank. The button's own rendered CSS was never affected by this - a separate, pre-existing mechanism (semantic.spacing.button-padding-top/right/bottom/left and the button-margin equivalents) already governs the real default padding and margin. This fix only wires the preset-property system (what the sidebar control reads) to the same values. Preset_Resolver already fully supports a per-corner (4-value array) preset property value - flatten_slots()/project() are already built and unit-tested for it, just never exercised by a real preset until now. No JS or resolver code changed; only the baseline preset data and two test fixtures that enumerated the old (padding/margin-less) property set.
…aller defaults still renders
…ches the renderer
…y its stored legs
…n keeps its shadow
…etects schema drift
…-shadow-binding [DTM] SOFT-4266 [6/6]: bring the image block's shadow up to the same binding and defaults
The Button was the only block whose baseline presets were named Primary and Secondary. Secondary is dropped, Primary becomes Default, and `$default` follows, so all six blocks now ship a single preset slugged `default`. The four `semantic.color.button-secondary-*` tokens existed only to feed the Secondary map, so they go with it rather than shipping as dead entries in the token picker. The four that remain lose their now-meaningless `primary` segment: `semantic.color.button-primary-bg` becomes `semantic.color.button-bg`, and likewise for text, bg-hover and text-hover, matching the sibling naming already used by column-bg, heading-bg and image-bg. One behavior follows from the rename. `default` is reserved against the *creation* of a preset the per-preset item route could never address, not against writing a slug the block already ships. The Button was the sole block shipping no `default`, so it was the only place that write was refused; it now merges onto the shipped preset like the other five.
Removing `testCreatingAPresetNamedDefaultIsRejected` took out everything between it and the next reserved-slug test: the capability checks on the write and read routes, the version-bump assertion, the malformed-shape and empty-slug validation, and the whole preset display-order sub-route suite. None of them have anything to do with the Button preset rename. The suite stayed green because the tests no longer existed. All twelve are back. Eight are byte-identical to their previous state. The four that changed are the ones that named the removed baseline slugs: the three set-order tests and the delete-order test now pair the shipped `default` with a user-created `accent` preset, since the Button no longer ships two. The only test this branch still removes is `testCreatingAPresetNamedDefaultIsRejected`, which the rename makes unreachable — every block now ships a `default` preset, so writing that slug is a merge rather than a refused creation, and `testCreatingAPresetNamedOrderIsRejected` still covers the guard's refusal branch.
…eset-for-consistency Ship one Default preset for the Button, matching every other block
…ry-host [DTM] SOFT-4261 [4/4]: Open the shared color popover from a border row in the Style Library
[DTM] Give the editor's color controls the same bottom spacing as their neighbors
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.
🎫 https://linear.app/nexcess/project/design-system-7186b33eeebd/overview
...
Also relies on stellarwp/kadence-helpers#7 and stellarwp/kadence-components#20
Checklist
Block specific checklist (where relevant)