diff --git a/.changeset/seven-lines-stay.md b/.changeset/seven-lines-stay.md new file mode 100644 index 0000000000..4148a4eb83 --- /dev/null +++ b/.changeset/seven-lines-stay.md @@ -0,0 +1,5 @@ +--- +'@backstage/ui': patch +--- + +We are restructuring our CSS to have a better layer structure. diff --git a/packages/ui/src/components/Avatar/Avatar.styles.css b/packages/ui/src/components/Avatar/Avatar.styles.css index ce3afea3b5..ce2573c4b0 100644 --- a/packages/ui/src/components/Avatar/Avatar.styles.css +++ b/packages/ui/src/components/Avatar/Avatar.styles.css @@ -14,52 +14,54 @@ * limitations under the License. */ -.bui-AvatarRoot { - display: inline-flex; - justify-content: center; - align-items: center; - vertical-align: middle; - border-radius: 100%; - user-select: none; - font-weight: 500; - color: var(--bui-fg-primary); - background-color: var(--bui-bg-surface-2); - font-size: 1rem; - line-height: 1; - overflow: hidden; - height: 2rem; - width: 2rem; -} +@layer components { + .bui-AvatarRoot { + display: inline-flex; + justify-content: center; + align-items: center; + vertical-align: middle; + border-radius: 100%; + user-select: none; + font-weight: 500; + color: var(--bui-fg-primary); + background-color: var(--bui-bg-surface-2); + font-size: 1rem; + line-height: 1; + overflow: hidden; + height: 2rem; + width: 2rem; + } -.bui-AvatarRoot[data-size='small'] { - height: 1.5rem; - width: 1.5rem; -} + .bui-AvatarRoot[data-size='small'] { + height: 1.5rem; + width: 1.5rem; + } -.bui-AvatarRoot[data-size='medium'] { - height: 2rem; - width: 2rem; -} + .bui-AvatarRoot[data-size='medium'] { + height: 2rem; + width: 2rem; + } -.bui-AvatarRoot[data-size='large'] { - height: 3rem; - width: 3rem; -} + .bui-AvatarRoot[data-size='large'] { + height: 3rem; + width: 3rem; + } -.bui-AvatarImage { - object-fit: cover; - height: 100%; - width: 100%; -} + .bui-AvatarImage { + object-fit: cover; + height: 100%; + width: 100%; + } -.bui-AvatarFallback { - align-items: center; - display: flex; - justify-content: center; - height: 100%; - width: 100%; - font-size: var(--bui-font-size-3); - font-weight: var(--bui-font-weight-regular); - box-shadow: inset 0 0 0 1px var(--bui-border); - border-radius: var(--bui-radius-full); + .bui-AvatarFallback { + align-items: center; + display: flex; + justify-content: center; + height: 100%; + width: 100%; + font-size: var(--bui-font-size-3); + font-weight: var(--bui-font-weight-regular); + box-shadow: inset 0 0 0 1px var(--bui-border); + border-radius: var(--bui-radius-full); + } } diff --git a/packages/ui/src/components/Box/styles.css b/packages/ui/src/components/Box/styles.css index c499657230..a1648b476c 100644 --- a/packages/ui/src/components/Box/styles.css +++ b/packages/ui/src/components/Box/styles.css @@ -1,5 +1,23 @@ -.bui-Box { - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@layer components { + .bui-Box { + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + } } diff --git a/packages/ui/src/components/Button/styles.css b/packages/ui/src/components/Button/styles.css index 03138a7c44..aec754c740 100644 --- a/packages/ui/src/components/Button/styles.css +++ b/packages/ui/src/components/Button/styles.css @@ -14,118 +14,120 @@ * limitations under the License. */ -.bui-Button { - border: none; - display: inline-flex; - align-items: center; - justify-content: center; - user-select: none; - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-bold); - padding: 0; - cursor: pointer; - border-radius: var(--bui-radius-2); - gap: var(--bui-space-1_5); - flex-shrink: 0; +@layer components { + .bui-Button { + border: none; + display: inline-flex; + align-items: center; + justify-content: center; + user-select: none; + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-bold); + padding: 0; + cursor: pointer; + border-radius: var(--bui-radius-2); + gap: var(--bui-space-1_5); + flex-shrink: 0; - &[data-disabled='true'] { - cursor: not-allowed; - } -} - -.bui-Button[data-variant='primary'] { - background-color: var(--bui-bg-solid); - color: var(--bui-fg-solid); - - &:hover { - background-color: var(--bui-bg-solid-hover); - transition: background-color 150ms ease; + &[data-disabled='true'] { + cursor: not-allowed; + } } - &:active { - background-color: var(--bui-bg-solid-pressed); + .bui-Button[data-variant='primary'] { + background-color: var(--bui-bg-solid); + color: var(--bui-fg-solid); + + &:hover { + background-color: var(--bui-bg-solid-hover); + transition: background-color 150ms ease; + } + + &:active { + background-color: var(--bui-bg-solid-pressed); + } + + &:focus-visible { + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + } + + &[data-disabled='true'] { + background-color: var(--bui-bg-solid-disabled); + color: var(--bui-fg-solid-disabled); + } } - &:focus-visible { - outline: 2px solid var(--bui-ring); - outline-offset: 2px; - } - - &[data-disabled='true'] { - background-color: var(--bui-bg-solid-disabled); - color: var(--bui-fg-solid-disabled); - } -} - -.bui-Button[data-variant='secondary'] { - background-color: var(--bui-bg-surface-1); - box-shadow: inset 0 0 0 1px var(--bui-border); - color: var(--bui-fg-primary); - - &:hover { - box-shadow: inset 0 0 0 1px var(--bui-border-hover); - transition: box-shadow 150ms ease; - } - - &:active { - box-shadow: inset 0 0 0 1px var(--bui-border-pressed); - } - - &:focus-visible { - outline: none; - transition: none; - box-shadow: inset 0 0 0 2px var(--bui-ring); - } - - &[data-disabled='true'] { - box-shadow: inset 0 0 0 1px var(--bui-border-disabled); - color: var(--bui-fg-disabled); - } -} - -.bui-Button[data-variant='tertiary'] { - background-color: transparent; - color: var(--bui-fg-primary); - - &:hover { + .bui-Button[data-variant='secondary'] { background-color: var(--bui-bg-surface-1); - transition: background-color 200ms ease; + box-shadow: inset 0 0 0 1px var(--bui-border); + color: var(--bui-fg-primary); + + &:hover { + box-shadow: inset 0 0 0 1px var(--bui-border-hover); + transition: box-shadow 150ms ease; + } + + &:active { + box-shadow: inset 0 0 0 1px var(--bui-border-pressed); + } + + &:focus-visible { + outline: none; + transition: none; + box-shadow: inset 0 0 0 2px var(--bui-ring); + } + + &[data-disabled='true'] { + box-shadow: inset 0 0 0 1px var(--bui-border-disabled); + color: var(--bui-fg-disabled); + } } - &:active { - background-color: var(--bui-bg-surface-2); - } - - &:focus-visible { - outline: none; - transition: none; - box-shadow: inset 0 0 0 2px var(--bui-ring); - } - - &[data-disabled='true'] { + .bui-Button[data-variant='tertiary'] { background-color: transparent; - color: var(--bui-fg-disabled); + color: var(--bui-fg-primary); + + &:hover { + background-color: var(--bui-bg-surface-1); + transition: background-color 200ms ease; + } + + &:active { + background-color: var(--bui-bg-surface-2); + } + + &:focus-visible { + outline: none; + transition: none; + box-shadow: inset 0 0 0 2px var(--bui-ring); + } + + &[data-disabled='true'] { + background-color: transparent; + color: var(--bui-fg-disabled); + } + } + + .bui-Button[data-size='medium'] { + font-size: var(--bui-font-size-4); + padding: 0 var(--bui-space-3); + height: 2.5rem; + } + + .bui-Button[data-size='small'] { + font-size: var(--bui-font-size-3); + padding: 0 var(--bui-space-2); + height: 2rem; + } + + .bui-Button[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + .bui-Button[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; } } - -.bui-Button[data-size='medium'] { - font-size: var(--bui-font-size-4); - padding: 0 var(--bui-space-3); - height: 2.5rem; -} - -.bui-Button[data-size='small'] { - font-size: var(--bui-font-size-3); - padding: 0 var(--bui-space-2); - height: 2rem; -} - -.bui-Button[data-size='small'] svg { - width: 1rem; - height: 1rem; -} - -.bui-Button[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; -} diff --git a/packages/ui/src/components/ButtonIcon/styles.css b/packages/ui/src/components/ButtonIcon/styles.css index cbd19071a9..56b73a8a66 100644 --- a/packages/ui/src/components/ButtonIcon/styles.css +++ b/packages/ui/src/components/ButtonIcon/styles.css @@ -14,17 +14,19 @@ * limitations under the License. */ -.bui-ButtonIcon { - align-items: center; - justify-content: center; -} +@layer components { + .bui-ButtonIcon { + align-items: center; + justify-content: center; + } -.bui-ButtonIcon[data-size='small'] { - padding: 0; - width: 2rem; -} + .bui-ButtonIcon[data-size='small'] { + padding: 0; + width: 2rem; + } -.bui-ButtonIcon[data-size='medium'] { - padding: 0; - width: 2.5rem; + .bui-ButtonIcon[data-size='medium'] { + padding: 0; + width: 2.5rem; + } } diff --git a/packages/ui/src/components/Card/Card.styles.css b/packages/ui/src/components/Card/Card.styles.css index 1643ba0b8a..670e5de2c3 100644 --- a/packages/ui/src/components/Card/Card.styles.css +++ b/packages/ui/src/components/Card/Card.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,30 +14,32 @@ * limitations under the License. */ -.bui-Card { - display: flex; - flex-direction: column; - gap: var(--bui-space-3); - background-color: var(--bui-bg-surface-1); - border-radius: var(--bui-radius-3); - padding-block: var(--bui-space-3); - color: var(--bui-fg-primary); - border: 1px solid var(--bui-border); - overflow: hidden; - min-height: 0; - width: 100%; -} +@layer components { + .bui-Card { + display: flex; + flex-direction: column; + gap: var(--bui-space-3); + background-color: var(--bui-bg-surface-1); + border-radius: var(--bui-radius-3); + padding-block: var(--bui-space-3); + color: var(--bui-fg-primary); + border: 1px solid var(--bui-border); + overflow: hidden; + min-height: 0; + width: 100%; + } -.bui-CardBody { - flex: 1; - min-height: 0; - overflow: auto; -} + .bui-CardBody { + flex: 1; + min-height: 0; + overflow: auto; + } -.bui-CardHeader { - padding-inline: var(--bui-space-3); -} + .bui-CardHeader { + padding-inline: var(--bui-space-3); + } -.bui-CardFooter { - padding-inline: var(--bui-space-3); + .bui-CardFooter { + padding-inline: var(--bui-space-3); + } } diff --git a/packages/ui/src/components/Checkbox/styles.css b/packages/ui/src/components/Checkbox/styles.css index 75d57e72aa..af813d4098 100644 --- a/packages/ui/src/components/Checkbox/styles.css +++ b/packages/ui/src/components/Checkbox/styles.css @@ -1,52 +1,70 @@ -.bui-CheckboxRoot { - border: none; - display: flex; - align-items: center; - justify-content: center; - width: 1rem; - height: 1rem; - box-shadow: inset 0 0 0 1px var(--bui-border); - cursor: pointer; - border-radius: 2px; - transition: background-color 0.2s ease-in-out; - background-color: var(--bui-bg-surface-1); - padding: 0; - flex-shrink: 0; -} +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -.bui-CheckboxRoot:focus-visible { - transition: none; - outline: 2px solid var(--bui-ring); - outline-offset: 2px; -} +@layer components { + .bui-CheckboxRoot { + border: none; + display: flex; + align-items: center; + justify-content: center; + width: 1rem; + height: 1rem; + box-shadow: inset 0 0 0 1px var(--bui-border); + cursor: pointer; + border-radius: 2px; + transition: background-color 0.2s ease-in-out; + background-color: var(--bui-bg-surface-1); + padding: 0; + flex-shrink: 0; + } -.bui-CheckboxRoot[data-checked] { - background-color: var(--bui-bg-solid); - box-shadow: none; - color: var(--bui-fg-solid); -} + .bui-CheckboxRoot:focus-visible { + transition: none; + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + } -.bui-CheckboxLabel { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - user-select: none; + .bui-CheckboxRoot[data-checked] { + background-color: var(--bui-bg-solid); + box-shadow: none; + color: var(--bui-fg-solid); + } - &:hover { - & .bui-CheckboxRoot:not([data-checked]) { - box-shadow: inset 0 0 0 1px var(--bui-border-hover); + .bui-CheckboxLabel { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + user-select: none; + + &:hover { + & .bui-CheckboxRoot:not([data-checked]) { + box-shadow: inset 0 0 0 1px var(--bui-border-hover); + } } } -} -.bui-CheckboxIndicator { - display: flex; - align-items: center; - justify-content: center; - color: var(--bui-fg-solid); + .bui-CheckboxIndicator { + display: flex; + align-items: center; + justify-content: center; + color: var(--bui-fg-solid); + } } diff --git a/packages/ui/src/components/Collapsible/Collapsible.styles.css b/packages/ui/src/components/Collapsible/Collapsible.styles.css index e1fbf00a82..35b0992a62 100644 --- a/packages/ui/src/components/Collapsible/Collapsible.styles.css +++ b/packages/ui/src/components/Collapsible/Collapsible.styles.css @@ -14,14 +14,16 @@ * limitations under the License. */ -.bui-CollapsiblePanel { - display: flex; - height: var(--collapsible-panel-height); - overflow: hidden; - transition: all 150ms ease-out; +@layer components { + .bui-CollapsiblePanel { + display: flex; + height: var(--collapsible-panel-height); + overflow: hidden; + transition: all 150ms ease-out; - &[data-starting-style], - &[data-ending-style] { - height: 0; + &[data-starting-style], + &[data-ending-style] { + height: 0; + } } } diff --git a/packages/ui/src/components/Container/styles.css b/packages/ui/src/components/Container/styles.css index a812b7c767..515e449457 100644 --- a/packages/ui/src/components/Container/styles.css +++ b/packages/ui/src/components/Container/styles.css @@ -1,12 +1,30 @@ -.bui-Container { - max-width: 120rem; - padding-inline: var(--bui-space-4); - margin-inline: auto; - transition: padding 0.2s ease-in-out; -} +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -@media (min-width: 640px) { +@layer components { .bui-Container { - padding-inline: var(--bui-space-5); + max-width: 120rem; + padding-inline: var(--bui-space-4); + margin-inline: auto; + transition: padding 0.2s ease-in-out; + } + + @media (min-width: 640px) { + .bui-Container { + padding-inline: var(--bui-space-5); + } } } diff --git a/packages/ui/src/components/FieldError/FieldError.styles.css b/packages/ui/src/components/FieldError/FieldError.styles.css index e69e8637d3..90b0547ab7 100644 --- a/packages/ui/src/components/FieldError/FieldError.styles.css +++ b/packages/ui/src/components/FieldError/FieldError.styles.css @@ -1,7 +1,25 @@ -.bui-FieldError { - display: inline-block; - color: var(--bui-fg-danger); - font-size: var(--bui-font-size-2); - font-weight: var(--bui-font-weight-regular); - margin-top: var(--bui-space-2); +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@layer components { + .bui-FieldError { + display: inline-block; + color: var(--bui-fg-danger); + font-size: var(--bui-font-size-2); + font-weight: var(--bui-font-weight-regular); + margin-top: var(--bui-space-2); + } } diff --git a/packages/ui/src/components/FieldLabel/FieldLabel.styles.css b/packages/ui/src/components/FieldLabel/FieldLabel.styles.css index 2dfc28a49d..0a70e69ea2 100644 --- a/packages/ui/src/components/FieldLabel/FieldLabel.styles.css +++ b/packages/ui/src/components/FieldLabel/FieldLabel.styles.css @@ -1,27 +1,45 @@ -.bui-FieldLabelWrapper { - display: flex; - flex-direction: column; - margin-bottom: var(--bui-space-3); - gap: var(--bui-space-1); -} +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -.bui-FieldLabel { - color: var(--bui-fg-primary); - margin-right: auto; - cursor: pointer; - font-weight: var(--bui-font-weight-regular); - font-size: var(--bui-font-size-2); -} +@layer components { + .bui-FieldLabelWrapper { + display: flex; + flex-direction: column; + margin-bottom: var(--bui-space-3); + gap: var(--bui-space-1); + } -.bui-FieldSecondaryLabel { - color: var(--bui-fg-secondary); - font-weight: var(--bui-font-weight-regular); - margin-left: var(--bui-space-1); -} + .bui-FieldLabel { + color: var(--bui-fg-primary); + margin-right: auto; + cursor: pointer; + font-weight: var(--bui-font-weight-regular); + font-size: var(--bui-font-size-2); + } -.bui-FieldDescription { - font-weight: var(--bui-font-weight-regular); - font-size: var(--bui-font-size-2); - color: var(--bui-fg-secondary); - margin: 0; + .bui-FieldSecondaryLabel { + color: var(--bui-fg-secondary); + font-weight: var(--bui-font-weight-regular); + margin-left: var(--bui-space-1); + } + + .bui-FieldDescription { + font-weight: var(--bui-font-weight-regular); + font-size: var(--bui-font-size-2); + color: var(--bui-fg-secondary); + margin: 0; + } } diff --git a/packages/ui/src/components/Flex/styles.css b/packages/ui/src/components/Flex/styles.css index 96c94ab58a..7c5eee12cd 100644 --- a/packages/ui/src/components/Flex/styles.css +++ b/packages/ui/src/components/Flex/styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,11 @@ * limitations under the License. */ -.bui-Flex { - display: flex; +@layer components { + .bui-Flex { + display: flex; - /* This helps when using `truncate` on text inside a flex container */ - min-width: 0; + /* This helps when using `truncate` on text inside a flex container */ + min-width: 0; + } } diff --git a/packages/ui/src/components/Grid/styles.css b/packages/ui/src/components/Grid/styles.css index e21191ad47..28e792ab54 100644 --- a/packages/ui/src/components/Grid/styles.css +++ b/packages/ui/src/components/Grid/styles.css @@ -1,3 +1,21 @@ -.bui-Grid { - display: grid; +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +@layer components { + .bui-Grid { + display: grid; + } } diff --git a/packages/ui/src/components/Header/Header.styles.css b/packages/ui/src/components/Header/Header.styles.css index 69c0065394..56f5573e0f 100644 --- a/packages/ui/src/components/Header/Header.styles.css +++ b/packages/ui/src/components/Header/Header.styles.css @@ -14,81 +14,83 @@ * limitations under the License. */ -.bui-HeaderToolbar { - margin-bottom: var(--bui-space-6); +@layer components { + .bui-HeaderToolbar { + margin-bottom: var(--bui-space-6); - &::before { - content: ''; - position: absolute; - top: 0; - left: 0px; - right: 0px; + &::before { + content: ''; + position: absolute; + top: 0; + left: 0px; + right: 0px; + height: 16px; + background-color: var(--bui-bg); + z-index: 0; + } + + &[data-has-tabs='true'] { + margin-bottom: 0; + } + } + + .bui-HeaderToolbarWrapper { + position: relative; + z-index: 1; + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + background-color: var(--bui-bg-surface-1); + padding-inline: var(--bui-space-5); + border-bottom: 1px solid var(--bui-border); + color: var(--bui-fg-primary); + height: 52px; + } + + .bui-HeaderToolbarContent { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + } + + .bui-HeaderToolbarName { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + font-size: var(--bui-font-size-3); + font-weight: var(--bui-font-weight-regular); + flex-shrink: 0; + } + + .bui-HeaderToolbarIcon { + width: 16px; height: 16px; - background-color: var(--bui-bg); - z-index: 0; + color: var(--bui-fg-primary); + + & svg { + width: 100%; + height: 100%; + } } - &[data-has-tabs='true'] { - margin-bottom: 0; + .bui-HeaderToolbarControls { + position: absolute; + right: var(--bui-space-5); + top: 50%; + transform: translateY(-50%); + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + } + + .bui-HeaderTabsWrapper { + margin-bottom: var(--bui-space-4); + padding-inline: var(--bui-space-3); + border-bottom: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); } } - -.bui-HeaderToolbarWrapper { - position: relative; - z-index: 1; - display: flex; - flex-direction: row; - align-items: center; - justify-content: space-between; - background-color: var(--bui-bg-surface-1); - padding-inline: var(--bui-space-5); - border-bottom: 1px solid var(--bui-border); - color: var(--bui-fg-primary); - height: 52px; -} - -.bui-HeaderToolbarContent { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); -} - -.bui-HeaderToolbarName { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); - font-size: var(--bui-font-size-3); - font-weight: var(--bui-font-weight-regular); - flex-shrink: 0; -} - -.bui-HeaderToolbarIcon { - width: 16px; - height: 16px; - color: var(--bui-fg-primary); - - & svg { - width: 100%; - height: 100%; - } -} - -.bui-HeaderToolbarControls { - position: absolute; - right: var(--bui-space-5); - top: 50%; - transform: translateY(-50%); - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); -} - -.bui-HeaderTabsWrapper { - margin-bottom: var(--bui-space-4); - padding-inline: var(--bui-space-3); - border-bottom: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); -} diff --git a/packages/ui/src/components/HeaderPage/HeaderPage.styles.css b/packages/ui/src/components/HeaderPage/HeaderPage.styles.css index aca756872c..b85320c9d4 100644 --- a/packages/ui/src/components/HeaderPage/HeaderPage.styles.css +++ b/packages/ui/src/components/HeaderPage/HeaderPage.styles.css @@ -14,34 +14,36 @@ * limitations under the License. */ -.bui-HeaderPage { - display: flex; - flex-direction: column; - gap: var(--bui-space-1); - margin-top: var(--bui-space-6); - margin-bottom: var(--bui-space-6); -} +@layer components { + .bui-HeaderPage { + display: flex; + flex-direction: column; + gap: var(--bui-space-1); + margin-top: var(--bui-space-6); + margin-bottom: var(--bui-space-6); + } -.bui-HeaderPageContent { - display: flex; - flex-direction: row; - justify-content: space-between; -} + .bui-HeaderPageContent { + display: flex; + flex-direction: row; + justify-content: space-between; + } -.bui-HeaderPageTabsWrapper { - margin-left: -8px; -} + .bui-HeaderPageTabsWrapper { + margin-left: -8px; + } -.bui-HeaderPageControls { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); -} + .bui-HeaderPageControls { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + } -.bui-HeaderPageBreadcrumbs { - display: flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); + .bui-HeaderPageBreadcrumbs { + display: flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + } } diff --git a/packages/ui/src/components/Icon/styles.css b/packages/ui/src/components/Icon/styles.css index a6a3f7d49c..b96d9d5f2b 100644 --- a/packages/ui/src/components/Icon/styles.css +++ b/packages/ui/src/components/Icon/styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,7 +14,9 @@ * limitations under the License. */ -.bui-Icon { - width: 1rem; - height: 1rem; +@layer components { + .bui-Icon { + width: 1rem; + height: 1rem; + } } diff --git a/packages/ui/src/components/Link/styles.css b/packages/ui/src/components/Link/styles.css index 76a56e2d7a..5931a1dfe2 100644 --- a/packages/ui/src/components/Link/styles.css +++ b/packages/ui/src/components/Link/styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,19 +14,21 @@ * limitations under the License. */ -.bui-Link { - font-family: var(--bui-font-regular); - padding: 0; - margin: 0; - cursor: pointer; - text-decoration-line: none; - display: inline-block; +@layer components { + .bui-Link { + font-family: var(--bui-font-regular); + padding: 0; + margin: 0; + cursor: pointer; + text-decoration-line: none; + display: inline-block; - &:hover { - text-decoration-line: underline; - text-decoration-style: solid; - text-decoration-thickness: min(2px, max(1px, 0.05em)); - text-underline-offset: calc(0.025em + 2px); - text-decoration-color: color-mix(in srgb, currentColor 30%, transparent); + &:hover { + text-decoration-line: underline; + text-decoration-style: solid; + text-decoration-thickness: min(2px, max(1px, 0.05em)); + text-underline-offset: calc(0.025em + 2px); + text-decoration-color: color-mix(in srgb, currentColor 30%, transparent); + } } } diff --git a/packages/ui/src/components/Menu/Menu.styles.css b/packages/ui/src/components/Menu/Menu.styles.css index 1d21233ae3..507c772d71 100644 --- a/packages/ui/src/components/Menu/Menu.styles.css +++ b/packages/ui/src/components/Menu/Menu.styles.css @@ -14,256 +14,258 @@ * limitations under the License. */ -.bui-MenuPopover { - display: flex; - flex-direction: column; - border: 1px solid var(--bui-border); - border-radius: var(--bui-radius-2); - background: var(--bui-bg-surface-1); - color: var(--bui-fg-primary); - outline: none; - transition: transform 200ms, opacity 200ms; - /* Let React Aria handle height constraints naturally */ - min-height: 0; - /* Remove overflow from popover since ScrollArea will handle it */ - overflow: hidden; - - &[data-entering], - &[data-exiting] { - transform: var(--origin); - opacity: 0; - } - - &[data-placement='top'] { - --origin: translateY(8px); - } - - &[data-placement='bottom'] { - --origin: translateY(-8px); - } - - &[data-placement='right'] { - --origin: translateX(-8px); - } - - &[data-placement='left'] { - --origin: translateX(8px); - } -} - -.bui-MenuContent { - max-height: inherit; - box-sizing: border-box; - overflow: auto; - padding: var(--bui-space-1); - min-width: 150px; - box-sizing: border-box; - outline: none; -} - -/* Ensure ScrollArea works properly within MenuRA popover */ -.bui-MenuPopover .bui-ScrollAreaRoot { - /* Take full height of popover */ - height: 100%; - min-height: 0; - flex: 1; - /* Ensure the root container has proper height constraints */ - display: flex; - flex-direction: column; -} - -.bui-MenuPopover .bui-ScrollAreaScrollbar { - margin-inline: var(--bui-space-1_5); -} - -.bui-MenuItem { - display: flex; - align-items: center; - justify-content: space-between; - height: 2rem; - padding-inline: var(--bui-space-2); - border-radius: var(--bui-radius-2); - outline: none; - cursor: default; - color: var(--bui-fg-primary); - font-size: var(--bui-font-size-3); - gap: var(--bui-space-6); - - &[data-focused] { - background: var(--bui-bg-surface-2); +@layer components { + .bui-MenuPopover { + display: flex; + flex-direction: column; + border: 1px solid var(--bui-border); + border-radius: var(--bui-radius-2); + background: var(--bui-bg-surface-1); color: var(--bui-fg-primary); - } + outline: none; + transition: transform 200ms, opacity 200ms; + /* Let React Aria handle height constraints naturally */ + min-height: 0; + /* Remove overflow from popover since ScrollArea will handle it */ + overflow: hidden; - &[data-open] { - background: var(--bui-bg-surface-2); - color: var(--bui-fg-primary); - } + &[data-entering], + &[data-exiting] { + transform: var(--origin); + opacity: 0; + } - &[data-color='danger'] { - color: var(--bui-fg-danger); - } + &[data-placement='top'] { + --origin: translateY(8px); + } - &[data-color='danger'][data-focused] { - background: var(--bui-bg-danger); - color: var(--bui-fg-danger); - } + &[data-placement='bottom'] { + --origin: translateY(-8px); + } - &[data-has-submenu] { - & > .bui-MenuItemArrow { - display: block; + &[data-placement='right'] { + --origin: translateX(-8px); + } + + &[data-placement='left'] { + --origin: translateX(8px); } } -} -.bui-MenuItemListBox { - display: flex; - align-items: center; - justify-content: space-between; - height: 2rem; - padding-inline: var(--bui-space-2); - border-radius: var(--bui-radius-2); - outline: none; - cursor: default; - color: var(--bui-fg-primary); - font-size: var(--bui-font-size-3); - gap: var(--bui-space-6); - - &:hover { - background: var(--bui-bg-surface-2); - color: var(--bui-fg-primary); + .bui-MenuContent { + max-height: inherit; + box-sizing: border-box; + overflow: auto; + padding: var(--bui-space-1); + min-width: 150px; + box-sizing: border-box; + outline: none; } - &[data-selected] .bui-MenuItemListBoxCheck { - & > svg { - opacity: 1; + /* Ensure ScrollArea works properly within MenuRA popover */ + .bui-MenuPopover .bui-ScrollAreaRoot { + /* Take full height of popover */ + height: 100%; + min-height: 0; + flex: 1; + /* Ensure the root container has proper height constraints */ + display: flex; + flex-direction: column; + } + + .bui-MenuPopover .bui-ScrollAreaScrollbar { + margin-inline: var(--bui-space-1_5); + } + + .bui-MenuItem { + display: flex; + align-items: center; + justify-content: space-between; + height: 2rem; + padding-inline: var(--bui-space-2); + border-radius: var(--bui-radius-2); + outline: none; + cursor: default; + color: var(--bui-fg-primary); + font-size: var(--bui-font-size-3); + gap: var(--bui-space-6); + + &[data-focused] { + background: var(--bui-bg-surface-2); color: var(--bui-fg-primary); } - } -} -.bui-MenuItemListBoxCheck { - display: flex; - align-items: center; - justify-content: center; - width: 1rem; - height: 1rem; + &[data-open] { + background: var(--bui-bg-surface-2); + color: var(--bui-fg-primary); + } - & > svg { - opacity: 0; - width: 1rem; - height: 1rem; - } -} + &[data-color='danger'] { + color: var(--bui-fg-danger); + } -.bui-MenuItemContent { - display: flex; - align-items: center; - gap: var(--bui-space-2); + &[data-color='danger'][data-focused] { + background: var(--bui-bg-danger); + color: var(--bui-fg-danger); + } - & > svg { - width: 1rem; - height: 1rem; - } -} - -.bui-MenuItemArrow { - display: none; - width: 1rem; - height: 1rem; - - & > svg { - width: 1rem; - height: 1rem; - } -} - -.bui-MenuSection { - &:first-child .bui-MenuSectionHeader { - padding-top: 0; - } -} - -.bui-MenuSectionHeader { - height: 2rem; - display: flex; - align-items: center; - padding-top: var(--bui-space-3); - padding-left: var(--bui-space-2); - color: var(--bui-fg-primary); - font-size: var(--bui-font-size-1); - font-weight: bold; - letter-spacing: 0.05rem; - text-transform: uppercase; -} - -.bui-MenuSeparator { - height: 1px; - background: var(--bui-border); - margin-inline: var(--bui-space-1_5); - margin-block: var(--bui-space-1); -} - -.bui-MenuSearchField { - position: relative; - font-family: var(--bui-font-regular); - width: 100%; - flex-shrink: 0; - - &[data-empty] { - .bui-MenuSearchFieldClear { - display: none; + &[data-has-submenu] { + & > .bui-MenuItemArrow { + display: block; + } } } -} -.bui-MenuSearchFieldInput { - display: flex; - align-items: center; - padding: 0 var(--bui-space-3); - border: none; - border-bottom: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - width: 100%; - height: 2rem; - cursor: inherit; - outline: none; + .bui-MenuItemListBox { + display: flex; + align-items: center; + justify-content: space-between; + height: 2rem; + padding-inline: var(--bui-space-2); + border-radius: var(--bui-radius-2); + outline: none; + cursor: default; + color: var(--bui-fg-primary); + font-size: var(--bui-font-size-3); + gap: var(--bui-space-6); - &::-webkit-search-cancel-button, - &::-webkit-search-decoration { - -webkit-appearance: none; + &:hover { + background: var(--bui-bg-surface-2); + color: var(--bui-fg-primary); + } + + &[data-selected] .bui-MenuItemListBoxCheck { + & > svg { + opacity: 1; + color: var(--bui-fg-primary); + } + } } -} -.bui-MenuSearchFieldClear { - position: absolute; - right: var(--bui-space-2); - top: 0; - bottom: 0; - display: flex; - align-items: center; - justify-content: center; - background-color: transparent; - border: none; - padding: 0; - margin: 0; - cursor: pointer; - color: var(--bui-fg-secondary); - transition: color 0.2s ease-in-out; - - & > svg { + .bui-MenuItemListBoxCheck { + display: flex; + align-items: center; + justify-content: center; width: 1rem; height: 1rem; + + & > svg { + opacity: 0; + width: 1rem; + height: 1rem; + } + } + + .bui-MenuItemContent { + display: flex; + align-items: center; + gap: var(--bui-space-2); + + & > svg { + width: 1rem; + height: 1rem; + } + } + + .bui-MenuItemArrow { + display: none; + width: 1rem; + height: 1rem; + + & > svg { + width: 1rem; + height: 1rem; + } + } + + .bui-MenuSection { + &:first-child .bui-MenuSectionHeader { + padding-top: 0; + } + } + + .bui-MenuSectionHeader { + height: 2rem; + display: flex; + align-items: center; + padding-top: var(--bui-space-3); + padding-left: var(--bui-space-2); + color: var(--bui-fg-primary); + font-size: var(--bui-font-size-1); + font-weight: bold; + letter-spacing: 0.05rem; + text-transform: uppercase; + } + + .bui-MenuSeparator { + height: 1px; + background: var(--bui-border); + margin-inline: var(--bui-space-1_5); + margin-block: var(--bui-space-1); + } + + .bui-MenuSearchField { + position: relative; + font-family: var(--bui-font-regular); + width: 100%; + flex-shrink: 0; + + &[data-empty] { + .bui-MenuSearchFieldClear { + display: none; + } + } + } + + .bui-MenuSearchFieldInput { + display: flex; + align-items: center; + padding: 0 var(--bui-space-3); + border: none; + border-bottom: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + width: 100%; + height: 2rem; + cursor: inherit; + outline: none; + + &::-webkit-search-cancel-button, + &::-webkit-search-decoration { + -webkit-appearance: none; + } + } + + .bui-MenuSearchFieldClear { + position: absolute; + right: var(--bui-space-2); + top: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + background-color: transparent; + border: none; + padding: 0; + margin: 0; + cursor: pointer; + color: var(--bui-fg-secondary); + transition: color 0.2s ease-in-out; + + & > svg { + width: 1rem; + height: 1rem; + } + } + + .bui-MenuEmptyState { + padding: var(--bui-space-1); + color: var(--bui-fg-secondary); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); } } - -.bui-MenuEmptyState { - padding: var(--bui-space-1); - color: var(--bui-fg-secondary); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); -} diff --git a/packages/ui/src/components/PasswordField/PasswordField.styles.css b/packages/ui/src/components/PasswordField/PasswordField.styles.css index 371d769ea6..55ea499a2c 100644 --- a/packages/ui/src/components/PasswordField/PasswordField.styles.css +++ b/packages/ui/src/components/PasswordField/PasswordField.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,57 +14,59 @@ * limitations under the License. */ -.bui-PasswordField { - display: flex; - flex-direction: column; - font-family: var(--bui-font-regular); - width: 100%; - flex-shrink: 0; - /* Reserve space for browser/password manager icon (e.g. 1Password) */ - --bui-passwordmanager-icon-width: var(--bui-space-1); -} - -.bui-InputVisibility { - position: absolute; - right: var(--bui-passwordmanager-icon-width); - top: 0; - bottom: 0; - background-color: transparent; - cursor: pointer; - border: none; - padding: 0; - margin: 0; - display: flex; - align-items: center; - justify-content: center; - color: var(--bui-fg-primary); - - /* Size: small */ - &[data-size='small'] { - width: 2rem; - height: 2rem; - } - &[data-size='small'] svg { - width: 1rem; - height: 1rem; +@layer components { + .bui-PasswordField { + display: flex; + flex-direction: column; + font-family: var(--bui-font-regular); + width: 100%; + flex-shrink: 0; + /* Reserve space for browser/password manager icon (e.g. 1Password) */ + --bui-passwordmanager-icon-width: var(--bui-space-1); } - /* Size: medium */ - &[data-size='medium'] { - width: 2.5rem; - height: 2.5rem; + .bui-InputVisibility { + position: absolute; + right: var(--bui-passwordmanager-icon-width); + top: 0; + bottom: 0; + background-color: transparent; + cursor: pointer; + border: none; + padding: 0; + margin: 0; + display: flex; + align-items: center; + justify-content: center; + color: var(--bui-fg-primary); + + /* Size: small */ + &[data-size='small'] { + width: 2rem; + height: 2rem; + } + &[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + /* Size: medium */ + &[data-size='medium'] { + width: 2.5rem; + height: 2.5rem; + } + &[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; + } } - &[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; + + /* Ensure input has enough right padding for our toggle + PM icon */ + .bui-PasswordField .bui-InputWrapper[data-size='small'] .bui-Input { + padding-right: calc(2rem + var(--bui-passwordmanager-icon-width)); + } + + .bui-PasswordField .bui-InputWrapper[data-size='medium'] .bui-Input { + padding-right: calc(2.5rem + var(--bui-passwordmanager-icon-width)); } } - -/* Ensure input has enough right padding for our toggle + PM icon */ -.bui-PasswordField .bui-InputWrapper[data-size='small'] .bui-Input { - padding-right: calc(2rem + var(--bui-passwordmanager-icon-width)); -} - -.bui-PasswordField .bui-InputWrapper[data-size='medium'] .bui-Input { - padding-right: calc(2.5rem + var(--bui-passwordmanager-icon-width)); -} diff --git a/packages/ui/src/components/Popover/Popover.styles.css b/packages/ui/src/components/Popover/Popover.styles.css index 23ae5c1019..3f1cf66440 100644 --- a/packages/ui/src/components/Popover/Popover.styles.css +++ b/packages/ui/src/components/Popover/Popover.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,14 @@ * limitations under the License. */ -.bui-Popover { - margin-right: 12px; - overflow: scroll; - background-color: var(--bui-bg-surface-1); - border: 1px solid var(--bui-border); - border-radius: var(--bui-radius-3); - padding-block: var(--bui-space-1); - box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); +@layer components { + .bui-Popover { + margin-right: 12px; + overflow: scroll; + background-color: var(--bui-bg-surface-1); + border: 1px solid var(--bui-border); + border-radius: var(--bui-radius-3); + padding-block: var(--bui-space-1); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1); + } } diff --git a/packages/ui/src/components/RadioGroup/RadioGroup.styles.css b/packages/ui/src/components/RadioGroup/RadioGroup.styles.css index f12d5571e0..400a5216f4 100644 --- a/packages/ui/src/components/RadioGroup/RadioGroup.styles.css +++ b/packages/ui/src/components/RadioGroup/RadioGroup.styles.css @@ -1,95 +1,113 @@ -.bui-RadioGroup { - display: flex; - flex-direction: column; - color: var(--bui-fg-primary); -} +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -.bui-RadioGroup[data-orientation='horizontal'] .bui-RadioGroupContent { - flex-direction: row; - gap: var(--bui-space-4); -} - -.bui-RadioGroupContent { - display: flex; - flex-direction: column; - gap: var(--bui-space-2); -} - -.bui-Radio { - display: flex; - /* This is needed so the HiddenInput is positioned correctly */ - position: relative; - align-items: center; - gap: var(--bui-space-2); - font-size: var(--bui-font-size-2); - color: var(--bui-fg-primary); - forced-color-adjust: none; - - &:before { - content: ''; - display: block; - width: 1rem; - height: 1rem; - box-sizing: border-box; - border: 0.125rem solid var(--bui-border); - background: var(--bui-gray-1); - border-radius: var(--bui-radius-full); - transition: all 200ms; +@layer components { + .bui-RadioGroup { + display: flex; + flex-direction: column; + color: var(--bui-fg-primary); } - &[data-pressed]:before { - border-color: var(--bui-border); + .bui-RadioGroup[data-orientation='horizontal'] .bui-RadioGroupContent { + flex-direction: row; + gap: var(--bui-space-4); } - &[data-selected] { + .bui-RadioGroupContent { + display: flex; + flex-direction: column; + gap: var(--bui-space-2); + } + + .bui-Radio { + display: flex; + /* This is needed so the HiddenInput is positioned correctly */ + position: relative; + align-items: center; + gap: var(--bui-space-2); + font-size: var(--bui-font-size-2); + color: var(--bui-fg-primary); + forced-color-adjust: none; + &:before { - border-color: var(--bui-bg-solid); - border-width: 0.25rem; + content: ''; + display: block; + width: 1rem; + height: 1rem; + box-sizing: border-box; + border: 0.125rem solid var(--bui-border); + background: var(--bui-gray-1); + border-radius: var(--bui-radius-full); + transition: all 200ms; } &[data-pressed]:before { - border-color: var(--bui-bg-solid); - } - } - - &[data-focus-visible]:before { - outline: 2px solid var(--bui-ring); - outline-offset: 2px; - } - - &[data-disabled] { - cursor: not-allowed; - color: var(--bui-fg-disabled); - - &:before { - border-color: var(--bui-border-disabled); - background: var(--bui-bg-disabled); + border-color: var(--bui-border); } - &[data-selected]:before { - border-color: var(--bui-border-disabled); - } - } + &[data-selected] { + &:before { + border-color: var(--bui-bg-solid); + border-width: 0.25rem; + } - &[data-invalid]:before { - border-color: var(--bui-border-danger); - } - - &[data-invalid][data-selected]:before { - border-color: var(--bui-border-danger); - } - - /* Ensure disabled state prevails over invalid state */ - &[data-disabled][data-invalid] { - color: var(--bui-fg-disabled); - - &:before { - border-color: var(--bui-border-disabled); - background: var(--bui-bg-disabled); + &[data-pressed]:before { + border-color: var(--bui-bg-solid); + } } - &[data-selected]:before { - border-color: var(--bui-border-disabled); + &[data-focus-visible]:before { + outline: 2px solid var(--bui-ring); + outline-offset: 2px; + } + + &[data-disabled] { + cursor: not-allowed; + color: var(--bui-fg-disabled); + + &:before { + border-color: var(--bui-border-disabled); + background: var(--bui-bg-disabled); + } + + &[data-selected]:before { + border-color: var(--bui-border-disabled); + } + } + + &[data-invalid]:before { + border-color: var(--bui-border-danger); + } + + &[data-invalid][data-selected]:before { + border-color: var(--bui-border-danger); + } + + /* Ensure disabled state prevails over invalid state */ + &[data-disabled][data-invalid] { + color: var(--bui-fg-disabled); + + &:before { + border-color: var(--bui-border-disabled); + background: var(--bui-bg-disabled); + } + + &[data-selected]:before { + border-color: var(--bui-border-disabled); + } } } } diff --git a/packages/ui/src/components/ScrollArea/ScrollArea.styles.css b/packages/ui/src/components/ScrollArea/ScrollArea.styles.css index 209168c329..4e2fea06a6 100644 --- a/packages/ui/src/components/ScrollArea/ScrollArea.styles.css +++ b/packages/ui/src/components/ScrollArea/ScrollArea.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,52 +14,54 @@ * limitations under the License. */ -.bui-ScrollAreaRoot { - box-sizing: border-box; - width: 100%; -} - -.bui-ScrollAreaViewport { - height: 100%; - overscroll-behavior: contain; -} - -.bui-ScrollAreaContent { - display: flex; - flex-direction: column; - gap: 1rem; - padding-block: 0.75rem; - padding-left: 1rem; - padding-right: 1.5rem; -} - -.bui-ScrollAreaScrollbar { - display: flex; - justify-content: center; - background-color: var(--bui-scrollbar); - width: 0.25rem; - border-radius: 0.375rem; - margin: 0.5rem; - opacity: 0; - transition: opacity 150ms 300ms; - - &[data-hovering], - &[data-scrolling] { - opacity: 1; - transition-duration: 75ms; - transition-delay: 0ms; +@layer components { + .bui-ScrollAreaRoot { + box-sizing: border-box; + width: 100%; } - &::before { - content: ''; - position: absolute; - width: 1.25rem; + .bui-ScrollAreaViewport { height: 100%; + overscroll-behavior: contain; + } + + .bui-ScrollAreaContent { + display: flex; + flex-direction: column; + gap: 1rem; + padding-block: 0.75rem; + padding-left: 1rem; + padding-right: 1.5rem; + } + + .bui-ScrollAreaScrollbar { + display: flex; + justify-content: center; + background-color: var(--bui-scrollbar); + width: 0.25rem; + border-radius: 0.375rem; + margin: 0.5rem; + opacity: 0; + transition: opacity 150ms 300ms; + + &[data-hovering], + &[data-scrolling] { + opacity: 1; + transition-duration: 75ms; + transition-delay: 0ms; + } + + &::before { + content: ''; + position: absolute; + width: 1.25rem; + height: 100%; + } + } + + .bui-ScrollAreaThumb { + width: 100%; + border-radius: inherit; + background-color: var(--bui-scrollbar-thumb); } } - -.bui-ScrollAreaThumb { - width: 100%; - border-radius: inherit; - background-color: var(--bui-scrollbar-thumb); -} diff --git a/packages/ui/src/components/SearchField/SearchField.styles.css b/packages/ui/src/components/SearchField/SearchField.styles.css index a13c455b44..996ee1eb07 100644 --- a/packages/ui/src/components/SearchField/SearchField.styles.css +++ b/packages/ui/src/components/SearchField/SearchField.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,125 +14,127 @@ * limitations under the License. */ -.bui-SearchField { - flex: 1; - flex-shrink: 0; +@layer components { + .bui-SearchField { + flex: 1; + flex-shrink: 0; - &[data-empty] { - .bui-InputClear { - display: none; + &[data-empty] { + .bui-InputClear { + display: none; + } + } + + &[data-start-collapsed='true'] { + transition: flex-basis 0.3s ease-in-out; + padding: 0; + flex: 0 1 auto; + + &[data-collapsed='true'] { + flex-basis: 200px; + } + + &[data-collapsed='false'] { + cursor: pointer; + + &[data-size='medium'] { + flex-basis: 2.5rem; + height: 2.5rem; + } + + &[data-size='small'] { + flex-basis: 2rem; + height: 2rem; + } + + &[data-size='medium'] .bui-Input { + &::placeholder { + opacity: 0; + } + } + + &[data-size='small'] .bui-Input { + &::placeholder { + opacity: 0; + } + } + + .bui-InputWrapper { + .bui-Input[data-icon] { + padding-right: 0px; + } + } + } } } - &[data-start-collapsed='true'] { - transition: flex-basis 0.3s ease-in-out; + .bui-SearchField .bui-Input { + transition: padding 0.3s ease-in-out, border-color 0.2s ease-in-out, + outline-color 0.2s ease-in-out; + + &[data-hovered] { + border-color: var(--bui-border-hover); + } + + &[data-focused] { + border-color: var(--bui-border-pressed); + outline-width: 0px; + } + } + + .bui-SearchField .bui-InputWrapper { + .bui-Input[data-icon] { + padding-right: var(--bui-space-6); + } + } + + .bui-SearchField .bui-InputIcon { + left: 0; + display: flex; + justify-content: center; + + &[data-size='small'] { + width: var(--bui-space-8); + } + + &[data-size='medium'] { + width: var(--bui-space-10); + } + } + + .bui-InputClear { + position: absolute; + right: 0; + top: 0; + bottom: 0; + display: flex; + align-items: center; + justify-content: center; + background-color: transparent; + border: none; padding: 0; - flex: 0 1 auto; - - &[data-collapsed='true'] { - flex-basis: 200px; - } - - &[data-collapsed='false'] { - cursor: pointer; - - &[data-size='medium'] { - flex-basis: 2.5rem; - height: 2.5rem; - } - - &[data-size='small'] { - flex-basis: 2rem; - height: 2rem; - } - - &[data-size='medium'] .bui-Input { - &::placeholder { - opacity: 0; - } - } - - &[data-size='small'] .bui-Input { - &::placeholder { - opacity: 0; - } - } - - .bui-InputWrapper { - .bui-Input[data-icon] { - padding-right: 0px; - } - } - } - } -} - -.bui-SearchField .bui-Input { - transition: padding 0.3s ease-in-out, border-color 0.2s ease-in-out, - outline-color 0.2s ease-in-out; - - &[data-hovered] { - border-color: var(--bui-border-hover); + margin: 0; + cursor: pointer; + color: var(--bui-fg-secondary); + transition: color 0.2s ease-in-out; } - &[data-focused] { - border-color: var(--bui-border-pressed); - outline-width: 0px; - } -} - -.bui-SearchField .bui-InputWrapper { - .bui-Input[data-icon] { - padding-right: var(--bui-space-6); - } -} - -.bui-SearchField .bui-InputIcon { - left: 0; - display: flex; - justify-content: center; - - &[data-size='small'] { - width: var(--bui-space-8); + .bui-InputClear:hover { + color: var(--bui-fg-primary); } - &[data-size='medium'] { - width: var(--bui-space-10); + .bui-InputClear[data-size='small'] { + width: 2rem; + height: 2rem; + } + + .bui-InputClear[data-size='medium'] { + width: 2.5rem; + height: 2.5rem; + } + + .bui-InputClear svg { + width: 1rem; + height: 1rem; } } - -.bui-InputClear { - position: absolute; - right: 0; - top: 0; - bottom: 0; - display: flex; - align-items: center; - justify-content: center; - background-color: transparent; - border: none; - padding: 0; - margin: 0; - cursor: pointer; - color: var(--bui-fg-secondary); - transition: color 0.2s ease-in-out; -} - -.bui-InputClear:hover { - color: var(--bui-fg-primary); -} - -.bui-InputClear[data-size='small'] { - width: 2rem; - height: 2rem; -} - -.bui-InputClear[data-size='medium'] { - width: 2.5rem; - height: 2.5rem; -} - -.bui-InputClear svg { - width: 1rem; - height: 1rem; -} diff --git a/packages/ui/src/components/Select/Select.styles.css b/packages/ui/src/components/Select/Select.styles.css index 2cbadfda32..a8dbe759dc 100644 --- a/packages/ui/src/components/Select/Select.styles.css +++ b/packages/ui/src/components/Select/Select.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,163 +14,165 @@ * limitations under the License. */ -.bui-Select[data-invalid] { - & .bui-SelectTrigger { - border-color: var(--bui-fg-danger); - } -} - -.bui-SelectTrigger { - box-sizing: border-box; - border-radius: var(--bui-radius-3); - border: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); - display: flex; - justify-content: space-between; - align-items: center; - cursor: pointer; - gap: var(--bui-space-2); - width: 100%; - - & svg { - flex-shrink: 0; - color: var(--bui-fg-secondary); +@layer components { + .bui-Select[data-invalid] { + & .bui-SelectTrigger { + border-color: var(--bui-fg-danger); + } } - &[data-size='small'] { - height: 2rem; - padding-inline: var(--bui-space-3); + .bui-SelectTrigger { + box-sizing: border-box; + border-radius: var(--bui-radius-3); + border: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + display: flex; + justify-content: space-between; + align-items: center; + cursor: pointer; + gap: var(--bui-space-2); + width: 100%; + + & svg { + flex-shrink: 0; + color: var(--bui-fg-secondary); + } + + &[data-size='small'] { + height: 2rem; + padding-inline: var(--bui-space-3); + } + + &[data-size='medium'] { + height: 3rem; + padding-inline: var(--bui-space-4); + } + + &[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + &[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; + } + + &::placeholder { + color: var(--bui-fg-secondary); + } + + &:hover { + transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; + border-color: var(--bui-border-hover); + } + + &:focus-visible { + border-color: var(--bui-border-pressed); + outline: 0; + } + + &[data-invalid] { + border-color: var(--bui-fg-danger); + } + &[data-invalid]:hover { + border-width: 2px; + } + + &[data-invalid]:focus-visible { + border-width: 2px; + } + + &[disabled] { + cursor: not-allowed; + border-color: var(--bui-border-disabled); + color: var(--bui-fg-disabled); + } + + &[disabled] .bui-SelectValue { + color: var(--bui-fg-disabled); + } + + &[data-popup-open] .bui-SelectIcon { + transform: rotate(180deg); + } } - &[data-size='medium'] { - height: 3rem; - padding-inline: var(--bui-space-4); - } - - &[data-size='small'] svg { - width: 1rem; - height: 1rem; - } - - &[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; - } - - &::placeholder { - color: var(--bui-fg-secondary); - } - - &:hover { - transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; - border-color: var(--bui-border-hover); - } - - &:focus-visible { - border-color: var(--bui-border-pressed); - outline: 0; - } - - &[data-invalid] { - border-color: var(--bui-fg-danger); - } - &[data-invalid]:hover { - border-width: 2px; - } - - &[data-invalid]:focus-visible { - border-width: 2px; - } - - &[disabled] { - cursor: not-allowed; - border-color: var(--bui-border-disabled); - color: var(--bui-fg-disabled); - } - - &[disabled] .bui-SelectValue { - color: var(--bui-fg-disabled); - } - - &[data-popup-open] .bui-SelectIcon { - transform: rotate(180deg); - } -} - -.bui-SelectValue { - text-overflow: ellipsis; - overflow: hidden; - white-space: nowrap; - width: 100%; - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - text-align: left; - - & .bui-SelectItemIndicator { - display: none; - } - - &[disabled] { - color: var(--bui-fg-disabled); - } -} - -.bui-SelectItem { - position: relative; - width: var(--anchor-width); - display: grid; - grid-template-areas: 'icon text'; - grid-template-columns: 1rem 1fr; - align-items: center; - padding-block: var(--bui-space-2); - padding-left: var(--bui-space-3); - padding-right: var(--bui-space-4); - color: var(--bui-fg-primary); - border-radius: var(--bui-radius-3); - cursor: pointer; - user-select: none; - font-size: var(--bui-font-size-3); - gap: var(--bui-space-1); - outline: none; - - &[data-focused] { - z-index: 0; - position: relative; + .bui-SelectValue { + text-overflow: ellipsis; + overflow: hidden; + white-space: nowrap; + width: 100%; + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); color: var(--bui-fg-primary); + text-align: left; + + & .bui-SelectItemIndicator { + display: none; + } + + &[disabled] { + color: var(--bui-fg-disabled); + } } - &[data-focused]::before { - content: ''; - z-index: -1; - position: absolute; - inset-block: 0; - inset-inline: 0.25rem; - border-radius: 0.25rem; - background-color: var(--bui-bg-tint-hover); + .bui-SelectItem { + position: relative; + width: var(--anchor-width); + display: grid; + grid-template-areas: 'icon text'; + grid-template-columns: 1rem 1fr; + align-items: center; + padding-block: var(--bui-space-2); + padding-left: var(--bui-space-3); + padding-right: var(--bui-space-4); + color: var(--bui-fg-primary); + border-radius: var(--bui-radius-3); + cursor: pointer; + user-select: none; + font-size: var(--bui-font-size-3); + gap: var(--bui-space-1); + outline: none; + + &[data-focused] { + z-index: 0; + position: relative; + color: var(--bui-fg-primary); + } + + &[data-focused]::before { + content: ''; + z-index: -1; + position: absolute; + inset-block: 0; + inset-inline: 0.25rem; + border-radius: 0.25rem; + background-color: var(--bui-bg-tint-hover); + } + + &[data-disabled] { + cursor: not-allowed; + color: var(--bui-fg-disabled); + } + + &[data-selected] .bui-SelectItemIndicator { + opacity: 1; + } } - &[data-disabled] { - cursor: not-allowed; - color: var(--bui-fg-disabled); + .bui-SelectItemIndicator { + grid-area: icon; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + transition: opacity 0.2s ease-in-out; } - &[data-selected] .bui-SelectItemIndicator { - opacity: 1; + .bui-SelectItemLabel { + flex: 1; + grid-area: text; } } - -.bui-SelectItemIndicator { - grid-area: icon; - display: flex; - align-items: center; - justify-content: center; - opacity: 0; - transition: opacity 0.2s ease-in-out; -} - -.bui-SelectItemLabel { - flex: 1; - grid-area: text; -} diff --git a/packages/ui/src/components/Skeleton/Skeleton.styles.css b/packages/ui/src/components/Skeleton/Skeleton.styles.css index bbbb6deaeb..cbf297d24d 100644 --- a/packages/ui/src/components/Skeleton/Skeleton.styles.css +++ b/packages/ui/src/components/Skeleton/Skeleton.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,12 +14,14 @@ * limitations under the License. */ -.bui-Skeleton { - animation: var(--bui-animate-pulse); - background-color: var(--bui-bg-surface-2); - border-radius: var(--bui-radius-2); -} +@layer components { + .bui-Skeleton { + animation: var(--bui-animate-pulse); + background-color: var(--bui-bg-surface-2); + border-radius: var(--bui-radius-2); + } -.bui-Skeleton[data-rounded='true'] { - border-radius: var(--bui-radius-full); + .bui-Skeleton[data-rounded='true'] { + border-radius: var(--bui-radius-full); + } } diff --git a/packages/ui/src/components/Switch/Switch.styles.css b/packages/ui/src/components/Switch/Switch.styles.css index ee2a24d013..58735e2b78 100644 --- a/packages/ui/src/components/Switch/Switch.styles.css +++ b/packages/ui/src/components/Switch/Switch.styles.css @@ -14,61 +14,63 @@ * limitations under the License. */ -.bui-Switch { - display: flex; - /* This is needed so the HiddenInput is positioned correctly */ - position: relative; - align-items: center; - gap: var(--bui-space-3); - font-size: var(--bui-font-size-3); - color: var(--bui-fg-primary); - cursor: pointer; - - &[data-pressed] .bui-SwitchIndicator { - &:before { - background: var(--bui-fg-solid); - } - } - - &[data-selected] { - .bui-SwitchIndicator { - background: var(--bui-bg-solid); +@layer components { + .bui-Switch { + display: flex; + /* This is needed so the HiddenInput is positioned correctly */ + position: relative; + align-items: center; + gap: var(--bui-space-3); + font-size: var(--bui-font-size-3); + color: var(--bui-fg-primary); + cursor: pointer; + &[data-pressed] .bui-SwitchIndicator { &:before { background: var(--bui-fg-solid); - transform: translateX(100%); } } - &[data-pressed] { - .indicator { - background: var(--bui-gray-3); + &[data-selected] { + .bui-SwitchIndicator { + background: var(--bui-bg-solid); + + &:before { + background: var(--bui-fg-solid); + transform: translateX(100%); + } } + + &[data-pressed] { + .indicator { + background: var(--bui-gray-3); + } + } + } + + &[data-focus-visible] .bui-SwitchIndicator { + outline: 2px solid; + outline-offset: 2px; } } - &[data-focus-visible] .bui-SwitchIndicator { - outline: 2px solid; - outline-offset: 2px; - } -} - -.bui-SwitchIndicator { - width: 2rem; - height: 1.143rem; - border: 2px; - background: var(--bui-gray-3); - border-radius: 1.143rem; - transition: all 200ms; - - &:before { - content: ''; - display: block; - margin: 0.143rem; - width: 0.857rem; - height: 0.857rem; - background: var(--bui-fg-solid); - border-radius: 16px; + .bui-SwitchIndicator { + width: 2rem; + height: 1.143rem; + border: 2px; + background: var(--bui-gray-3); + border-radius: 1.143rem; transition: all 200ms; + + &:before { + content: ''; + display: block; + margin: 0.143rem; + width: 0.857rem; + height: 0.857rem; + background: var(--bui-fg-solid); + border-radius: 16px; + transition: all 200ms; + } } } diff --git a/packages/ui/src/components/Table/Table.styles.css b/packages/ui/src/components/Table/Table.styles.css index 84d417604a..0bb49be742 100644 --- a/packages/ui/src/components/Table/Table.styles.css +++ b/packages/ui/src/components/Table/Table.styles.css @@ -14,136 +14,138 @@ * limitations under the License. */ -.bui-Table { - width: 100%; - caption-side: bottom; - border-collapse: collapse; -} - -.bui-TableHeader { - border-bottom: 1px solid var(--bui-border); - transition: color 0.2s ease-in-out; -} - -.bui-TableHead { - text-align: left; - padding: var(--bui-space-3); - font-size: var(--bui-font-size-3); - color: var(--bui-fg-primary); -} - -.bui-TableHeadSortButton { - cursor: pointer; - user-select: none; - display: inline-flex; - align-items: center; - gap: var(--bui-space-1); - - &:hover svg { - opacity: 0.5; +@layer components { + .bui-Table { + width: 100%; + caption-side: bottom; + border-collapse: collapse; } - & svg { - opacity: 0; - transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; + .bui-TableHeader { + border-bottom: 1px solid var(--bui-border); + transition: color 0.2s ease-in-out; } - &[data-sort-order='asc'] svg { - opacity: 1; - transform: rotate(0); + .bui-TableHead { + text-align: left; + padding: var(--bui-space-3); + font-size: var(--bui-font-size-3); + color: var(--bui-fg-primary); } - &[data-sort-order='desc'] svg { - opacity: 1; - transform: rotate(180deg); - } -} - -.bui-TableBody { - color: var(--bui-fg-primary); -} - -.bui-TableRow { - border-bottom: 1px solid var(--bui-border); - transition: color 0.2s ease-in-out; - - &[data-react-aria-pressable='true'] { + .bui-TableHeadSortButton { cursor: pointer; + user-select: none; + display: inline-flex; + align-items: center; + gap: var(--bui-space-1); + + &:hover svg { + opacity: 0.5; + } + + & svg { + opacity: 0; + transition: opacity 0.1s ease-in-out, transform 0.1s ease-in-out; + } + + &[data-sort-order='asc'] svg { + opacity: 1; + transform: rotate(0); + } + + &[data-sort-order='desc'] svg { + opacity: 1; + transform: rotate(180deg); + } + } + + .bui-TableBody { + color: var(--bui-fg-primary); + } + + .bui-TableRow { + border-bottom: 1px solid var(--bui-border); + transition: color 0.2s ease-in-out; + + &[data-react-aria-pressable='true'] { + cursor: pointer; + } + } + + .bui-TableBody .bui-TableRow:hover { + background-color: var(--bui-gray-2); + } + + .bui-TableCell { + padding: var(--bui-space-3); + font-size: var(--bui-font-size-3); + } + + .bui-TableCell { + padding: var(--bui-space-3); + font-size: var(--bui-font-size-3); + } + + .bui-TableCellContentWrapper { + display: inline-flex; + flex-direction: row; + align-items: center; + gap: var(--bui-space-2); + } + + .bui-TableCellIcon, + .bui-TableCellIcon svg { + display: inline-flex; + align-items: center; + color: var(--bui-fg-primary); + } + + .bui-TableCellContent { + display: flex; + flex-direction: column; + gap: var(--bui-space-0_5); + } + + .bui-TableCellProfile { + display: flex; + flex-direction: row; + gap: var(--bui-space-2); + align-items: center; + } + + .bui-TableCellProfileAvatar { + display: inline-flex; + justify-content: center; + align-items: center; + vertical-align: middle; + border-radius: 100%; + user-select: none; + font-weight: 500; + color: var(--bui-fg-primary); + background-color: var(--bui-bg-surface-2); + font-size: 1rem; + line-height: 1; + overflow: hidden; + height: 1.25rem; + width: 1.25rem; + } + + .bui-TableCellProfileAvatarImage { + object-fit: cover; + height: 100%; + width: 100%; + } + + .bui-TableCellProfileAvatarFallback { + align-items: center; + display: flex; + justify-content: center; + height: 100%; + width: 100%; + font-size: var(--bui-font-size-2); + font-weight: var(--bui-font-weight-regular); + box-shadow: inset 0 0 0 1px var(--bui-border); + border-radius: var(--bui-radius-full); } } - -.bui-TableBody .bui-TableRow:hover { - background-color: var(--bui-gray-2); -} - -.bui-TableCell { - padding: var(--bui-space-3); - font-size: var(--bui-font-size-3); -} - -.bui-TableCell { - padding: var(--bui-space-3); - font-size: var(--bui-font-size-3); -} - -.bui-TableCellContentWrapper { - display: inline-flex; - flex-direction: row; - align-items: center; - gap: var(--bui-space-2); -} - -.bui-TableCellIcon, -.bui-TableCellIcon svg { - display: inline-flex; - align-items: center; - color: var(--bui-fg-primary); -} - -.bui-TableCellContent { - display: flex; - flex-direction: column; - gap: var(--bui-space-0_5); -} - -.bui-TableCellProfile { - display: flex; - flex-direction: row; - gap: var(--bui-space-2); - align-items: center; -} - -.bui-TableCellProfileAvatar { - display: inline-flex; - justify-content: center; - align-items: center; - vertical-align: middle; - border-radius: 100%; - user-select: none; - font-weight: 500; - color: var(--bui-fg-primary); - background-color: var(--bui-bg-surface-2); - font-size: 1rem; - line-height: 1; - overflow: hidden; - height: 1.25rem; - width: 1.25rem; -} - -.bui-TableCellProfileAvatarImage { - object-fit: cover; - height: 100%; - width: 100%; -} - -.bui-TableCellProfileAvatarFallback { - align-items: center; - display: flex; - justify-content: center; - height: 100%; - width: 100%; - font-size: var(--bui-font-size-2); - font-weight: var(--bui-font-weight-regular); - box-shadow: inset 0 0 0 1px var(--bui-border); - border-radius: var(--bui-radius-full); -} diff --git a/packages/ui/src/components/TablePagination/TablePagination.styles.css b/packages/ui/src/components/TablePagination/TablePagination.styles.css index f7cbb44fc2..e305967ebe 100644 --- a/packages/ui/src/components/TablePagination/TablePagination.styles.css +++ b/packages/ui/src/components/TablePagination/TablePagination.styles.css @@ -1,23 +1,41 @@ -.bui-DataTablePagination { - display: flex; - align-items: center; - justify-content: space-between; - padding-top: var(--bui-space-5); -} +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ -.bui-DataTablePagination--left { - display: flex; - align-items: center; - justify-content: space-between; -} +@layer components { + .bui-DataTablePagination { + display: flex; + align-items: center; + justify-content: space-between; + padding-top: var(--bui-space-5); + } -.bui-DataTablePagination--right { - display: flex; - align-items: center; - justify-content: space-between; - gap: var(--bui-space-2); -} + .bui-DataTablePagination--left { + display: flex; + align-items: center; + justify-content: space-between; + } -.bui-DataTablePagination--select { - min-width: 10.5rem; + .bui-DataTablePagination--right { + display: flex; + align-items: center; + justify-content: space-between; + gap: var(--bui-space-2); + } + + .bui-DataTablePagination--select { + min-width: 10.5rem; + } } diff --git a/packages/ui/src/components/Tabs/Tabs.styles.css b/packages/ui/src/components/Tabs/Tabs.styles.css index 819fe458ed..a58d123559 100644 --- a/packages/ui/src/components/Tabs/Tabs.styles.css +++ b/packages/ui/src/components/Tabs/Tabs.styles.css @@ -1,82 +1,100 @@ -.bui-Tabs { - /* Initialize CSS variables */ - --active-tab-left: 0px; - --active-tab-right: 0px; - --active-tab-top: 0px; - --active-tab-bottom: 0px; - --active-tab-width: 0px; - --active-tab-height: 0px; - --active-transition-duration: 0s; +/* + * Copyright 2025 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ - --hovered-tab-left: 0px; - --hovered-tab-right: 0px; - --hovered-tab-top: 0px; - --hovered-tab-bottom: 0px; - --hovered-tab-width: 0px; - --hovered-tab-height: 0px; - --hovered-tab-opacity: 0; - --hovered-transition-duration: 0s; -} +@layer components { + .bui-Tabs { + /* Initialize CSS variables */ + --active-tab-left: 0px; + --active-tab-right: 0px; + --active-tab-top: 0px; + --active-tab-bottom: 0px; + --active-tab-width: 0px; + --active-tab-height: 0px; + --active-transition-duration: 0s; -.bui-TabList { - display: flex; - flex-direction: row; -} + --hovered-tab-left: 0px; + --hovered-tab-right: 0px; + --hovered-tab-top: 0px; + --hovered-tab-bottom: 0px; + --hovered-tab-width: 0px; + --hovered-tab-height: 0px; + --hovered-tab-opacity: 0; + --hovered-transition-duration: 0s; + } -.bui-TabListWrapper { - position: relative; -} + .bui-TabList { + display: flex; + flex-direction: row; + } -.bui-Tab { - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-secondary); - height: 36px; - display: flex; - align-items: center; - justify-content: center; - cursor: pointer; - position: relative; - z-index: 2; - padding-inline: var(--bui-space-2); + .bui-TabListWrapper { + position: relative; + } - &[data-selected='true'] { - color: var(--bui-fg-primary); + .bui-Tab { + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-secondary); + height: 36px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + position: relative; + z-index: 2; + padding-inline: var(--bui-space-2); + + &[data-selected='true'] { + color: var(--bui-fg-primary); + } + } + + .bui-TabActive { + content: ''; + position: absolute; + left: calc(var(--active-tab-left) + var(--bui-space-2)); + bottom: -1px; + width: calc(var(--active-tab-width) - var(--bui-space-4)); + height: 1px; + background-color: var(--bui-fg-primary); + border-radius: 4px; + transition: left var(--active-transition-duration) ease-out, + opacity 0.15s ease-out, width var(--active-transition-duration) ease-out; + opacity: 1; + } + + .bui-TabHovered { + content: ''; + position: absolute; + left: var(--hovered-tab-left); + top: calc(var(--hovered-tab-top) + 4px); + width: var(--hovered-tab-width); + height: calc(var(--hovered-tab-height) - 8px); + background-color: var(--bui-gray-2); + border-radius: 4px; + opacity: var(--hovered-tab-opacity); + transition: left var(--hovered-transition-duration) ease-out, + top var(--hovered-transition-duration) ease-out, + width var(--hovered-transition-duration) ease-out, + height var(--hovered-transition-duration) ease-out, opacity 0.15s ease-out; + } + + .bui-TabPanel { + padding-inline: var(--bui-space-2); + padding-top: var(--bui-space-4); } } - -.bui-TabActive { - content: ''; - position: absolute; - left: calc(var(--active-tab-left) + var(--bui-space-2)); - bottom: -1px; - width: calc(var(--active-tab-width) - var(--bui-space-4)); - height: 1px; - background-color: var(--bui-fg-primary); - border-radius: 4px; - transition: left var(--active-transition-duration) ease-out, - opacity 0.15s ease-out, width var(--active-transition-duration) ease-out; - opacity: 1; -} - -.bui-TabHovered { - content: ''; - position: absolute; - left: var(--hovered-tab-left); - top: calc(var(--hovered-tab-top) + 4px); - width: var(--hovered-tab-width); - height: calc(var(--hovered-tab-height) - 8px); - background-color: var(--bui-gray-2); - border-radius: 4px; - opacity: var(--hovered-tab-opacity); - transition: left var(--hovered-transition-duration) ease-out, - top var(--hovered-transition-duration) ease-out, - width var(--hovered-transition-duration) ease-out, - height var(--hovered-transition-duration) ease-out, opacity 0.15s ease-out; -} - -.bui-TabPanel { - padding-inline: var(--bui-space-2); - padding-top: var(--bui-space-4); -} diff --git a/packages/ui/src/components/TagGroup/TagGroup.styles.css b/packages/ui/src/components/TagGroup/TagGroup.styles.css index 9da99a4290..096d003f83 100644 --- a/packages/ui/src/components/TagGroup/TagGroup.styles.css +++ b/packages/ui/src/components/TagGroup/TagGroup.styles.css @@ -14,77 +14,79 @@ * limitations under the License. */ -.bui-TagList { - display: flex; - flex-wrap: wrap; - gap: var(--bui-space-2); -} +@layer components { + .bui-TagList { + display: flex; + flex-wrap: wrap; + gap: var(--bui-space-2); + } -.bui-Tag { - color: var(--bui-fg-primary); - background-color: var(--bui-gray-2); - border-radius: var(--bui-radius-2); - display: flex; - align-items: center; - justify-content: center; - font-weight: var(--bui-font-weight-regular); - gap: var(--bui-space-1); - transition-property: background-color, box-shadow, color; - transition-duration: 0.2s; - transition-timing-function: ease-in-out; - box-sizing: border-box; -} + .bui-Tag { + color: var(--bui-fg-primary); + background-color: var(--bui-gray-2); + border-radius: var(--bui-radius-2); + display: flex; + align-items: center; + justify-content: center; + font-weight: var(--bui-font-weight-regular); + gap: var(--bui-space-1); + transition-property: background-color, box-shadow, color; + transition-duration: 0.2s; + transition-timing-function: ease-in-out; + box-sizing: border-box; + } -.bui-Tag[data-size='small'] { - height: 26px; - padding: 0 var(--bui-space-2); - font-size: var(--bui-font-size-1); -} + .bui-Tag[data-size='small'] { + height: 26px; + padding: 0 var(--bui-space-2); + font-size: var(--bui-font-size-1); + } -.bui-Tag[data-size='medium'] { - height: 32px; - padding: 0 var(--bui-space-2); - font-size: var(--bui-font-size-2); -} + .bui-Tag[data-size='medium'] { + height: 32px; + padding: 0 var(--bui-space-2); + font-size: var(--bui-font-size-2); + } -.bui-Tag[data-hovered] { - background-color: var(--bui-gray-3); - cursor: pointer; -} + .bui-Tag[data-hovered] { + background-color: var(--bui-gray-3); + cursor: pointer; + } -.bui-Tag[data-focus-visible] { - outline: 2px solid var(--bui-ring); - outline-offset: 1px; -} + .bui-Tag[data-focus-visible] { + outline: 2px solid var(--bui-ring); + outline-offset: 1px; + } -.bui-Tag[data-selected] { - box-shadow: inset 0 0 0 1px var(--bui-gray-8); -} + .bui-Tag[data-selected] { + box-shadow: inset 0 0 0 1px var(--bui-gray-8); + } -.bui-Tag[data-disabled] { - color: var(--bui-fg-disabled); - cursor: not-allowed; -} + .bui-Tag[data-disabled] { + color: var(--bui-fg-disabled); + cursor: not-allowed; + } -.bui-TagRemoveButton { - background-color: transparent; - border: none; - cursor: pointer; - color: var(--bui-fg-primary); - padding: 0; - margin: 0; - width: 1rem; - height: 1rem; -} - -.bui-TagIcon { - display: flex; - align-items: center; - justify-content: center; - transition: color 0.2s ease-in-out; - - svg { + .bui-TagRemoveButton { + background-color: transparent; + border: none; + cursor: pointer; + color: var(--bui-fg-primary); + padding: 0; + margin: 0; width: 1rem; height: 1rem; } + + .bui-TagIcon { + display: flex; + align-items: center; + justify-content: center; + transition: color 0.2s ease-in-out; + + svg { + width: 1rem; + height: 1rem; + } + } } diff --git a/packages/ui/src/components/Text/styles.css b/packages/ui/src/components/Text/styles.css index 562d2a5356..47f38fe30d 100644 --- a/packages/ui/src/components/Text/styles.css +++ b/packages/ui/src/components/Text/styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,90 +14,92 @@ * limitations under the License. */ -.bui-Text { - font-family: var(--bui-font-regular); - padding: 0; - margin: 0; -} +@layer components { + .bui-Text { + font-family: var(--bui-font-regular); + padding: 0; + margin: 0; + } -.bui-Text[data-variant='title-large'] { - font-size: var(--bui-font-size-8); - line-height: 140%; -} + .bui-Text[data-variant='title-large'] { + font-size: var(--bui-font-size-8); + line-height: 140%; + } -.bui-Text[data-variant='title-medium'] { - font-size: var(--bui-font-size-7); - line-height: 140%; -} + .bui-Text[data-variant='title-medium'] { + font-size: var(--bui-font-size-7); + line-height: 140%; + } -.bui-Text[data-variant='title-small'] { - font-size: var(--bui-font-size-6); - line-height: 140%; -} + .bui-Text[data-variant='title-small'] { + font-size: var(--bui-font-size-6); + line-height: 140%; + } -.bui-Text[data-variant='title-x-small'] { - font-size: var(--bui-font-size-5); - line-height: 140%; -} + .bui-Text[data-variant='title-x-small'] { + font-size: var(--bui-font-size-5); + line-height: 140%; + } -.bui-Text[data-variant='body-large'] { - font-size: var(--bui-font-size-4); - line-height: 140%; -} + .bui-Text[data-variant='body-large'] { + font-size: var(--bui-font-size-4); + line-height: 140%; + } -.bui-Text[data-variant='body-medium'] { - font-size: var(--bui-font-size-3); - line-height: 140%; -} + .bui-Text[data-variant='body-medium'] { + font-size: var(--bui-font-size-3); + line-height: 140%; + } -.bui-Text[data-variant='body-small'] { - font-size: var(--bui-font-size-2); - line-height: 140%; -} + .bui-Text[data-variant='body-small'] { + font-size: var(--bui-font-size-2); + line-height: 140%; + } -.bui-Text[data-variant='body-x-small'] { - font-size: var(--bui-font-size-1); - line-height: 140%; -} + .bui-Text[data-variant='body-x-small'] { + font-size: var(--bui-font-size-1); + line-height: 140%; + } -.bui-Text[data-weight='regular'] { - font-weight: var(--bui-font-weight-regular); -} + .bui-Text[data-weight='regular'] { + font-weight: var(--bui-font-weight-regular); + } -.bui-Text[data-weight='bold'] { - font-weight: var(--bui-font-weight-bold); -} + .bui-Text[data-weight='bold'] { + font-weight: var(--bui-font-weight-bold); + } -.bui-Text[data-color='primary'] { - color: var(--bui-fg-primary); -} + .bui-Text[data-color='primary'] { + color: var(--bui-fg-primary); + } -.bui-Text[data-color='secondary'] { - color: var(--bui-fg-secondary); -} + .bui-Text[data-color='secondary'] { + color: var(--bui-fg-secondary); + } -.bui-Text[data-color='danger'] { - color: var(--bui-fg-danger); -} + .bui-Text[data-color='danger'] { + color: var(--bui-fg-danger); + } -.bui-Text[data-color='warning'] { - color: var(--bui-fg-warning); -} + .bui-Text[data-color='warning'] { + color: var(--bui-fg-warning); + } -.bui-Text[data-color='success'] { - color: var(--bui-fg-success); -} + .bui-Text[data-color='success'] { + color: var(--bui-fg-success); + } -.bui-Text[data-truncate] { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} + .bui-Text[data-truncate] { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } -.bui-Text[data-as='span'], -.bui-Text[data-as='label'], -.bui-Text[data-as='strong'], -.bui-Text[data-as='em'], -.bui-Text[data-as='small'] { - display: inline-block; + .bui-Text[data-as='span'], + .bui-Text[data-as='label'], + .bui-Text[data-as='strong'], + .bui-Text[data-as='em'], + .bui-Text[data-as='small'] { + display: inline-block; + } } diff --git a/packages/ui/src/components/TextField/TextField.styles.css b/packages/ui/src/components/TextField/TextField.styles.css index 792d5d85c9..170349a760 100644 --- a/packages/ui/src/components/TextField/TextField.styles.css +++ b/packages/ui/src/components/TextField/TextField.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,105 +14,107 @@ * limitations under the License. */ -.bui-TextField { - display: flex; - flex-direction: column; - font-family: var(--bui-font-regular); - width: 100%; - flex-shrink: 0; -} - -.bui-InputWrapper { - position: relative; - - &[data-size='small'] .bui-Input { - height: 2rem; +@layer components { + .bui-TextField { + display: flex; + flex-direction: column; + font-family: var(--bui-font-regular); + width: 100%; + flex-shrink: 0; } - &[data-size='medium'] .bui-Input { - height: 2.5rem; + .bui-InputWrapper { + position: relative; + + &[data-size='small'] .bui-Input { + height: 2rem; + } + + &[data-size='medium'] .bui-Input { + height: 2.5rem; + } + + &[data-size='small'] .bui-Input[data-icon] { + padding-left: var(--bui-space-8); + } + + &[data-size='medium'] .bui-Input[data-icon] { + padding-left: var(--bui-space-9); + } } - &[data-size='small'] .bui-Input[data-icon] { - padding-left: var(--bui-space-8); + .bui-InputIcon { + position: absolute; + left: var(--bui-space-3); + top: 50%; + transform: translateY(-50%); + margin-right: var(--bui-space-1); + color: var(--bui-fg-primary); + flex-shrink: 0; + pointer-events: none; + /* To animate the icon when the input is collapsed */ + transition: left 0.2s ease-in-out; + + &[data-size='small'], + &[data-size='small'] svg { + width: 1rem; + height: 1rem; + } + + &[data-size='medium'], + &[data-size='medium'] svg { + width: 1.25rem; + height: 1.25rem; + } } - &[data-size='medium'] .bui-Input[data-icon] { - padding-left: var(--bui-space-9); - } -} - -.bui-InputIcon { - position: absolute; - left: var(--bui-space-3); - top: 50%; - transform: translateY(-50%); - margin-right: var(--bui-space-1); - color: var(--bui-fg-primary); - flex-shrink: 0; - pointer-events: none; - /* To animate the icon when the input is collapsed */ - transition: left 0.2s ease-in-out; - - &[data-size='small'], - &[data-size='small'] svg { - width: 1rem; - height: 1rem; - } - - &[data-size='medium'], - &[data-size='medium'] svg { - width: 1.25rem; - height: 1.25rem; - } -} - -.bui-Input { - display: flex; - align-items: center; - padding: 0 var(--bui-space-3); - border-radius: var(--bui-radius-2); - border: 1px solid var(--bui-border); - background-color: var(--bui-bg-surface-1); - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - font-weight: var(--bui-font-weight-regular); - color: var(--bui-fg-primary); - transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; - width: 100%; - height: 100%; - cursor: inherit; - - &::-webkit-search-cancel-button, - &::-webkit-search-decoration { - -webkit-appearance: none; - } - - &::placeholder { - color: var(--bui-fg-secondary); - } - - &[data-focused] { - outline-color: var(--bui-border-pressed); - outline-width: 0px; - } - - &[data-hovered] { - border-color: var(--bui-border-hover); - } - - &[data-focused] { - border-color: var(--bui-border-pressed); - outline-width: 0px; - } - - &[data-invalid] { - border-color: var(--bui-fg-danger); - } - - &[data-disabled] { - opacity: 0.5; - cursor: not-allowed; - border: 1px solid var(--bui-border-disabled); + .bui-Input { + display: flex; + align-items: center; + padding: 0 var(--bui-space-3); + border-radius: var(--bui-radius-2); + border: 1px solid var(--bui-border); + background-color: var(--bui-bg-surface-1); + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + font-weight: var(--bui-font-weight-regular); + color: var(--bui-fg-primary); + transition: border-color 0.2s ease-in-out, outline-color 0.2s ease-in-out; + width: 100%; + height: 100%; + cursor: inherit; + + &::-webkit-search-cancel-button, + &::-webkit-search-decoration { + -webkit-appearance: none; + } + + &::placeholder { + color: var(--bui-fg-secondary); + } + + &[data-focused] { + outline-color: var(--bui-border-pressed); + outline-width: 0px; + } + + &[data-hovered] { + border-color: var(--bui-border-hover); + } + + &[data-focused] { + border-color: var(--bui-border-pressed); + outline-width: 0px; + } + + &[data-invalid] { + border-color: var(--bui-fg-danger); + } + + &[data-disabled] { + opacity: 0.5; + cursor: not-allowed; + border: 1px solid var(--bui-border-disabled); + } } } diff --git a/packages/ui/src/components/Tooltip/Tooltip.styles.css b/packages/ui/src/components/Tooltip/Tooltip.styles.css index f80a12bbc1..7c035888ed 100644 --- a/packages/ui/src/components/Tooltip/Tooltip.styles.css +++ b/packages/ui/src/components/Tooltip/Tooltip.styles.css @@ -1,5 +1,5 @@ /* - * Copyright 2024 The Backstage Authors + * Copyright 2025 The Backstage Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,110 +14,112 @@ * limitations under the License. */ -.bui-Tooltip { - box-shadow: 0 10px 15px -3px rgba(0 0 0 / 0.1), - 0 4px 6px -4px rgba(0 0 0 / 0.1); - border-radius: 4px; - background: var(--bui-bg-surface-1); - border: 1px solid var(--bui-gray-3); - forced-color-adjust: none; - outline: none; - padding: var(--bui-space-2) var(--bui-space-3); - max-width: 240px; - /* fixes FF gap */ - transform: translate3d(0, 0, 0); - transition: transform 200ms, opacity 200ms; - font-size: var(--bui-font-size-3); - font-family: var(--bui-font-regular); - color: var(--bui-fg-primary); +@layer components { + .bui-Tooltip { + box-shadow: 0 10px 15px -3px rgba(0 0 0 / 0.1), + 0 4px 6px -4px rgba(0 0 0 / 0.1); + border-radius: 4px; + background: var(--bui-bg-surface-1); + border: 1px solid var(--bui-gray-3); + forced-color-adjust: none; + outline: none; + padding: var(--bui-space-2) var(--bui-space-3); + max-width: 240px; + /* fixes FF gap */ + transform: translate3d(0, 0, 0); + transition: transform 200ms, opacity 200ms; + font-size: var(--bui-font-size-3); + font-family: var(--bui-font-regular); + color: var(--bui-fg-primary); - &[data-entering], - &[data-exiting] { - transform: var(--origin); - opacity: 0; + &[data-entering], + &[data-exiting] { + transform: var(--origin); + opacity: 0; + } + + --tooltip-offset: var(--bui-space-3); + + &[data-placement='top'] { + margin-bottom: var(--tooltip-offset); + --origin: translateY(4px); + } + + &[data-placement='right'] { + margin-left: var(--tooltip-offset); + --origin: translateX(-4px); + } + + &[data-placement='bottom'] { + margin-top: var(--tooltip-offset); + --origin: translateY(-4px); + } + + &[data-placement='left'] { + margin-right: var(--tooltip-offset); + --origin: translateX(4px); + } } - --tooltip-offset: var(--bui-space-3); + .bui-TooltipArrow { + & svg { + display: block; - &[data-placement='top'] { - margin-bottom: var(--tooltip-offset); - --origin: translateY(4px); - } - - &[data-placement='right'] { - margin-left: var(--tooltip-offset); - --origin: translateX(-4px); - } - - &[data-placement='bottom'] { - margin-top: var(--tooltip-offset); - --origin: translateY(-4px); - } - - &[data-placement='left'] { - margin-right: var(--tooltip-offset); - --origin: translateX(4px); - } -} - -.bui-TooltipArrow { - & svg { - display: block; - - /* The tooltip is rendered overlaying the main + /* The tooltip is rendered overlaying the main tooltip element by 1px. This causes the borders to overlap, which causes minor visual artifacts with transparent border colors. To mitigate this, we split the stroke and fill across separate elements in order to guarantee that the stroke is always overlaying a consistent color. */ - path:nth-child(1) { - fill: var(--bui-bg-surface-1); - } + path:nth-child(1) { + fill: var(--bui-bg-surface-1); + } - path:nth-child(2) { - fill: var(--bui-gray-3); - } + path:nth-child(2) { + fill: var(--bui-gray-3); + } - /* The arrow svg overlaps the tooltip by 2px, so we + /* The arrow svg overlaps the tooltip by 2px, so we need to adjust the margins accordingly. */ - --tooltip-arrow-overlap: -2px; - } - - &[data-placement='top'] svg { - margin-top: var(--tooltip-arrow-overlap); - } - - &[data-placement='bottom'] svg { - margin-bottom: var(--tooltip-arrow-overlap); - transform: rotate(180deg); - } - - &[data-placement='right'] svg { - margin-right: var(--tooltip-arrow-overlap); - transform: rotate(90deg); - } - - &[data-placement='left'] svg { - margin-left: var(--tooltip-arrow-overlap); - transform: rotate(-90deg); - } -} - -[data-theme='dark'] { - .bui-Tooltip { - background: var(--bui-bg-surface-2); - box-shadow: none; - border: 1px solid var(--bui-gray-4); - } - - .bui-TooltipArrow { - svg path:nth-child(1) { - fill: var(--bui-bg-surface-2); + --tooltip-arrow-overlap: -2px; } - svg path:nth-child(2) { - fill: var(--bui-gray-4); + &[data-placement='top'] svg { + margin-top: var(--tooltip-arrow-overlap); + } + + &[data-placement='bottom'] svg { + margin-bottom: var(--tooltip-arrow-overlap); + transform: rotate(180deg); + } + + &[data-placement='right'] svg { + margin-right: var(--tooltip-arrow-overlap); + transform: rotate(90deg); + } + + &[data-placement='left'] svg { + margin-left: var(--tooltip-arrow-overlap); + transform: rotate(-90deg); + } + } + + [data-theme='dark'] { + .bui-Tooltip { + background: var(--bui-bg-surface-2); + box-shadow: none; + border: 1px solid var(--bui-gray-4); + } + + .bui-TooltipArrow { + svg path:nth-child(1) { + fill: var(--bui-bg-surface-2); + } + + svg path:nth-child(2) { + fill: var(--bui-gray-4); + } } } }