Skip to content

marker: stylex.when.* specificity + derive types from runtime functions (#5)#8

Merged
dogmar merged 20 commits into
mainfrom
claude/silly-moore-bdbc86
May 3, 2026
Merged

marker: stylex.when.* specificity + derive types from runtime functions (#5)#8
dogmar merged 20 commits into
mainfrom
claude/silly-moore-bdbc86

Conversation

@dogmar
Copy link
Copy Markdown
Collaborator

@dogmar dogmar commented May 3, 2026

Closes klink-ing/bearbones#5.

Summary

Two layered changes:

  1. Marker selectors mirror StyleX's when.* specificity contract — every relation wraps the marker observation in :where(...) so the observed marker contributes zero specificity. The styled rule lands at (0, 1, 0), same as a plain utility, so toggling a marker doesn't unconditionally beat a utility class. Surface expanded from 3 relations to StyleX's 5: ancestor, descendant, siblingBefore, siblingAfter, siblingAny. Selector templates centralized in a single RELATION_SELECTOR_ENTRIES table that drives both runtime and type emit.

  2. Marker types are fully derived from runtime function return types — every literal in the patched css.d.ts either comes from ReturnType<typeof fn<...>> or from a single-source typed map. No hand-maintained CSS in the type emit.

Selector contract

Relation Lowered selector Specificity
ancestor :where(${m}) & 0,1,0
descendant &:where(:has(${m})) 0,1,0
siblingBefore :where(${m}) ~ & 0,1,0
siblingAfter &:where(:has(~ ${m})) 0,1,0
siblingAny &:where(:has(~ ${m})), :where(${m}) ~ & 0,1,0

m is the user's condition value with every & substituted for .bearbones-marker-<id>_<hash>. The &-prefixed branch comes first in siblingAny so the literal type satisfies Panda's AnySelector.

How types are derived

The patched css.d.ts now reads:

import type {
  composeRelationSelectors,
  markerAnchor,
  markerAnchorClass,
  substituteAmp,
} from '@bearbones/vite';

type BearbonesMarkerAnchor<Id extends string> = ReturnType<typeof markerAnchor<Id, "<HASH>">>;

type BearbonesObserver<Id extends string, Cond extends string> = ReturnType<
  typeof substituteAmp<Cond, BearbonesMarkerAnchor<Id>>
>;

export interface BearbonesMarkerBuilder<Id extends string, Cond extends string> {
  readonly is: ReturnType<typeof composeRelationSelectors<BearbonesObserver<Id, Cond>>>;
}

type BearbonesMarkerConditions = {
  readonly "hover": "&:is(:hover, [data-hover])";
  readonly "focusVisible": "&:is(:focus-visible, [data-focus-visible])";
  /* …one entry per condition the host has registered */
};

type BearbonesMarkerShortcuts<Id extends string> = {
  readonly [K in keyof BearbonesMarkerConditions as `_${K & string}`]:
    BearbonesMarkerBuilder<Id, BearbonesMarkerConditions[K]>;
};

export interface BearbonesMarker<Id extends string = string>
  extends BearbonesMarkerShortcuts<Id> {
  readonly anchor: ReturnType<typeof markerAnchorClass<Id, string>>;
  <C extends string>(condValue: C): BearbonesMarkerBuilder<Id, C>;
}

So cardMarker._hover.is.ancestor evaluates at the type level to the exact runtime selector — modulo the build-time SHA1 hash, which the type substitutes with the literal placeholder <HASH> (verified by eight pinned literal-type assertions in css-typing.ts).

Repo changes

Selector pipeline (packages/bearbones-vite)

  • marker-registry.ts: introduces RELATION_SELECTOR_ENTRIES (the segment table), RELATION_SELECTORS (record form), MARKER_RELATIONS (tuple), RelationSelectors<T>, composeRelationSelectors, applyRelationSelector, markerAnchor, markerAnchorClass. buildRelationSelector now pipes through substituteAmp + applyRelationSelector so runtime mirrors the type-level derivation step-by-step.
  • transform.ts: runtime __bearbones_relations helper is generated at build time from RELATION_SELECTORS (sentinel-split + JS concat), so build-time and runtime stay byte-identical without a hand-maintained duplicate. renderMarkerRecord iterates MARKER_RELATIONS.
  • codegen-patch.ts: renderMarkerTypes emits the four runtime-function-derived alias types above, plus BearbonesMarkerConditions (single source of truth for condition strings) and BearbonesMarkerShortcuts (mapped type that synthesizes one _<name> shortcut per entry).

New package: @bearbones/utils

Private workspace package (never publishes) holding the generic TS utilities the marker pipeline depends on:

  • Type-level: InterpolateParts, EntryNames, SubstituteAmp
  • Runtime: substituteAmp, deepAssign, shortHash

@bearbones/vite declares @bearbones/utils under devDependencies and inlines its source/types into the published dist via tsdown's deps.alwaysBundle. vite.config.ts declares the build task with dependsOn: ["@bearbones/utils#build"] so vp run -r build orders correctly.

Specificity test

marker-registry.test.ts has a real specificity-contract assertion that runs every emitted selector through @bramus/specificity (canonical CSS Specificity Calculator), substituting & with a sentinel class, asserting (0, 1, 0) per comma-branch.

Other

  • Stable dts pipeline — dropped @typescript/native-preview (experimental tsgo) for reliability.
  • Marker chains accept arbitrary condition values verbatim; & is required and substituted into the relation observer.
  • Demo / __type-tests__/css-typing.ts updated to use siblingAny and pin the literal-string evaluation of every relation.

Test plan

  • vp check clean
  • vp run -r test — 60/60 in @bearbones/vite, 17/17 in @bearbones/utils
  • vp run -r build end-to-end — utils → preset → vite → website panda+tsc+vite production bundle
  • Eight pinned literal-type assertions in css-typing.ts verify the cardMarker(...).is.<relation> evaluation matches the runtime selector

Files

  • packages/utils/ — new private workspace package
  • packages/bearbones-vite/src/marker-registry.tsRELATION_SELECTOR_ENTRIES + helpers
  • packages/bearbones-vite/src/transform.ts — runtime helper derived from RELATION_SELECTORS
  • packages/bearbones-vite/src/codegen-patch.tsBearbonesMarkerConditions + BearbonesMarkerShortcuts mapped emit
  • packages/bearbones-vite/tests/marker-registry.test.ts — specificity contract + per-relation assertions
  • packages/bearbones-vite/tests/codegen-patch.test.ts — single-occurrence + derivation assertions
  • apps/website/src/__type-tests__/css-typing.ts — pinned literal-type assertions
  • apps/website/src/Demo.tsxsiblingAny showcase + missing-& fix
  • docs/superpowers/specs/2026-05-02-marker-stylex-specificity-design.md — design spec

🤖 Generated with Claude Code

dogmar and others added 16 commits May 2, 2026 15:00
Covers issue #5: rewrite marker relational selectors to wrap the
marker-side observation in :where(...) for zero specificity, expand
the relation surface from 3 (ancestor/descendant/sibling) to 5
(ancestor/descendant/siblingBefore/siblingAfter/siblingAny) to mirror
stylex.when.*, and centralize selector templates in a single readable
RELATION_SELECTORS table.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Apply advisory recommendations from the spec review pass: derive the
MarkerRelation type from MARKER_RELATIONS for single-source-of-truth,
replace the buggy runtime-helper code example with illustrative
pseudocode, simplify the AnySelector justification, and strengthen
the specificity-contract test to catch wrapper misplacement.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update the marker-stylex spec to use @bramus/specificity (the canonical
CSS specificity calculator package) for the specificity-contract test
instead of substring proxies. Test substitutes & with a sentinel
class, runs each emitted selector through the calculator, and asserts
every comma-branch reports (0,1,0). Drops the matching "structural,
not semantic" caveat from the edge-cases section.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Update file paths and component plans to reflect the merge of #7:
- bearbones package is gone; marker types now live in
  codegen-patch.ts's renderMarkerTypes() injected into the patched
  css.d.ts
- buildRelationSelector takes a Panda condition value (with `&`
  placeholder) and substitutes `&` with the anchor class before
  wrapping in the relation
- Phantom-literal `is` keys (_bbm_${Id}_${Cond}_*) replace the
  template-literal-typed selector strings; we expand the suffix set
  from three to five (a/d/sb/sa/san) to cover the new relations
- Test files moved/renamed; references updated to the post-#7 line
  numbers and shapes

Selector contract and specificity goals are unchanged — :where()
wrapping for 0-specificity marker observation, five-relation surface
matching stylex.when.*, single readable RELATION_SELECTORS table.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors stylex.when.* by wrapping every relation in :where() so the
marker-side observation contributes zero specificity. The styled
element's own class — Panda's `&` placeholder — is the only
contributor, putting marker rules at exactly (0,1,0): same level as a
plain utility, no override-on-toggle.

Surface expanded from 3 relations to StyleX's 5: ancestor, descendant,
siblingBefore, siblingAfter, siblingAny. The previous `sibling` is
gone (it was equivalent to siblingAny). Selector templates moved to a
single readable RELATION_SELECTORS table at the top of
marker-registry.ts; the runtime helper and codegen-patch type emit
both derive from this table — no second copy maintained by hand.

In codegen-patch's renderMarkerTypes, replace phantom `_bbm_${Id}_${Cond}_*`
literal keys with real-shape selector templates parameterized by a
recursive `&`-substitution type and a fixed HASH placeholder for the
runtime-only hash slot. This makes hover/error output show the actual
selector shape (e.g. `:where(.bearbones-marker-card_HASH:hover) &`)
instead of an opaque `_bbm_card_hover_a &`. Each `_<name>` shortcut now
passes the resolved condition VALUE (not the name) as the Cond
parameter, so the substituted observer reflects what runtime emits.

siblingAny comma order is `&:where(:has(~ M)), :where(M) ~ &` (not the
StyleX-natural order) so the literal type starts with `&` and
satisfies Panda's AnySelector (`${string}&` | `&${string}`). CSS
treats comma-joined branches order-independently.

Tests:
- marker-registry.test.ts: assert real selector strings per relation,
  add a specificity-contract test that runs each emitted selector
  through @bramus/specificity (real CSS Specificity Calculator) with
  `&` substituted for a sentinel class, asserting (0,1,0) per
  comma-branch.
- transform.test.ts: pin the new wrapped shapes for all five lowering
  paths (call form + underscore shortcut for ancestor/descendant;
  call form for the three sibling variants); update multi-`&`
  substitution test.
- codegen-patch.test.ts: assert SubstituteAmp/MarkerAnchor/Observer
  type emit, real-shape relation patterns, and condition-value
  passthrough on `_<name>` shortcuts; regenerate snapshot.
- bramus-specificity.d.ts shim under tests/types/ — package ships
  JS-only.

Consumer updates:
- apps/website/src/__type-tests__/css-typing.ts: rename .is.sibling →
  .is.siblingAny.
- Demo.tsx unchanged (only uses .is.ancestor and .is.descendant).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Introduced the `composeRelationSelectors` function to preserve the literal selector shape for each relation, ensuring accurate CSS output. Enhanced the `MARKER_RELATIONS` to be a precise tuple of the relation selectors' keys in declared order. Updated tests to validate the new functionality and ensure consistency with the expected selector shapes.
…v server

Addressed an issue where utility strings and marker chains were not rendered correctly in development mode due to a cross-process hand-off problem. Implemented a JSON cache file to ensure the utility map is populated consistently across processes. Verified end-to-end functionality with the demo, ensuring correct output for both top-level utility strings and marker-chain object arguments.
Add type-level assertions verifying that `marker(...).is.<relation>`
evaluates to the exact runtime selector string at the type level,
modulo the unknown hash slot (replaced with the literal `<HASH>`
placeholder by codegen-patch's renderMarkerTypes).

Coverage:
- call form (`marker("&:has(.flag-error)").is.ancestor`)
- underscore form on a registered condition
  (`cardMarker._hover.is.{ancestor, descendant}`)
- all five relations (siblingBefore/siblingAfter/siblingAny)
- multi-`&` substitution
- parent-nesting condition value (anchor lands in leading position)

These are pure type-level checks: each constant assigns the chain
result to its expected literal string type. If the recursive
`BearbonesSubstituteAmp` type ever loses concreteness (e.g. widens
to `${string}` somewhere), one of these assignments fails and `tsc`
in the website build flags it.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The codegen-patch's BearbonesMarkerBuilder type emit no longer
hand-rewrites the relation selector shapes. Instead it derives the
type-level evaluation directly from the return types of the runtime
functions in marker-registry.ts:

- BearbonesMarkerAnchor<Id> = ReturnType<typeof markerAnchor<Id, "<HASH>">>
- BearbonesObserver<Id, Cond> = ReturnType<typeof substituteAmp<Cond, BearbonesMarkerAnchor<Id>>>
- BearbonesMarkerBuilder<Id, Cond>.is = ReturnType<typeof composeRelationSelectors<BearbonesObserver<Id, Cond>>>

Adds the missing pieces:
- substituteAmp(s, anchor): SubstituteAmp<S, Anchor> — typed runtime
  helper for the &-substitution; SubstituteAmp recursively replaces &.
- markerAnchor(id, hash): `.bearbones-marker-${Id}_${Hash}` — typed
  builder for the anchor selector.
- buildRelationSelector now pipes through substituteAmp +
  applyRelationSelector so the runtime path mirrors the type-level
  derivation step-by-step.

Public exports now include applyRelationSelector, buildRelationSelector,
composeRelationSelectors, describeMarker, markerAnchor, substituteAmp,
MARKER_RELATIONS, RELATION_SELECTORS, and the matching types
(MarkerDescriptor, MarkerRelation, RelationSelectors, SubstituteAmp).

The host's patched css.d.ts now ships an `import type` for the three
runtime functions whose return types it derives from — single source
of truth, no risk of the type emit drifting from runtime emit.

Existing literal-type assertions in css-typing.ts continue to pass
(verifying the substitution still evaluates concrete), and all
59 vitest tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Move the generic, marker-agnostic TS utilities out of marker-registry.ts
into their own workspace package so other bearbones packages can share
them:

- InterpolateParts<Parts, T> — recursive template-literal interpolation
- EntryNames<Entries> — homomorphic tuple-name extraction
- SubstituteAmp<S, Anchor> — recursive `&` substitution (type)
- substituteAmp(s, anchor) — paired runtime helper with literal-typed
  return

The new package is `@bearbones/utils` at packages/utils/. It's marked
`private: true` and never publishes; consumers inline its source/types
into their published dist via tsdown's `deps.alwaysBundle`. The package
keeps a build script that emits `dist/index.{mjs,d.mts}` so cross-package
dts pipelines (vite-plus's tsgo) can resolve the types — but consumers
list it under `devDependencies`, not `dependencies`, so the published
`@bearbones/vite` doesn't carry an unresolvable workspace specifier.

@bearbones/vite changes:
- marker-registry.ts: import substituteAmp/InterpolateParts/EntryNames
  from @bearbones/utils (was inline).
- index.ts: re-export substituteAmp + SubstituteAmp from @bearbones/utils
  so the codegen-patch's emitted host import (`from @bearbones/vite`)
  keeps working unchanged.
- vite.config.ts: declare run.tasks.build with dependsOn
  ["@bearbones/utils#build"], moving the build script out of
  package.json so vite-plus can wire the cross-package dependency. Also
  add `deps.alwaysBundle: ["@bearbones/utils"]` so utils' code is
  inlined into the published dist.
- package.json: drop the duplicate `build` script (now in vite.config.ts);
  keep `dev`, `test`, `check`. Move @bearbones/utils to devDependencies.

@bearbones/preset: just rebuild against new utils pipeline.

10 new tests in @bearbones/utils cover substituteAmp behavior +
literal-type assertions for the type-level utilities. Existing 59
@bearbones/vite tests still pass; the eight pinned literal-type
assertions in css-typing.ts still evaluate correctly because the
inlined utils source preserves return-type literals.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two more general-purpose runtime helpers move out of bearbones-vite
into the shared utils package, after the audit across the monorepo:

- deepAssign(target, source): recursive deep-merge for plain objects
  (was inline in transform.ts, used to merge style fragments). Generic
  over `Record<string, unknown>` so it composes with any plain-object
  shape — style fragments, token trees, config blobs.
- shortHash(input): 8-hex SHA1 hash builder (was inline in
  marker-registry.ts, used for marker suffix derivation). Also
  applicable to any "stable build-time id from a string" use case.

bearbones-vite imports both from @bearbones/utils now. Behavior
unchanged. 7 new tests in @bearbones/utils cover deepAssign merge
semantics (last-write-wins, nested-recursion, array-replacement,
type-coercion) and shortHash determinism + format.

Other audit candidates that I deliberately left in place because the
abstraction would be net-negative:
- cachePath/readCache/writeCache (index.ts): tightly coupled to the
  single Panda↔Vite cross-process cache pattern, only one consumer.
- serialize/hydrate pairs (utility-map.ts, conditions-stash.ts):
  package-shape-specific; the JSON.stringify/parse pattern isn't
  worth a generic helper.
- AST walker / babel helpers in transform.ts: tied to babel
  conventions; no second consumer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switch all package builds from the experimental tsgo path
(`pack.dts.tsgo: true` + `@typescript/native-preview` dev-dep) to the
stable rolldown-plugin-dts default. Reliability over bleeding-edge:
tsgo is marked experimental by vite-plus and was the source of the
cross-package rootDir limitation we worked around earlier.

Now that `@bearbones/utils` builds first via `run.tasks.build.dependsOn`,
the stable dts pipeline can resolve types through the workspace
package's emitted `dist/index.d.mts` cleanly — no isolated-declarations
re-export trip-up like we hit before.

Removes `@typescript/native-preview` from the three package devDeps
and rewrites each `vite.config.ts` to use `dts: true` instead of
`dts: { tsgo: true }`. All 76 tests still pass; website codegen
unchanged; literal-type assertions in css-typing.ts still pin the
exact runtime selector strings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Demo.tsx had `cardMarker(":hover").is.siblingAny` which violates the
runtime contract — every `marker()` call form requires the `&`
placeholder so substituteAmp can splice the anchor selector in. The
build was failing on `bearbones: marker() requires the '&' placeholder;
got: ":hover"`. Use `&:hover` instead, matching the convention every
other call site already follows.

Found by `vp run -r build` once the toolchain switched off the
experimental tsgo path — the build pipeline now exercises the demo's
extraction and surfaces this kind of contract violation as expected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The last hand-written template literal in the codegen-patch's emit
(BearbonesMarker<Id>.anchor: bearbones-marker-${Id}_${string}) is now
derived from a runtime function's return type, like every other piece
of the marker type surface.

Adds markerAnchorClass(id, hash) returning the literal-typed bare
class name `bearbones-marker-${Id}_${Hash}`. Refactors:

- markerAnchor (selector form, with leading `.`) composes via
  `.${ReturnType<typeof markerAnchorClass<Id, Hash>>}` — its return
  type is itself derived, so the two helpers stay in lockstep
  structurally.
- describeMarker delegates to markerAnchorClass for the runtime
  anchorClass field, so the runtime path mirrors the type-level
  derivation step-by-step.
- codegen-patch's BearbonesMarker.anchor emits as
  `ReturnType<typeof markerAnchorClass<Id, string>>` (no manual
  template). The `string` arg widens the unknown hash slot — fine
  here because consumers read .anchor as a className string, not as
  a computed-key constraint.

@bearbones/vite re-exports markerAnchorClass alongside markerAnchor
so the codegen-patch's emitted host import resolves cleanly.

Updated codegen-patch test asserts the new derivation patterns and
regenerated the snapshot. 59/59 + 17/17 tests pass; full
`vp run -r build` clean (utils → preset → vite → website panda+tsc+vite).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…Conditions

The BearbonesMarker interface was emitting one line per condition with
the literal CSS string repeated as the Cond type argument:

  readonly _hover: BearbonesMarkerBuilder<Id, "&:is(:hover, [data-hover])">;
  readonly _focusVisible: BearbonesMarkerBuilder<Id, "&:is(:focus-visible, [data-focus-visible])">;
  ...

That duplicates the host's condition vocabulary in dozens of places —
the literal strings only need to appear once.

Now codegen-patch emits a single typed map holding the full vocabulary:

  type BearbonesMarkerConditions = {
    readonly "hover": "&:is(:hover, [data-hover])";
    readonly "focusVisible": "&:is(:focus-visible, [data-focus-visible])";
    ...
  };

…and derives the per-shortcut shape via a mapped type:

  type BearbonesMarkerShortcuts<Id extends string> = {
    readonly [K in keyof BearbonesMarkerConditions as `_${K & string}`]:
      BearbonesMarkerBuilder<Id, BearbonesMarkerConditions[K]>;
  };

  export interface BearbonesMarker<Id extends string = string>
    extends BearbonesMarkerShortcuts<Id> {
    readonly anchor: ReturnType<typeof markerAnchorClass<Id, string>>;
    <C extends string>(condValue: C): BearbonesMarkerBuilder<Id, C>;
  }

Each CSS condition string now appears exactly once in the patched
css.d.ts (verified by a new test that counts occurrences). Hover-info
on `marker._hover.is.ancestor` still resolves to the exact runtime
selector literal — the indirection is purely structural.

Drops the now-unused `quoteIdentifierIfNeeded` helper; the mapped type's
key remapping handles non-identifier names natively.

Tests: 60/60 pass (added a "single-occurrence" assertion + updated the
shortcut-derivation assertion). Snapshot regenerated. Website production
build clean end-to-end.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dogmar dogmar changed the title Spec: marker selectors mirror stylex.when.* for proper specificity (#5) marker: stylex.when.* specificity + derive types from runtime functions (#5) May 3, 2026
dogmar and others added 4 commits May 2, 2026 19:54
Every package now references `typescript: "catalog:"` and
`vite-plus: "catalog:"` instead of hardcoded version ranges. Single
place to bump these — `pnpm-workspace.yaml` `catalog:` entry — and
every package picks the change up automatically. Bumps the catalog's
typescript range from ^5 to ^6.0.2 to match what was already installed
across the workspace.

Affects: packages/utils, packages/bearbones-vite, packages/bearbones-preset,
apps/website.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds @pandacss/preset-base and @pandacss/types alongside the existing
@pandacss/dev catalog entry, then switches every workspace package's
direct dep on these to "catalog:" — single source of version truth in
pnpm-workspace.yaml. Peer-dep entries stay as "*" intentionally
(consumers pick the resolved version).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds @babel/parser, fast-glob, and magic-string to the catalog and
switches @bearbones/vite's runtime dependencies to "catalog:". With
this every workspace package's deps go through the catalog — single
place to bump every shared version, no per-package drift.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Switches pnpm's catalogMode from "prefer" to "strict". With strict mode,
any direct version specifier in a workspace package's package.json that
isn't a "catalog:" reference will error at install time. Forces every
new dependency to go through the catalog — `vp add foo --save-catalog`
adds it to pnpm-workspace.yaml's catalog and references "catalog:" in
the package's package.json automatically; a plain `vp add foo` errors
out, prompting the developer to either use the flag or align with an
existing catalog entry.

Workspace-internal packages (workspace:*) are unaffected — those are a
separate resolution channel that pnpm doesn't route through the catalog.

Existing install passes cleanly under strict mode (every dep already
references "catalog:"); build + check + tests all green.

Sources:
- https://pnpm.io/catalogs (strict/prefer/manual modes)
- https://pnpm.io/settings (catalogMode reference)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@dogmar dogmar merged commit d4896f7 into main May 3, 2026
2 checks passed
@dogmar dogmar deleted the claude/silly-moore-bdbc86 branch May 3, 2026 03:01
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.

Make sure markers match selectors and selector specificity of stylex.when.* selectors

1 participant