Skip to content

feat(#427): put the depth vocabulary on the DaisyUI primitives - #437

Merged
TortoiseWolfe merged 1 commit into
mainfrom
feat/427-primitives-depth
Jul 29, 2026
Merged

feat(#427): put the depth vocabulary on the DaisyUI primitives#437
TortoiseWolfe merged 1 commit into
mainfrom
feat/427-primitives-depth

Conversation

@TortoiseWolfe

Copy link
Copy Markdown
Owner

Puts the depth vocabulary on the DaisyUI base classes so the remaining page tickets are composition work, not re-shadowing.

Why this comes first

The refresh was scoped to the six surfaces the comp drew. Measured across the app: 43 routes, 5 carrying any depth token, 38 never touched (#426). Those 38 are thin shells — /profile is 40 lines, /payment 31 — over 46 shared components built from ten DaisyUI primitives:

primitive files primitive files
btn 106 badge 52
alert 88 textarea 37
input 78 modal 30
select 69 stat 29
card 60 table 19

Going route-by-route would hand-restyle the same button 106 times. This moves the whole app at once.

What changed

Two blocks of literal-black drop shadow are replaced. They existed so unmigrated pages still looked deliberate, and their own comment set the exit condition — "Remove this block entirely once every surface is on the depth tokens" — assuming migration meant hand-applying sh-plate everywhere. It doesn't have to.

treatment applied to
plate (raised) .card .alert .modal-box .btn
well (cut) .stats
groove (channel) .input .select .textarea .file-input .table thead th · .btn:active

Literal black is also what --sh-ink-shadow exists to replace: it derives from the theme's own surface, so it stays correct on both house themes rather than being tuned for the dark one and tolerated on the light.

Verified in a browser, not assumed

  • .cardoklch(0.0959 0.038 282.93 / .55) on scripthammer-dark, oklch(0.4022 0.009 67.72 / .55) on scripthammer-light — each derived from that theme's base-100.
  • retro is untouched, keeping its own DaisyUI shadow. The 32-stock-theme contract holds.
  • 5 solid buttons take the plate; all 45 .btn-ghost on the home page take none. Ghost and link are flat by definition — shadowing them would make a quiet action read as a raised one.
  • Focus rings survive. DaisyUI draws focus with outline: 2px solid, not box-shadow (components/input.css), so no rule here can erase it. Measured outlineWidth=2px outlineStyle=solid on a focused .input. This was the main a11y risk and it was checked before writing the CSS, not after.

The first probe of .btn returned none and looked like a failure — it had resolved querySelector('.btn') to a btn-ghost btn-circle in the nav, which is the excluded case. Re-probed against a non-ghost button.

Deliberately excluded

.badge — a ~20px pill with an inset shadow reads as mud at that size. Badges carry meaning through colour here, not depth. Called out so this reads as a decision rather than nine of ten.

The :not() chain is load-bearing

These selectors are [data-theme] .class — specificity 0,2,0 — while a Tailwind @utility is 0,1,0. Without the opt-out chain this block beats sh-plate/sh-well/sh-groove and an element carrying a depth utility silently renders its primitive's default instead. That exact failure is #379. Any rule added here needs the same chain.

Found while verifying this

#436 — form fields sit beside or below their label depending on the length of the label text. On /contact the four fields have byte-identical markup; .label is inline-flex, so the input wraps below only when labelWidth + inputWidth > containerWidth. "Subject" (59px) fits beside its input at 379 against a 384px container and lands one label-width off the grid. Predicts sharesLine in 4 of 4 fields. className="label" appears 32 times across 14 files. Not caused by this PR, and not fixed here.

Closes #427.

Replaces two blocks of literal-black drop shadow that existed so unmigrated
pages still looked deliberate. Their comment set the exit condition — remove
once every surface is on the depth tokens — and assumed that meant hand-
applying sh-plate across 43 routes. It does not: 38 of those routes are thin
shells over 46 shared components built from these primitives, so the
vocabulary goes on the base classes and the page tickets (#428-#435) are left
with composition instead of re-shadowing.

  plate   .card .alert .modal-box .btn
  well    .stats
  groove  .input .select .textarea .file-input .table thead th, .btn:active

Verified in the browser rather than assumed:

- .card resolves to oklch(0.0959 0.038 282.93 / .55) on scripthammer-dark and
  oklch(0.4022 0.009 67.72 / .55) on scripthammer-light — derived from each
  theme's own base-100, which is the point of --sh-ink-shadow over literal
  black.
- retro is untouched (keeps its own DaisyUI shadow), so the 32-stock-theme
  contract holds.
- 5 solid buttons take the plate; all 45 .btn-ghost on the home page take
  none. Ghost and link are flat by definition — shadowing them would make a
  quiet action read as a raised one.
- Focus rings survive. DaisyUI draws focus with `outline: 2px solid`, not
  box-shadow (components/input.css), so none of these rules can erase it.
  Measured outlineWidth=2px outlineStyle=solid on a focused .input.

.badge is deliberately excluded: a ~20px pill with an inset shadow reads as
mud at that size. Badges carry meaning through colour here, not depth.

Closes #427.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Depth on the DaisyUI primitives — the cascade that carries most of the 38 routes

2 participants