Skip to content

Commit 54be93e

Browse files
committed
fix: address review comments for theme-dependent mixin support
- Mark useTheme() hook for splitVariantsResolvedValue branches too, not just splitVariantsResolvedStyles - Extract shared markThemeHookForVariants helper to avoid duplication - Skip destructured defaults check for dotted prop names (e.g., theme.isDark) since root-binding defaults don't inform member truthiness https://claude.ai/code/session_01DchMcXQzMb1tdBUmKf6Hek
1 parent af1f507 commit 54be93e

File tree

4 files changed

+33
-11
lines changed

4 files changed

+33
-11
lines changed

src/internal/builtin-handlers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,9 +344,12 @@ function tryResolveArrowFnCallWithConditionalArgs(
344344
// Support destructured defaults when we can statically determine their truthiness.
345345
// Destructuring defaults only apply when the prop is `undefined`, so we must
346346
// preserve that distinction in the emitted condition.
347+
// Skip for dotted prop names (e.g., "theme.isDark") since the default applies
348+
// to the root binding, not the member access — truthiness would be semantically wrong.
347349
if (
348350
bindings.kind === "destructured" &&
349351
bindings.defaults &&
352+
!propName.includes(".") &&
350353
bindings.defaults.has(propName)
351354
) {
352355
const defaultValue = extractStaticLiteralValue(bindings.defaults.get(propName));

src/internal/lower-rules/rule-interpolated-declaration.ts

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1253,17 +1253,7 @@ export function handleInterpolatedDeclaration(args: InterpolatedDeclarationConte
12531253
if (bail) {
12541254
break;
12551255
}
1256-
// If any variant condition references theme, trigger useTheme() hook import/declaration
1257-
const referencesTheme = res.variants.some(
1258-
(v: { when: string }) =>
1259-
v.when === "theme" ||
1260-
v.when.startsWith("theme.") ||
1261-
v.when === "!theme" ||
1262-
v.when.startsWith("!theme."),
1263-
);
1264-
if (referencesTheme) {
1265-
markDeclNeedsUseThemeHook(decl);
1266-
}
1256+
markThemeHookForVariants(decl, res.variants);
12671257
decl.needsWrapperComponent = true;
12681258
continue;
12691259
}
@@ -1289,6 +1279,9 @@ export function handleInterpolatedDeclaration(args: InterpolatedDeclarationConte
12891279
bailUnsupported: bailUnsupportedLocal,
12901280
})
12911281
) {
1282+
if (res && "variants" in res) {
1283+
markThemeHookForVariants(decl, res.variants as ReadonlyArray<{ when: string }>);
1284+
}
12921285
continue;
12931286
}
12941287

@@ -2884,3 +2877,27 @@ function tryHandleMultiSlotTernary(ctx: DeclProcessingState, d: CssDeclarationIR
28842877

28852878
return true;
28862879
}
2880+
2881+
/**
2882+
* If any variant `when` condition references the styled-components theme object,
2883+
* mark the declaration as needing the `useTheme()` hook so the emitted wrapper
2884+
* has `const theme = useTheme()` in scope.
2885+
*/
2886+
function markThemeHookForVariants(
2887+
decl: StyledDecl,
2888+
variants: ReadonlyArray<{ when: string }> | undefined,
2889+
): void {
2890+
if (!variants) {
2891+
return;
2892+
}
2893+
const needsTheme = variants.some(
2894+
(v) =>
2895+
v.when === "theme" ||
2896+
v.when.startsWith("theme.") ||
2897+
v.when === "!theme" ||
2898+
v.when.startsWith("!theme."),
2899+
);
2900+
if (needsTheme) {
2901+
markDeclNeedsUseThemeHook(decl);
2902+
}
2903+
}

test-cases/mixin-dynamicArgTheme.input.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import styled from "styled-components";
33
import { truncateMultiline } from "./lib/helpers";
44

5+
// Theme-dependent mixin: theme.isDark controls the argument to the helper
56
const ThemeText = styled.div`
67
line-height: 1rem;
78
${({ theme }) => truncateMultiline(theme.isDark ? 1 : 2)};

test-cases/mixin-dynamicArgTheme.output.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as stylex from "@stylexjs/stylex";
33
import { useTheme } from "styled-components";
44
import { helpers } from "./lib/helpers.stylex";
55

6+
// Theme-dependent mixin: theme.isDark controls the argument to the helper
67
function ThemeText(props: React.PropsWithChildren<{}>) {
78
const theme = useTheme();
89

0 commit comments

Comments
 (0)