diff --git a/.changeset/bui-bg-inherit-css-var.md b/.changeset/bui-bg-inherit-css-var.md new file mode 100644 index 0000000000..214e370c2e --- /dev/null +++ b/.changeset/bui-bg-inherit-css-var.md @@ -0,0 +1,24 @@ +--- +'@backstage/ui': patch +--- + +Added a public `--bui-bg-inherit` CSS variable that resolves to the background +color of the nearest enclosing bg provider (`Box`, `Flex`, `Grid`, `Card`, +`Accordion`, or any element with a `data-bg` attribute), falling back to +`--bui-bg-app`. Use it from CSS for sticky or fixed elements that need to match +their surrounding surface without hardcoding a specific level. + +```css +.searchBarContainer { + position: sticky; + top: 0; + background-color: var(--bui-bg-inherit); +} +``` + +As part of this change, the `data-bg` painting rules previously duplicated in +`Box`, `Flex`, `Grid`, `Accordion`, and `Card` have been centralized into a +single source in `core.css`. Painting and component behavior are unchanged for +all existing usages, with one minor expansion: any element with a `data-bg` +attribute (including provider elements and any element that sets it directly) +is now painted, not only `Box`/`Flex`/`Grid`/`Card`/`Accordion` elements. diff --git a/docs-ui/src/app/tokens/page.mdx b/docs-ui/src/app/tokens/page.mdx index f359c10525..dbaab30252 100644 --- a/docs-ui/src/app/tokens/page.mdx +++ b/docs-ui/src/app/tokens/page.mdx @@ -264,6 +264,42 @@ pressed, and disabled variants for interactive states. +## Inherited background + +`--bui-bg-inherit` resolves to the bg color of the nearest enclosing element with a +`data-bg` attribute (set by `Box`, `Flex`, `Grid`, `Card`, `Accordion`, or any +element that explicitly sets `data-bg`). When no such ancestor exists it falls +back to `--bui-bg-app`. Use it from CSS when a sticky, fixed, or otherwise +overlapping element needs to match its surrounding bg without hardcoding a level. + + + + + + + Prop + Description + + + + + + --bui-bg-inherit + + + Resolves to the bg color of the nearest enclosing `data-bg` ancestor, + falling back to `--bui-bg-app`. + + + + + ## Solid background colors diff --git a/packages/ui/src/components/Accordion/Accordion.module.css b/packages/ui/src/components/Accordion/Accordion.module.css index 83ae6c24b8..06598d0529 100644 --- a/packages/ui/src/components/Accordion/Accordion.module.css +++ b/packages/ui/src/components/Accordion/Accordion.module.css @@ -21,18 +21,12 @@ width: 100%; border-radius: var(--bui-radius-3); padding: var(--bui-space-3); + } - &[data-bg='neutral-1'] { - background-color: var(--bui-bg-neutral-1); - } - - &[data-bg='neutral-2'] { - background-color: var(--bui-bg-neutral-2); - } - - &[data-bg='neutral-3'] { - background-color: var(--bui-bg-neutral-3); - } + .bui-Accordion[data-bg='danger'], + .bui-Accordion[data-bg='warning'], + .bui-Accordion[data-bg='success'] { + background-color: transparent; } .bui-AccordionTrigger { diff --git a/packages/ui/src/components/Box/Box.module.css b/packages/ui/src/components/Box/Box.module.css index dd1ff447bc..688358fda0 100644 --- a/packages/ui/src/components/Box/Box.module.css +++ b/packages/ui/src/components/Box/Box.module.css @@ -22,28 +22,4 @@ font-weight: var(--bui-font-weight-regular); color: var(--bui-fg-primary); } - - .bui-Box[data-bg='neutral-1'] { - background-color: var(--bui-bg-neutral-1); - } - - .bui-Box[data-bg='neutral-2'] { - background-color: var(--bui-bg-neutral-2); - } - - .bui-Box[data-bg='neutral-3'] { - background-color: var(--bui-bg-neutral-3); - } - - .bui-Box[data-bg='danger'] { - background-color: var(--bui-bg-danger); - } - - .bui-Box[data-bg='warning'] { - background-color: var(--bui-bg-warning); - } - - .bui-Box[data-bg='success'] { - background-color: var(--bui-bg-success); - } } diff --git a/packages/ui/src/components/Card/Card.module.css b/packages/ui/src/components/Card/Card.module.css index 91c533aaa5..617c922707 100644 --- a/packages/ui/src/components/Card/Card.module.css +++ b/packages/ui/src/components/Card/Card.module.css @@ -29,18 +29,6 @@ padding: var(--bui-space-3); } - .bui-Card[data-bg='neutral-1'] { - --bui-card-bg: var(--bui-bg-neutral-1); - } - - .bui-Card[data-bg='neutral-2'] { - --bui-card-bg: var(--bui-bg-neutral-2); - } - - .bui-Card[data-bg='neutral-3'] { - --bui-card-bg: var(--bui-bg-neutral-3); - } - .bui-Card:has(.bui-CardHeader, .bui-CardBody, .bui-CardFooter) { padding: 0; } @@ -127,8 +115,8 @@ margin-bottom: -1.5rem; background: linear-gradient( to bottom, - var(--bui-card-bg), - rgb(from var(--bui-card-bg) r g b / 0) + var(--bui-bg-inherit), + rgb(from var(--bui-bg-inherit) r g b / 0) ); pointer-events: none; opacity: 0; @@ -146,8 +134,8 @@ margin-top: -1.5rem; background: linear-gradient( to top, - var(--bui-card-bg), - rgb(from var(--bui-card-bg) r g b / 0) + var(--bui-bg-inherit), + rgb(from var(--bui-bg-inherit) r g b / 0) ); pointer-events: none; opacity: 0; diff --git a/packages/ui/src/components/Flex/Flex.module.css b/packages/ui/src/components/Flex/Flex.module.css index 499326b9ea..0d44fbd12f 100644 --- a/packages/ui/src/components/Flex/Flex.module.css +++ b/packages/ui/src/components/Flex/Flex.module.css @@ -23,28 +23,4 @@ /* This helps when using `truncate` on text inside a flex container */ min-width: 0; } - - .bui-Flex[data-bg='neutral-1'] { - background-color: var(--bui-bg-neutral-1); - } - - .bui-Flex[data-bg='neutral-2'] { - background-color: var(--bui-bg-neutral-2); - } - - .bui-Flex[data-bg='neutral-3'] { - background-color: var(--bui-bg-neutral-3); - } - - .bui-Flex[data-bg='danger'] { - background-color: var(--bui-bg-danger); - } - - .bui-Flex[data-bg='warning'] { - background-color: var(--bui-bg-warning); - } - - .bui-Flex[data-bg='success'] { - background-color: var(--bui-bg-success); - } } diff --git a/packages/ui/src/components/Grid/Grid.module.css b/packages/ui/src/components/Grid/Grid.module.css index 8fdaf15c3b..ff98e9337f 100644 --- a/packages/ui/src/components/Grid/Grid.module.css +++ b/packages/ui/src/components/Grid/Grid.module.css @@ -20,34 +20,4 @@ .bui-Grid { display: grid; } - - .bui-Grid[data-bg='neutral-1'], - .bui-GridItem[data-bg='neutral-1'] { - background-color: var(--bui-bg-neutral-1); - } - - .bui-Grid[data-bg='neutral-2'], - .bui-GridItem[data-bg='neutral-2'] { - background-color: var(--bui-bg-neutral-2); - } - - .bui-Grid[data-bg='neutral-3'], - .bui-GridItem[data-bg='neutral-3'] { - background-color: var(--bui-bg-neutral-3); - } - - .bui-Grid[data-bg='danger'], - .bui-GridItem[data-bg='danger'] { - background-color: var(--bui-bg-danger); - } - - .bui-Grid[data-bg='warning'], - .bui-GridItem[data-bg='warning'] { - background-color: var(--bui-bg-warning); - } - - .bui-Grid[data-bg='success'], - .bui-GridItem[data-bg='success'] { - background-color: var(--bui-bg-success); - } } diff --git a/packages/ui/src/css/colors.stories.tsx b/packages/ui/src/css/colors.stories.tsx index 2d1a3614a7..49e3cdaec5 100644 --- a/packages/ui/src/css/colors.stories.tsx +++ b/packages/ui/src/css/colors.stories.tsx @@ -23,6 +23,24 @@ const meta = preview.meta({ tags: ['!manifest'], }); +/** + * A `
` styled with `background: var(--bui-bg-inherit)` should always + * resolve to the same color as the surrounding bg provider — at every level + * of the neutral chain and inside intent surfaces. + */ +const Probe = ({ label }: { label: string }) => ( +
+ {label} +
+); + export const Default = meta.story({ render: () => (
@@ -151,3 +169,37 @@ export const Default = meta.story({
), }); + +export const BgInherit = meta.story({ + render: () => ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ), +}); diff --git a/packages/ui/src/css/core.css b/packages/ui/src/css/core.css index 1047215ee8..74f5960017 100644 --- a/packages/ui/src/css/core.css +++ b/packages/ui/src/css/core.css @@ -47,4 +47,38 @@ [data-theme-mode='light'] { color-scheme: light; } + + :root { + --bui-bg-inherit: var(--bui-bg-app); + } + + [data-bg='neutral-1'] { + background-color: var(--bui-bg-neutral-1); + --bui-bg-inherit: var(--bui-bg-neutral-1); + } + + [data-bg='neutral-2'] { + background-color: var(--bui-bg-neutral-2); + --bui-bg-inherit: var(--bui-bg-neutral-2); + } + + [data-bg='neutral-3'] { + background-color: var(--bui-bg-neutral-3); + --bui-bg-inherit: var(--bui-bg-neutral-3); + } + + [data-bg='danger'] { + background-color: var(--bui-bg-danger); + --bui-bg-inherit: var(--bui-bg-danger); + } + + [data-bg='warning'] { + background-color: var(--bui-bg-warning); + --bui-bg-inherit: var(--bui-bg-warning); + } + + [data-bg='success'] { + background-color: var(--bui-bg-success); + --bui-bg-inherit: var(--bui-bg-success); + } }