Repository navigation
fix(react-provider): escape theme delimiters instead of omitting valid nested theme values - #36985
Draft
Victor Genaev (mainframev) wants to merge 1 commit into
Conversation
📊 Bundle size reportUnchanged fixtures
|
|
Pull request demo site: URL |
| @@ -7,10 +7,11 @@ underscores are rejected in names. Values must be strings or finite numbers. | |||
| Values containing `<`, `>`, `{`, `}`, `;`, `\`, `[`, `]`, `!`, the CSS comment opener `/*`, or non-whitespace control | |||
There was a problem hiding this comment.
🕵🏾♀️ visual changes to review in the Visual Change Report
vr-tests-react-components/Avatar Converged 1 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/Avatar Converged.badgeMask.normal.chromium.png | 6 | Changed |
vr-tests-react-components/Positioning 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/Positioning.Positioning end.chromium.png | 33 | Changed |
| vr-tests-react-components/Positioning.Positioning end.updated 2 times.chromium.png | 767 | Changed |
vr-tests-react-components/ProgressBar converged 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/ProgressBar converged.Indeterminate + thickness - Dark Mode.default.chromium.png | 1 | Changed |
| vr-tests-react-components/ProgressBar converged.Indeterminate + thickness - High Contrast.default.chromium.png | 69 | Changed |
vr-tests-react-components/TagPicker 2 screenshots
| Image Name | Diff(in Pixels) | Image Type |
|---|---|---|
| vr-tests-react-components/TagPicker.disabled - Dark Mode.chromium.png | 658 | Changed |
| vr-tests-react-components/TagPicker.disabled - RTL.disabled input hover.chromium.png | 635 | Changed |
There were 2 duplicate changes discarded. Check the build logs for more information.
…d nested theme values
createCSSRuleFromTheme omitted theme values whose parentheses were nested or
whose function arguments were quoted, so valid tokens such as
var(--a, rgb(0 0 0)) and oklch(from var(--a) l c h / 0.5) were silently
dropped from the FluentProvider style tag.
Escape <, >, {, }, ; and backslash in token names and values instead, and
serialize everything else unchanged. Each token stays inside its declaration,
the rule and the style tag. A malformed value can still affect later tokens in
the same provider rule; this tradeoff is accepted to avoid a CSS syntax
validator.
Victor Genaev (mainframev)
force-pushed
the
fix/react-provider-nested-theme-token-values
branch
from
October 23, 2026 14:58
c14de9f to
c4c5101
Compare
This branch has not been deployed
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.

Previous Behavior
#36830 replaced escaping in
createCSSRuleFromTheme(used byFluentProvider) with blocklists plus a leftover-delimiter check. That check only discards flat(...)groups and top-level strings, so valid values with nested functions or quoted arguments are silently omitted from the provider style tag:var(--custom-color, rgb(0 0 0)),var(--a, var(--b)),var(--font, "Segoe UI")calc(var(--size) * 2),clamp(1rem, calc(var(--scale, 1) * 2vw), 3rem)color-mix(in srgb, var(--a) 50%, transparent),oklch(from var(--a) l c h / 0.5)The built-in themes only use flat values, so no test in this repo caught it. Downstream, Microsoft 365 Copilot (Bebop) derives hover and pressed colors with relative color syntax, for example
calc(l - 0.03 * clamp(1,(.5 - l)/.1,3)) c h / calc(alpha + 0.04)andoklch(from var(--token) var(--interactionStandardHover)). With@fluentui/react-provider@9.22.22those tokens disappear and the dependent colors fall back to transparent.New Behavior
Go back to escaping, as in the first revision of #36830. Token names and values are serialized unchanged except for
<,>,{,},;and\, which become CSS escapes. That keeps every token inside its own declaration, the generated rule and the surrounding<style>tag, which is what the fix for MSRC 129538 required. Quotes and parentheses are no longer checked, so valid nested values are preserved.<and>: the value can't close the<style>tag (SSR).{and}: the value can't close the rule or open a new one.;: the value can't add declarations to the provider rule.\: the value can't escape the separator that follows it, for example a trailingred\.Selector escaping (#36464, backslash parity) is unchanged.
Tradeoff, accepted deliberately: values are no longer validated. A malformed value, such as an unclosed string, comment or function (
"unfinished,calc(1px,red /* x), can absorb the later tokens in the same provider rule. This is the token-isolation class from MSRC 138890 that #36713/#36830 addressed by validation. The value still cannot leave the declaration list, the rule or the<style>tag, so the markup/rule breakout from MSRC 129538 stays fixed. Theme data from untrusted sources still needs an application-specific schema, as the docs say. Development warnings and omit-and-warn behavior are removed. Docs (Theming.mdx,createCSSRuleFromThemeDescription.md) are updated.Compared with the first revision of #36830 (
3c21f40), this also escapes;(as its second commit did) and keeps the current backslash-parity selector escaping from #36464 instead of escaping\in selectors.Validation
jest src/components/FluentProvider(react-provider): 8 suites, 108 tests passed. This includes the jsdom CSSOM check thatred; } .other { color: transparentstays a single rule with no injectedcolorand later tokens intact, and the SSR check that markup values produce one<style>element and no<script>.eslintandprettier --checkon the changed files: passed.Related Issue(s)