Repository navigation
Description
Before submitting a new issue
- I tested using the latest version of the library, as the bug might be already fixed.
- I tested using a supported version of react native.
- I checked for possible duplicate issues, with possible answers.
Bug summary
A CSS-wide keyword passed as a runtime variable value does not take its CSS meaning. Custom properties inherit, so unset and inherit take the parent's value, and initial is the guaranteed-invalid value, which makes a var() use its fallback (css-variables-1 §2, css-cascade-5 §7.3).
With an outer VariableContextProvider setting --my-var: red and an inner one setting the keyword, .test { color: var(--my-var, green) } renders:
| Inner value | main |
Browsers |
|---|---|---|
"unset" |
no color | red |
"inherit" |
color: "inherit" |
red |
"initial" |
color: "initial" |
green |
"unset" clears because resolveValue turns the string "unset" into null for every value, which is how background-color: unset resets a style (#90). A variable holding "unset" goes through the same path, so the property that reads it is cleared. #431 kept that as the way to clear a variable from the runtime, and its test asserts it.
A possible fix, for VariableContextProvider and vars():
"unset"and"inherit"produce no key, asundefineddoes since fix(native): a custom property with no value produces no key #431, so the inherited value applies."initial"stores the guaranteed-invalid value, so avar()reading it uses its fallback, and with no fallback the property is cleared.
background-color: unset and the #431 behaviour for undefined stay as they are, and clearing stays available through "initial", which gives the result #431's "clears a variable with unset" test expects. The one change is that a runtime "unset" inherits, as in browsers, so that test would use "initial".
Does this match the intended semantics? If so, I'm happy to open a pull request. #503 covers the same keywords in compiled CSS (.child { --my-var: unset }), so the runtime side could reuse its representation of the guaranteed-invalid value.
Library version
3.1.0-rc.1 (main at 811f357)
Environment info
This repository's Jest suite on main, macOS, Node 24. Not platform specific.Steps to reproduce
Add to src/__tests__/native/variables.test.tsx and run yarn test variables:
test.each([
["unset", "red"],
["inherit", "red"],
["initial", "green"],
])("VariableContextProvider %s", (keyword, expected) => {
registerCSS(`
.other { --my-var: blue; }
.other-2 { --my-var: purple; }
.test { color: var(--my-var, green); }
`);
render(
<VariableContextProvider value={{ "--my-var": "red" }}>
<VariableContextProvider value={{ "--my-var": keyword }}>
<View testID={testID} className="test" />
</VariableContextProvider>
</VariableContextProvider>,
);
expect(screen.getByTestId(testID).props.style).toStrictEqual({
color: expected,
});
});Reproducible example repository
Reproduces in this repository's own Jest suite (steps above).
Activity