diff --git a/package-lock.json b/package-lock.json index 0e9e5e24..f0aa2cec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6,7 +6,8 @@ "packages": { "": { "name": "@react-ui-org/react-ui", - "version": "0.52.0", + "version": "0.54.0", + "hasInstallScript": true, "license": "MIT", "dependencies": { "normalize.css": "^8.0.1" @@ -30,7 +31,7 @@ "babel-jest": "^29.6.4", "babel-loader": "^9.1.3", "core-js": "^3.32.1", - "css-loader": "^6.8.1", + "css-loader": "^6.10.0", "eslint": "^8.48.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.28.1", @@ -5319,19 +5320,19 @@ } }, "node_modules/css-loader": { - "version": "6.8.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.8.1.tgz", - "integrity": "sha512-xDAXtEVGlD0gJ07iclwWVkLoZOpEvAWaSyf6W18S2pOC//K8+qUDIx8IIT3D+HjnmkJPQeesOPv5aiUaJsCM2g==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.10.0.tgz", + "integrity": "sha512-LTSA/jWbwdMlk+rhmElbDR2vbtQoTBPr7fkJE+mxrHj+7ru0hUmHafDRzWIjIHTwpitWVaqY2/UWGRca3yUgRw==", "dev": true, "dependencies": { "icss-utils": "^5.1.0", - "postcss": "^8.4.21", + "postcss": "^8.4.33", "postcss-modules-extract-imports": "^3.0.0", - "postcss-modules-local-by-default": "^4.0.3", - "postcss-modules-scope": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.4", + "postcss-modules-scope": "^3.1.1", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.2.0", - "semver": "^7.3.8" + "semver": "^7.5.4" }, "engines": { "node": ">= 12.13.0" @@ -5341,7 +5342,16 @@ "url": "https://opencollective.com/webpack" }, "peerDependencies": { + "@rspack/core": "0.x || 1.x", "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, "node_modules/css-loader/node_modules/lru-cache": { @@ -10814,9 +10824,9 @@ "dev": true }, "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ { @@ -11404,9 +11414,9 @@ } }, "node_modules/postcss": { - "version": "8.4.29", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.29.tgz", - "integrity": "sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw==", + "version": "8.4.35", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", + "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", "dev": true, "funding": [ { @@ -11423,7 +11433,7 @@ } ], "dependencies": { - "nanoid": "^3.3.6", + "nanoid": "^3.3.7", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" }, @@ -11505,9 +11515,9 @@ } }, "node_modules/postcss-modules-local-by-default": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.3.tgz", - "integrity": "sha512-2/u2zraspoACtrbFRnTijMiQtb4GW4BvatjaG/bCjYQo8kLTdevCUlwuBHx2sCnSyrI3x3qj4ZK1j5LQBgzmwA==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.4.tgz", + "integrity": "sha512-L4QzMnOdVwRm1Qb8m4x8jsZzKAaPAgrUF1r/hjDR2Xj7R+8Zsf97jAlSQzWtKx5YNiNGN8QxmPFIc/sh+RQl+Q==", "dev": true, "dependencies": { "icss-utils": "^5.0.0", @@ -11522,9 +11532,9 @@ } }, "node_modules/postcss-modules-scope": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", - "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.1.1.tgz", + "integrity": "sha512-uZgqzdTleelWjzJY+Fhti6F3C9iF1JR/dODLs/JDefozYcKTBCdD8BIl6nNPbTbcLnGrk56hzwZC2DaGNvYjzA==", "dev": true, "dependencies": { "postcss-selector-parser": "^6.0.4" diff --git a/package.json b/package.json index 6ccb038d..c84bc3d2 100644 --- a/package.json +++ b/package.json @@ -76,7 +76,7 @@ "babel-jest": "^29.6.4", "babel-loader": "^9.1.3", "core-js": "^3.32.1", - "css-loader": "^6.8.1", + "css-loader": "^6.10.0", "eslint": "^8.48.0", "eslint-config-airbnb": "^19.0.4", "eslint-plugin-import": "^2.28.1", diff --git a/src/components/Alert/Alert.jsx b/src/components/Alert/Alert.jsx index f4e7d735..33a7b2bd 100644 --- a/src/components/Alert/Alert.jsx +++ b/src/components/Alert/Alert.jsx @@ -7,7 +7,7 @@ import { import { transferProps } from '../_helpers/transferProps'; import { classNames } from '../../utils/classNames'; import { getRootColorClassName } from '../_helpers/getRootColorClassName'; -import styles from './Alert.scss'; +import styles from './Alert.module.scss'; export const Alert = ({ children, diff --git a/src/components/Alert/Alert.module.scss b/src/components/Alert/Alert.module.scss new file mode 100644 index 00000000..285e7476 --- /dev/null +++ b/src/components/Alert/Alert.module.scss @@ -0,0 +1,100 @@ +@use "sass:map"; +@use "../../styles/theme/typography"; +@use "../../styles/tools/accessibility"; +@use "../../styles/tools/reset"; +@use "settings"; +@use "theme"; +@use "tools"; + +@layer components.alert { + .root { + position: relative; + display: flex; + align-items: flex-start; + width: 100%; + color: var(--rui-local-color); + border-width: theme.$border-width theme.$border-width theme.$border-width theme.$stripe-width; + border-style: solid; + border-color: var(--rui-local-foreground-color); + border-radius: theme.$border-radius; + background-color: var(--rui-local-background-color); + } + + .icon, + .message { + padding: theme.$padding; + } + + .close, + .icon { + height: settings.$min-height; + color: var(--rui-local-foreground-color); + } + + .icon { + display: flex; + flex: none; + align-items: center; + justify-content: center; + padding-right: 0; + } + + .message { + flex-grow: 1; + font-weight: theme.$font-weight; + font-size: settings.$font-size; + line-height: settings.$line-height; + } + + .message a, + .message strong { + font-weight: theme.$emphasis-font-weight; + color: var(--rui-local-foreground-color); + } + + .close { + @include reset.button(); + @include accessibility.min-tap-target(); + + padding: theme.$padding; + font-size: map.get(typography.$font-size-values, 4); + line-height: 1; + } + + .closeSign { + position: relative; + top: -0.1em; + } + + .isRootColorSuccess { + @include tools.color(success); + } + + .isRootColorWarning { + @include tools.color(warning); + } + + .isRootColorDanger { + @include tools.color(danger); + } + + .isRootColorHelp { + @include tools.color(help); + } + + .isRootColorInfo { + @include tools.color(info); + } + + .isRootColorNote { + @include tools.color(note); + } + + .isRootColorLight { + @include tools.color(light); + } + + .isRootColorDark { + @include tools.color(dark); + } +} diff --git a/src/components/Alert/Alert.scss b/src/components/Alert/Alert.scss deleted file mode 100644 index da962be1..00000000 --- a/src/components/Alert/Alert.scss +++ /dev/null @@ -1,98 +0,0 @@ -@use "sass:map"; -@use "../../styles/theme/typography"; -@use "../../styles/tools/accessibility"; -@use "../../styles/tools/reset"; -@use "settings"; -@use "theme"; -@use "tools"; - -.root { - position: relative; - display: flex; - align-items: flex-start; - width: 100%; - color: var(--rui-local-color); - border-width: theme.$border-width theme.$border-width theme.$border-width theme.$stripe-width; - border-style: solid; - border-color: var(--rui-local-foreground-color); - border-radius: theme.$border-radius; - background-color: var(--rui-local-background-color); -} - -.icon, -.message { - padding: theme.$padding; -} - -.close, -.icon { - height: settings.$min-height; - color: var(--rui-local-foreground-color); -} - -.icon { - display: flex; - flex: none; - align-items: center; - justify-content: center; - padding-right: 0; -} - -.message { - flex-grow: 1; - font-weight: theme.$font-weight; - font-size: settings.$font-size; - line-height: settings.$line-height; -} - -.message a, -.message strong { - font-weight: theme.$emphasis-font-weight; - color: var(--rui-local-foreground-color); -} - -.close { - @include reset.button(); - @include accessibility.min-tap-target(); - - padding: theme.$padding; - font-size: map.get(typography.$font-size-values, 4); - line-height: 1; -} - -.closeSign { - position: relative; - top: -0.1em; -} - -.isRootColorSuccess { - @include tools.color(success); -} - -.isRootColorWarning { - @include tools.color(warning); -} - -.isRootColorDanger { - @include tools.color(danger); -} - -.isRootColorHelp { - @include tools.color(help); -} - -.isRootColorInfo { - @include tools.color(info); -} - -.isRootColorNote { - @include tools.color(note); -} - -.isRootColorLight { - @include tools.color(light); -} - -.isRootColorDark { - @include tools.color(dark); -} diff --git a/src/components/Badge/Badge.jsx b/src/components/Badge/Badge.jsx index ed24635f..53869644 100644 --- a/src/components/Badge/Badge.jsx +++ b/src/components/Badge/Badge.jsx @@ -4,7 +4,7 @@ import { withGlobalProps } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; import { classNames } from '../../utils/classNames'; import { getRootColorClassName } from '../_helpers/getRootColorClassName'; -import styles from './Badge.scss'; +import styles from './Badge.module.scss'; export const Badge = ({ color, diff --git a/src/components/Badge/Badge.module.scss b/src/components/Badge/Badge.module.scss new file mode 100644 index 00000000..a78c7022 --- /dev/null +++ b/src/components/Badge/Badge.module.scss @@ -0,0 +1,109 @@ +@use "sass:map"; +@use "sass:math"; +@use "../../styles/theme/borders"; +@use "../../styles/theme/typography"; + +$_badge-size: 1.25rem; + +@layer components.badge { + .root { + display: inline-block; + min-width: $_badge-size; + height: $_badge-size; + padding: 0.25rem 0.35rem; + overflow: hidden; + font-weight: map.get(typography.$font-weight-values, bold); + font-size: typography.$font-size-smaller; + line-height: 1; + text-align: center; + white-space: nowrap; + vertical-align: baseline; + color: var(--rui-local-color); + border-radius: math.div($_badge-size, 2); + background-color: var(--rui-local-background-color); + box-shadow: var(--rui-local-box-shadow, #{0 0 0 2px rgb(255 255 255 / 80%)}); + } + + .isRootColorSuccess { + --rui-local-color: var(--rui-color-feedback-on-success); + --rui-local-background-color: var(--rui-color-feedback-success); + } + + .isRootColorWarning { + --rui-local-color: var(--rui-color-feedback-on-warning); + --rui-local-background-color: var(--rui-color-feedback-warning); + } + + .isRootColorDanger { + --rui-local-color: var(--rui-color-feedback-on-danger); + --rui-local-background-color: var(--rui-color-feedback-danger); + } + + .isRootColorHelp { + --rui-local-color: var(--rui-color-feedback-on-help); + --rui-local-background-color: var(--rui-color-feedback-help); + } + + .isRootColorInfo { + --rui-local-color: var(--rui-color-feedback-on-info); + --rui-local-background-color: var(--rui-color-feedback-info); + } + + .isRootColorNote { + --rui-local-color: var(--rui-color-feedback-on-note); + --rui-local-background-color: var(--rui-color-feedback-note); + } + + .isRootColorLight { + --rui-local-color: var(--rui-color-neutral-on-light); + --rui-local-background-color: var(--rui-color-neutral-light); + --rui-local-box-shadow: none; + } + + .isRootColorDark { + --rui-local-color: var(--rui-color-neutral-on-dark); + --rui-local-background-color: var(--rui-color-neutral-dark); + --rui-local-box-shadow: none; + } + + .isRootPriorityOutline { + --rui-local-background-color: transparent; + --rui-local-box-shadow: none; + + padding-top: 0.1875rem; + padding-bottom: 0.1875rem; + border: borders.$width solid currentcolor; + } + + .isRootPriorityOutline.isRootColorSuccess { + --rui-local-color: var(--rui-color-feedback-success); + } + + .isRootPriorityOutline.isRootColorWarning { + --rui-local-color: var(--rui-color-feedback-warning); + } + + .isRootPriorityOutline.isRootColorDanger { + --rui-local-color: var(--rui-color-feedback-danger); + } + + .isRootPriorityOutline.isRootColorHelp { + --rui-local-color: var(--rui-color-feedback-help); + } + + .isRootPriorityOutline.isRootColorInfo { + --rui-local-color: var(--rui-color-feedback-info); + } + + .isRootPriorityOutline.isRootColorNote { + --rui-local-color: var(--rui-color-feedback-note); + } + + .isRootPriorityOutline.isRootColorLight { + --rui-local-color: var(--rui-color-neutral-light); + } + + .isRootPriorityOutline.isRootColorDark { + --rui-local-color: var(--rui-color-neutral-dark); + } +} diff --git a/src/components/Badge/Badge.scss b/src/components/Badge/Badge.scss deleted file mode 100644 index f5520ebf..00000000 --- a/src/components/Badge/Badge.scss +++ /dev/null @@ -1,107 +0,0 @@ -@use "sass:map"; -@use "sass:math"; -@use "../../styles/theme/borders"; -@use "../../styles/theme/typography"; - -$_badge-size: 1.25rem; - -.root { - display: inline-block; - min-width: $_badge-size; - height: $_badge-size; - padding: 0.25rem 0.35rem; - overflow: hidden; - font-weight: map.get(typography.$font-weight-values, bold); - font-size: typography.$font-size-smaller; - line-height: 1; - text-align: center; - white-space: nowrap; - vertical-align: baseline; - color: var(--rui-local-color); - border-radius: math.div($_badge-size, 2); - background-color: var(--rui-local-background-color); - box-shadow: var(--rui-local-box-shadow, #{0 0 0 2px rgb(255 255 255 / 80%)}); -} - -.isRootColorSuccess { - --rui-local-color: var(--rui-color-feedback-on-success); - --rui-local-background-color: var(--rui-color-feedback-success); -} - -.isRootColorWarning { - --rui-local-color: var(--rui-color-feedback-on-warning); - --rui-local-background-color: var(--rui-color-feedback-warning); -} - -.isRootColorDanger { - --rui-local-color: var(--rui-color-feedback-on-danger); - --rui-local-background-color: var(--rui-color-feedback-danger); -} - -.isRootColorHelp { - --rui-local-color: var(--rui-color-feedback-on-help); - --rui-local-background-color: var(--rui-color-feedback-help); -} - -.isRootColorInfo { - --rui-local-color: var(--rui-color-feedback-on-info); - --rui-local-background-color: var(--rui-color-feedback-info); -} - -.isRootColorNote { - --rui-local-color: var(--rui-color-feedback-on-note); - --rui-local-background-color: var(--rui-color-feedback-note); -} - -.isRootColorLight { - --rui-local-color: var(--rui-color-neutral-on-light); - --rui-local-background-color: var(--rui-color-neutral-light); - --rui-local-box-shadow: none; -} - -.isRootColorDark { - --rui-local-color: var(--rui-color-neutral-on-dark); - --rui-local-background-color: var(--rui-color-neutral-dark); - --rui-local-box-shadow: none; -} - -.isRootPriorityOutline { - --rui-local-background-color: transparent; - --rui-local-box-shadow: none; - - padding-top: 0.1875rem; - padding-bottom: 0.1875rem; - border: borders.$width solid currentcolor; -} - -.isRootPriorityOutline.isRootColorSuccess { - --rui-local-color: var(--rui-color-feedback-success); -} - -.isRootPriorityOutline.isRootColorWarning { - --rui-local-color: var(--rui-color-feedback-warning); -} - -.isRootPriorityOutline.isRootColorDanger { - --rui-local-color: var(--rui-color-feedback-danger); -} - -.isRootPriorityOutline.isRootColorHelp { - --rui-local-color: var(--rui-color-feedback-help); -} - -.isRootPriorityOutline.isRootColorInfo { - --rui-local-color: var(--rui-color-feedback-info); -} - -.isRootPriorityOutline.isRootColorNote { - --rui-local-color: var(--rui-color-feedback-note); -} - -.isRootPriorityOutline.isRootColorLight { - --rui-local-color: var(--rui-color-neutral-light); -} - -.isRootPriorityOutline.isRootColorDark { - --rui-local-color: var(--rui-color-neutral-dark); -} diff --git a/src/components/Button/Button.jsx b/src/components/Button/Button.jsx index 94675ecd..b93d455c 100644 --- a/src/components/Button/Button.jsx +++ b/src/components/Button/Button.jsx @@ -10,7 +10,7 @@ import { ButtonGroupContext } from '../ButtonGroup'; import { InputGroupContext } from '../InputGroup/InputGroupContext'; import getRootPriorityClassName from '../_helpers/getRootPriorityClassName'; import getRootLabelVisibilityClassName from './helpers/getRootLabelVisibilityClassName'; -import styles from './Button.scss'; +import styles from './Button.module.scss'; export const Button = React.forwardRef((props, ref) => { const { diff --git a/src/components/Button/Button.scss b/src/components/Button/Button.module.scss similarity index 100% rename from src/components/Button/Button.scss rename to src/components/Button/Button.module.scss diff --git a/src/components/Button/_base.scss b/src/components/Button/_base.scss index 7f725df9..de235821 100644 --- a/src/components/Button/_base.scss +++ b/src/components/Button/_base.scss @@ -7,151 +7,153 @@ @use "theme"; @use "tools"; -.root { - @include tools.button(); -} +@layer components.button { + .root { + @include tools.button(); + } -.label { - display: block; -} + .label { + display: block; + } -.beforeLabel, -.afterLabel, -.startCorner, -.endCorner, -.feedbackIcon { - display: flex; - align-items: baseline; - justify-content: center; -} + .beforeLabel, + .afterLabel, + .startCorner, + .endCorner, + .feedbackIcon { + display: flex; + align-items: baseline; + justify-content: center; + } -.startCorner, -.endCorner { - position: absolute; - top: -0.35rem; - z-index: 2; -} + .startCorner, + .endCorner { + position: absolute; + top: -0.35rem; + z-index: 2; + } -.startCorner { - left: 0; - margin-left: -0.35rem; -} + .startCorner { + left: 0; + margin-left: -0.35rem; + } -.endCorner { - right: 0; - margin-right: -0.35rem; -} + .endCorner { + right: 0; + margin-right: -0.35rem; + } -.feedbackIcon { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - z-index: 1; - align-items: center; -} + .feedbackIcon { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + align-items: center; + } -.isRootSizeSmall { - @include tools.button-size(small); -} + .isRootSizeSmall { + @include tools.button-size(small); + } -.isRootSizeMedium { - @include tools.button-size(medium); -} + .isRootSizeMedium { + @include tools.button-size(medium); + } -.isRootSizeLarge { - @include tools.button-size(large); -} + .isRootSizeLarge { + @include tools.button-size(large); + } -.isRootBlock { - width: 100%; -} + .isRootBlock { + width: 100%; + } -.hasRootFeedback:disabled { - opacity: theme.$feedback-opacity; - cursor: theme.$feedback-cursor; -} + .hasRootFeedback:disabled { + opacity: theme.$feedback-opacity; + cursor: theme.$feedback-cursor; + } -.hasRootFeedback .label, -.hasRootFeedback .beforeLabel, -.hasRootFeedback .afterLabel { - color: transparent; -} + .hasRootFeedback .label, + .hasRootFeedback .beforeLabel, + .hasRootFeedback .afterLabel { + color: transparent; + } -.isRootInButtonGroup, -.isRootInInputGroup { - z-index: map.get(settings.$group-z-indexes, button); + .isRootInButtonGroup, + .isRootInInputGroup { + z-index: map.get(settings.$group-z-indexes, button); - &:not(:first-child) { - border-start-start-radius: var(--rui-local-inner-border-radius); - border-end-start-radius: var(--rui-local-inner-border-radius); - } + &:not(:first-child) { + border-start-start-radius: var(--rui-local-inner-border-radius); + border-end-start-radius: var(--rui-local-inner-border-radius); + } - &:not(:last-child) { - border-start-end-radius: var(--rui-local-inner-border-radius); - border-end-end-radius: var(--rui-local-inner-border-radius); + &:not(:last-child) { + border-start-end-radius: var(--rui-local-inner-border-radius); + border-end-end-radius: var(--rui-local-inner-border-radius); + } } -} -.isRootInButtonGroup:not(:first-child) { - margin-inline-start: var(--rui-local-gap); // 1. -} + .isRootInButtonGroup:not(:first-child) { + margin-inline-start: var(--rui-local-gap); // 1. + } -.isRootInButtonGroup:focus, -.isRootInButtonGroup:not(:disabled):hover { - z-index: map.get(settings.$group-z-indexes, button-hover); -} + .isRootInButtonGroup:focus, + .isRootInButtonGroup:not(:disabled):hover { + z-index: map.get(settings.$group-z-indexes, button-hover); + } -.isRootInButtonGroup .startCorner, -.isRootInInputGroup .startCorner, -.isRootInButtonGroup .endCorner, -.isRootInInputGroup .endCorner { - z-index: map.get(settings.$group-z-indexes, button-overflowing-elements); -} + .isRootInButtonGroup .startCorner, + .isRootInInputGroup .startCorner, + .isRootInButtonGroup .endCorner, + .isRootInInputGroup .endCorner { + z-index: map.get(settings.$group-z-indexes, button-overflowing-elements); + } -.hasLabelHidden, -.hasLabelVisibleSm, -.hasLabelVisibleMd, -.hasLabelVisibleLg, -.hasLabelVisibleXl, -.hasLabelVisibleX2l, -.hasLabelVisibleX3l { - @include tools.hide-label(); -} + .hasLabelHidden, + .hasLabelVisibleSm, + .hasLabelVisibleMd, + .hasLabelVisibleLg, + .hasLabelVisibleXl, + .hasLabelVisibleX2l, + .hasLabelVisibleX3l { + @include tools.hide-label(); + } -.hasLabelVisibleSm { - @include breakpoint.up(sm) { - @include tools.show-label(); + .hasLabelVisibleSm { + @include breakpoint.up(sm) { + @include tools.show-label(); + } } -} -.hasLabelVisibleMd { - @include breakpoint.up(md) { - @include tools.show-label(); + .hasLabelVisibleMd { + @include breakpoint.up(md) { + @include tools.show-label(); + } } -} -.hasLabelVisibleLg { - @include breakpoint.up(lg) { - @include tools.show-label(); + .hasLabelVisibleLg { + @include breakpoint.up(lg) { + @include tools.show-label(); + } } -} -.hasLabelVisibleXl { - @include breakpoint.up(xl) { - @include tools.show-label(); + .hasLabelVisibleXl { + @include breakpoint.up(xl) { + @include tools.show-label(); + } } -} -.hasLabelVisibleX2l { - @include breakpoint.up(x2l) { - @include tools.show-label(); + .hasLabelVisibleX2l { + @include breakpoint.up(x2l) { + @include tools.show-label(); + } } -} -.hasLabelVisibleX3l { - @include breakpoint.up(x3l) { - @include tools.show-label(); + .hasLabelVisibleX3l { + @include breakpoint.up(x3l) { + @include tools.show-label(); + } } } diff --git a/src/components/Button/_priorities.scss b/src/components/Button/_priorities.scss index 08ec823c..eb94ce6a 100644 --- a/src/components/Button/_priorities.scss +++ b/src/components/Button/_priorities.scss @@ -3,145 +3,147 @@ @use "theme"; @use "tools"; -.isRootPriorityFilled.isRootColorPrimary { - @include tools.button-color(filled, primary); -} - -.isRootPriorityFilled.isRootColorSecondary { - @include tools.button-color(filled, secondary); -} - -.isRootPriorityFilled.isRootColorSelected { - @include tools.button-color(filled, selected); -} - -.isRootPriorityFilled.isRootColorSuccess { - @include tools.button-color(filled, success); -} - -.isRootPriorityFilled.isRootColorWarning { - @include tools.button-color(filled, warning); -} - -.isRootPriorityFilled.isRootColorDanger { - @include tools.button-color(filled, danger); -} - -.isRootPriorityFilled.isRootColorHelp { - @include tools.button-color(filled, help); -} - -.isRootPriorityFilled.isRootColorInfo { - @include tools.button-color(filled, info); -} - -.isRootPriorityFilled.isRootColorNote { - @include tools.button-color(filled, note); -} - -.isRootPriorityFilled.isRootColorLight { - @include tools.button-color(filled, light); -} - -.isRootPriorityFilled.isRootColorDark { - @include tools.button-color(filled, dark); -} - -.isRootPriorityOutline.isRootColorPrimary { - @include tools.button-color(outline, primary); -} - -.isRootPriorityOutline.isRootColorSecondary { - @include tools.button-color(outline, secondary); -} - -.isRootPriorityOutline.isRootColorSelected { - @include tools.button-color(outline, selected); -} - -.isRootPriorityOutline.isRootColorSuccess { - @include tools.button-color(outline, success); -} +@layer components.button { + .isRootPriorityFilled.isRootColorPrimary { + @include tools.button-color(filled, primary); + } -.isRootPriorityOutline.isRootColorWarning { - @include tools.button-color(outline, warning); -} - -.isRootPriorityOutline.isRootColorDanger { - @include tools.button-color(outline, danger); -} + .isRootPriorityFilled.isRootColorSecondary { + @include tools.button-color(filled, secondary); + } -.isRootPriorityOutline.isRootColorHelp { - @include tools.button-color(outline, help); -} + .isRootPriorityFilled.isRootColorSelected { + @include tools.button-color(filled, selected); + } -.isRootPriorityOutline.isRootColorInfo { - @include tools.button-color(outline, info); -} + .isRootPriorityFilled.isRootColorSuccess { + @include tools.button-color(filled, success); + } -.isRootPriorityOutline.isRootColorNote { - @include tools.button-color(outline, note); -} + .isRootPriorityFilled.isRootColorWarning { + @include tools.button-color(filled, warning); + } -.isRootPriorityOutline.isRootColorLight { - @include tools.button-color(outline, light); -} + .isRootPriorityFilled.isRootColorDanger { + @include tools.button-color(filled, danger); + } -.isRootPriorityOutline.isRootColorDark { - @include tools.button-color(outline, dark); -} + .isRootPriorityFilled.isRootColorHelp { + @include tools.button-color(filled, help); + } -.isRootPriorityFlat.isRootColorPrimary { - @include tools.button-color(flat, primary); -} - -.isRootPriorityFlat.isRootColorSecondary { - @include tools.button-color(flat, secondary); -} - -.isRootPriorityFlat.isRootColorSelected { - @include tools.button-color(flat, selected); -} - -.isRootPriorityFlat.isRootColorSuccess { - @include tools.button-color(flat, success); -} - -.isRootPriorityFlat.isRootColorWarning { - @include tools.button-color(flat, warning); -} - -.isRootPriorityFlat.isRootColorDanger { - @include tools.button-color(flat, danger); -} - -.isRootPriorityFlat.isRootColorHelp { - @include tools.button-color(flat, help); -} - -.isRootPriorityFlat.isRootColorInfo { - @include tools.button-color(flat, info); -} - -.isRootPriorityFlat.isRootColorNote { - @include tools.button-color(flat, note); -} - -.isRootPriorityFlat.isRootColorLight { - @include tools.button-color(flat, light); -} - -.isRootPriorityFlat.isRootColorDark { - @include tools.button-color(flat, dark); -} + .isRootPriorityFilled.isRootColorInfo { + @include tools.button-color(filled, info); + } -.isRootInButtonGroup:not(:first-child)::before { - content: ""; - position: absolute; - top: calc(-1 * #{theme.$border-width}); - bottom: calc(-1 * #{theme.$border-width}); - left: calc(-1 * #{theme.$border-width}); - z-index: map.get(settings.$group-z-indexes, separator); - border-left: var(--rui-local-separator-width) solid var(--rui-local-separator-color); - transform: translateX(calc(-0.5 * var(--rui-local-gap) - 50%)); + .isRootPriorityFilled.isRootColorNote { + @include tools.button-color(filled, note); + } + + .isRootPriorityFilled.isRootColorLight { + @include tools.button-color(filled, light); + } + + .isRootPriorityFilled.isRootColorDark { + @include tools.button-color(filled, dark); + } + + .isRootPriorityOutline.isRootColorPrimary { + @include tools.button-color(outline, primary); + } + + .isRootPriorityOutline.isRootColorSecondary { + @include tools.button-color(outline, secondary); + } + + .isRootPriorityOutline.isRootColorSelected { + @include tools.button-color(outline, selected); + } + + .isRootPriorityOutline.isRootColorSuccess { + @include tools.button-color(outline, success); + } + + .isRootPriorityOutline.isRootColorWarning { + @include tools.button-color(outline, warning); + } + + .isRootPriorityOutline.isRootColorDanger { + @include tools.button-color(outline, danger); + } + + .isRootPriorityOutline.isRootColorHelp { + @include tools.button-color(outline, help); + } + + .isRootPriorityOutline.isRootColorInfo { + @include tools.button-color(outline, info); + } + + .isRootPriorityOutline.isRootColorNote { + @include tools.button-color(outline, note); + } + + .isRootPriorityOutline.isRootColorLight { + @include tools.button-color(outline, light); + } + + .isRootPriorityOutline.isRootColorDark { + @include tools.button-color(outline, dark); + } + + .isRootPriorityFlat.isRootColorPrimary { + @include tools.button-color(flat, primary); + } + + .isRootPriorityFlat.isRootColorSecondary { + @include tools.button-color(flat, secondary); + } + + .isRootPriorityFlat.isRootColorSelected { + @include tools.button-color(flat, selected); + } + + .isRootPriorityFlat.isRootColorSuccess { + @include tools.button-color(flat, success); + } + + .isRootPriorityFlat.isRootColorWarning { + @include tools.button-color(flat, warning); + } + + .isRootPriorityFlat.isRootColorDanger { + @include tools.button-color(flat, danger); + } + + .isRootPriorityFlat.isRootColorHelp { + @include tools.button-color(flat, help); + } + + .isRootPriorityFlat.isRootColorInfo { + @include tools.button-color(flat, info); + } + + .isRootPriorityFlat.isRootColorNote { + @include tools.button-color(flat, note); + } + + .isRootPriorityFlat.isRootColorLight { + @include tools.button-color(flat, light); + } + + .isRootPriorityFlat.isRootColorDark { + @include tools.button-color(flat, dark); + } + + .isRootInButtonGroup:not(:first-child)::before { + content: ""; + position: absolute; + top: calc(-1 * #{theme.$border-width}); + bottom: calc(-1 * #{theme.$border-width}); + left: calc(-1 * #{theme.$border-width}); + z-index: map.get(settings.$group-z-indexes, separator); + border-left: var(--rui-local-separator-width) solid var(--rui-local-separator-color); + transform: translateX(calc(-0.5 * var(--rui-local-gap) - 50%)); + } } diff --git a/src/components/ButtonGroup/ButtonGroup.jsx b/src/components/ButtonGroup/ButtonGroup.jsx index b97642e4..a567d659 100644 --- a/src/components/ButtonGroup/ButtonGroup.jsx +++ b/src/components/ButtonGroup/ButtonGroup.jsx @@ -7,7 +7,7 @@ import { classNames } from '../../utils/classNames'; import getRootPriorityClassName from '../_helpers/getRootPriorityClassName'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { transferProps } from '../_helpers/transferProps'; -import styles from './ButtonGroup.scss'; +import styles from './ButtonGroup.module.scss'; import { ButtonGroupContext } from './ButtonGroupContext'; export const ButtonGroup = ({ diff --git a/src/components/ButtonGroup/ButtonGroup.module.scss b/src/components/ButtonGroup/ButtonGroup.module.scss new file mode 100644 index 00000000..8f8d304c --- /dev/null +++ b/src/components/ButtonGroup/ButtonGroup.module.scss @@ -0,0 +1,35 @@ +// 1. ButtonGroup gap is implemented using the `margin` property on buttons so the buttons can overlap and reduce +// duplicate borders. + +@use "theme"; + +@layer components.button-group { + .root { + --rui-local-inner-border-radius: #{theme.$inner-border-radius}; + + display: inline-flex; // 1. + } + + .isRootPriorityFilled { + --rui-local-gap: #{theme.$filled-gap}; + --rui-local-separator-width: #{theme.$filled-separator-width}; + --rui-local-separator-color: #{theme.$filled-separator-color}; + } + + .isRootPriorityOutline { + --rui-local-gap: #{theme.$outline-gap}; + --rui-local-separator-width: #{theme.$outline-separator-width}; + --rui-local-separator-color: #{theme.$outline-separator-color}; + } + + .isRootPriorityFlat { + --rui-local-gap: #{theme.$flat-gap}; + --rui-local-separator-width: #{theme.$flat-separator-width}; + --rui-local-separator-color: #{theme.$flat-separator-color}; + } + + .isRootBlock { + display: flex; + width: 100%; + } +} diff --git a/src/components/ButtonGroup/ButtonGroup.scss b/src/components/ButtonGroup/ButtonGroup.scss deleted file mode 100644 index c07129aa..00000000 --- a/src/components/ButtonGroup/ButtonGroup.scss +++ /dev/null @@ -1,33 +0,0 @@ -// 1. ButtonGroup gap is implemented using the `margin` property on buttons so the buttons can overlap and reduce -// duplicate borders. - -@use "theme"; - -.root { - --rui-local-inner-border-radius: #{theme.$inner-border-radius}; - - display: inline-flex; // 1. -} - -.isRootPriorityFilled { - --rui-local-gap: #{theme.$filled-gap}; - --rui-local-separator-width: #{theme.$filled-separator-width}; - --rui-local-separator-color: #{theme.$filled-separator-color}; -} - -.isRootPriorityOutline { - --rui-local-gap: #{theme.$outline-gap}; - --rui-local-separator-width: #{theme.$outline-separator-width}; - --rui-local-separator-color: #{theme.$outline-separator-color}; -} - -.isRootPriorityFlat { - --rui-local-gap: #{theme.$flat-gap}; - --rui-local-separator-width: #{theme.$flat-separator-width}; - --rui-local-separator-color: #{theme.$flat-separator-color}; -} - -.isRootBlock { - display: flex; - width: 100%; -} diff --git a/src/components/Card/Card.jsx b/src/components/Card/Card.jsx index c733da5f..14bbdd08 100644 --- a/src/components/Card/Card.jsx +++ b/src/components/Card/Card.jsx @@ -4,7 +4,7 @@ import { withGlobalProps } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; import { classNames } from '../../utils/classNames'; import { getRootColorClassName } from '../_helpers/getRootColorClassName'; -import styles from './Card.scss'; +import styles from './Card.module.scss'; export const Card = ({ children, diff --git a/src/components/Card/Card.module.scss b/src/components/Card/Card.module.scss new file mode 100644 index 00000000..046c9be3 --- /dev/null +++ b/src/components/Card/Card.module.scss @@ -0,0 +1,72 @@ +// 1. Retain equal card widths in flex and grid layouts independently on their content. + +@use "theme"; +@use "tools"; + +@layer components.card { + .root { + --rui-local-padding: #{theme.$padding}; + + display: flex; + flex-direction: column; + min-width: 0; // 1. + color: var(--rui-local-color); + border: theme.$border-width solid var(--rui-local-border-color); + border-radius: theme.$border-radius; + background-color: var(--rui-local-background-color); + } + + .body { + flex: 1 0 auto; + padding: var(--rui-local-padding); + } + + .footer { + padding: var(--rui-local-padding); + } + + .isRootDense { + --rui-local-padding: #{theme.$dense-padding}; + } + + .isRootRaised { + box-shadow: theme.$raised-box-shadow; + } + + .isRootColorSuccess { + @include tools.color(success); + } + + .isRootColorWarning { + @include tools.color(warning); + } + + .isRootColorDanger { + @include tools.color(danger); + } + + .isRootColorHelp { + @include tools.color(help); + } + + .isRootColorInfo { + @include tools.color(info); + } + + .isRootColorNote { + @include tools.color(note); + } + + .isRootColorLight { + @include tools.color(light); + } + + .isRootColorDark { + @include tools.color(dark); + } + + .isRootDisabled { + background-color: theme.$disabled-background-color; + opacity: theme.$disabled-opacity; + } +} diff --git a/src/components/Card/Card.scss b/src/components/Card/Card.scss deleted file mode 100644 index 2aeae20a..00000000 --- a/src/components/Card/Card.scss +++ /dev/null @@ -1,70 +0,0 @@ -// 1. Retain equal card widths in flex and grid layouts independently on their content. - -@use "theme"; -@use "tools"; - -.root { - --rui-local-padding: #{theme.$padding}; - - display: flex; - flex-direction: column; - min-width: 0; // 1. - color: var(--rui-local-color); - border: theme.$border-width solid var(--rui-local-border-color); - border-radius: theme.$border-radius; - background-color: var(--rui-local-background-color); -} - -.body { - flex: 1 0 auto; - padding: var(--rui-local-padding); -} - -.footer { - padding: var(--rui-local-padding); -} - -.isRootDense { - --rui-local-padding: #{theme.$dense-padding}; -} - -.isRootRaised { - box-shadow: theme.$raised-box-shadow; -} - -.isRootColorSuccess { - @include tools.color(success); -} - -.isRootColorWarning { - @include tools.color(warning); -} - -.isRootColorDanger { - @include tools.color(danger); -} - -.isRootColorHelp { - @include tools.color(help); -} - -.isRootColorInfo { - @include tools.color(info); -} - -.isRootColorNote { - @include tools.color(note); -} - -.isRootColorLight { - @include tools.color(light); -} - -.isRootColorDark { - @include tools.color(dark); -} - -.isRootDisabled { - background-color: theme.$disabled-background-color; - opacity: theme.$disabled-opacity; -} diff --git a/src/components/Card/CardBody.jsx b/src/components/Card/CardBody.jsx index 0c99b453..9c44ba43 100644 --- a/src/components/Card/CardBody.jsx +++ b/src/components/Card/CardBody.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { withGlobalProps } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; -import styles from './Card.scss'; +import styles from './Card.module.scss'; export const CardBody = ({ children, diff --git a/src/components/Card/CardFooter.jsx b/src/components/Card/CardFooter.jsx index 00388e78..df74695d 100644 --- a/src/components/Card/CardFooter.jsx +++ b/src/components/Card/CardFooter.jsx @@ -3,7 +3,7 @@ import React from 'react'; import { withGlobalProps } from '../../provider'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { transferProps } from '../_helpers/transferProps'; -import styles from './Card.scss'; +import styles from './Card.module.scss'; export const CardFooter = ({ children, diff --git a/src/components/CheckboxField/CheckboxField.jsx b/src/components/CheckboxField/CheckboxField.jsx index 0ce6f715..33d4fc18 100644 --- a/src/components/CheckboxField/CheckboxField.jsx +++ b/src/components/CheckboxField/CheckboxField.jsx @@ -5,7 +5,7 @@ import { classNames } from '../../utils/classNames'; import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName'; import { transferProps } from '../_helpers/transferProps'; import { FormLayoutContext } from '../FormLayout'; -import styles from './CheckboxField.scss'; +import styles from './CheckboxField.module.scss'; export const CheckboxField = React.forwardRef((props, ref) => { const { diff --git a/src/components/CheckboxField/CheckboxField.module.scss b/src/components/CheckboxField/CheckboxField.module.scss new file mode 100644 index 00000000..d8625888 --- /dev/null +++ b/src/components/CheckboxField/CheckboxField.module.scss @@ -0,0 +1,63 @@ +@use "../../styles/tools/form-fields/foundation"; +@use "../../styles/tools/form-fields/inline-field-elements"; +@use "../../styles/tools/form-fields/inline-field-layout"; +@use "../../styles/tools/form-fields/variants"; +@use "../../styles/tools/accessibility"; + +@layer components.checkbox-field { + // Foundation + .root { + @include foundation.root(); + @include inline-field-layout.root(); + @include inline-field-elements.min-tap-target($type: checkbox); + @include variants.visual(check); + } + + .label { + @include foundation.label(); + } + + .field { + @include inline-field-layout.field($type: checkbox); + } + + .input { + @include inline-field-elements.check-input($type: checkbox); + } + + .helpText, + .validationText { + @include foundation.help-text(); + } + + .isRootRequired .label { + @include foundation.label-required(); + } + + // States + .isRootStateInvalid { + @include variants.validation(invalid); + } + + .isRootStateValid { + @include variants.validation(valid); + } + + .isRootStateWarning { + @include variants.validation(warning); + } + + // Invisible label + .isLabelHidden { + @include accessibility.hide-text(); + } + + // Layouts + .hasRootLabelBefore { + @include inline-field-layout.has-label-before(); + } + + .isRootInFormLayout { + @include inline-field-layout.in-form-layout(); + } +} diff --git a/src/components/CheckboxField/CheckboxField.scss b/src/components/CheckboxField/CheckboxField.scss deleted file mode 100644 index b9eb8afb..00000000 --- a/src/components/CheckboxField/CheckboxField.scss +++ /dev/null @@ -1,61 +0,0 @@ -@use "../../styles/tools/form-fields/foundation"; -@use "../../styles/tools/form-fields/inline-field-elements"; -@use "../../styles/tools/form-fields/inline-field-layout"; -@use "../../styles/tools/form-fields/variants"; -@use "../../styles/tools/accessibility"; - -// Foundation -.root { - @include foundation.root(); - @include inline-field-layout.root(); - @include inline-field-elements.min-tap-target($type: checkbox); - @include variants.visual(check); -} - -.label { - @include foundation.label(); -} - -.field { - @include inline-field-layout.field($type: checkbox); -} - -.input { - @include inline-field-elements.check-input($type: checkbox); -} - -.helpText, -.validationText { - @include foundation.help-text(); -} - -.isRootRequired .label { - @include foundation.label-required(); -} - -// States -.isRootStateInvalid { - @include variants.validation(invalid); -} - -.isRootStateValid { - @include variants.validation(valid); -} - -.isRootStateWarning { - @include variants.validation(warning); -} - -// Invisible label -.isLabelHidden { - @include accessibility.hide-text(); -} - -// Layouts -.hasRootLabelBefore { - @include inline-field-layout.has-label-before(); -} - -.isRootInFormLayout { - @include inline-field-layout.in-form-layout(); -} diff --git a/src/components/FileInputField/FileInputField.jsx b/src/components/FileInputField/FileInputField.jsx index 63993e4c..dfddfb36 100644 --- a/src/components/FileInputField/FileInputField.jsx +++ b/src/components/FileInputField/FileInputField.jsx @@ -6,7 +6,7 @@ import { getRootValidationStateClassName } from '../_helpers/getRootValidationSt import { resolveContextOrProp } from '../_helpers/resolveContextOrProp'; import { transferProps } from '../_helpers/transferProps'; import { FormLayoutContext } from '../FormLayout'; -import styles from './FileInputField.scss'; +import styles from './FileInputField.module.scss'; export const FileInputField = React.forwardRef((props, ref) => { const { diff --git a/src/components/FileInputField/FileInputField.module.scss b/src/components/FileInputField/FileInputField.module.scss new file mode 100644 index 00000000..fe1da776 --- /dev/null +++ b/src/components/FileInputField/FileInputField.module.scss @@ -0,0 +1,65 @@ +@use "../../styles/tools/form-fields/box-field-elements"; +@use "../../styles/tools/form-fields/box-field-layout"; +@use "../../styles/tools/form-fields/foundation"; +@use "../../styles/tools/form-fields/variants"; +@use "../../styles/tools/accessibility"; + +@layer components.file-input-field { + // Foundation + .root { + @include foundation.root(); + } + + .label { + @include foundation.label(); + } + + .inputContainer { + @include box-field-elements.input-container(); + } + + .helpText, + .validationText { + @include foundation.help-text(); + } + + .isRootRequired .label { + @include foundation.label-required(); + } + + // States + .isRootStateInvalid { + @include variants.validation(invalid); + } + + .isRootStateValid { + @include variants.validation(valid); + } + + .isRootStateWarning { + @include variants.validation(warning); + } + + // Invisible label + .isLabelHidden { + @include accessibility.hide-text(); + } + + // Layouts + .isRootLayoutVertical, + .isRootLayoutHorizontal { + @include box-field-layout.vertical(); + } + + .isRootLayoutHorizontal { + @include box-field-layout.horizontal(); + } + + .isRootFullWidth { + @include box-field-layout.full-width(); + } + + .isRootInFormLayout { + @include box-field-layout.in-form-layout(); + } +} diff --git a/src/components/FileInputField/FileInputField.scss b/src/components/FileInputField/FileInputField.scss deleted file mode 100644 index 58391aae..00000000 --- a/src/components/FileInputField/FileInputField.scss +++ /dev/null @@ -1,63 +0,0 @@ -@use "../../styles/tools/form-fields/box-field-elements"; -@use "../../styles/tools/form-fields/box-field-layout"; -@use "../../styles/tools/form-fields/foundation"; -@use "../../styles/tools/form-fields/variants"; -@use "../../styles/tools/accessibility"; - -// Foundation -.root { - @include foundation.root(); -} - -.label { - @include foundation.label(); -} - -.inputContainer { - @include box-field-elements.input-container(); -} - -.helpText, -.validationText { - @include foundation.help-text(); -} - -.isRootRequired .label { - @include foundation.label-required(); -} - -// States -.isRootStateInvalid { - @include variants.validation(invalid); -} - -.isRootStateValid { - @include variants.validation(valid); -} - -.isRootStateWarning { - @include variants.validation(warning); -} - -// Invisible label -.isLabelHidden { - @include accessibility.hide-text(); -} - -// Layouts -.isRootLayoutVertical, -.isRootLayoutHorizontal { - @include box-field-layout.vertical(); -} - -.isRootLayoutHorizontal { - @include box-field-layout.horizontal(); -} - -.isRootFullWidth { - @include box-field-layout.full-width(); -} - -.isRootInFormLayout { - @include box-field-layout.in-form-layout(); -} diff --git a/src/components/FormLayout/FormLayout.jsx b/src/components/FormLayout/FormLayout.jsx index f5fff9ad..097c2d0a 100644 --- a/src/components/FormLayout/FormLayout.jsx +++ b/src/components/FormLayout/FormLayout.jsx @@ -5,7 +5,7 @@ import { transferProps } from '../_helpers/transferProps'; import { classNames } from '../../utils/classNames'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { FormLayoutContext } from './FormLayoutContext'; -import styles from './FormLayout.scss'; +import styles from './FormLayout.module.scss'; const PREDEFINED_LABEL_WIDTH_VALUES = ['auto', 'default', 'limited']; diff --git a/src/components/FormLayout/FormLayout.scss b/src/components/FormLayout/FormLayout.module.scss similarity index 51% rename from src/components/FormLayout/FormLayout.scss rename to src/components/FormLayout/FormLayout.module.scss index 98277ef3..4e13aa17 100644 --- a/src/components/FormLayout/FormLayout.scss +++ b/src/components/FormLayout/FormLayout.module.scss @@ -18,41 +18,43 @@ @use "../../styles/tools/spacing"; @use "theme"; -.root { - --rui-local-field-width: 1fr; +@layer components.form-layout { + .root { + --rui-local-field-width: 1fr; - @include spacing.bottom(layouts); -} + @include spacing.bottom(layouts); + } -.isRootFieldLayoutVertical, -.isRootFieldLayoutHorizontal { - display: grid; - grid-template-columns: var(--rui-local-field-width); - grid-row-gap: theme.$row-gap; -} + .isRootFieldLayoutVertical, + .isRootFieldLayoutHorizontal { + display: grid; + grid-template-columns: var(--rui-local-field-width); + grid-row-gap: theme.$row-gap; + } -.isRootFieldLayoutHorizontal { - @include breakpoint.up(forms.$horizontal-breakpoint) { - grid-template-columns: var(--rui-local-label-width) var(--rui-local-field-width); // 1. + .isRootFieldLayoutHorizontal { + @include breakpoint.up(forms.$horizontal-breakpoint) { + grid-template-columns: var(--rui-local-label-width) var(--rui-local-field-width); // 1. + } } -} -.hasRootLabelWidthDefault { - --rui-local-label-width: #{theme.$horizontal-label-width}; // 1., 2. -} + .hasRootLabelWidthDefault { + --rui-local-label-width: #{theme.$horizontal-label-width}; // 1., 2. + } -.hasRootLabelWidthAuto { - --rui-local-label-width: #{theme.$horizontal-label-width-auto}; // 4. -} + .hasRootLabelWidthAuto { + --rui-local-label-width: #{theme.$horizontal-label-width-auto}; // 4. + } -.hasRootLabelWidthLimited { - --rui-local-label-width: #{theme.$horizontal-label-width-limited}; // 4. -} + .hasRootLabelWidthLimited { + --rui-local-label-width: #{theme.$horizontal-label-width-limited}; // 4. + } -.hasRootLabelWidthCustom { - --rui-local-label-width: var(--rui-custom-label-width); // 3. -} + .hasRootLabelWidthCustom { + --rui-local-label-width: var(--rui-custom-label-width); // 3. + } -.isRootAutoWidth { - --rui-local-field-width: min-content; + .isRootAutoWidth { + --rui-local-field-width: min-content; + } } diff --git a/src/components/FormLayout/FormLayoutCustomField.jsx b/src/components/FormLayout/FormLayoutCustomField.jsx index 04309262..bd76b37c 100644 --- a/src/components/FormLayout/FormLayoutCustomField.jsx +++ b/src/components/FormLayout/FormLayoutCustomField.jsx @@ -7,7 +7,7 @@ import { getRootSizeClassName } from '../_helpers/getRootSizeClassName'; import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { FormLayoutContext } from './FormLayoutContext'; -import styles from './FormLayoutCustomField.scss'; +import styles from './FormLayoutCustomField.module.scss'; const renderLabel = (id, label, labelForId) => { if (labelForId && label) { diff --git a/src/components/FormLayout/FormLayoutCustomField.module.scss b/src/components/FormLayout/FormLayoutCustomField.module.scss new file mode 100644 index 00000000..e41383e5 --- /dev/null +++ b/src/components/FormLayout/FormLayoutCustomField.module.scss @@ -0,0 +1,65 @@ +@use "../../styles/tools/form-fields/foundation"; +@use "../../styles/tools/form-fields/box-field-layout"; +@use "../../styles/tools/form-fields/box-field-sizes"; +@use "../../styles/tools/form-fields/variants"; + +@layer components.form-layout { + // Foundation + .root { + @include box-field-layout.in-form-layout(); + @include variants.visual(custom); + } + + .label { + @include foundation.label(); + } + + .isRootRequired .label { + @include foundation.label-required(); + } + + // States + .isRootStateInvalid { + @include variants.validation(invalid); + } + + .isRootStateValid { + @include variants.validation(valid); + } + + .isRootStateWarning { + @include variants.validation(warning); + } + + // Layouts + .isRootLayoutVertical, + .isRootLayoutHorizontal { + @include box-field-layout.vertical(); + } + + .isRootLayoutHorizontal { + @include box-field-layout.horizontal(); + } + + .isRootLayoutVertical .field, + .isRootLayoutHorizontal .field { + width: auto; + } + + .isRootFullWidth .field { + justify-self: stretch; + } + + // Sizes + .isRootSizeSmall { + @include box-field-sizes.size(small); + } + + .isRootSizeMedium { + @include box-field-sizes.size(medium); + } + + .isRootSizeLarge { + @include box-field-sizes.size(large); + } +} diff --git a/src/components/FormLayout/FormLayoutCustomField.scss b/src/components/FormLayout/FormLayoutCustomField.scss deleted file mode 100644 index f4bec812..00000000 --- a/src/components/FormLayout/FormLayoutCustomField.scss +++ /dev/null @@ -1,63 +0,0 @@ -@use "../../styles/tools/form-fields/foundation"; -@use "../../styles/tools/form-fields/box-field-layout"; -@use "../../styles/tools/form-fields/box-field-sizes"; -@use "../../styles/tools/form-fields/variants"; - -// Foundation -.root { - @include box-field-layout.in-form-layout(); - @include variants.visual(custom); -} - -.label { - @include foundation.label(); -} - -.isRootRequired .label { - @include foundation.label-required(); -} - -// States -.isRootStateInvalid { - @include variants.validation(invalid); -} - -.isRootStateValid { - @include variants.validation(valid); -} - -.isRootStateWarning { - @include variants.validation(warning); -} - -// Layouts -.isRootLayoutVertical, -.isRootLayoutHorizontal { - @include box-field-layout.vertical(); -} - -.isRootLayoutHorizontal { - @include box-field-layout.horizontal(); -} - -.isRootLayoutVertical .field, -.isRootLayoutHorizontal .field { - width: auto; -} - -.isRootFullWidth .field { - justify-self: stretch; -} - -// Sizes -.isRootSizeSmall { - @include box-field-sizes.size(small); -} - -.isRootSizeMedium { - @include box-field-sizes.size(medium); -} - -.isRootSizeLarge { - @include box-field-sizes.size(large); -} diff --git a/src/components/Grid/Grid.jsx b/src/components/Grid/Grid.jsx index 0e0799ff..d3f8f238 100644 --- a/src/components/Grid/Grid.jsx +++ b/src/components/Grid/Grid.jsx @@ -4,7 +4,7 @@ import { withGlobalProps } from '../../provider'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { transferProps } from '../_helpers/transferProps'; import { generateResponsiveCustomProperties } from './_helpers/generateResponsiveCustomProperties'; -import styles from './Grid.scss'; +import styles from './Grid.module.scss'; const SPACING_VALUES = [0, 1, 2, 3, 4, 5, 6, 7]; diff --git a/src/components/Grid/Grid.module.scss b/src/components/Grid/Grid.module.scss new file mode 100644 index 00000000..76e314ed --- /dev/null +++ b/src/components/Grid/Grid.module.scss @@ -0,0 +1,66 @@ +// 1. Read value of `--rui-local--` that might have been defined by +// JavaScript and assign it to `--rui-local-` used in 2. +// +// Fallback cascade containing fallbacks for all previous breakpoints recursively is included +// using CSS custom property fallback mechanism like this: +// +// Fallback for `xs` breakpoint: `` +// Fallback for `sm` breakpoint: `var(--rui-local--xs, )` +// Fallback for `md` breakpoint: `var(--rui-local--sm, var(--rui-local--xs, ))` +// +// … etc, up to the largest breakpoint. +// +// A media query is then created for each breakpoint (with exception of `xs` which doesn't need a +// media query) and a corresponding responsive custom property variant is assigned to +// `--rui-local-` that is used later in CSS, see 2. +// +// Example for `sm` breakpoint: +// +// `--rui-local-: var(--rui-local--sm, var(--rui-local--xs, ))` +// +// 2. Apply custom property value that is defined within current breakpoint, see 1. + +@use "sass:map"; +@use "../../styles/tools/spacing"; +@use "settings"; +@use "tools"; + +@layer components.grid { + .root { + @include tools.assign-responsive-custom-properties(settings.$grid-responsive-properties); // 1. + @include spacing.bottom(layouts); + + display: grid; + grid-template-columns: var(--rui-local-columns); // 2. + grid-template-rows: var(--rui-local-rows); // 2. + grid-auto-flow: var(--rui-local-auto-flow); // 2. + grid-gap: var(--rui-local-row-gap) var(--rui-local-column-gap); // 2. + align-content: var(--rui-local-align-content); // 2. + align-items: var(--rui-local-align-items); // 2. + justify-content: var(--rui-local-justify-content); // 2. + justify-items: var(--rui-local-justify-items); // 2. + } + + // stylelint-disable-next-line selector-max-universal -- Reset any previously added margins. + .root > * { + margin-block: 0; + } + + .span { + @include tools.assign-responsive-custom-properties(settings.$grid-span-responsive-properties); // 1. + + grid-column: span var(--rui-local-column-span); // 2. + grid-row: span var(--rui-local-row-span); // 2. + } + + // stylelint-disable selector-no-qualifying-type + dl.root, + ol.root, + ul.root { + padding-left: 0; + margin-left: 0; + list-style: none; + } + + // stylelint-enable selector-no-qualifying-type +} diff --git a/src/components/Grid/Grid.scss b/src/components/Grid/Grid.scss deleted file mode 100644 index f954ab0a..00000000 --- a/src/components/Grid/Grid.scss +++ /dev/null @@ -1,63 +0,0 @@ -// 1. Read value of `--rui-local--` that might have been defined by -// JavaScript and assign it to `--rui-local-` used in 2. -// -// Fallback cascade containing fallbacks for all previous breakpoints recursively is included -// using CSS custom property fallback mechanism like this: -// -// Fallback for `xs` breakpoint: `` -// Fallback for `sm` breakpoint: `var(--rui-local--xs, )` -// Fallback for `md` breakpoint: `var(--rui-local--sm, var(--rui-local--xs, ))` -// -// … etc, up to the largest breakpoint. -// -// A media query is then created for each breakpoint (with exception of `xs` which doesn't need a -// media query) and a corresponding responsive custom property variant is assigned to -// `--rui-local-` that is used later in CSS, see 2. -// -// Example for `sm` breakpoint: -// -// `--rui-local-: var(--rui-local--sm, var(--rui-local--xs, ))` -// -// 2. Apply custom property value that is defined within current breakpoint, see 1. - -@use "sass:map"; -@use "../../styles/tools/spacing"; -@use "settings"; -@use "tools"; - -.root { - @include tools.assign-responsive-custom-properties(settings.$grid-responsive-properties); // 1. - @include spacing.bottom(layouts); - - display: grid; - grid-template-columns: var(--rui-local-columns); // 2. - grid-template-rows: var(--rui-local-rows); // 2. - grid-auto-flow: var(--rui-local-auto-flow); // 2. - grid-gap: var(--rui-local-row-gap) var(--rui-local-column-gap); // 2. - align-content: var(--rui-local-align-content); // 2. - align-items: var(--rui-local-align-items); // 2. - justify-content: var(--rui-local-justify-content); // 2. - justify-items: var(--rui-local-justify-items); // 2. -} - -// stylelint-disable-next-line selector-max-universal -- Reset any previously added margins. -.root > * { - margin-block: 0; -} - -.span { - @include tools.assign-responsive-custom-properties(settings.$grid-span-responsive-properties); // 1. - - grid-column: span var(--rui-local-column-span); // 2. - grid-row: span var(--rui-local-row-span); // 2. -} - -// stylelint-disable selector-no-qualifying-type -dl.root, -ol.root, -ul.root { - padding-left: 0; - margin-left: 0; - list-style: none; -} -// stylelint-enable selector-no-qualifying-type diff --git a/src/components/Grid/GridSpan.jsx b/src/components/Grid/GridSpan.jsx index 4c6df1d8..7d778483 100644 --- a/src/components/Grid/GridSpan.jsx +++ b/src/components/Grid/GridSpan.jsx @@ -4,7 +4,7 @@ import { withGlobalProps } from '../../provider'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { transferProps } from '../_helpers/transferProps'; import { generateResponsiveCustomProperties } from './_helpers/generateResponsiveCustomProperties'; -import styles from './Grid.scss'; +import styles from './Grid.module.scss'; export const GridSpan = ({ children, diff --git a/src/components/InputGroup/InputGroup.jsx b/src/components/InputGroup/InputGroup.jsx index 98a8a843..e68eb9bd 100644 --- a/src/components/InputGroup/InputGroup.jsx +++ b/src/components/InputGroup/InputGroup.jsx @@ -13,7 +13,7 @@ import { resolveContextOrProp } from '../_helpers/resolveContextOrProp'; import { transferProps } from '../_helpers/transferProps'; import { FormLayoutContext } from '../FormLayout'; import { InputGroupContext } from './InputGroupContext'; -import styles from './InputGroup.scss'; +import styles from './InputGroup.module.scss'; export const InputGroup = ({ children, diff --git a/src/components/InputGroup/InputGroup.module.scss b/src/components/InputGroup/InputGroup.module.scss new file mode 100644 index 00000000..0c6d80e1 --- /dev/null +++ b/src/components/InputGroup/InputGroup.module.scss @@ -0,0 +1,93 @@ +// 1. The class name is intentionally singular because it's targeted by other mixins too. +// 2. Use a block-level display mode to prevent extra white space below grouped inputs in Safari. +// 3. Prevent individual inputs from overlapping inside narrow containers. +// 4. Legends are tricky to style, let's use a `div` instead. +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset#styling_with_css + +@use "../../styles/tools/form-fields/box-field-elements"; +@use "../../styles/tools/form-fields/box-field-layout"; +@use "../../styles/tools/form-fields/box-field-sizes"; +@use "../../styles/tools/form-fields/foundation"; +@use "../../styles/tools/form-fields/variants"; +@use "../../styles/tools/accessibility"; +@use "../../styles/tools/reset"; +@use "theme"; + +@layer components.input-group { + .root { + @include foundation.root(); + @include foundation.fieldset(); + } + + // 4. + .legend { + @include accessibility.hide-text(); + } + + // 4. + .label { + @include foundation.label(); + } + + .inputGroup { + --rui-local-inner-border-radius: #{theme.$inner-border-radius}; + + display: flex; // 2. + gap: theme.$gap; + } + + // 1. + .validationText { + @include reset.list(); + @include foundation.help-text(); + } + + .isRootRequired .label { + @include foundation.label-required(); + } + + // States + .isRootStateInvalid { + @include variants.validation(invalid); + } + + .isRootStateValid { + @include variants.validation(valid); + } + + .isRootStateWarning { + @include variants.validation(warning); + } + + // Layouts + .isRootLayoutVertical, + .isRootLayoutHorizontal { + @include box-field-layout.vertical(); + } + + .isRootLayoutVertical .field, + .isRootLayoutHorizontal .field { + max-width: none; // 3. + } + + .isRootLayoutHorizontal { + @include box-field-layout.horizontal(); + } + + .isRootInFormLayout { + @include box-field-layout.in-form-layout($is-fieldset: true); + } + + // Sizes + .isRootSizeSmall { + @include box-field-sizes.size(small, $has-input: false); + } + + .isRootSizeMedium { + @include box-field-sizes.size(medium, $has-input: false); + } + + .isRootSizeLarge { + @include box-field-sizes.size(large, $has-input: false); + } +} diff --git a/src/components/InputGroup/InputGroup.scss b/src/components/InputGroup/InputGroup.scss deleted file mode 100644 index a0ff0107..00000000 --- a/src/components/InputGroup/InputGroup.scss +++ /dev/null @@ -1,91 +0,0 @@ -// 1. The class name is intentionally singular because it's targeted by other mixins too. -// 2. Use a block-level display mode to prevent extra white space below grouped inputs in Safari. -// 3. Prevent individual inputs from overlapping inside narrow containers. -// 4. Legends are tricky to style, let's use a `div` instead. -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset#styling_with_css - -@use "../../styles/tools/form-fields/box-field-elements"; -@use "../../styles/tools/form-fields/box-field-layout"; -@use "../../styles/tools/form-fields/box-field-sizes"; -@use "../../styles/tools/form-fields/foundation"; -@use "../../styles/tools/form-fields/variants"; -@use "../../styles/tools/accessibility"; -@use "../../styles/tools/reset"; -@use "theme"; - -.root { - @include foundation.root(); - @include foundation.fieldset(); -} - -// 4. -.legend { - @include accessibility.hide-text(); -} - -// 4. -.label { - @include foundation.label(); -} - -.inputGroup { - --rui-local-inner-border-radius: #{theme.$inner-border-radius}; - - display: flex; // 2. - gap: theme.$gap; -} - -// 1. -.validationText { - @include reset.list(); - @include foundation.help-text(); -} - -.isRootRequired .label { - @include foundation.label-required(); -} - -// States -.isRootStateInvalid { - @include variants.validation(invalid); -} - -.isRootStateValid { - @include variants.validation(valid); -} - -.isRootStateWarning { - @include variants.validation(warning); -} - -// Layouts -.isRootLayoutVertical, -.isRootLayoutHorizontal { - @include box-field-layout.vertical(); -} - -.isRootLayoutVertical .field, -.isRootLayoutHorizontal .field { - max-width: none; // 3. -} - -.isRootLayoutHorizontal { - @include box-field-layout.horizontal(); -} - -.isRootInFormLayout { - @include box-field-layout.in-form-layout($is-fieldset: true); -} - -// Sizes -.isRootSizeSmall { - @include box-field-sizes.size(small, $has-input: false); -} - -.isRootSizeMedium { - @include box-field-sizes.size(medium, $has-input: false); -} - -.isRootSizeLarge { - @include box-field-sizes.size(large, $has-input: false); -} diff --git a/src/components/Modal/Modal.jsx b/src/components/Modal/Modal.jsx index dfcd993f..b152754b 100644 --- a/src/components/Modal/Modal.jsx +++ b/src/components/Modal/Modal.jsx @@ -8,7 +8,7 @@ import { getPositionClassName } from './_helpers/getPositionClassName'; import { getSizeClassName } from './_helpers/getSizeClassName'; import { useModalFocus } from './_hooks/useModalFocus'; import { useModalScrollPrevention } from './_hooks/useModalScrollPrevention'; -import styles from './Modal.scss'; +import styles from './Modal.module.scss'; const preRender = ( children, diff --git a/src/components/Modal/Modal.module.scss b/src/components/Modal/Modal.module.scss new file mode 100644 index 00000000..95db9249 --- /dev/null +++ b/src/components/Modal/Modal.module.scss @@ -0,0 +1,80 @@ +@use "sass:map"; +@use "../../styles/theme/typography"; +@use "../../styles/tools/accessibility"; +@use "../../styles/tools/breakpoint"; +@use "../../styles/tools/reset"; +@use "../../styles/tools/spacing"; +@use "settings"; +@use "theme"; + +@layer components.modal { + .root { + --rui-local-outer-spacing: #{theme.$outer-spacing-xs}; + --rui-local-max-width: calc(100% - (2 * var(--rui-local-outer-spacing))); + --rui-local-max-height: calc(100% - (2 * var(--rui-local-outer-spacing))); + + position: fixed; + left: 50%; + z-index: settings.$z-index; + display: flex; + flex-direction: column; + max-width: var(--rui-local-max-width); + max-height: var(--rui-local-max-height); + overflow-y: auto; + overscroll-behavior: contain; + border-radius: settings.$border-radius; + background: theme.$background; + box-shadow: theme.$box-shadow; + transform: translateX(-50%); + + @include breakpoint.up(sm) { + --rui-local-outer-spacing: #{theme.$outer-spacing-sm}; + } + } + + .backdrop { + position: fixed; + top: 0; + left: 0; + z-index: settings.$backdrop-z-index; + width: 100vw; + height: 100vh; + background: theme.$backdrop-background; + } + + .isRootSizeSmall { + width: map.get(theme.$sizes, small, width); + } + + .isRootSizeMedium { + width: map.get(theme.$sizes, medium, width); + } + + .isRootSizeLarge { + width: map.get(theme.$sizes, large, width); + } + + .isRootSizeFullscreen { + width: map.get(theme.$sizes, fullscreen, width); + height: map.get(theme.$sizes, fullscreen, height); + } + + .isRootSizeFullscreen .content { + height: 100%; + } + + .isRootSizeAuto { + width: auto; + min-width: min(var(--rui-local-max-width), #{map.get(theme.$sizes, auto, min-width)}); + max-width: min(var(--rui-local-max-width), #{map.get(theme.$sizes, auto, max-width)}); + } + + .isRootPositionCenter { + top: 50%; + transform: translate(-50%, -50%); + } + + .isRootPositionTop { + top: var(--rui-local-outer-spacing); + } +} diff --git a/src/components/Modal/Modal.scss b/src/components/Modal/Modal.scss deleted file mode 100644 index 1a1f3237..00000000 --- a/src/components/Modal/Modal.scss +++ /dev/null @@ -1,78 +0,0 @@ -@use "sass:map"; -@use "../../styles/theme/typography"; -@use "../../styles/tools/accessibility"; -@use "../../styles/tools/breakpoint"; -@use "../../styles/tools/reset"; -@use "../../styles/tools/spacing"; -@use "settings"; -@use "theme"; - -.root { - --rui-local-outer-spacing: #{theme.$outer-spacing-xs}; - --rui-local-max-width: calc(100% - (2 * var(--rui-local-outer-spacing))); - --rui-local-max-height: calc(100% - (2 * var(--rui-local-outer-spacing))); - - position: fixed; - left: 50%; - z-index: settings.$z-index; - display: flex; - flex-direction: column; - max-width: var(--rui-local-max-width); - max-height: var(--rui-local-max-height); - overflow-y: auto; - overscroll-behavior: contain; - border-radius: settings.$border-radius; - background: theme.$background; - box-shadow: theme.$box-shadow; - transform: translateX(-50%); - - @include breakpoint.up(sm) { - --rui-local-outer-spacing: #{theme.$outer-spacing-sm}; - } -} - -.backdrop { - position: fixed; - top: 0; - left: 0; - z-index: settings.$backdrop-z-index; - width: 100vw; - height: 100vh; - background: theme.$backdrop-background; -} - -.isRootSizeSmall { - width: map.get(theme.$sizes, small, width); -} - -.isRootSizeMedium { - width: map.get(theme.$sizes, medium, width); -} - -.isRootSizeLarge { - width: map.get(theme.$sizes, large, width); -} - -.isRootSizeFullscreen { - width: map.get(theme.$sizes, fullscreen, width); - height: map.get(theme.$sizes, fullscreen, height); -} - -.isRootSizeFullscreen .content { - height: 100%; -} - -.isRootSizeAuto { - width: auto; - min-width: min(var(--rui-local-max-width), #{map.get(theme.$sizes, auto, min-width)}); - max-width: min(var(--rui-local-max-width), #{map.get(theme.$sizes, auto, max-width)}); -} - -.isRootPositionCenter { - top: 50%; - transform: translate(-50%, -50%); -} - -.isRootPositionTop { - top: var(--rui-local-outer-spacing); -} diff --git a/src/components/Modal/ModalBody.jsx b/src/components/Modal/ModalBody.jsx index 8d4bf2dc..98063a03 100644 --- a/src/components/Modal/ModalBody.jsx +++ b/src/components/Modal/ModalBody.jsx @@ -5,7 +5,7 @@ import { transferProps } from '../_helpers/transferProps'; import { classNames } from '../../utils/classNames'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { getScrollingClassName } from './_helpers/getScrollingClassName'; -import styles from './ModalBody.scss'; +import styles from './ModalBody.module.scss'; export const ModalBody = ({ children, diff --git a/src/components/Modal/ModalBody.module.scss b/src/components/Modal/ModalBody.module.scss new file mode 100644 index 00000000..06f2340c --- /dev/null +++ b/src/components/Modal/ModalBody.module.scss @@ -0,0 +1,20 @@ +@layer components.modal { + .root { + flex: 1 1 auto; + } + + .isRootScrollingAuto, + .isRootScrollingCustom { + min-height: 0; + } + + .isRootScrollingAuto { + overflow-y: auto; + overscroll-behavior: contain; + } + + .isRootScrollingCustom { + display: flex; + flex-direction: column; + } +} diff --git a/src/components/Modal/ModalBody.scss b/src/components/Modal/ModalBody.scss deleted file mode 100644 index 6ac5e6e7..00000000 --- a/src/components/Modal/ModalBody.scss +++ /dev/null @@ -1,18 +0,0 @@ -.root { - flex: 1 1 auto; -} - -.isRootScrollingAuto, -.isRootScrollingCustom { - min-height: 0; -} - -.isRootScrollingAuto { - overflow-y: auto; - overscroll-behavior: contain; -} - -.isRootScrollingCustom { - display: flex; - flex-direction: column; -} diff --git a/src/components/Modal/ModalCloseButton.jsx b/src/components/Modal/ModalCloseButton.jsx index b6abde14..919d0fc5 100644 --- a/src/components/Modal/ModalCloseButton.jsx +++ b/src/components/Modal/ModalCloseButton.jsx @@ -5,7 +5,7 @@ import { withGlobalProps, } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; -import styles from './ModalCloseButton.scss'; +import styles from './ModalCloseButton.module.scss'; export const ModalCloseButton = React.forwardRef((props, ref) => { const { diff --git a/src/components/Modal/ModalCloseButton.module.scss b/src/components/Modal/ModalCloseButton.module.scss new file mode 100644 index 00000000..13b15cc9 --- /dev/null +++ b/src/components/Modal/ModalCloseButton.module.scss @@ -0,0 +1,20 @@ +@use "sass:map"; +@use "../../styles/theme/typography"; +@use "../../styles/tools/accessibility"; +@use "../../styles/tools/reset"; +@use "../../styles/tools/spacing"; + +@layer components.modal { + .root { + @include reset.button(); + @include accessibility.min-tap-target(); + + font-size: map.get(typography.$font-size-values, 4); + line-height: 1; + color: inherit; + + &:disabled { + cursor: var(--rui-cursor-not-allowed); + } + } +} diff --git a/src/components/Modal/ModalCloseButton.scss b/src/components/Modal/ModalCloseButton.scss deleted file mode 100644 index f4733cf6..00000000 --- a/src/components/Modal/ModalCloseButton.scss +++ /dev/null @@ -1,18 +0,0 @@ -@use "sass:map"; -@use "../../styles/theme/typography"; -@use "../../styles/tools/accessibility"; -@use "../../styles/tools/reset"; -@use "../../styles/tools/spacing"; - -.root { - @include reset.button(); - @include accessibility.min-tap-target(); - - font-size: map.get(typography.$font-size-values, 4); - line-height: 1; - color: inherit; - - &:disabled { - cursor: var(--rui-cursor-not-allowed); - } -} diff --git a/src/components/Modal/ModalContent.jsx b/src/components/Modal/ModalContent.jsx index c5656a29..0bb26405 100644 --- a/src/components/Modal/ModalContent.jsx +++ b/src/components/Modal/ModalContent.jsx @@ -3,7 +3,7 @@ import React from 'react'; import { withGlobalProps } from '../../provider'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { transferProps } from '../_helpers/transferProps'; -import styles from './ModalContent.scss'; +import styles from './ModalContent.module.scss'; export const ModalContent = ({ children, diff --git a/src/components/Modal/ModalContent.module.scss b/src/components/Modal/ModalContent.module.scss new file mode 100644 index 00000000..049f01b0 --- /dev/null +++ b/src/components/Modal/ModalContent.module.scss @@ -0,0 +1,7 @@ +@use "theme"; + +@layer components.modal { + .root { + padding: theme.$padding-y theme.$padding-x; + } +} diff --git a/src/components/Modal/ModalContent.scss b/src/components/Modal/ModalContent.scss deleted file mode 100644 index 144760c5..00000000 --- a/src/components/Modal/ModalContent.scss +++ /dev/null @@ -1,5 +0,0 @@ -@use "theme"; - -.root { - padding: theme.$padding-y theme.$padding-x; -} diff --git a/src/components/Modal/ModalFooter.jsx b/src/components/Modal/ModalFooter.jsx index 49e31149..525bd6cb 100644 --- a/src/components/Modal/ModalFooter.jsx +++ b/src/components/Modal/ModalFooter.jsx @@ -4,7 +4,7 @@ import { withGlobalProps } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; import { classNames } from '../../utils/classNames'; import { getJustifyClassName } from './_helpers/getJustifyClassName'; -import styles from './ModalFooter.scss'; +import styles from './ModalFooter.module.scss'; export const ModalFooter = ({ children, diff --git a/src/components/Modal/ModalFooter.module.scss b/src/components/Modal/ModalFooter.module.scss new file mode 100644 index 00000000..922d2c19 --- /dev/null +++ b/src/components/Modal/ModalFooter.module.scss @@ -0,0 +1,37 @@ +@use "settings"; +@use "theme"; + +@layer components.modal { + .root { + display: flex; + flex: none; + flex-wrap: wrap; + gap: theme.$footer-gap; + align-items: center; + padding: theme.$padding-y theme.$padding-x; + border-top: theme.$separator-width solid theme.$separator-color; + border-bottom-right-radius: settings.$border-radius; + border-bottom-left-radius: settings.$border-radius; + background: theme.$footer-background; + } + + .isRootJustifiedToStart { + justify-content: flex-start; + } + + .isRootJustifiedToCenter { + justify-content: center; + } + + .isRootJustifiedToEnd { + justify-content: flex-end; + } + + .isRootJustifiedToSpaceBetween { + justify-content: space-between; + } + + .isRootJustifiedToStretch { + display: block; + } +} diff --git a/src/components/Modal/ModalFooter.scss b/src/components/Modal/ModalFooter.scss deleted file mode 100644 index aa00fd0a..00000000 --- a/src/components/Modal/ModalFooter.scss +++ /dev/null @@ -1,35 +0,0 @@ -@use "settings"; -@use "theme"; - -.root { - display: flex; - flex: none; - flex-wrap: wrap; - gap: theme.$footer-gap; - align-items: center; - padding: theme.$padding-y theme.$padding-x; - border-top: theme.$separator-width solid theme.$separator-color; - border-bottom-right-radius: settings.$border-radius; - border-bottom-left-radius: settings.$border-radius; - background: theme.$footer-background; -} - -.isRootJustifiedToStart { - justify-content: flex-start; -} - -.isRootJustifiedToCenter { - justify-content: center; -} - -.isRootJustifiedToEnd { - justify-content: flex-end; -} - -.isRootJustifiedToSpaceBetween { - justify-content: space-between; -} - -.isRootJustifiedToStretch { - display: block; -} diff --git a/src/components/Modal/ModalHeader.jsx b/src/components/Modal/ModalHeader.jsx index dbc1b35d..589cc897 100644 --- a/src/components/Modal/ModalHeader.jsx +++ b/src/components/Modal/ModalHeader.jsx @@ -6,7 +6,7 @@ import { import { transferProps } from '../_helpers/transferProps'; import { classNames } from '../../utils/classNames'; import { getJustifyClassName } from './_helpers/getJustifyClassName'; -import styles from './ModalHeader.scss'; +import styles from './ModalHeader.module.scss'; export const ModalHeader = ({ children, diff --git a/src/components/Modal/ModalHeader.module.scss b/src/components/Modal/ModalHeader.module.scss new file mode 100644 index 00000000..116d55d5 --- /dev/null +++ b/src/components/Modal/ModalHeader.module.scss @@ -0,0 +1,32 @@ +@use "theme"; + +@layer components.modal { + .root { + display: flex; + flex: none; + gap: theme.$header-gap; + align-items: baseline; + padding: theme.$padding-y theme.$padding-x; + border-bottom: theme.$separator-width solid theme.$separator-color; + } + + .isRootJustifiedToStart { + justify-content: flex-start; + } + + .isRootJustifiedToCenter { + justify-content: center; + } + + .isRootJustifiedToEnd { + justify-content: flex-end; + } + + .isRootJustifiedToSpaceBetween { + justify-content: space-between; + } + + .isRootJustifiedToStretch { + display: block; + } +} diff --git a/src/components/Modal/ModalHeader.scss b/src/components/Modal/ModalHeader.scss deleted file mode 100644 index e6170848..00000000 --- a/src/components/Modal/ModalHeader.scss +++ /dev/null @@ -1,30 +0,0 @@ -@use "theme"; - -.root { - display: flex; - flex: none; - gap: theme.$header-gap; - align-items: baseline; - padding: theme.$padding-y theme.$padding-x; - border-bottom: theme.$separator-width solid theme.$separator-color; -} - -.isRootJustifiedToStart { - justify-content: flex-start; -} - -.isRootJustifiedToCenter { - justify-content: center; -} - -.isRootJustifiedToEnd { - justify-content: flex-end; -} - -.isRootJustifiedToSpaceBetween { - justify-content: space-between; -} - -.isRootJustifiedToStretch { - display: block; -} diff --git a/src/components/Modal/ModalTitle.jsx b/src/components/Modal/ModalTitle.jsx index 17efda65..f11dd825 100644 --- a/src/components/Modal/ModalTitle.jsx +++ b/src/components/Modal/ModalTitle.jsx @@ -4,7 +4,7 @@ import { withGlobalProps, } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; -import styles from './ModalTitle.scss'; +import styles from './ModalTitle.module.scss'; export const ModalTitle = ({ children, diff --git a/src/components/Modal/ModalTitle.module.scss b/src/components/Modal/ModalTitle.module.scss new file mode 100644 index 00000000..face49d1 --- /dev/null +++ b/src/components/Modal/ModalTitle.module.scss @@ -0,0 +1,12 @@ +@use "settings"; + +@layer components.modal { + .root { + margin-block: 0; + font-size: settings.$title-font-size; + + &:not(:last-child) { + margin-bottom: 0; + } + } +} diff --git a/src/components/Modal/ModalTitle.scss b/src/components/Modal/ModalTitle.scss deleted file mode 100644 index 1893c27c..00000000 --- a/src/components/Modal/ModalTitle.scss +++ /dev/null @@ -1,10 +0,0 @@ -@use "settings"; - -.root { - margin-block: 0; - font-size: settings.$title-font-size; - - &:not(:last-child) { - margin-bottom: 0; - } -} diff --git a/src/components/Paper/Paper.jsx b/src/components/Paper/Paper.jsx index e8b037a4..6f9621ca 100644 --- a/src/components/Paper/Paper.jsx +++ b/src/components/Paper/Paper.jsx @@ -3,7 +3,7 @@ import React from 'react'; import { withGlobalProps } from '../../provider'; import { classNames } from '../../utils/classNames'; import { transferProps } from '../_helpers/transferProps'; -import styles from './Paper.scss'; +import styles from './Paper.module.scss'; export const Paper = ({ children, diff --git a/src/components/Paper/Paper.module.scss b/src/components/Paper/Paper.module.scss new file mode 100644 index 00000000..550eda82 --- /dev/null +++ b/src/components/Paper/Paper.module.scss @@ -0,0 +1,19 @@ +@use "theme"; + +@layer components.paper { + .root { + padding: theme.$padding; + border: theme.$border-width solid theme.$border-color; + border-radius: theme.$border-radius; + background-color: theme.$background-color; + } + + .isRootMuted { + background-color: theme.$muted-background-color; + opacity: theme.$muted-opacity; + } + + .isRootRaised { + box-shadow: theme.$raised-box-shadow; + } +} diff --git a/src/components/Paper/Paper.scss b/src/components/Paper/Paper.scss deleted file mode 100644 index 736c48cf..00000000 --- a/src/components/Paper/Paper.scss +++ /dev/null @@ -1,17 +0,0 @@ -@use "theme"; - -.root { - padding: theme.$padding; - border: theme.$border-width solid theme.$border-color; - border-radius: theme.$border-radius; - background-color: theme.$background-color; -} - -.isRootMuted { - background-color: theme.$muted-background-color; - opacity: theme.$muted-opacity; -} - -.isRootRaised { - box-shadow: theme.$raised-box-shadow; -} diff --git a/src/components/Popover/Popover.jsx b/src/components/Popover/Popover.jsx index c30e9bb8..484970ca 100644 --- a/src/components/Popover/Popover.jsx +++ b/src/components/Popover/Popover.jsx @@ -6,7 +6,7 @@ import { classNames } from '../../utils/classNames'; import { transferProps } from '../_helpers/transferProps'; import getRootSideClassName from './_helpers/getRootSideClassName'; import getRootAlignmentClassName from './_helpers/getRootAlignmentClassName'; -import styles from './Popover.scss'; +import styles from './Popover.module.scss'; export const Popover = React.forwardRef((props, ref) => { const { diff --git a/src/components/Popover/Popover.module.scss b/src/components/Popover/Popover.module.scss new file mode 100644 index 00000000..b4a746bb --- /dev/null +++ b/src/components/Popover/Popover.module.scss @@ -0,0 +1,238 @@ +// 1. Reset positioning for controlled variant. +// 2. Shift Popover so there is space for the arrow between Popover and reference element. +// 3. Add top offset in case it's not defined by external library. + +@use "theme"; + +@layer components.popover { + .root { + position: absolute; + width: max-content; + max-width: theme.$max-width; + padding: theme.$padding; + text-align: left; + white-space: normal; + word-break: normal; + word-wrap: break-word; + color: theme.$color; + border: theme.$border-width solid theme.$border-color; + border-radius: theme.$border-radius; + background-color: theme.$background-color; + box-shadow: theme.$box-shadow; + } + + .arrow { + position: absolute; + width: theme.$arrow-width; + height: theme.$arrow-height; + transform-origin: center bottom; + + &::before, + &::after { + content: ""; + position: absolute; + display: block; + border-style: solid; + border-color: transparent; + } + + &::before { + bottom: 0; + border-width: theme.$arrow-height theme.$arrow-height 0; + border-top-color: theme.$border-color; + } + + &::after { + bottom: theme.$border-width; + border-width: theme.$arrow-height theme.$arrow-height 0; + border-top-color: theme.$background-color; + } + } + + // Sides + .isRootAtTop { + bottom: 100%; + } + + .isRootAtBottom { + top: 100%; + } + + .isRootAtLeft { + right: 100%; + } + + .isRootAtRight { + left: 100%; + } + + // Arrows + .isRootAtTop > .arrow { + top: 100%; + } + + .isRootAtBottom > .arrow { + bottom: 100%; + } + + .isRootAtLeft > .arrow { + left: 100%; + } + + .isRootAtRight > .arrow { + right: 100%; + } + + // Side alignments: top + .isRootAtTop.isRootAtCenter { + left: 50%; + transform: translate(-50%, #{-1 * theme.$arrow-height}); + } + + .isRootAtTop.isRootAtStart { + left: 0; + transform: translate(0, #{-1 * theme.$arrow-height}); + } + + .isRootAtTop.isRootAtEnd { + right: 0; + transform: translate(0, #{-1 * theme.$arrow-height}); + } + + .isRootAtTop.isRootAtCenter > .arrow { + left: 50%; + transform: translate(-50%, 0) rotateZ(0); + } + + .isRootAtTop.isRootAtStart > .arrow { + left: theme.$arrow-corner-offset; + transform: translate(0, 0) rotateZ(0); + } + + .isRootAtTop.isRootAtEnd > .arrow { + right: theme.$arrow-corner-offset; + transform: translate(0, 0) rotateZ(0); + } + + // Side alignments: bottom + .isRootAtBottom.isRootAtCenter { + left: 50%; + transform: translate(-50%, #{theme.$arrow-height}); + } + + .isRootAtBottom.isRootAtStart { + left: 0; + transform: translate(0, #{theme.$arrow-height}); + } + + .isRootAtBottom.isRootAtEnd { + right: 0; + transform: translate(0, #{theme.$arrow-height}); + } + + .isRootAtBottom.isRootAtCenter > .arrow { + left: 50%; + transform: translate(-50%, -100%) rotateZ(180deg); + } + + .isRootAtBottom.isRootAtStart > .arrow { + left: theme.$arrow-corner-offset; + transform: translate(0, -100%) rotateZ(180deg); + } + + .isRootAtBottom.isRootAtEnd > .arrow { + right: theme.$arrow-corner-offset; + transform: translate(0, -100%) rotateZ(180deg); + } + + // Side alignments: left + .isRootAtLeft.isRootAtCenter { + top: 50%; + transform: translate(#{-1 * theme.$arrow-height}, -50%); + } + + .isRootAtLeft.isRootAtStart { + top: 0; + transform: translate(#{-1 * theme.$arrow-height}, 0); + } + + .isRootAtLeft.isRootAtEnd { + bottom: 0; + transform: translate(#{-1 * theme.$arrow-height}, 0); + } + + .isRootAtLeft.isRootAtCenter > .arrow { + top: 50%; + transform: translate(0, -100%) rotateZ(-90deg); + } + + .isRootAtLeft.isRootAtStart > .arrow { + top: theme.$arrow-corner-offset; + transform: translate(0, 0) rotateZ(-90deg); + } + + .isRootAtLeft.isRootAtEnd > .arrow { + bottom: theme.$arrow-corner-offset; + transform: translate(0, -100%) rotateZ(-90deg); + } + + // Side alignments: right + .isRootAtRight.isRootAtCenter { + top: 50%; + transform: translate(#{theme.$arrow-height}, -50%); + } + + .isRootAtRight.isRootAtStart { + top: 0; + transform: translate(#{theme.$arrow-height}, 0); + } + + .isRootAtRight.isRootAtEnd { + bottom: 0; + transform: translate(#{theme.$arrow-height}, 0); + } + + .isRootAtRight.isRootAtCenter > .arrow { + top: 50%; + transform: translate(0, -100%) rotateZ(90deg); + } + + .isRootAtRight.isRootAtStart > .arrow { + top: theme.$arrow-corner-offset; + transform: translate(0, 0) rotateZ(90deg); + } + + .isRootAtRight.isRootAtEnd > .arrow { + bottom: theme.$arrow-corner-offset; + transform: translate(0, -100%) rotateZ(90deg); + } + + // Controlled placement + .isRootControlled.isRootAtTop, + .isRootControlled.isRootAtBottom, + .isRootControlled.isRootAtLeft, + .isRootControlled.isRootAtRight { + inset: unset; // 1. + } + + .isRootControlled.isRootAtTop { + transform: translate(0, #{-1 * theme.$arrow-height}); // 2. + } + + .isRootControlled.isRootAtBottom { + transform: translate(0, #{theme.$arrow-height}); // 2. + } + + .isRootControlled.isRootAtLeft { + transform: translate(#{-1 * theme.$arrow-height}, 0); // 2. + } + + .isRootControlled.isRootAtRight { + transform: translate(#{theme.$arrow-height}, 0); // 2. + } + + .isRootControlled.isRootAtLeft.isRootAtStart, + .isRootControlled.isRootAtRight.isRootAtStart { + top: 0; // 3. + } +} diff --git a/src/components/Popover/Popover.scss b/src/components/Popover/Popover.scss deleted file mode 100644 index f6b5a7f9..00000000 --- a/src/components/Popover/Popover.scss +++ /dev/null @@ -1,236 +0,0 @@ -// 1. Reset positioning for controlled variant. -// 2. Shift Popover so there is space for the arrow between Popover and reference element. -// 3. Add top offset in case it's not defined by external library. - -@use "theme"; - -.root { - position: absolute; - width: max-content; - max-width: theme.$max-width; - padding: theme.$padding; - text-align: left; - white-space: normal; - word-break: normal; - word-wrap: break-word; - color: theme.$color; - border: theme.$border-width solid theme.$border-color; - border-radius: theme.$border-radius; - background-color: theme.$background-color; - box-shadow: theme.$box-shadow; -} - -.arrow { - position: absolute; - width: theme.$arrow-width; - height: theme.$arrow-height; - transform-origin: center bottom; - - &::before, - &::after { - content: ""; - position: absolute; - display: block; - border-style: solid; - border-color: transparent; - } - - &::before { - bottom: 0; - border-width: theme.$arrow-height theme.$arrow-height 0; - border-top-color: theme.$border-color; - } - - &::after { - bottom: theme.$border-width; - border-width: theme.$arrow-height theme.$arrow-height 0; - border-top-color: theme.$background-color; - } -} - -// Sides -.isRootAtTop { - bottom: 100%; -} - -.isRootAtBottom { - top: 100%; -} - -.isRootAtLeft { - right: 100%; -} - -.isRootAtRight { - left: 100%; -} - -// Arrows -.isRootAtTop > .arrow { - top: 100%; -} - -.isRootAtBottom > .arrow { - bottom: 100%; -} - -.isRootAtLeft > .arrow { - left: 100%; -} - -.isRootAtRight > .arrow { - right: 100%; -} - -// Side alignments: top -.isRootAtTop.isRootAtCenter { - left: 50%; - transform: translate(-50%, #{-1 * theme.$arrow-height}); -} - -.isRootAtTop.isRootAtStart { - left: 0; - transform: translate(0, #{-1 * theme.$arrow-height}); -} - -.isRootAtTop.isRootAtEnd { - right: 0; - transform: translate(0, #{-1 * theme.$arrow-height}); -} - -.isRootAtTop.isRootAtCenter > .arrow { - left: 50%; - transform: translate(-50%, 0) rotateZ(0); -} - -.isRootAtTop.isRootAtStart > .arrow { - left: theme.$arrow-corner-offset; - transform: translate(0, 0) rotateZ(0); -} - -.isRootAtTop.isRootAtEnd > .arrow { - right: theme.$arrow-corner-offset; - transform: translate(0, 0) rotateZ(0); -} - -// Side alignments: bottom -.isRootAtBottom.isRootAtCenter { - left: 50%; - transform: translate(-50%, #{theme.$arrow-height}); -} - -.isRootAtBottom.isRootAtStart { - left: 0; - transform: translate(0, #{theme.$arrow-height}); -} - -.isRootAtBottom.isRootAtEnd { - right: 0; - transform: translate(0, #{theme.$arrow-height}); -} - -.isRootAtBottom.isRootAtCenter > .arrow { - left: 50%; - transform: translate(-50%, -100%) rotateZ(180deg); -} - -.isRootAtBottom.isRootAtStart > .arrow { - left: theme.$arrow-corner-offset; - transform: translate(0, -100%) rotateZ(180deg); -} - -.isRootAtBottom.isRootAtEnd > .arrow { - right: theme.$arrow-corner-offset; - transform: translate(0, -100%) rotateZ(180deg); -} - -// Side alignments: left -.isRootAtLeft.isRootAtCenter { - top: 50%; - transform: translate(#{-1 * theme.$arrow-height}, -50%); -} - -.isRootAtLeft.isRootAtStart { - top: 0; - transform: translate(#{-1 * theme.$arrow-height}, 0); -} - -.isRootAtLeft.isRootAtEnd { - bottom: 0; - transform: translate(#{-1 * theme.$arrow-height}, 0); -} - -.isRootAtLeft.isRootAtCenter > .arrow { - top: 50%; - transform: translate(0, -100%) rotateZ(-90deg); -} - -.isRootAtLeft.isRootAtStart > .arrow { - top: theme.$arrow-corner-offset; - transform: translate(0, 0) rotateZ(-90deg); -} - -.isRootAtLeft.isRootAtEnd > .arrow { - bottom: theme.$arrow-corner-offset; - transform: translate(0, -100%) rotateZ(-90deg); -} - -// Side alignments: right -.isRootAtRight.isRootAtCenter { - top: 50%; - transform: translate(#{theme.$arrow-height}, -50%); -} - -.isRootAtRight.isRootAtStart { - top: 0; - transform: translate(#{theme.$arrow-height}, 0); -} - -.isRootAtRight.isRootAtEnd { - bottom: 0; - transform: translate(#{theme.$arrow-height}, 0); -} - -.isRootAtRight.isRootAtCenter > .arrow { - top: 50%; - transform: translate(0, -100%) rotateZ(90deg); -} - -.isRootAtRight.isRootAtStart > .arrow { - top: theme.$arrow-corner-offset; - transform: translate(0, 0) rotateZ(90deg); -} - -.isRootAtRight.isRootAtEnd > .arrow { - bottom: theme.$arrow-corner-offset; - transform: translate(0, -100%) rotateZ(90deg); -} - -// Controlled placement -.isRootControlled.isRootAtTop, -.isRootControlled.isRootAtBottom, -.isRootControlled.isRootAtLeft, -.isRootControlled.isRootAtRight { - inset: unset; // 1. -} - -.isRootControlled.isRootAtTop { - transform: translate(0, #{-1 * theme.$arrow-height}); // 2. -} - -.isRootControlled.isRootAtBottom { - transform: translate(0, #{theme.$arrow-height}); // 2. -} - -.isRootControlled.isRootAtLeft { - transform: translate(#{-1 * theme.$arrow-height}, 0); // 2. -} - -.isRootControlled.isRootAtRight { - transform: translate(#{theme.$arrow-height}, 0); // 2. -} - -.isRootControlled.isRootAtLeft.isRootAtStart, -.isRootControlled.isRootAtRight.isRootAtStart { - top: 0; // 3. -} diff --git a/src/components/Popover/PopoverWrapper.jsx b/src/components/Popover/PopoverWrapper.jsx index 9f248c71..63976492 100644 --- a/src/components/Popover/PopoverWrapper.jsx +++ b/src/components/Popover/PopoverWrapper.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { withGlobalProps } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; -import styles from './PopoverWrapper.scss'; +import styles from './PopoverWrapper.module.scss'; export const PopoverWrapper = ({ children, @@ -36,4 +36,3 @@ PopoverWrapper.propTypes = { export const PopoverWrapperWithContext = withGlobalProps(PopoverWrapper, 'PopoverWrapper'); export default PopoverWrapperWithContext; - diff --git a/src/components/Popover/PopoverWrapper.module.scss b/src/components/Popover/PopoverWrapper.module.scss new file mode 100644 index 00000000..6df2ee52 --- /dev/null +++ b/src/components/Popover/PopoverWrapper.module.scss @@ -0,0 +1,5 @@ +@layer components.popover { + .root { + position: relative; + } +} diff --git a/src/components/Popover/PopoverWrapper.scss b/src/components/Popover/PopoverWrapper.scss deleted file mode 100644 index 3010bbfd..00000000 --- a/src/components/Popover/PopoverWrapper.scss +++ /dev/null @@ -1,3 +0,0 @@ -.root { - position: relative; -} diff --git a/src/components/Radio/Radio.jsx b/src/components/Radio/Radio.jsx index 67f4eb78..b1fb853f 100644 --- a/src/components/Radio/Radio.jsx +++ b/src/components/Radio/Radio.jsx @@ -6,7 +6,7 @@ import { getRootValidationStateClassName } from '../_helpers/getRootValidationSt import { resolveContextOrProp } from '../_helpers/resolveContextOrProp'; import { transferProps } from '../_helpers/transferProps'; import { FormLayoutContext } from '../FormLayout'; -import styles from './Radio.scss'; +import styles from './Radio.module.scss'; export const Radio = ({ disabled, diff --git a/src/components/Radio/Radio.module.scss b/src/components/Radio/Radio.module.scss new file mode 100644 index 00000000..4d7d0372 --- /dev/null +++ b/src/components/Radio/Radio.module.scss @@ -0,0 +1,85 @@ +// 1. Legends are tricky to style, let's use a `div` instead. +// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset#styling_with_css + +@use "../../styles/tools/form-fields/box-field-elements"; +@use "../../styles/tools/form-fields/box-field-layout"; +@use "../../styles/tools/form-fields/foundation"; +@use "../../styles/tools/form-fields/inline-field-elements"; +@use "../../styles/tools/form-fields/inline-field-layout"; +@use "../../styles/tools/form-fields/variants"; +@use "../../styles/tools/accessibility"; +@use "../../styles/tools/reset"; +@use "../../styles/tools/spacing"; + +@layer components.radio { + // Foundation + .root { + @include foundation.root(); + @include foundation.fieldset(); + @include variants.visual(check); + } + + // 1. + .legend { + @include accessibility.hide-text(); + } + + // 1. + .label, + .optionLabel { + @include foundation.label(); + } + + .options { + @include reset.list(); + } + + .option { + @include inline-field-layout.field($type: radio); + @include inline-field-elements.min-tap-target($type: radio); + } + + .input { + @include inline-field-elements.check-input($type: radio); + } + + .helpText, + .validationText { + @include foundation.help-text(); + } + + .isRootRequired .label { + @include foundation.label-required(); + } + + // States + .isRootStateInvalid { + @include variants.validation(invalid); + } + + .isRootStateValid { + @include variants.validation(valid); + } + + .isRootStateWarning { + @include variants.validation(warning); + } + + // Layouts + .isRootLayoutVertical, + .isRootLayoutHorizontal { + @include box-field-layout.vertical($has-list: true); + } + + .isRootLayoutHorizontal { + @include box-field-layout.horizontal($has-min-tap-target: true); + } + + .isRootFullWidth { + @include box-field-layout.full-width(); + } + + .isRootInFormLayout { + @include box-field-layout.in-form-layout($is-fieldset: true); + } +} diff --git a/src/components/Radio/Radio.scss b/src/components/Radio/Radio.scss deleted file mode 100644 index b0dae8c8..00000000 --- a/src/components/Radio/Radio.scss +++ /dev/null @@ -1,83 +0,0 @@ -// 1. Legends are tricky to style, let's use a `div` instead. -// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/fieldset#styling_with_css - -@use "../../styles/tools/form-fields/box-field-elements"; -@use "../../styles/tools/form-fields/box-field-layout"; -@use "../../styles/tools/form-fields/foundation"; -@use "../../styles/tools/form-fields/inline-field-elements"; -@use "../../styles/tools/form-fields/inline-field-layout"; -@use "../../styles/tools/form-fields/variants"; -@use "../../styles/tools/accessibility"; -@use "../../styles/tools/reset"; -@use "../../styles/tools/spacing"; - -// Foundation -.root { - @include foundation.root(); - @include foundation.fieldset(); - @include variants.visual(check); -} - -// 1. -.legend { - @include accessibility.hide-text(); -} - -// 1. -.label, -.optionLabel { - @include foundation.label(); -} - -.options { - @include reset.list(); -} - -.option { - @include inline-field-layout.field($type: radio); - @include inline-field-elements.min-tap-target($type: radio); -} - -.input { - @include inline-field-elements.check-input($type: radio); -} - -.helpText, -.validationText { - @include foundation.help-text(); -} - -.isRootRequired .label { - @include foundation.label-required(); -} - -// States -.isRootStateInvalid { - @include variants.validation(invalid); -} - -.isRootStateValid { - @include variants.validation(valid); -} - -.isRootStateWarning { - @include variants.validation(warning); -} - -// Layouts -.isRootLayoutVertical, -.isRootLayoutHorizontal { - @include box-field-layout.vertical($has-list: true); -} - -.isRootLayoutHorizontal { - @include box-field-layout.horizontal($has-min-tap-target: true); -} - -.isRootFullWidth { - @include box-field-layout.full-width(); -} - -.isRootInFormLayout { - @include box-field-layout.in-form-layout($is-fieldset: true); -} diff --git a/src/components/ScrollView/ScrollView.jsx b/src/components/ScrollView/ScrollView.jsx index 985cd00a..eb1532c1 100644 --- a/src/components/ScrollView/ScrollView.jsx +++ b/src/components/ScrollView/ScrollView.jsx @@ -15,7 +15,7 @@ import { transferProps } from '../_helpers/transferProps'; import { getElementsPositionDifference } from './_helpers/getElementsPositionDifference'; import { useLoadResize } from './_hooks/useLoadResizeHook'; import { useScrollPosition } from './_hooks/useScrollPositionHook'; -import styles from './ScrollView.scss'; +import styles from './ScrollView.module.scss'; // Function `getElementsPositionDifference` sometimes returns floating point values that results // in inaccurate detection of start/end. It is necessary to accept this inaccuracy and take diff --git a/src/components/ScrollView/ScrollView.module.scss b/src/components/ScrollView/ScrollView.module.scss new file mode 100644 index 00000000..d8e92fce --- /dev/null +++ b/src/components/ScrollView/ScrollView.module.scss @@ -0,0 +1,233 @@ +// 1. Scrolling shadows are implemented as pseudo elements. This way we can customise them only +// with custom properties. +// +// 2. Stack scrolling shadows over viewport content while keeping the content interactive. +// +// - `.scrollingShadows` is positioned absolutely over the `.root`, with auto `z-index` (this is +// important!), and with `overflow: hidden` to clip the shadows (ie. its pseudo elements). +// - The `.viewport` is in `.root`'s stacking context and remains interactive because its +// `z-index` is higher than the auto `z-index` of `.scrollingShadows`. +// +// 3. Optional arrows are positioned relative to the `.root` and stacked on top of scrolling +// shadows. They can be shifted outside the `ScrollView` area only because `overflow: hidden` is +// **not** present at `.root`. +// +// 4. Make the `.content`'s bounding rectangle spread beyond the part visible through `.viewport`. +// +// 5. Prevent undesired vertical scrolling that may occur with tables inside. +// +// 6. Make `ScrollView` adjust to flexible layouts. +// +// 7. Hide content overflowing in the other direction because scrollbars would be unreachable under +// scrolling shadows. +// +// 8. Use the `clip` value for `overflow` to prevent the content from unwanted scrolling on the +// cross axis during keyboard navigation. + +@use "../../styles/tools/accessibility"; +@use "../../styles/tools/caret"; +@use "../../styles/tools/reset"; +@use "../../styles/tools/scrollbar"; +@use "../../styles/tools/spacing"; +@use "../../styles/tools/transition"; + +$_arrow-inner-spacing: spacing.of(2); +$_arrow-outer-spacing: spacing.of(4); + +@layer components.scroll-view { + .root { + position: relative; // 2. + display: flex; + flex-direction: column; + width: 100%; + } + + // 1. + .scrollingShadows { + position: absolute; // 2. + width: 100%; // 2. + height: 100%; // 2. + overflow: hidden; // 2. + pointer-events: none; // 2. + + &::before, + &::after { + @include transition.add((visibility, opacity, transform)); + + content: ""; + position: absolute; + z-index: 2; // 2. + display: block; + visibility: hidden; + opacity: 0; + } + + &::before { + background: var(--rui-local-start-shadow-background); + } + + &::after { + background: var(--rui-local-end-shadow-background); + } + } + + .viewport { + z-index: 1; // 2. + width: 100%; + scroll-behavior: smooth; + } + + .arrowPrev, + .arrowNext { + @include reset.button(); + @include accessibility.min-tap-target(); + @include transition.add((visibility, opacity, transform)); + + position: absolute; // 3. + z-index: 3; // 3. + display: flex; + align-items: center; + justify-content: center; + visibility: hidden; + opacity: 0; + } + + .arrowIcon { + @include caret.create(); + } + + .isRootVertical { + height: 100%; + min-height: 0; // 6. + } + + .isRootVertical .viewport { + height: 100%; + overflow-x: clip; // 7., 8. + overflow-y: auto; // 2. + } + + .isRootVertical .arrowPrev { + top: 0; + right: 0; + left: 0; + width: 100%; + padding-top: $_arrow-outer-spacing; + padding-bottom: $_arrow-inner-spacing; + color: var(--rui-local-prev-arrow-color); + transform: translateY(var(--rui-local-prev-arrow-initial-offset)); + } + + .isRootVertical .arrowPrev .arrowIcon { + @include caret.rotate(180); + } + + .isRootVertical .arrowNext { + right: 0; + bottom: 0; + left: 0; + width: 100%; + padding-top: $_arrow-inner-spacing; + padding-bottom: $_arrow-outer-spacing; + color: var(--rui-local-next-arrow-color); + transform: translateY(calc(-1 * var(--rui-local-next-arrow-initial-offset))); + } + + .isRootHorizontal { + min-width: 0; // 6. + } + + .isRootHorizontal .arrowPrev { + top: 0; + bottom: 0; + left: 0; + padding-right: $_arrow-inner-spacing; + padding-left: $_arrow-outer-spacing; + transform: translateX(var(--rui-local-prev-arrow-initial-offset)); + } + + .isRootHorizontal .arrowPrev .arrowIcon { + @include caret.rotate(90); + } + + .isRootHorizontal .arrowNext { + top: 0; + right: 0; + bottom: 0; + padding-right: $_arrow-outer-spacing; + padding-left: $_arrow-inner-spacing; + transform: translateX(calc(-1 * var(--rui-local-next-arrow-initial-offset))); + } + + .isRootHorizontal .arrowNext .arrowIcon { + @include caret.rotate(270); + } + + .isRootVertical .scrollingShadows::before, + .isRootVertical .scrollingShadows::after { + right: 0; + left: 0; + width: auto; + } + + .isRootVertical .scrollingShadows::before { + top: 0; + height: var(--rui-local-start-shadow-size); + transform: translateY(var(--rui-local-start-shadow-initial-offset)); + } + + .isRootVertical .scrollingShadows::after { + bottom: 0; + height: var(--rui-local-end-shadow-size); + transform: translateY(calc(-1 * var(--rui-local-end-shadow-initial-offset))); + } + + .isRootHorizontal .viewport { + overflow-x: auto; // 2. + overflow-y: clip; // 5., 7., 8. + } + + .isRootHorizontal .content { + display: inline-flex; // 4. + min-width: 100%; + overflow: clip; // 8. + vertical-align: top; + } + + .isRootHorizontal .scrollingShadows::before, + .isRootHorizontal .scrollingShadows::after { + top: 0; + bottom: 0; + height: auto; + } + + .isRootHorizontal .scrollingShadows::before { + left: 0; + width: var(--rui-local-start-shadow-size); + transform: translateX(var(--rui-local-start-shadow-initial-offset)); + } + + .isRootHorizontal .scrollingShadows::after { + right: 0; + width: var(--rui-local-end-shadow-size); + transform: translateX(calc(-1 * var(--rui-local-end-shadow-initial-offset))); + } + + .isRootScrolledAtStart .scrollingShadows::before, + .isRootScrolledAtStart .arrowPrev { + visibility: visible; + opacity: 1; + transform: translate(0, 0); + } + + .isRootScrolledAtEnd .scrollingShadows::after, + .isRootScrolledAtEnd .arrowNext { + visibility: visible; + opacity: 1; + transform: translate(0, 0); + } + + .hasRootScrollbarDisabled .viewport { + @include scrollbar.hide(); + } +} diff --git a/src/components/ScrollView/ScrollView.scss b/src/components/ScrollView/ScrollView.scss deleted file mode 100644 index 21212b6b..00000000 --- a/src/components/ScrollView/ScrollView.scss +++ /dev/null @@ -1,231 +0,0 @@ -// 1. Scrolling shadows are implemented as pseudo elements. This way we can customise them only -// with custom properties. -// -// 2. Stack scrolling shadows over viewport content while keeping the content interactive. -// -// - `.scrollingShadows` is positioned absolutely over the `.root`, with auto `z-index` (this is -// important!), and with `overflow: hidden` to clip the shadows (ie. its pseudo elements). -// - The `.viewport` is in `.root`'s stacking context and remains interactive because its -// `z-index` is higher than the auto `z-index` of `.scrollingShadows`. -// -// 3. Optional arrows are positioned relative to the `.root` and stacked on top of scrolling -// shadows. They can be shifted outside the `ScrollView` area only because `overflow: hidden` is -// **not** present at `.root`. -// -// 4. Make the `.content`'s bounding rectangle spread beyond the part visible through `.viewport`. -// -// 5. Prevent undesired vertical scrolling that may occur with tables inside. -// -// 6. Make `ScrollView` adjust to flexible layouts. -// -// 7. Hide content overflowing in the other direction because scrollbars would be unreachable under -// scrolling shadows. -// -// 8. Use the `clip` value for `overflow` to prevent the content from unwanted scrolling on the -// cross axis during keyboard navigation. - -@use "../../styles/tools/accessibility"; -@use "../../styles/tools/caret"; -@use "../../styles/tools/reset"; -@use "../../styles/tools/scrollbar"; -@use "../../styles/tools/spacing"; -@use "../../styles/tools/transition"; - -$_arrow-inner-spacing: spacing.of(2); -$_arrow-outer-spacing: spacing.of(4); - -.root { - position: relative; // 2. - display: flex; - flex-direction: column; - width: 100%; -} - -// 1. -.scrollingShadows { - position: absolute; // 2. - width: 100%; // 2. - height: 100%; // 2. - overflow: hidden; // 2. - pointer-events: none; // 2. - - &::before, - &::after { - @include transition.add((visibility, opacity, transform)); - - content: ""; - position: absolute; - z-index: 2; // 2. - display: block; - visibility: hidden; - opacity: 0; - } - - &::before { - background: var(--rui-local-start-shadow-background); - } - - &::after { - background: var(--rui-local-end-shadow-background); - } -} - -.viewport { - z-index: 1; // 2. - width: 100%; - scroll-behavior: smooth; -} - -.arrowPrev, -.arrowNext { - @include reset.button(); - @include accessibility.min-tap-target(); - @include transition.add((visibility, opacity, transform)); - - position: absolute; // 3. - z-index: 3; // 3. - display: flex; - align-items: center; - justify-content: center; - visibility: hidden; - opacity: 0; -} - -.arrowIcon { - @include caret.create(); -} - -.isRootVertical { - height: 100%; - min-height: 0; // 6. -} - -.isRootVertical .viewport { - height: 100%; - overflow-x: clip; // 7., 8. - overflow-y: auto; // 2. -} - -.isRootVertical .arrowPrev { - top: 0; - right: 0; - left: 0; - width: 100%; - padding-top: $_arrow-outer-spacing; - padding-bottom: $_arrow-inner-spacing; - color: var(--rui-local-prev-arrow-color); - transform: translateY(var(--rui-local-prev-arrow-initial-offset)); -} - -.isRootVertical .arrowPrev .arrowIcon { - @include caret.rotate(180); -} - -.isRootVertical .arrowNext { - right: 0; - bottom: 0; - left: 0; - width: 100%; - padding-top: $_arrow-inner-spacing; - padding-bottom: $_arrow-outer-spacing; - color: var(--rui-local-next-arrow-color); - transform: translateY(calc(-1 * var(--rui-local-next-arrow-initial-offset))); -} - -.isRootHorizontal { - min-width: 0; // 6. -} - -.isRootHorizontal .arrowPrev { - top: 0; - bottom: 0; - left: 0; - padding-right: $_arrow-inner-spacing; - padding-left: $_arrow-outer-spacing; - transform: translateX(var(--rui-local-prev-arrow-initial-offset)); -} - -.isRootHorizontal .arrowPrev .arrowIcon { - @include caret.rotate(90); -} - -.isRootHorizontal .arrowNext { - top: 0; - right: 0; - bottom: 0; - padding-right: $_arrow-outer-spacing; - padding-left: $_arrow-inner-spacing; - transform: translateX(calc(-1 * var(--rui-local-next-arrow-initial-offset))); -} - -.isRootHorizontal .arrowNext .arrowIcon { - @include caret.rotate(270); -} - -.isRootVertical .scrollingShadows::before, -.isRootVertical .scrollingShadows::after { - right: 0; - left: 0; - width: auto; -} - -.isRootVertical .scrollingShadows::before { - top: 0; - height: var(--rui-local-start-shadow-size); - transform: translateY(var(--rui-local-start-shadow-initial-offset)); -} - -.isRootVertical .scrollingShadows::after { - bottom: 0; - height: var(--rui-local-end-shadow-size); - transform: translateY(calc(-1 * var(--rui-local-end-shadow-initial-offset))); -} - -.isRootHorizontal .viewport { - overflow-x: auto; // 2. - overflow-y: clip; // 5., 7., 8. -} - -.isRootHorizontal .content { - display: inline-flex; // 4. - min-width: 100%; - overflow: clip; // 8. - vertical-align: top; -} - -.isRootHorizontal .scrollingShadows::before, -.isRootHorizontal .scrollingShadows::after { - top: 0; - bottom: 0; - height: auto; -} - -.isRootHorizontal .scrollingShadows::before { - left: 0; - width: var(--rui-local-start-shadow-size); - transform: translateX(var(--rui-local-start-shadow-initial-offset)); -} - -.isRootHorizontal .scrollingShadows::after { - right: 0; - width: var(--rui-local-end-shadow-size); - transform: translateX(calc(-1 * var(--rui-local-end-shadow-initial-offset))); -} - -.isRootScrolledAtStart .scrollingShadows::before, -.isRootScrolledAtStart .arrowPrev { - visibility: visible; - opacity: 1; - transform: translate(0, 0); -} - -.isRootScrolledAtEnd .scrollingShadows::after, -.isRootScrolledAtEnd .arrowNext { - visibility: visible; - opacity: 1; - transform: translate(0, 0); -} - -.hasRootScrollbarDisabled .viewport { - @include scrollbar.hide(); -} diff --git a/src/components/SelectField/SelectField.jsx b/src/components/SelectField/SelectField.jsx index 969ce0e2..d1cd1c34 100644 --- a/src/components/SelectField/SelectField.jsx +++ b/src/components/SelectField/SelectField.jsx @@ -9,7 +9,7 @@ import { transferProps } from '../_helpers/transferProps'; import { FormLayoutContext } from '../FormLayout'; import { InputGroupContext } from '../InputGroup/InputGroupContext'; import { Option } from './_components/Option'; -import styles from './SelectField.scss'; +import styles from './SelectField.module.scss'; export const SelectField = React.forwardRef((props, ref) => { const { diff --git a/src/components/SelectField/SelectField.module.scss b/src/components/SelectField/SelectField.module.scss new file mode 100644 index 00000000..d97161af --- /dev/null +++ b/src/components/SelectField/SelectField.module.scss @@ -0,0 +1,111 @@ +@use "../../styles/tools/form-fields/box-field-elements"; +@use "../../styles/tools/form-fields/box-field-layout"; +@use "../../styles/tools/form-fields/box-field-sizes"; +@use "../../styles/tools/form-fields/foundation"; +@use "../../styles/tools/form-fields/variants"; +@use "../../styles/tools/accessibility"; + +@layer components.select-field { + // Foundation + .root { + @include foundation.root(); + } + + .label { + @include foundation.label(); + } + + .inputContainer { + @include box-field-elements.input-container(); + } + + .input { + @include box-field-elements.input(); + @include box-field-elements.input-select(); + @include box-field-elements.input-select-option(); + } + + .caret { + @include box-field-elements.caret(); + } + + .caretIcon { + @include box-field-elements.caret-icon(); + } + + .bottomLine { + @include box-field-elements.bottom-line(); + } + + .helpText, + .validationText { + @include foundation.help-text(); + } + + .isRootRequired .label { + @include foundation.label-required(); + } + + // Variants + .isRootVariantFilled { + @include variants.visual(box, $variant: filled, $has-caret: true); + } + + .isRootVariantOutline { + @include variants.visual(box, $variant: outline, $has-caret: true); + } + + // States + .isRootStateInvalid { + @include variants.validation(invalid); + } + + .isRootStateValid { + @include variants.validation(valid); + } + + .isRootStateWarning { + @include variants.validation(warning); + } + + // Invisible label + .isLabelHidden { + @include accessibility.hide-text(); + } + + // Layouts + .isRootLayoutVertical, + .isRootLayoutHorizontal { + @include box-field-layout.vertical(); + } + + .isRootLayoutHorizontal { + @include box-field-layout.horizontal(); + } + + .isRootFullWidth { + @include box-field-layout.full-width(); + } + + .isRootInFormLayout { + @include box-field-layout.in-form-layout(); + } + + // Sizes + .isRootSizeSmall { + @include box-field-sizes.size(small); + } + + .isRootSizeMedium { + @include box-field-sizes.size(medium); + } + + .isRootSizeLarge { + @include box-field-sizes.size(large); + } + + // Groups + .isRootGrouped { + @include box-field-elements.in-group-layout(); + } +} diff --git a/src/components/SelectField/SelectField.scss b/src/components/SelectField/SelectField.scss deleted file mode 100644 index b10b83c8..00000000 --- a/src/components/SelectField/SelectField.scss +++ /dev/null @@ -1,109 +0,0 @@ -@use "../../styles/tools/form-fields/box-field-elements"; -@use "../../styles/tools/form-fields/box-field-layout"; -@use "../../styles/tools/form-fields/box-field-sizes"; -@use "../../styles/tools/form-fields/foundation"; -@use "../../styles/tools/form-fields/variants"; -@use "../../styles/tools/accessibility"; - -// Foundation -.root { - @include foundation.root(); -} - -.label { - @include foundation.label(); -} - -.inputContainer { - @include box-field-elements.input-container(); -} - -.input { - @include box-field-elements.input(); - @include box-field-elements.input-select(); - @include box-field-elements.input-select-option(); -} - -.caret { - @include box-field-elements.caret(); -} - -.caretIcon { - @include box-field-elements.caret-icon(); -} - -.bottomLine { - @include box-field-elements.bottom-line(); -} - -.helpText, -.validationText { - @include foundation.help-text(); -} - -.isRootRequired .label { - @include foundation.label-required(); -} - -// Variants -.isRootVariantFilled { - @include variants.visual(box, $variant: filled, $has-caret: true); -} - -.isRootVariantOutline { - @include variants.visual(box, $variant: outline, $has-caret: true); -} - -// States -.isRootStateInvalid { - @include variants.validation(invalid); -} - -.isRootStateValid { - @include variants.validation(valid); -} - -.isRootStateWarning { - @include variants.validation(warning); -} - -// Invisible label -.isLabelHidden { - @include accessibility.hide-text(); -} - -// Layouts -.isRootLayoutVertical, -.isRootLayoutHorizontal { - @include box-field-layout.vertical(); -} - -.isRootLayoutHorizontal { - @include box-field-layout.horizontal(); -} - -.isRootFullWidth { - @include box-field-layout.full-width(); -} - -.isRootInFormLayout { - @include box-field-layout.in-form-layout(); -} - -// Sizes -.isRootSizeSmall { - @include box-field-sizes.size(small); -} - -.isRootSizeMedium { - @include box-field-sizes.size(medium); -} - -.isRootSizeLarge { - @include box-field-sizes.size(large); -} - -// Groups -.isRootGrouped { - @include box-field-elements.in-group-layout(); -} diff --git a/src/components/Table/Table.jsx b/src/components/Table/Table.jsx index 7165ccc0..4b4f4103 100644 --- a/src/components/Table/Table.jsx +++ b/src/components/Table/Table.jsx @@ -4,7 +4,7 @@ import { withGlobalProps } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; import { TableHeaderCell } from './_components/TableHeaderCell'; import { TableBodyCell } from './_components/TableBodyCell'; -import styles from './Table.scss'; +import styles from './Table.module.scss'; export const Table = ({ columns, diff --git a/src/components/Table/Table.module.scss b/src/components/Table/Table.module.scss new file mode 100644 index 00000000..b912d1ce --- /dev/null +++ b/src/components/Table/Table.module.scss @@ -0,0 +1,30 @@ +@use "../../styles/tools/transition"; +@use "settings"; + +@layer components.table { + .table { + width: 100%; + border-collapse: collapse; + } + + .tableRow, + .tableHeadRow { + @include transition.add((background-color)); + } + + .tableRow { + background-color: settings.$background-color; + + &:hover { + background-color: settings.$hover-background-color; + } + } + + .tableHeadRow { + background-color: settings.$head-background-color; + + &:hover { + background-color: settings.$head-background-color; + } + } +} diff --git a/src/components/Table/Table.scss b/src/components/Table/Table.scss deleted file mode 100644 index 97e8c5e3..00000000 --- a/src/components/Table/Table.scss +++ /dev/null @@ -1,28 +0,0 @@ -@use "../../styles/tools/transition"; -@use "settings"; - -.table { - width: 100%; - border-collapse: collapse; -} - -.tableRow, -.tableHeadRow { - @include transition.add((background-color)); -} - -.tableRow { - background-color: settings.$background-color; - - &:hover { - background-color: settings.$hover-background-color; - } -} - -.tableHeadRow { - background-color: settings.$head-background-color; - - &:hover { - background-color: settings.$head-background-color; - } -} diff --git a/src/components/Table/_components/TableBodyCell/TableBodyCell.jsx b/src/components/Table/_components/TableBodyCell/TableBodyCell.jsx index d3dfd760..1ee1109e 100644 --- a/src/components/Table/_components/TableBodyCell/TableBodyCell.jsx +++ b/src/components/Table/_components/TableBodyCell/TableBodyCell.jsx @@ -1,6 +1,6 @@ import PropTypes from 'prop-types'; import React from 'react'; -import styles from '../TableCell.scss'; +import styles from '../TableCell.module.scss'; export const TableBodyCell = ({ format, diff --git a/src/components/Table/_components/TableCell.module.scss b/src/components/Table/_components/TableCell.module.scss new file mode 100644 index 00000000..8b8bff6e --- /dev/null +++ b/src/components/Table/_components/TableCell.module.scss @@ -0,0 +1,28 @@ +@use "../settings"; + +@layer components.table { + .tableCell, + .tableHeadCell, + .isTableCellSortingActive, + .isTableHeadCellSortingActive { + padding: settings.$cell-padding-y settings.$cell-padding-x; + text-align: left; + border-bottom: settings.$border-width solid settings.$border-color; + } + + .tableHeadCell { + font-weight: settings.$head-font-weight; + border-bottom-width: 2px; + } + + .tableHeadCellLayout { + display: flex; + gap: settings.$cell-padding-x; + align-items: center; + } + + .isTableCellSortingActive, + .isTableHeadCellSortingActive { + background-color: settings.$sorted-background-color; + } +} diff --git a/src/components/Table/_components/TableCell.scss b/src/components/Table/_components/TableCell.scss deleted file mode 100644 index 5875d97a..00000000 --- a/src/components/Table/_components/TableCell.scss +++ /dev/null @@ -1,26 +0,0 @@ -@use "../settings"; - -.tableCell, -.tableHeadCell, -.isTableCellSortingActive, -.isTableHeadCellSortingActive { - padding: settings.$cell-padding-y settings.$cell-padding-x; - text-align: left; - border-bottom: settings.$border-width solid settings.$border-color; -} - -.tableHeadCell { - font-weight: settings.$head-font-weight; - border-bottom-width: 2px; -} - -.tableHeadCellLayout { - display: flex; - gap: settings.$cell-padding-x; - align-items: center; -} - -.isTableCellSortingActive, -.isTableHeadCellSortingActive { - background-color: settings.$sorted-background-color; -} diff --git a/src/components/Table/_components/TableHeaderCell/TableHeaderCell.jsx b/src/components/Table/_components/TableHeaderCell/TableHeaderCell.jsx index 482d32d3..f182468f 100644 --- a/src/components/Table/_components/TableHeaderCell/TableHeaderCell.jsx +++ b/src/components/Table/_components/TableHeaderCell/TableHeaderCell.jsx @@ -1,7 +1,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { Button } from '../../../Button'; -import styles from '../TableCell.scss'; +import styles from '../TableCell.module.scss'; export const TableHeaderCell = ({ column, diff --git a/src/components/Tabs/Tabs.jsx b/src/components/Tabs/Tabs.jsx index 9a2ef918..449c8733 100644 --- a/src/components/Tabs/Tabs.jsx +++ b/src/components/Tabs/Tabs.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { withGlobalProps } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; -import styles from './Tabs.scss'; +import styles from './Tabs.module.scss'; export const Tabs = ({ children, diff --git a/src/components/Tabs/Tabs.module.scss b/src/components/Tabs/Tabs.module.scss new file mode 100644 index 00000000..b489b549 --- /dev/null +++ b/src/components/Tabs/Tabs.module.scss @@ -0,0 +1,31 @@ +// 1. Use the `clip` value to prevent the content from unwanted vertical scrolling during keyboard navigation. +// 2. Decorative bottom border. + +@use "../../styles/tools/reset"; +@use "theme"; + +@layer components.tabs { + .list { + @include reset.list(); + + position: relative; + display: inline-flex; + min-width: 100%; + padding-right: theme.$padding-x; + padding-left: theme.$padding-x; + overflow-y: clip; // 1. + white-space: nowrap; + + // 2. + &::after { + content: ""; + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + height: theme.$border-bottom-width; + background-color: theme.$border-bottom-color; + } + } +} diff --git a/src/components/Tabs/Tabs.scss b/src/components/Tabs/Tabs.scss deleted file mode 100644 index 3f724a22..00000000 --- a/src/components/Tabs/Tabs.scss +++ /dev/null @@ -1,29 +0,0 @@ -// 1. Use the `clip` value to prevent the content from unwanted vertical scrolling during keyboard navigation. -// 2. Decorative bottom border. - -@use "../../styles/tools/reset"; -@use "theme"; - -.list { - @include reset.list(); - - position: relative; - display: inline-flex; - min-width: 100%; - padding-right: theme.$padding-x; - padding-left: theme.$padding-x; - overflow-y: clip; // 1. - white-space: nowrap; - - // 2. - &::after { - content: ""; - position: absolute; - right: 0; - bottom: 0; - left: 0; - z-index: 1; - height: theme.$border-bottom-width; - background-color: theme.$border-bottom-color; - } -} diff --git a/src/components/Tabs/TabsItem.jsx b/src/components/Tabs/TabsItem.jsx index 2880a41e..35b7b5a9 100644 --- a/src/components/Tabs/TabsItem.jsx +++ b/src/components/Tabs/TabsItem.jsx @@ -3,7 +3,7 @@ import React from 'react'; import { withGlobalProps } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; import { classNames } from '../../utils/classNames'; -import styles from './TabsItem.scss'; +import styles from './TabsItem.module.scss'; export const TabsItem = ({ afterLabel, diff --git a/src/components/Tabs/TabsItem.module.scss b/src/components/Tabs/TabsItem.module.scss new file mode 100644 index 00000000..fcbde8fe --- /dev/null +++ b/src/components/Tabs/TabsItem.module.scss @@ -0,0 +1,119 @@ +// 1. Keep inactive items under Tabs' decorative bottom border and pop active ones above it. + +@use "../../styles/tools/breakpoint"; +@use "../../styles/tools/reset"; +@use "../../styles/tools/transition"; +@use "theme"; + +@layer components.tabs { + .root { + @include transition.add(transform); + + position: relative; // 1. + z-index: 1; // 1. + flex: none; + padding-top: calc(-1 * #{theme.$item-active-shift-y}); + margin-bottom: theme.$item-active-shift-y; + transform: translateY(0); + + &:hover, + &:focus-within { + transform: translateY(theme.$item-hover-shift-y); + } + + &:not(:last-child) { + margin-right: theme.$gap-xs; + } + + @include breakpoint.up(sm) { + &:not(:last-child) { + margin-right: theme.$gap-sm; + } + } + + @include breakpoint.up(md) { + &:not(:last-child) { + margin-right: theme.$gap-md; + } + } + } + + .link { + @include reset.link(); + @include transition.add((color, border-color, background-color, box-shadow)); + + display: block; + padding: theme.$item-padding-xs; + font-weight: theme.$item-font-weight; + line-height: 1; + text-decoration: none; + color: theme.$item-color; + border: theme.$item-border-width solid; + border-color: theme.$item-border-color; + border-top-left-radius: theme.$item-border-radius; + border-top-right-radius: theme.$item-border-radius; + background-color: theme.$item-background-color; + box-shadow: theme.$item-box-shadow; + + &:hover, + &:focus { + font-weight: theme.$item-hover-font-weight; + color: theme.$item-hover-color; + border-width: theme.$item-hover-border-width; + border-color: theme.$item-hover-border-color; + background-color: theme.$item-hover-background-color; + box-shadow: theme.$item-hover-box-shadow; + } + + @include breakpoint.up(sm) { + padding: theme.$item-padding-sm; + } + + @include breakpoint.up(md) { + padding: theme.$item-padding-md; + } + } + + .linkContent { + @include transition.add(transform); + + display: flex; + align-items: center; + transform: translateY(0); + } + + .label:not(:first-child) { + margin-left: theme.$item-icon-gap; + } + + .label:not(:last-child) { + margin-right: theme.$item-icon-gap; + } + + .isRootActive, + .isRootActive:hover, + .isRootActive:focus-within { + z-index: 2; // 1. + transform: translateY(theme.$item-active-shift-y); + } + + .isRootActive .link { + font-weight: theme.$item-active-font-weight; + color: theme.$item-active-color; + border-width: theme.$item-active-border-width; + border-color: theme.$item-active-border-color; + background-color: theme.$item-active-background-color; + box-shadow: theme.$item-active-box-shadow; + } + + .link:hover .linkContent, + .link:focus .linkContent { + transform: translateY(theme.$item-hover-label-shift-y); + } + + .isRootActive .link .linkContent, + .isRootActive .link:hover .linkContent, + .isRootActive .link:focus .linkContent { + transform: translateY(theme.$item-active-label-shift-y); + } +} diff --git a/src/components/Tabs/TabsItem.scss b/src/components/Tabs/TabsItem.scss deleted file mode 100644 index 29e2efb4..00000000 --- a/src/components/Tabs/TabsItem.scss +++ /dev/null @@ -1,117 +0,0 @@ -// 1. Keep inactive items under Tabs' decorative bottom border and pop active ones above it. - -@use "../../styles/tools/breakpoint"; -@use "../../styles/tools/reset"; -@use "../../styles/tools/transition"; -@use "theme"; - -.root { - @include transition.add(transform); - - position: relative; // 1. - z-index: 1; // 1. - flex: none; - padding-top: calc(-1 * #{theme.$item-active-shift-y}); - margin-bottom: theme.$item-active-shift-y; - transform: translateY(0); - - &:hover, - &:focus-within { - transform: translateY(theme.$item-hover-shift-y); - } - - &:not(:last-child) { - margin-right: theme.$gap-xs; - } - - @include breakpoint.up(sm) { - &:not(:last-child) { - margin-right: theme.$gap-sm; - } - } - - @include breakpoint.up(md) { - &:not(:last-child) { - margin-right: theme.$gap-md; - } - } -} - -.link { - @include reset.link(); - @include transition.add((color, border-color, background-color, box-shadow)); - - display: block; - padding: theme.$item-padding-xs; - font-weight: theme.$item-font-weight; - line-height: 1; - text-decoration: none; - color: theme.$item-color; - border: theme.$item-border-width solid; - border-color: theme.$item-border-color; - border-top-left-radius: theme.$item-border-radius; - border-top-right-radius: theme.$item-border-radius; - background-color: theme.$item-background-color; - box-shadow: theme.$item-box-shadow; - - &:hover, - &:focus { - font-weight: theme.$item-hover-font-weight; - color: theme.$item-hover-color; - border-width: theme.$item-hover-border-width; - border-color: theme.$item-hover-border-color; - background-color: theme.$item-hover-background-color; - box-shadow: theme.$item-hover-box-shadow; - } - - @include breakpoint.up(sm) { - padding: theme.$item-padding-sm; - } - - @include breakpoint.up(md) { - padding: theme.$item-padding-md; - } -} - -.linkContent { - @include transition.add(transform); - - display: flex; - align-items: center; - transform: translateY(0); -} - -.label:not(:first-child) { - margin-left: theme.$item-icon-gap; -} - -.label:not(:last-child) { - margin-right: theme.$item-icon-gap; -} - -.isRootActive, -.isRootActive:hover, -.isRootActive:focus-within { - z-index: 2; // 1. - transform: translateY(theme.$item-active-shift-y); -} - -.isRootActive .link { - font-weight: theme.$item-active-font-weight; - color: theme.$item-active-color; - border-width: theme.$item-active-border-width; - border-color: theme.$item-active-border-color; - background-color: theme.$item-active-background-color; - box-shadow: theme.$item-active-box-shadow; -} - -.link:hover .linkContent, -.link:focus .linkContent { - transform: translateY(theme.$item-hover-label-shift-y); -} - -.isRootActive .link .linkContent, -.isRootActive .link:hover .linkContent, -.isRootActive .link:focus .linkContent { - transform: translateY(theme.$item-active-label-shift-y); -} diff --git a/src/components/Text/Text.jsx b/src/components/Text/Text.jsx index e7861edd..64f1c73e 100644 --- a/src/components/Text/Text.jsx +++ b/src/components/Text/Text.jsx @@ -7,7 +7,7 @@ import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { getRootClampClassName } from './_helpers/getRootClampClassName'; import { getRootHyphensClassName } from './_helpers/getRootHyphensClassName'; import { getRootWordWrappingClassName } from './_helpers/getRootWordWrappingClassName'; -import styles from './Text.scss'; +import styles from './Text.module.scss'; export const Text = ({ blockLevel, diff --git a/src/components/Text/Text.module.scss b/src/components/Text/Text.module.scss new file mode 100644 index 00000000..1cd0e3c0 --- /dev/null +++ b/src/components/Text/Text.module.scss @@ -0,0 +1,42 @@ +// 1. `word-break: break-word` is deprecated in favour of `overflow-wrap: anywhere`, but it's still +// required for Safari. +// https://caniuse.com/mdn-css_properties_overflow-wrap_anywhere +// +// 2. Different approaches are used for single and multiline texts because the latter approach +// doesn't always work for single-line texts. + +@layer components.text { + .isRootClampSingleLine { + display: block; // 2. + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + // stylelint-disable property-no-vendor-prefix, value-no-vendor-prefix + .isRootClampMultiLine { + display: -webkit-box; // 2. + -webkit-line-clamp: var(--rui-custom-lines); + -webkit-box-orient: vertical; + overflow: hidden; + text-overflow: ellipsis; + } + // stylelint-enable property-no-vendor-prefix, value-no-vendor-prefix + + .isRootHyphensAuto { + hyphens: auto; + } + + .isRootHyphensManual { + hyphens: manual; + } + + .isRootWordWrappingAnywhere { + word-break: break-all; + } + + .isRootWordWrappingLongWords { + word-break: break-word; // 1. + overflow-wrap: anywhere; + } +} diff --git a/src/components/Text/Text.scss b/src/components/Text/Text.scss deleted file mode 100644 index ecd178d3..00000000 --- a/src/components/Text/Text.scss +++ /dev/null @@ -1,40 +0,0 @@ -// 1. `word-break: break-word` is deprecated in favour of `overflow-wrap: anywhere`, but it's still -// required for Safari. -// https://caniuse.com/mdn-css_properties_overflow-wrap_anywhere -// -// 2. Different approaches are used for single and multiline texts because the latter approach -// doesn't always work for single-line texts. - -.isRootClampSingleLine { - display: block; // 2. - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -// stylelint-disable property-no-vendor-prefix, value-no-vendor-prefix -.isRootClampMultiLine { - display: -webkit-box; // 2. - -webkit-line-clamp: var(--rui-custom-lines); - -webkit-box-orient: vertical; - overflow: hidden; - text-overflow: ellipsis; -} -// stylelint-enable property-no-vendor-prefix, value-no-vendor-prefix - -.isRootHyphensAuto { - hyphens: auto; -} - -.isRootHyphensManual { - hyphens: manual; -} - -.isRootWordWrappingAnywhere { - word-break: break-all; -} - -.isRootWordWrappingLongWords { - word-break: break-word; // 1. - overflow-wrap: anywhere; -} diff --git a/src/components/TextArea/TextArea.jsx b/src/components/TextArea/TextArea.jsx index f51a9709..f1c11ebe 100644 --- a/src/components/TextArea/TextArea.jsx +++ b/src/components/TextArea/TextArea.jsx @@ -7,7 +7,7 @@ import { getRootValidationStateClassName } from '../_helpers/getRootValidationSt import { resolveContextOrProp } from '../_helpers/resolveContextOrProp'; import { transferProps } from '../_helpers/transferProps'; import { FormLayoutContext } from '../FormLayout'; -import styles from './TextArea.scss'; +import styles from './TextArea.module.scss'; export const TextArea = React.forwardRef((props, ref) => { const { diff --git a/src/components/TextArea/TextArea.module.scss b/src/components/TextArea/TextArea.module.scss new file mode 100644 index 00000000..49b57f50 --- /dev/null +++ b/src/components/TextArea/TextArea.module.scss @@ -0,0 +1,97 @@ +@use "../../styles/tools/form-fields/box-field-elements"; +@use "../../styles/tools/form-fields/box-field-layout"; +@use "../../styles/tools/form-fields/box-field-sizes"; +@use "../../styles/tools/form-fields/foundation"; +@use "../../styles/tools/form-fields/variants"; +@use "../../styles/tools/accessibility"; + +@layer components.text-area { + // Foundation + .root { + @include foundation.root(); + } + + .label { + @include foundation.label(); + } + + .inputContainer { + @include box-field-elements.input-container(); + } + + .input { + @include box-field-elements.input(); + @include box-field-elements.input-textarea(); + } + + .bottomLine { + @include box-field-elements.bottom-line(); + } + + .helpText, + .validationText { + @include foundation.help-text(); + } + + .isRootRequired .label { + @include foundation.label-required(); + } + + // Visual variants + .isRootVariantFilled { + @include variants.visual(box, $variant: filled); + } + + .isRootVariantOutline { + @include variants.visual(box, $variant: outline); + } + + // States + .isRootStateInvalid { + @include variants.validation(invalid); + } + + .isRootStateValid { + @include variants.validation(valid); + } + + .isRootStateWarning { + @include variants.validation(warning); + } + + // Invisible label + .isLabelHidden { + @include accessibility.hide-text(); + } + + // Layouts + .isRootLayoutVertical, + .isRootLayoutHorizontal { + @include box-field-layout.vertical(); + } + + .isRootLayoutHorizontal { + @include box-field-layout.horizontal(); + } + + .isRootFullWidth { + @include box-field-layout.full-width(); + } + + .isRootInFormLayout { + @include box-field-layout.in-form-layout(); + } + + // Sizes + .isRootSizeSmall { + @include box-field-sizes.size(small, $is-multiline: true); + } + + .isRootSizeMedium { + @include box-field-sizes.size(medium, $is-multiline: true); + } + + .isRootSizeLarge { + @include box-field-sizes.size(large, $is-multiline: true); + } +} diff --git a/src/components/TextArea/TextArea.scss b/src/components/TextArea/TextArea.scss deleted file mode 100644 index 219d9c1d..00000000 --- a/src/components/TextArea/TextArea.scss +++ /dev/null @@ -1,95 +0,0 @@ -@use "../../styles/tools/form-fields/box-field-elements"; -@use "../../styles/tools/form-fields/box-field-layout"; -@use "../../styles/tools/form-fields/box-field-sizes"; -@use "../../styles/tools/form-fields/foundation"; -@use "../../styles/tools/form-fields/variants"; -@use "../../styles/tools/accessibility"; - -// Foundation -.root { - @include foundation.root(); -} - -.label { - @include foundation.label(); -} - -.inputContainer { - @include box-field-elements.input-container(); -} - -.input { - @include box-field-elements.input(); - @include box-field-elements.input-textarea(); -} - -.bottomLine { - @include box-field-elements.bottom-line(); -} - -.helpText, -.validationText { - @include foundation.help-text(); -} - -.isRootRequired .label { - @include foundation.label-required(); -} - -// Visual variants -.isRootVariantFilled { - @include variants.visual(box, $variant: filled); -} - -.isRootVariantOutline { - @include variants.visual(box, $variant: outline); -} - -// States -.isRootStateInvalid { - @include variants.validation(invalid); -} - -.isRootStateValid { - @include variants.validation(valid); -} - -.isRootStateWarning { - @include variants.validation(warning); -} - -// Invisible label -.isLabelHidden { - @include accessibility.hide-text(); -} - -// Layouts -.isRootLayoutVertical, -.isRootLayoutHorizontal { - @include box-field-layout.vertical(); -} - -.isRootLayoutHorizontal { - @include box-field-layout.horizontal(); -} - -.isRootFullWidth { - @include box-field-layout.full-width(); -} - -.isRootInFormLayout { - @include box-field-layout.in-form-layout(); -} - -// Sizes -.isRootSizeSmall { - @include box-field-sizes.size(small, $is-multiline: true); -} - -.isRootSizeMedium { - @include box-field-sizes.size(medium, $is-multiline: true); -} - -.isRootSizeLarge { - @include box-field-sizes.size(large, $is-multiline: true); -} diff --git a/src/components/TextField/TextField.jsx b/src/components/TextField/TextField.jsx index 4970d389..c3967256 100644 --- a/src/components/TextField/TextField.jsx +++ b/src/components/TextField/TextField.jsx @@ -8,7 +8,7 @@ import { resolveContextOrProp } from '../_helpers/resolveContextOrProp'; import { transferProps } from '../_helpers/transferProps'; import { FormLayoutContext } from '../FormLayout'; import { InputGroupContext } from '../InputGroup/InputGroupContext'; -import styles from './TextField.scss'; +import styles from './TextField.module.scss'; const SMALL_INPUT_SIZE = 10; diff --git a/src/components/TextField/TextField.module.scss b/src/components/TextField/TextField.module.scss new file mode 100644 index 00000000..d88598f8 --- /dev/null +++ b/src/components/TextField/TextField.module.scss @@ -0,0 +1,109 @@ +@use "../../styles/tools/form-fields/box-field-elements"; +@use "../../styles/tools/form-fields/box-field-layout"; +@use "../../styles/tools/form-fields/box-field-sizes"; +@use "../../styles/tools/form-fields/foundation"; +@use "../../styles/tools/form-fields/variants"; +@use "../../styles/tools/accessibility"; + +@layer components.text-field { + // Foundation + .root { + @include foundation.root(); + } + + .label { + @include foundation.label(); + } + + .inputContainer { + @include box-field-elements.input-container(); + } + + .input { + @include box-field-elements.input(); + } + + .bottomLine { + @include box-field-elements.bottom-line(); + } + + .helpText, + .validationText { + @include foundation.help-text(); + } + + .hasRootCustomInputSize .input { + @include box-field-elements.input-size(); + } + + .isRootRequired .label { + @include foundation.label-required(); + } + + // Variants + .isRootVariantFilled { + @include variants.visual(box, $variant: filled); + } + + .isRootVariantOutline { + @include variants.visual(box, $variant: outline); + } + + // States + .isRootStateInvalid { + @include variants.validation(invalid); + } + + .isRootStateValid { + @include variants.validation(valid); + } + + .isRootStateWarning { + @include variants.validation(warning); + } + + // Invisible label + .isLabelHidden { + @include accessibility.hide-text(); + } + + // Layouts + .isRootLayoutVertical, + .isRootLayoutHorizontal { + @include box-field-layout.vertical(); + } + + .isRootLayoutHorizontal { + @include box-field-layout.horizontal(); + } + + .isRootFullWidth { + @include box-field-layout.full-width(); + } + + .isRootInFormLayout { + @include box-field-layout.in-form-layout(); + } + + .hasRootSmallInput.isRootLayoutHorizontal { + @include box-field-layout.horizontal-with-small-input(); + } + + // Sizes + .isRootSizeSmall { + @include box-field-sizes.size(small); + } + + .isRootSizeMedium { + @include box-field-sizes.size(medium); + } + + .isRootSizeLarge { + @include box-field-sizes.size(large); + } + + // Groups + .isRootGrouped { + @include box-field-elements.in-group-layout(); + } +} diff --git a/src/components/TextField/TextField.scss b/src/components/TextField/TextField.scss deleted file mode 100644 index 5cfb34a3..00000000 --- a/src/components/TextField/TextField.scss +++ /dev/null @@ -1,107 +0,0 @@ -@use "../../styles/tools/form-fields/box-field-elements"; -@use "../../styles/tools/form-fields/box-field-layout"; -@use "../../styles/tools/form-fields/box-field-sizes"; -@use "../../styles/tools/form-fields/foundation"; -@use "../../styles/tools/form-fields/variants"; -@use "../../styles/tools/accessibility"; - -// Foundation -.root { - @include foundation.root(); -} - -.label { - @include foundation.label(); -} - -.inputContainer { - @include box-field-elements.input-container(); -} - -.input { - @include box-field-elements.input(); -} - -.bottomLine { - @include box-field-elements.bottom-line(); -} - -.helpText, -.validationText { - @include foundation.help-text(); -} - -.hasRootCustomInputSize .input { - @include box-field-elements.input-size(); -} - -.isRootRequired .label { - @include foundation.label-required(); -} - -// Variants -.isRootVariantFilled { - @include variants.visual(box, $variant: filled); -} - -.isRootVariantOutline { - @include variants.visual(box, $variant: outline); -} - -// States -.isRootStateInvalid { - @include variants.validation(invalid); -} - -.isRootStateValid { - @include variants.validation(valid); -} - -.isRootStateWarning { - @include variants.validation(warning); -} - -// Invisible label -.isLabelHidden { - @include accessibility.hide-text(); -} - -// Layouts -.isRootLayoutVertical, -.isRootLayoutHorizontal { - @include box-field-layout.vertical(); -} - -.isRootLayoutHorizontal { - @include box-field-layout.horizontal(); -} - -.isRootFullWidth { - @include box-field-layout.full-width(); -} - -.isRootInFormLayout { - @include box-field-layout.in-form-layout(); -} - -.hasRootSmallInput.isRootLayoutHorizontal { - @include box-field-layout.horizontal-with-small-input(); -} - -// Sizes -.isRootSizeSmall { - @include box-field-sizes.size(small); -} - -.isRootSizeMedium { - @include box-field-sizes.size(medium); -} - -.isRootSizeLarge { - @include box-field-sizes.size(large); -} - -// Groups -.isRootGrouped { - @include box-field-elements.in-group-layout(); -} diff --git a/src/components/TextLink/TextLink.jsx b/src/components/TextLink/TextLink.jsx index 2b38081b..e98889b2 100644 --- a/src/components/TextLink/TextLink.jsx +++ b/src/components/TextLink/TextLink.jsx @@ -2,7 +2,7 @@ import PropTypes from 'prop-types'; import React from 'react'; import { withGlobalProps } from '../../provider'; import { transferProps } from '../_helpers/transferProps'; -import styles from './TextLink.scss'; +import styles from './TextLink.module.scss'; export const TextLink = ({ href, diff --git a/src/components/TextLink/TextLink.module.scss b/src/components/TextLink/TextLink.module.scss new file mode 100644 index 00000000..4e44942f --- /dev/null +++ b/src/components/TextLink/TextLink.module.scss @@ -0,0 +1,18 @@ +@use "theme"; + +@layer components.text-link { + .root { + text-decoration: theme.$text-decoration; + color: theme.$color; + + &:hover { + text-decoration: theme.$hover-text-decoration; + color: theme.$hover-color; + } + + &:active { + text-decoration: theme.$active-text-decoration; + color: theme.$active-color; + } + } +} diff --git a/src/components/TextLink/TextLink.scss b/src/components/TextLink/TextLink.scss deleted file mode 100644 index f3d81900..00000000 --- a/src/components/TextLink/TextLink.scss +++ /dev/null @@ -1,16 +0,0 @@ -@use "theme"; - -.root { - text-decoration: theme.$text-decoration; - color: theme.$color; - - &:hover { - text-decoration: theme.$hover-text-decoration; - color: theme.$hover-color; - } - - &:active { - text-decoration: theme.$active-text-decoration; - color: theme.$active-color; - } -} diff --git a/src/components/Toggle/Toggle.jsx b/src/components/Toggle/Toggle.jsx index 48081a9f..9af911a9 100644 --- a/src/components/Toggle/Toggle.jsx +++ b/src/components/Toggle/Toggle.jsx @@ -5,7 +5,7 @@ import { classNames } from '../../utils/classNames'; import { getRootValidationStateClassName } from '../_helpers/getRootValidationStateClassName'; import { transferProps } from '../_helpers/transferProps'; import { FormLayoutContext } from '../FormLayout'; -import styles from './Toggle.scss'; +import styles from './Toggle.module.scss'; export const Toggle = React.forwardRef((props, ref) => { const { diff --git a/src/components/Toggle/Toggle.module.scss b/src/components/Toggle/Toggle.module.scss new file mode 100644 index 00000000..68846cbf --- /dev/null +++ b/src/components/Toggle/Toggle.module.scss @@ -0,0 +1,63 @@ +@use "../../styles/tools/form-fields/foundation"; +@use "../../styles/tools/form-fields/inline-field-elements"; +@use "../../styles/tools/form-fields/inline-field-layout"; +@use "../../styles/tools/form-fields/variants"; +@use "../../styles/tools/accessibility"; + +@layer components.toggle { + // Foundation + .root { + @include foundation.root(); + @include inline-field-layout.root(); + @include inline-field-elements.min-tap-target($type: toggle); + @include variants.visual(check); + } + + .label { + @include foundation.label(); + } + + .field { + @include inline-field-layout.field($type: toggle); + } + + .input { + @include inline-field-elements.check-input($type: toggle); + } + + .helpText, + .validationText { + @include foundation.help-text(); + } + + .isRootRequired .label { + @include foundation.label-required(); + } + + // States + .isRootStateInvalid { + @include variants.validation(invalid); + } + + .isRootStateValid { + @include variants.validation(valid); + } + + .isRootStateWarning { + @include variants.validation(warning); + } + + // Invisible label + .isLabelHidden { + @include accessibility.hide-text(); + } + + // Layouts + .hasRootLabelBefore { + @include inline-field-layout.has-label-before(); + } + + .isRootInFormLayout { + @include inline-field-layout.in-form-layout(); + } +} diff --git a/src/components/Toggle/Toggle.scss b/src/components/Toggle/Toggle.scss deleted file mode 100644 index 4e34fd8d..00000000 --- a/src/components/Toggle/Toggle.scss +++ /dev/null @@ -1,61 +0,0 @@ -@use "../../styles/tools/form-fields/foundation"; -@use "../../styles/tools/form-fields/inline-field-elements"; -@use "../../styles/tools/form-fields/inline-field-layout"; -@use "../../styles/tools/form-fields/variants"; -@use "../../styles/tools/accessibility"; - -// Foundation -.root { - @include foundation.root(); - @include inline-field-layout.root(); - @include inline-field-elements.min-tap-target($type: toggle); - @include variants.visual(check); -} - -.label { - @include foundation.label(); -} - -.field { - @include inline-field-layout.field($type: toggle); -} - -.input { - @include inline-field-elements.check-input($type: toggle); -} - -.helpText, -.validationText { - @include foundation.help-text(); -} - -.isRootRequired .label { - @include foundation.label-required(); -} - -// States -.isRootStateInvalid { - @include variants.validation(invalid); -} - -.isRootStateValid { - @include variants.validation(valid); -} - -.isRootStateWarning { - @include variants.validation(warning); -} - -// Invisible label -.isLabelHidden { - @include accessibility.hide-text(); -} - -// Layouts -.hasRootLabelBefore { - @include inline-field-layout.has-label-before(); -} - -.isRootInFormLayout { - @include inline-field-layout.in-form-layout(); -} diff --git a/src/components/Toolbar/Toolbar.jsx b/src/components/Toolbar/Toolbar.jsx index 770974d7..cef878f0 100644 --- a/src/components/Toolbar/Toolbar.jsx +++ b/src/components/Toolbar/Toolbar.jsx @@ -6,7 +6,7 @@ import { classNames } from '../../utils/classNames'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { getAlignClassName } from './_helpers/getAlignClassName'; import { getJustifyClassName } from './_helpers/getJustifyClassName'; -import styles from './Toolbar.scss'; +import styles from './Toolbar.module.scss'; export const Toolbar = ({ align, diff --git a/src/components/Toolbar/Toolbar.module.scss b/src/components/Toolbar/Toolbar.module.scss new file mode 100644 index 00000000..d7dcc624 --- /dev/null +++ b/src/components/Toolbar/Toolbar.module.scss @@ -0,0 +1,85 @@ +// 1. Get rid of unwanted spacing of inline elements by invocation of flex layout. + +@use "../../styles/tools/spacing"; +@use "theme"; + +@layer components.toolbar { + .toolbar, + .group { + display: flex; + flex-wrap: wrap; + gap: theme.$gap; + } + + .toolbar { + @include spacing.bottom(layouts); + } + + .item { + display: flex; // 1. + flex: none; + flex-direction: column; // 1. + } + + .isItemFlexible { + flex: 1; + min-width: 0; + } + + .isToolbarAlignedToTop, + .isGroupAlignedToTop { + align-items: flex-start; + } + + .isToolbarAlignedToMiddle, + .isGroupAlignedToMiddle { + align-items: center; + } + + .isToolbarAlignedToBottom, + .isGroupAlignedToBottom { + align-items: flex-end; + } + + .isToolbarAlignedToBaseline, + .isGroupAlignedToBaseline { + align-items: baseline; + } + + .isToolbarJustifiedToStart, + .isGroupJustifiedToStart { + justify-content: flex-start; + } + + .isToolbarJustifiedToCenter, + .isGroupJustifiedToCenter { + justify-content: center; + } + + .isToolbarJustifiedToEnd, + .isGroupJustifiedToEnd { + justify-content: flex-end; + } + + .isToolbarJustifiedToSpaceBetween, + .isGroupJustifiedToSpaceBetween { + justify-content: space-between; + } + + .isToolbarDense, + .isGroupDense, + .isToolbarDense .group, + .isGroupDense .group { + gap: theme.$gap-dense; + } + + .isToolbarNowrap, + .isGroupNowrap { + flex-wrap: nowrap; + } + + .isToolbarNowrap > .item:not(.isItemFlexible), + .isGroupNowrap > .item:not(.isItemFlexible) { + flex: 0 1 auto; + } +} diff --git a/src/components/Toolbar/Toolbar.scss b/src/components/Toolbar/Toolbar.scss deleted file mode 100644 index 207dde29..00000000 --- a/src/components/Toolbar/Toolbar.scss +++ /dev/null @@ -1,83 +0,0 @@ -// 1. Get rid of unwanted spacing of inline elements by invocation of flex layout. - -@use "../../styles/tools/spacing"; -@use "theme"; - -.toolbar, -.group { - display: flex; - flex-wrap: wrap; - gap: theme.$gap; -} - -.toolbar { - @include spacing.bottom(layouts); -} - -.item { - display: flex; // 1. - flex: none; - flex-direction: column; // 1. -} - -.isItemFlexible { - flex: 1; - min-width: 0; -} - -.isToolbarAlignedToTop, -.isGroupAlignedToTop { - align-items: flex-start; -} - -.isToolbarAlignedToMiddle, -.isGroupAlignedToMiddle { - align-items: center; -} - -.isToolbarAlignedToBottom, -.isGroupAlignedToBottom { - align-items: flex-end; -} - -.isToolbarAlignedToBaseline, -.isGroupAlignedToBaseline { - align-items: baseline; -} - -.isToolbarJustifiedToStart, -.isGroupJustifiedToStart { - justify-content: flex-start; -} - -.isToolbarJustifiedToCenter, -.isGroupJustifiedToCenter { - justify-content: center; -} - -.isToolbarJustifiedToEnd, -.isGroupJustifiedToEnd { - justify-content: flex-end; -} - -.isToolbarJustifiedToSpaceBetween, -.isGroupJustifiedToSpaceBetween { - justify-content: space-between; -} - -.isToolbarDense, -.isGroupDense, -.isToolbarDense .group, -.isGroupDense .group { - gap: theme.$gap-dense; -} - -.isToolbarNowrap, -.isGroupNowrap { - flex-wrap: nowrap; -} - -.isToolbarNowrap > .item:not(.isItemFlexible), -.isGroupNowrap > .item:not(.isItemFlexible) { - flex: 0 1 auto; -} diff --git a/src/components/Toolbar/ToolbarGroup.jsx b/src/components/Toolbar/ToolbarGroup.jsx index 17944247..2f10a7af 100644 --- a/src/components/Toolbar/ToolbarGroup.jsx +++ b/src/components/Toolbar/ToolbarGroup.jsx @@ -5,7 +5,7 @@ import { transferProps } from '../_helpers/transferProps'; import { classNames } from '../../utils/classNames'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; import { getAlignClassName } from './_helpers/getAlignClassName'; -import styles from './Toolbar.scss'; +import styles from './Toolbar.module.scss'; export const ToolbarGroup = ({ align, diff --git a/src/components/Toolbar/ToolbarItem.jsx b/src/components/Toolbar/ToolbarItem.jsx index 98fcd6b1..88a500dd 100644 --- a/src/components/Toolbar/ToolbarItem.jsx +++ b/src/components/Toolbar/ToolbarItem.jsx @@ -4,7 +4,7 @@ import { transferProps } from '../_helpers/transferProps'; import { classNames } from '../../utils/classNames'; import { withGlobalProps } from '../../provider'; import { isChildrenEmpty } from '../_helpers/isChildrenEmpty'; -import styles from './Toolbar.scss'; +import styles from './Toolbar.module.scss'; export const ToolbarItem = ({ children, diff --git a/src/docs/contribute/css.md b/src/docs/contribute/css.md index aa770bf5..7cb9a025 100644 --- a/src/docs/contribute/css.md +++ b/src/docs/contribute/css.md @@ -56,10 +56,10 @@ There are three simple rules to follow when organizing React UI CSS: ├── * ├── ├── … - ├── _settings.scss Component's non-themeable Sass variables - ├── _theme.scss Component's Sass interface to its CSS custom properties in `theme.scss` - ├── _tools.scss Component's Sass mixins and functions - ├── Component.scss Component's main stylesheet + ├── _settings.scss Component's non-themeable Sass variables + ├── _theme.scss Component's Sass interface to its CSS custom properties in `theme.scss` + ├── _tools.scss Component's Sass mixins and functions + ├── Component.module.scss Component's main stylesheet loaded as CSS Module └── … ├── … ├── styles Partials for top-level Sass endpoints and shared styles @@ -77,11 +77,35 @@ There are three simple rules to follow when organizing React UI CSS: └── theme.scss Default theme, a collection of hundreds of CSS custom properties ``` +### Cascade Layers + +React UI CSS is organized into [cascade layers], each with its own specificity +level. The layers are as follows: + +1. `@layer theme` — a collection of hundreds of [CSS custom properties] that + define the look and feel of your UI. +2. `@layer foundation` — mandatory ground-zero CSS for components and other + styling. Includes sublayers like `@layer foundation.generic` and + `@layer foundation.elements`. +3. `@layer helpers` — small styling abstractions that can be used across the + whole UI. +4. `@layer components` — component styles are written as CSS modules which + output into this layer. Also, each component has its own cascade layer, e.g. + `@layer components.modal`. +5. `@layer utilities` — tiny classes to control selected CSS properties, + forcing them with `!important`. + +Any custom CSS can be added to the end of the cascade, but it's recommended to +use any of the existing layers to keep the CSS organized. + +👉 With `!important` styles, layered styles take precedence over unlayered +styles. + ## CSS Modules -React UI leverages [CSS modules] (not to be confused with [modular CSS -specification] of the same name) to take advantage of writing native CSS -(meaning “not JSS or CSS in JS”). Together with +For components, React UI leverages [CSS modules] (not to be confused with +[modular CSS specification] of the same name) to take advantage of writing +native CSS (meaning “not JSS or CSS in JS”). Together with [Sass](#preprocessing-with-sass), CSS modules represent flexibility and popular programming features needed to author modern stylesheets perfectly familiar to traditional CSS developers. @@ -109,7 +133,7 @@ For example, this JSX: … with this SCSS: ```scss -// Button.scss +// Button.module.scss .root { // … @@ -130,23 +154,16 @@ For example, this JSX: … produces following CSS class names: -- `Button__root__2yVxr5IZ` -- `Button__beforeLabel__1rrmrrWj` -- `Button__afterLabel__38eMTilM` -- `Button__label__23iTNlfS` +- `Button-module__root__2yVxr5IZ` +- `Button-module__beforeLabel__1rrmrrWj` +- `Button-module__afterLabel__38eMTilM` +- `Button-module__label__23iTNlfS` Resulting CSS class names are both unique and human-readable at the same time which is convenient for development. Class names are further shortened and obfuscated for production environments. -### Helpers and Utilities - -There are also global helper and utility classes (both documented as CSS Helpers -for the sake of comprehensibility for non-CSS guys) that can be used by -developers and thus remain unaltered by CSS modules. For example, -`:global(.display-block)` selector produces `display-block` CSS class. - -## Class Naming Rules +### Class Naming Rules Following rules make it clear both in JSX and CSS what is affected by a CSS class. @@ -200,6 +217,16 @@ There are three kinds of custom properties used: other custom property types. Refer to the [theming overview] to learn how their names are created. +## Helpers and Utilities + +There are also global helper and utility classes (both documented as CSS Helpers +for the sake of comprehensibility for non-CSS guys) that can be used by +developers and thus remain unaltered by CSS modules. + +### Class Naming Rules + +Class names must use kebab-case notation to be usable in HTML context. + ## Preprocessing with Sass All React UI CSS source is written in SCSS syntax of [Sass] preprocessor. @@ -234,9 +261,9 @@ according to [Browserslist] configuration stored in `.browserslistrc`. [stylelint-config-visionapps-order]: https://github.com/visionappscz/stylelint-config-visionapps-order [stylelint-config-css-modules]: https://github.com/pascalduez/stylelint-config-css-modules [Web Components]: https://developer.mozilla.org/en-US/docs/Web/Web_Components -[ITCSS]: https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/ [foundation CSS layer]: /docs/getting-started/usage#foundation-css [foundation-css-source]: https://github.com/react-ui-org/react-ui/blob/master/src/foundation.scss +[cascade layers]: https://developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Cascade_layers [CSS modules]: https://github.com/css-modules/css-modules [modular CSS specification]: https://developer.mozilla.org/en-US/docs/Learn/CSS/First_steps/What_is_CSS#css_modules [modern browsers]: /docs/getting-started/browsers-and-devices diff --git a/src/docs/foundation/spacing.md b/src/docs/foundation/spacing.md index b81116b5..0eda76d2 100644 --- a/src/docs/foundation/spacing.md +++ b/src/docs/foundation/spacing.md @@ -40,27 +40,23 @@ For demonstration purposes, all elements that are direct descendants of live playgrounds in these docs are given a standard margin on all sides which suppresses default spacing behavior described above: -~~~markdown ```docoff-react-preview -

This paragraph will have standard playground margin an all sides.

-

This paragraph will have it too.

+

This paragraph will have standard playground margin an all sides.

+

This paragraph will have it too.

``` -~~~ Once wrapped in a `div`, all elements and components remain unaffected and have exactly the same margins as they would have in a real-world React UI project: -~~~markdown ```docoff-react-preview -
+

- This paragraph will have bottom margin of - --rui-dimension-space-bottom-base. + This paragraph will have bottom margin of + --rui-dimension-space-bottom-base.

- This paragraph is a last child of its parent and thus will have no bottom - margin. + This paragraph is a last child of its parent and thus will have no bottom + margin.

-
+
``` -~~~ diff --git a/src/docs/getting-started/usage.md b/src/docs/getting-started/usage.md index fbeb39b3..c9b1a238 100644 --- a/src/docs/getting-started/usage.md +++ b/src/docs/getting-started/usage.md @@ -28,28 +28,28 @@ performance). ## CSS -React UI honors [ITCSS][itcss] principles to make sure that its CSS code base -will work and perform well even in large scale. There are four CSS layers: - -1. **Theme:** a collection of hundreds of CSS custom properties that define the - look of your app. See [Theming][theming] for more. -2. **Foundation:** mandatory ground-zero CSS for React UI components. Includes - global resets and fixes rendering inconsistencies across browsers with - `normalize.css`. (Not to be confused with the Foundation CSS framework.) -3. **Components:** React UI components' styles. Components utilize [CSS modules] - to avoid class name conflicts and to keep the class names scoped. -4. **CSS helpers:** tiny CSS classes that can handle details like - [typography][typography], [spacing][spacing], [colors][colors], etc. Class - name notation is [inspired by Bootstrap][bootstrap-utilities], so if you are - familiar with Bootstrap, you will feel at home here. - -All layers are written in Sass and compiled to CSS. You can import them all in -a **ready-to-use CSS bundle** like this: +React UI styles are written in Sass and compiled to CSS. You can import them +in a **ready-to-use CSS bundle** like this: ```js import '@react-ui-org/react-ui/dist/react-ui.css'; ``` +Under the hood, there are several CSS layers: + +1. **Layers definition:** establish [CSS cascade layers]. +2. **Theme:** a collection of hundreds of [design tokens] that define the look + and feel of your app. See [Theming] for more. +3. **Foundation:** mandatory ground-zero CSS for React UI components. Includes + global resets and fixes rendering inconsistencies across browsers with + `normalize.css`. (Not to be confused with the Foundation CSS framework!) +4. **Components:** React UI components' styles. Components utilize [CSS modules] + to avoid class name conflicts and to keep the class names scoped. +5. **CSS helpers:** tiny CSS classes (helpers and utilities) that can handle + details like [typography], [spacing], [colors], etc. Class name notation is + [inspired by Bootstrap utilities][bootstrap-utilities], so if you are + familiar with Bootstrap, you will feel at home here. + ### Sass 👉 As of now, we don't provide a way to import the Sass files directly. @@ -67,7 +67,7 @@ import { Button } from '@react-ui-org/react-ui'; ### Controlled vs. Uncontrolled While you may find out some components are working for you as uncontrolled, we -currently support only [controlled components][controlled-components]. +currently support only [controlled components]. ## Full Example @@ -118,11 +118,12 @@ React UI is also available on CDN: 👉 Consider using a specific version instead of `latest` in production. -[itcss]: https://www.xfive.co/blog/itcss-scalable-maintainable-css-architecture/ -[theming]: /docs/customize/theming/overview -[controlled-components]: https://reactjs.org/docs/forms.html#controlled-components +[CSS cascade layers]: /docs/contribute/css#cascade-layers +[design tokens]: /docs/foundation/design-tokens +[Theming]: /docs/customize/theming/overview +[CSS modules]: /docs/contribute/css#css-modules [typography]: /docs/css-helpers/typography [spacing]: /docs/css-helpers/spacing [colors]: /docs/css-helpers/colors -[bootstrap-utilities]: https://getbootstrap.com/docs/5.1/utilities/ -[CSS modules]: https://github.com/css-modules/css-modules +[bootstrap-utilities]: https://getbootstrap.com/docs/5.3/utilities/api/ +[controlled components]: https://reactjs.org/docs/forms.html#controlled-components diff --git a/src/foundation.scss b/src/foundation.scss index 0fd9e967..c0a8fed7 100644 --- a/src/foundation.scss +++ b/src/foundation.scss @@ -1,28 +1,33 @@ // Mandatory themeable CSS layer to prepare ground for components. -// Structured according to ITCSS methodology, ie. most importantly in ascending specificity. + +@use "sass:meta"; // -// 1. Generic -// ========== +// Generic +// ======= // // Ground-zero styles. -@use "styles/generic/box-sizing"; -@use "normalize.css/normalize.css"; -@use "styles/generic/focus"; -@use "styles/generic/forms"; -@use "styles/generic/reset"; -@use "styles/generic/shared"; +@layer foundation.generic { + @include meta.load-css("styles/generic/box-sizing"); + @include meta.load-css("normalize.css/normalize.css"); + @include meta.load-css("styles/generic/focus"); + @include meta.load-css("styles/generic/forms"); + @include meta.load-css("styles/generic/reset"); + @include meta.load-css("styles/generic/shared"); +} // -// 2. Elements -// =========== +// Elements +// ======== // // Unclassed HTML elements (type selectors). -@use "styles/elements/code"; -@use "styles/elements/links"; -@use "styles/elements/lists"; -@use "styles/elements/page"; -@use "styles/elements/rulers"; -@use "styles/elements/small"; +@layer foundation.elements { + @include meta.load-css("styles/elements/code"); + @include meta.load-css("styles/elements/links"); + @include meta.load-css("styles/elements/lists"); + @include meta.load-css("styles/elements/page"); + @include meta.load-css("styles/elements/rulers"); + @include meta.load-css("styles/elements/small"); +} diff --git a/src/helpers.scss b/src/helpers.scss index 00d6128c..7910ebf7 100644 --- a/src/helpers.scss +++ b/src/helpers.scss @@ -1,22 +1,26 @@ // Optional layer with helper CSS classes to easily adjust visual details. -// Structured according to ITCSS methodology, ie. most importantly in ascending specificity. -// This file should be imported as the very last of your stylesheets. + +@use "sass:meta"; // -// 1. Helpers -// ========== +// Helpers +// ======= // // General purpose helpers for common situations. They can compose multiple CSS rules to do a bit // more complicated tasks. -@use "styles/helpers/animation"; +@layer helpers { + @include meta.load-css("styles/helpers/animation"); +} // -// 2. Utilities -// ============ +// Utilities +// ========= // // Utility classes to tweak small details like typography, margins or padding. They do just one // thing: they set a single CSS rule and use the otherwise disallowed `!important` to enforce it. // Also they are often responsive (can be adjusted for individual breakpoints). -@use "styles/utilities"; +@layer utilities { + @include meta.load-css("styles/utilities"); +} diff --git a/src/index.js b/src/index.js index 44f73d0c..921bc8e1 100644 --- a/src/index.js +++ b/src/index.js @@ -1,9 +1,7 @@ // Global definitions -// These need to be imported here to be placed in the distribution CSS file. -// Component styles are imported in the component files themselves. -import './theme.scss'; -import './foundation.scss'; -import './helpers.scss'; +// The styles need to be imported here to be placed in the distribution CSS file. +// Component styles are imported in the components themselves below. +import './index.scss'; // Components export { Alert } from './components/Alert'; diff --git a/src/index.scss b/src/index.scss new file mode 100644 index 00000000..a3a08717 --- /dev/null +++ b/src/index.scss @@ -0,0 +1,7 @@ +// First establish cascade layers: +@forward "layers"; // ⚠️ Must come first for the cascade layers to work as intended. + +// Then import the rest of the files, already organized by layer: +@forward "theme"; +@forward "foundation"; +@forward "helpers"; diff --git a/src/layers.scss b/src/layers.scss new file mode 100644 index 00000000..e6cd23ae --- /dev/null +++ b/src/layers.scss @@ -0,0 +1,4 @@ +// Establish CSS cascade layers. +// ⚠️ WARNING: This file must be called before other React UI styles for the cascade layers to work as intended. + +@layer theme, foundation, helpers, components, utilities; diff --git a/src/styles/helpers/_animation.scss b/src/styles/helpers/_animation.scss index 25b2dd98..4bd6956d 100644 --- a/src/styles/helpers/_animation.scss +++ b/src/styles/helpers/_animation.scss @@ -12,10 +12,10 @@ $_spin-easing: cubic-bezier(0.31, 0.3, 0.34, -0.17); } } -:global(.animation-spin-clockwise) { +.animation-spin-clockwise { animation: spin $_spin-duration $_spin-easing infinite; } -:global(.animation-spin-counterclockwise) { +.animation-spin-counterclockwise { animation: spin $_spin-duration $_spin-easing infinite reverse; } diff --git a/src/styles/tools/_utilities.scss b/src/styles/tools/_utilities.scss index d60bb54f..a64a7676 100644 --- a/src/styles/tools/_utilities.scss +++ b/src/styles/tools/_utilities.scss @@ -20,7 +20,7 @@ // Don't prefix if value key is null (e.g. with shadow class) $property-class-modifier: if($key, "-" + $key, ""); - :global(.#{$property-class + $infix + $property-class-modifier}) { + .#{$property-class + $infix + $property-class-modifier} { @each $property in $properties { // stylelint-disable-next-line declaration-no-important #{$property}: $value !important; diff --git a/src/theme.scss b/src/theme.scss index 57aacdaf..ae0ebb51 100644 --- a/src/theme.scss +++ b/src/theme.scss @@ -4,1042 +4,1044 @@ @use "styles/theme-constants/colors"; @use "styles/theme-constants/svg"; -:root, -:host { - // ============================================================================================ // - // GLOBAL TOKENS // - // ============================================================================================ // - - // - // Dimensions - // ========== - - // Borders - --rui-dimension-border-width-1: 1px; - - // Breakpoints - // - // ⚠️ Breakpoints are read-only in CSS. Custom properties cannot be used within media queries - // since media query is not a property. - // https://www.w3.org/TR/css-variables-1/#using-variables - --rui-dimension-breakpoint-xs: #{breakpoints.$xs}; - --rui-dimension-breakpoint-sm: #{breakpoints.$sm}; - --rui-dimension-breakpoint-md: #{breakpoints.$md}; - --rui-dimension-breakpoint-lg: #{breakpoints.$lg}; - --rui-dimension-breakpoint-xl: #{breakpoints.$xl}; - --rui-dimension-breakpoint-x2l: #{breakpoints.$x2l}; - --rui-dimension-breakpoint-x3l: #{breakpoints.$x3l}; - - // Radii - --rui-dimension-radius-1: 0.125rem; - --rui-dimension-radius-2: 0.25rem; - - // Spacing - --rui-dimension-space-0: 0; - --rui-dimension-space-1: 0.25rem; - --rui-dimension-space-2: 0.5rem; - --rui-dimension-space-3: 0.75rem; - --rui-dimension-space-4: 1rem; - --rui-dimension-space-5: 1.5rem; - --rui-dimension-space-6: 2rem; - --rui-dimension-space-7: 2.5rem; - - // - // Font Families - // ============= - - --rui-font-family-base: "Titillium Web", helvetica, roboto, arial, sans-serif; - --rui-font-family-monospace: - "SFMono-Regular", - "Menlo", - "Monaco", - "Consolas", - "Liberation Mono", - "Courier New", - monospace; - - // - // Font Weights - // ============ - - --rui-font-weight-base: 400; - --rui-font-weight-light: 300; - --rui-font-weight-bold: 700; - - // - // Ratios - // ====== - - --rui-ratio-opacity-medium: 0.5; - - // - // Shadows - // ======= - - --rui-shadow-1: 0 0.01rem 0.65rem -0.1rem rgb(0 0 0 / 30%); - --rui-shadow-2: 0.2rem 0.25rem 1.2rem -0.1rem rgb(0 0 0 / 15%); - - // - // Other - // ===== - - // ⚠️ Non-standard token types! - // The DTF specification is still in the draft status, and the following token types have proven necessary. - // - // To be honest, some of these tokens are NOT context agnostic as required by the global tokens category. - // These will be probably superseded by semantic typography styles in the future. - - // Font sizes - --rui-font-size-base: 100%; - --rui-font-size-small: 0.889rem; - --rui-font-size-smaller: 0.75rem; - --rui-font-size-code: 85%; - - // Modular scale ratio: 1.125 / 8:9 / major second - --rui-font-size-1: 1rem; - --rui-font-size-2: 1.125rem; - --rui-font-size-3: 1.266rem; - --rui-font-size-4: 1.424rem; - --rui-font-size-5: 1.602rem; - --rui-font-size-6: 1.802rem; - - // Line heights - --rui-line-height-base: 1.5; - --rui-line-height-small: 1.25; - - // Text decorations - --rui-text-decoration-link: none; - --rui-text-decoration-link-hover: underline; - --rui-text-decoration-link-active: underline; - - // List styles - --rui-list-style-unordered: square; - - // Cursors - --rui-cursor-not-allowed: not-allowed; - - // ============================================================================================ // - // SEMANTIC TOKENS // - // ============================================================================================ // - - // - // Borders - // ======= - - --rui-border-focus-ring: var(--rui-dimension-space-1) solid #{colors.$focus}; - - // - // Colors - // ====== - - // 👉 Actual color values are stored in separate SCSS so they can be generated programmatically. - - // Text colors - --rui-color-text-primary: #{colors.$black}; - --rui-color-text-primary-disabled: #{colors.$gray-300}; - --rui-color-text-secondary: #{colors.$gray-500}; - --rui-color-text-secondary-disabled: #{colors.$gray-300}; - --rui-color-text-link: #{colors.$note}; - --rui-color-text-link-hover: #{colors.$note-dark}; - --rui-color-text-link-active: #{colors.$note-darker}; - - // Action colors - --rui-color-action-primary: #{colors.$primary}; - --rui-color-action-primary-hover: #{colors.$primary-dark}; - --rui-color-action-primary-active: #{colors.$primary-darker}; - --rui-color-action-on-primary: #{colors.$on-primary}; - --rui-color-action-secondary: #{colors.$secondary}; - --rui-color-action-secondary-hover: #{colors.$secondary-dark}; - --rui-color-action-secondary-active: #{colors.$secondary-darker}; - --rui-color-action-on-secondary: #{colors.$on-secondary}; - --rui-color-action-selected: #{colors.$selected}; - --rui-color-action-selected-hover: #{colors.$selected-dark}; - --rui-color-action-selected-active: #{colors.$selected-darker}; - --rui-color-action-on-selected: #{colors.$on-selected}; - - // Feedback colors - --rui-color-feedback-success: #{colors.$success}; - --rui-color-feedback-success-hover: #{colors.$success-dark}; - --rui-color-feedback-success-active: #{colors.$success-darker}; - --rui-color-feedback-on-success: #{colors.$on-success}; - --rui-color-feedback-warning: #{colors.$warning}; - --rui-color-feedback-warning-hover: #{colors.$warning-dark}; - --rui-color-feedback-warning-active: #{colors.$warning-darker}; - --rui-color-feedback-on-warning: #{colors.$on-warning}; - --rui-color-feedback-danger: #{colors.$danger}; - --rui-color-feedback-danger-hover: #{colors.$danger-dark}; - --rui-color-feedback-danger-active: #{colors.$danger-darker}; - --rui-color-feedback-on-danger: #{colors.$on-danger}; - --rui-color-feedback-help: #{colors.$help}; - --rui-color-feedback-help-hover: #{colors.$help-dark}; - --rui-color-feedback-help-active: #{colors.$help-darker}; - --rui-color-feedback-on-help: #{colors.$on-help}; - --rui-color-feedback-info: #{colors.$info}; - --rui-color-feedback-info-hover: #{colors.$info-dark}; - --rui-color-feedback-info-active: #{colors.$info-darker}; - --rui-color-feedback-on-info: #{colors.$on-info}; - --rui-color-feedback-note: #{colors.$note}; - --rui-color-feedback-note-hover: #{colors.$note-dark}; - --rui-color-feedback-note-active: #{colors.$note-darker}; - --rui-color-feedback-on-note: #{colors.$on-note}; - - // Neutral colors - --rui-color-neutral-light: #{colors.$white}; - --rui-color-neutral-light-hover: #{colors.$gray-50}; - --rui-color-neutral-light-active: #{colors.$gray-100}; - --rui-color-neutral-on-light: #{colors.$gray-700}; - --rui-color-neutral-dark: #{colors.$gray-700}; - --rui-color-neutral-dark-hover: #{colors.$gray-800}; - --rui-color-neutral-dark-active: #{colors.$gray-900}; - --rui-color-neutral-on-dark: #{colors.$white}; - - // Background colors - --rui-color-background-base: #{colors.$gray-50}; - --rui-color-background-layer-1: #{colors.$white}; - --rui-color-background-layer-2: #{colors.$white}; - --rui-color-background-basic: #{colors.$white}; - --rui-color-background-disabled: #{colors.$gray-50}; - --rui-color-background-interactive: #{colors.$transparent}; - --rui-color-background-interactive-hover: #{colors.$gray-50}; - --rui-color-background-interactive-active: #{colors.$gray-100}; - --rui-color-background-primary: #{colors.$primary-light}; - --rui-color-background-secondary: #{colors.$secondary-light}; - --rui-color-background-selected: #{colors.$selected-light}; - --rui-color-background-success: #{colors.$success-light}; - --rui-color-background-warning: #{colors.$warning-light}; - --rui-color-background-danger: #{colors.$danger-light}; - --rui-color-background-help: #{colors.$help-light}; - --rui-color-background-info: #{colors.$info-light}; - --rui-color-background-note: #{colors.$note-light}; - --rui-color-background-light: #{colors.$gray-100}; - --rui-color-background-dark: #{colors.$gray-600}; - - // Border colors - --rui-color-border-primary: #{colors.$gray-200}; - --rui-color-border-primary-hover: #{colors.$gray-500}; - --rui-color-border-primary-active: #{colors.$selected-darker}; - --rui-color-border-secondary: #{colors.$gray-100}; - - // - // Dimensions - // ========== - - // Accessibility - --rui-dimension-focus-ring-offset: var(--rui-dimension-border-width-1); - --rui-dimension-tap-target-size: var(--rui-dimension-space-7); - - // Shared bottom spacings - --rui-dimension-space-bottom-base: var(--rui-dimension-space-5); - --rui-dimension-space-bottom-headings: var(--rui-dimension-space-5); - --rui-dimension-space-bottom-layouts: var(--rui-dimension-space-5); - - // - // Ratios - // ====== - - --rui-ratio-disabled-opacity: var(--rui-ratio-opacity-medium); - - // - // Shadows - // ======= - - // 1. Use `initial`, `revert` or `unset` to keep the original box shadow of the component. - - --rui-shadow-layer-1: var(--rui-shadow-1); - --rui-shadow-layer-2: var(--rui-shadow-2); - --rui-shadow-focus-ring: initial; // 1. - - // ============================================================================================ // - // COMPONENT TOKENS // - // ============================================================================================ // - - // - // Alert - // ===== - - // Alert: common properties - --rui-Alert__padding: var(--rui-dimension-space-3); - --rui-Alert__font-weight: var(--rui-font-weight-base); - --rui-Alert__border-width: var(--rui-dimension-border-width-1); - --rui-Alert__border-radius: var(--rui-dimension-radius-2); - --rui-Alert__emphasis__font-weight: var(--rui-font-weight-bold); - --rui-Alert__stripe__width: var(--rui-dimension-border-width-1); - - // Alert: variant: success - --rui-Alert--success__color: var(--rui-color-text-primary); - --rui-Alert--success__foreground-color: var(--rui-color-feedback-success); - --rui-Alert--success__background-color: var(--rui-color-background-success); - - // Alert: variant: warning - --rui-Alert--warning__color: var(--rui-color-text-primary); - --rui-Alert--warning__foreground-color: var(--rui-color-feedback-warning); - --rui-Alert--warning__background-color: var(--rui-color-background-warning); - - // Alert: variant: danger - --rui-Alert--danger__color: var(--rui-color-text-primary); - --rui-Alert--danger__foreground-color: var(--rui-color-feedback-danger); - --rui-Alert--danger__background-color: var(--rui-color-background-danger); - - // Alert: variant: info - --rui-Alert--info__color: var(--rui-color-text-primary); - --rui-Alert--info__foreground-color: var(--rui-color-feedback-info); - --rui-Alert--info__background-color: var(--rui-color-background-info); - - // Alert: variant: help - --rui-Alert--help__color: var(--rui-color-text-primary); - --rui-Alert--help__foreground-color: var(--rui-color-feedback-help); - --rui-Alert--help__background-color: var(--rui-color-background-help); - - // Alert: variant: note - --rui-Alert--note__color: var(--rui-color-text-primary); - --rui-Alert--note__foreground-color: var(--rui-color-feedback-note); - --rui-Alert--note__background-color: var(--rui-color-background-note); - - // Alert: variant: light - --rui-Alert--light__color: var(--rui-color-neutral-on-light); - --rui-Alert--light__foreground-color: var(--rui-color-neutral-on-light); - --rui-Alert--light__background-color: var(--rui-color-background-light); - - // Alert: variant: dark - --rui-Alert--dark__color: var(--rui-color-neutral-on-dark); - --rui-Alert--dark__foreground-color: var(--rui-color-neutral-on-dark); - --rui-Alert--dark__background-color: var(--rui-color-background-dark); - - // - // Button - // ====== - - // Buttons: common properties - --rui-Button__font-weight: var(--rui-font-weight-base); - --rui-Button__letter-spacing: 0; - --rui-Button__text-transform: none; - --rui-Button__border-width: var(--rui-dimension-border-width-1); - --rui-Button__border-radius: var(--rui-dimension-radius-2); - --rui-Button--disabled__opacity: var(--rui-ratio-disabled-opacity); - --rui-Button--disabled__cursor: var(--rui-cursor-not-allowed); - --rui-Button--feedback__opacity: 1; - --rui-Button--feedback__cursor: var(--rui-cursor-not-allowed); - - // Buttons: filled priority - - // Buttons: filled priority: primary variant - --rui-Button--filled--primary--default__color: var(--rui-color-action-on-primary); - --rui-Button--filled--primary--default__border-color: var(--rui-color-action-primary); - --rui-Button--filled--primary--default__background: var(--rui-color-action-primary); - --rui-Button--filled--primary--default__box-shadow: none; - --rui-Button--filled--primary--hover__color: var(--rui-color-action-on-primary); - --rui-Button--filled--primary--hover__border-color: var(--rui-color-action-primary-hover); - --rui-Button--filled--primary--hover__background: var(--rui-color-action-primary-hover); - --rui-Button--filled--primary--hover__box-shadow: none; - --rui-Button--filled--primary--active__color: var(--rui-color-action-on-primary); - --rui-Button--filled--primary--active__border-color: var(--rui-color-action-primary-active); - --rui-Button--filled--primary--active__background: var(--rui-color-action-primary-active); - --rui-Button--filled--primary--active__box-shadow: none; - - // Buttons: filled priority: secondary variant - --rui-Button--filled--secondary--default__color: var(--rui-color-action-on-secondary); - --rui-Button--filled--secondary--default__border-color: var(--rui-color-action-secondary); - --rui-Button--filled--secondary--default__background: var(--rui-color-action-secondary); - --rui-Button--filled--secondary--default__box-shadow: none; - --rui-Button--filled--secondary--hover__color: var(--rui-color-action-on-secondary); - --rui-Button--filled--secondary--hover__border-color: var(--rui-color-action-secondary-hover); - --rui-Button--filled--secondary--hover__background: var(--rui-color-action-secondary-hover); - --rui-Button--filled--secondary--hover__box-shadow: none; - --rui-Button--filled--secondary--active__color: var(--rui-color-action-on-secondary); - --rui-Button--filled--secondary--active__border-color: var(--rui-color-action-secondary-active); - --rui-Button--filled--secondary--active__background: var(--rui-color-action-secondary-active); - --rui-Button--filled--secondary--active__box-shadow: none; - - // Buttons: filled priority: selected variant - --rui-Button--filled--selected--default__color: var(--rui-color-action-on-selected); - --rui-Button--filled--selected--default__border-color: var(--rui-color-action-selected); - --rui-Button--filled--selected--default__background: var(--rui-color-action-selected); - --rui-Button--filled--selected--default__box-shadow: none; - --rui-Button--filled--selected--hover__color: var(--rui-color-action-on-selected); - --rui-Button--filled--selected--hover__border-color: var(--rui-color-action-selected-hover); - --rui-Button--filled--selected--hover__background: var(--rui-color-action-selected-hover); - --rui-Button--filled--selected--hover__box-shadow: none; - --rui-Button--filled--selected--active__color: var(--rui-color-action-on-selected); - --rui-Button--filled--selected--active__border-color: var(--rui-color-action-selected-active); - --rui-Button--filled--selected--active__background: var(--rui-color-action-selected-active); - --rui-Button--filled--selected--active__box-shadow: none; - - // Buttons: filled priority: success variant - --rui-Button--filled--success--default__color: var(--rui-color-feedback-on-success); - --rui-Button--filled--success--default__border-color: var(--rui-color-feedback-success); - --rui-Button--filled--success--default__background: var(--rui-color-feedback-success); - --rui-Button--filled--success--default__box-shadow: none; - --rui-Button--filled--success--hover__color: var(--rui-color-feedback-on-success); - --rui-Button--filled--success--hover__border-color: var(--rui-color-feedback-success-hover); - --rui-Button--filled--success--hover__background: var(--rui-color-feedback-success-hover); - --rui-Button--filled--success--hover__box-shadow: none; - --rui-Button--filled--success--active__color: var(--rui-color-feedback-on-success); - --rui-Button--filled--success--active__border-color: var(--rui-color-feedback-success-active); - --rui-Button--filled--success--active__background: var(--rui-color-feedback-success-active); - --rui-Button--filled--success--active__box-shadow: none; - - // Buttons: filled priority: warning variant - --rui-Button--filled--warning--default__color: var(--rui-color-feedback-on-warning); - --rui-Button--filled--warning--default__border-color: var(--rui-color-feedback-warning); - --rui-Button--filled--warning--default__background: var(--rui-color-feedback-warning); - --rui-Button--filled--warning--default__box-shadow: none; - --rui-Button--filled--warning--hover__color: var(--rui-color-feedback-on-warning); - --rui-Button--filled--warning--hover__border-color: var(--rui-color-feedback-warning-hover); - --rui-Button--filled--warning--hover__background: var(--rui-color-feedback-warning-hover); - --rui-Button--filled--warning--hover__box-shadow: none; - --rui-Button--filled--warning--active__color: var(--rui-color-feedback-on-warning); - --rui-Button--filled--warning--active__border-color: var(--rui-color-feedback-warning-active); - --rui-Button--filled--warning--active__background: var(--rui-color-feedback-warning-active); - --rui-Button--filled--warning--active__box-shadow: none; - - // Buttons: filled priority: danger variant - --rui-Button--filled--danger--default__color: var(--rui-color-feedback-on-danger); - --rui-Button--filled--danger--default__border-color: var(--rui-color-feedback-danger); - --rui-Button--filled--danger--default__background: var(--rui-color-feedback-danger); - --rui-Button--filled--danger--default__box-shadow: none; - --rui-Button--filled--danger--hover__color: var(--rui-color-feedback-on-danger); - --rui-Button--filled--danger--hover__border-color: var(--rui-color-feedback-danger-hover); - --rui-Button--filled--danger--hover__background: var(--rui-color-feedback-danger-hover); - --rui-Button--filled--danger--hover__box-shadow: none; - --rui-Button--filled--danger--active__color: var(--rui-color-feedback-on-danger); - --rui-Button--filled--danger--active__border-color: var(--rui-color-feedback-danger-active); - --rui-Button--filled--danger--active__background: var(--rui-color-feedback-danger-active); - --rui-Button--filled--danger--active__box-shadow: none; - - // Buttons: filled priority: help variant - --rui-Button--filled--help--default__color: var(--rui-color-feedback-on-help); - --rui-Button--filled--help--default__border-color: var(--rui-color-feedback-help); - --rui-Button--filled--help--default__background: var(--rui-color-feedback-help); - --rui-Button--filled--help--default__box-shadow: none; - --rui-Button--filled--help--hover__color: var(--rui-color-feedback-on-help); - --rui-Button--filled--help--hover__border-color: var(--rui-color-feedback-help-hover); - --rui-Button--filled--help--hover__background: var(--rui-color-feedback-help-hover); - --rui-Button--filled--help--hover__box-shadow: none; - --rui-Button--filled--help--active__color: var(--rui-color-feedback-on-help); - --rui-Button--filled--help--active__border-color: var(--rui-color-feedback-help-active); - --rui-Button--filled--help--active__background: var(--rui-color-feedback-help-active); - --rui-Button--filled--help--active__box-shadow: none; - - // Buttons: filled priority: info variant - --rui-Button--filled--info--default__color: var(--rui-color-feedback-on-info); - --rui-Button--filled--info--default__border-color: var(--rui-color-feedback-info); - --rui-Button--filled--info--default__background: var(--rui-color-feedback-info); - --rui-Button--filled--info--default__box-shadow: none; - --rui-Button--filled--info--hover__color: var(--rui-color-feedback-on-info); - --rui-Button--filled--info--hover__border-color: var(--rui-color-feedback-info-hover); - --rui-Button--filled--info--hover__background: var(--rui-color-feedback-info-hover); - --rui-Button--filled--info--hover__box-shadow: none; - --rui-Button--filled--info--active__color: var(--rui-color-feedback-on-info); - --rui-Button--filled--info--active__border-color: var(--rui-color-feedback-info-active); - --rui-Button--filled--info--active__background: var(--rui-color-feedback-info-active); - --rui-Button--filled--info--active__box-shadow: none; - - // Buttons: filled priority: note variant - --rui-Button--filled--note--default__color: var(--rui-color-feedback-on-note); - --rui-Button--filled--note--default__border-color: var(--rui-color-feedback-note); - --rui-Button--filled--note--default__background: var(--rui-color-feedback-note); - --rui-Button--filled--note--default__box-shadow: none; - --rui-Button--filled--note--hover__color: var(--rui-color-feedback-on-note); - --rui-Button--filled--note--hover__border-color: var(--rui-color-feedback-note-hover); - --rui-Button--filled--note--hover__background: var(--rui-color-feedback-note-hover); - --rui-Button--filled--note--hover__box-shadow: none; - --rui-Button--filled--note--active__color: var(--rui-color-feedback-on-note); - --rui-Button--filled--note--active__border-color: var(--rui-color-feedback-note-active); - --rui-Button--filled--note--active__background: var(--rui-color-feedback-note-active); - --rui-Button--filled--note--active__box-shadow: none; - - // Buttons: filled priority: light variant - --rui-Button--filled--light--default__color: var(--rui-color-neutral-on-light); - --rui-Button--filled--light--default__border-color: var(--rui-color-neutral-light); - --rui-Button--filled--light--default__background: var(--rui-color-neutral-light); - --rui-Button--filled--light--default__box-shadow: none; - --rui-Button--filled--light--hover__color: var(--rui-color-neutral-on-light); - --rui-Button--filled--light--hover__border-color: var(--rui-color-neutral-light-hover); - --rui-Button--filled--light--hover__background: var(--rui-color-neutral-light-hover); - --rui-Button--filled--light--hover__box-shadow: none; - --rui-Button--filled--light--active__color: var(--rui-color-neutral-on-light); - --rui-Button--filled--light--active__border-color: var(--rui-color-neutral-light-active); - --rui-Button--filled--light--active__background: var(--rui-color-neutral-light-active); - --rui-Button--filled--light--active__box-shadow: none; - - // Buttons: filled priority: dark variant - --rui-Button--filled--dark--default__color: var(--rui-color-neutral-on-dark); - --rui-Button--filled--dark--default__border-color: var(--rui-color-neutral-dark); - --rui-Button--filled--dark--default__background: var(--rui-color-neutral-dark); - --rui-Button--filled--dark--default__box-shadow: none; - --rui-Button--filled--dark--hover__color: var(--rui-color-neutral-on-dark); - --rui-Button--filled--dark--hover__border-color: var(--rui-color-neutral-dark-hover); - --rui-Button--filled--dark--hover__background: var(--rui-color-neutral-dark-hover); - --rui-Button--filled--dark--hover__box-shadow: none; - --rui-Button--filled--dark--active__color: var(--rui-color-neutral-on-dark); - --rui-Button--filled--dark--active__border-color: var(--rui-color-neutral-dark-active); - --rui-Button--filled--dark--active__background: var(--rui-color-neutral-dark-active); - --rui-Button--filled--dark--active__box-shadow: none; - - // Buttons: outline priority - - // Buttons: outline priority: primary variant - --rui-Button--outline--primary--default__color: var(--rui-color-action-primary); - --rui-Button--outline--primary--default__border-color: var(--rui-color-action-primary); - --rui-Button--outline--primary--default__background: transparent; - --rui-Button--outline--primary--hover__color: var(--rui-color-action-on-primary); - --rui-Button--outline--primary--hover__border-color: var(--rui-color-action-primary-hover); - --rui-Button--outline--primary--hover__background: var(--rui-color-action-primary-hover); - --rui-Button--outline--primary--active__color: var(--rui-color-action-on-primary); - --rui-Button--outline--primary--active__border-color: var(--rui-color-action-primary-active); - --rui-Button--outline--primary--active__background: var(--rui-color-action-primary-active); - - // Buttons: outline priority: secondary variant - --rui-Button--outline--secondary--default__color: var(--rui-color-action-secondary); - --rui-Button--outline--secondary--default__border-color: var(--rui-color-action-secondary); - --rui-Button--outline--secondary--default__background: transparent; - --rui-Button--outline--secondary--hover__color: var(--rui-color-action-on-secondary); - --rui-Button--outline--secondary--hover__border-color: var(--rui-color-action-secondary-hover); - --rui-Button--outline--secondary--hover__background: var(--rui-color-action-secondary-hover); - --rui-Button--outline--secondary--active__color: var(--rui-color-action-on-secondary); - --rui-Button--outline--secondary--active__border-color: var(--rui-color-action-secondary-active); - --rui-Button--outline--secondary--active__background: var(--rui-color-action-secondary-active); - - // Buttons: outline priority: selected variant - --rui-Button--outline--selected--default__color: var(--rui-color-action-selected); - --rui-Button--outline--selected--default__border-color: var(--rui-color-action-selected); - --rui-Button--outline--selected--default__background: var(--rui-color-background-selected); - --rui-Button--outline--selected--hover__color: var(--rui-color-action-on-selected); - --rui-Button--outline--selected--hover__border-color: var(--rui-color-action-selected-hover); - --rui-Button--outline--selected--hover__background: var(--rui-color-action-selected-hover); - --rui-Button--outline--selected--active__color: var(--rui-color-action-on-selected); - --rui-Button--outline--selected--active__border-color: var(--rui-color-action-selected-active); - --rui-Button--outline--selected--active__background: var(--rui-color-action-selected-active); - - // Buttons: outline priority: success variant - --rui-Button--outline--success--default__color: var(--rui-color-feedback-success); - --rui-Button--outline--success--default__border-color: var(--rui-color-feedback-success); - --rui-Button--outline--success--default__background: transparent; - --rui-Button--outline--success--hover__color: var(--rui-color-feedback-on-success); - --rui-Button--outline--success--hover__border-color: var(--rui-color-feedback-success-hover); - --rui-Button--outline--success--hover__background: var(--rui-color-feedback-success-hover); - --rui-Button--outline--success--active__color: var(--rui-color-feedback-on-success); - --rui-Button--outline--success--active__border-color: var(--rui-color-feedback-success-active); - --rui-Button--outline--success--active__background: var(--rui-color-feedback-success-active); - - // Buttons: outline priority: warning variant - --rui-Button--outline--warning--default__color: var(--rui-color-feedback-warning); - --rui-Button--outline--warning--default__border-color: var(--rui-color-feedback-warning); - --rui-Button--outline--warning--default__background: transparent; - --rui-Button--outline--warning--hover__color: var(--rui-color-feedback-on-warning); - --rui-Button--outline--warning--hover__border-color: var(--rui-color-feedback-warning-hover); - --rui-Button--outline--warning--hover__background: var(--rui-color-feedback-warning-hover); - --rui-Button--outline--warning--active__color: var(--rui-color-feedback-on-warning); - --rui-Button--outline--warning--active__border-color: var(--rui-color-feedback-warning-active); - --rui-Button--outline--warning--active__background: var(--rui-color-feedback-warning-active); - - // Buttons: outline priority: danger variant - --rui-Button--outline--danger--default__color: var(--rui-color-feedback-danger); - --rui-Button--outline--danger--default__border-color: var(--rui-color-feedback-danger); - --rui-Button--outline--danger--default__background: transparent; - --rui-Button--outline--danger--hover__color: var(--rui-color-feedback-on-danger); - --rui-Button--outline--danger--hover__border-color: var(--rui-color-feedback-danger-hover); - --rui-Button--outline--danger--hover__background: var(--rui-color-feedback-danger-hover); - --rui-Button--outline--danger--active__color: var(--rui-color-feedback-on-danger); - --rui-Button--outline--danger--active__border-color: var(--rui-color-feedback-danger-active); - --rui-Button--outline--danger--active__background: var(--rui-color-feedback-danger-active); - - // Buttons: outline priority: help variant - --rui-Button--outline--help--default__color: var(--rui-color-feedback-help); - --rui-Button--outline--help--default__border-color: var(--rui-color-feedback-help); - --rui-Button--outline--help--default__background: transparent; - --rui-Button--outline--help--hover__color: var(--rui-color-feedback-on-help); - --rui-Button--outline--help--hover__border-color: var(--rui-color-feedback-help-hover); - --rui-Button--outline--help--hover__background: var(--rui-color-feedback-help-hover); - --rui-Button--outline--help--active__color: var(--rui-color-feedback-on-help); - --rui-Button--outline--help--active__border-color: var(--rui-color-feedback-help-active); - --rui-Button--outline--help--active__background: var(--rui-color-feedback-help-active); - - // Buttons: outline priority: info variant - --rui-Button--outline--info--default__color: var(--rui-color-feedback-info); - --rui-Button--outline--info--default__border-color: var(--rui-color-feedback-info); - --rui-Button--outline--info--default__background: transparent; - --rui-Button--outline--info--hover__color: var(--rui-color-feedback-on-info); - --rui-Button--outline--info--hover__border-color: var(--rui-color-feedback-info-hover); - --rui-Button--outline--info--hover__background: var(--rui-color-feedback-info-hover); - --rui-Button--outline--info--active__color: var(--rui-color-feedback-on-info); - --rui-Button--outline--info--active__border-color: var(--rui-color-feedback-info-active); - --rui-Button--outline--info--active__background: var(--rui-color-feedback-info-active); - - // Buttons: outline priority: note variant - --rui-Button--outline--note--default__color: var(--rui-color-feedback-note); - --rui-Button--outline--note--default__border-color: var(--rui-color-feedback-note); - --rui-Button--outline--note--default__background: transparent; - --rui-Button--outline--note--hover__color: var(--rui-color-feedback-on-note); - --rui-Button--outline--note--hover__border-color: var(--rui-color-feedback-note-hover); - --rui-Button--outline--note--hover__background: var(--rui-color-feedback-note-hover); - --rui-Button--outline--note--active__color: var(--rui-color-feedback-on-note); - --rui-Button--outline--note--active__border-color: var(--rui-color-feedback-note-active); - --rui-Button--outline--note--active__background: var(--rui-color-feedback-note-active); - - // Buttons: outline priority: light variant - --rui-Button--outline--light--default__color: var(--rui-color-neutral-light); - --rui-Button--outline--light--default__border-color: var(--rui-color-neutral-light); - --rui-Button--outline--light--default__background: transparent; - --rui-Button--outline--light--hover__color: var(--rui-color-neutral-on-light); - --rui-Button--outline--light--hover__border-color: var(--rui-color-neutral-light-hover); - --rui-Button--outline--light--hover__background: var(--rui-color-neutral-light-hover); - --rui-Button--outline--light--active__color: var(--rui-color-neutral-on-light); - --rui-Button--outline--light--active__border-color: var(--rui-color-neutral-light-active); - --rui-Button--outline--light--active__background: var(--rui-color-neutral-light-active); - - // Buttons: outline priority: dark variant - --rui-Button--outline--dark--default__color: var(--rui-color-neutral-dark); - --rui-Button--outline--dark--default__border-color: var(--rui-color-neutral-dark); - --rui-Button--outline--dark--default__background: transparent; - --rui-Button--outline--dark--hover__color: var(--rui-color-neutral-on-dark); - --rui-Button--outline--dark--hover__border-color: var(--rui-color-neutral-dark-hover); - --rui-Button--outline--dark--hover__background: var(--rui-color-neutral-dark-hover); - --rui-Button--outline--dark--active__color: var(--rui-color-neutral-on-dark); - --rui-Button--outline--dark--active__border-color: var(--rui-color-neutral-dark-active); - --rui-Button--outline--dark--active__background: var(--rui-color-neutral-dark-active); - - // Buttons: flat - - // Buttons: flat priority: primary variant - --rui-Button--flat--primary--default__color: var(--rui-color-action-primary); - --rui-Button--flat--primary--default__background: transparent; - --rui-Button--flat--primary--hover__color: var(--rui-color-action-primary-hover); - --rui-Button--flat--primary--hover__background: var(--rui-color-background-primary); - --rui-Button--flat--primary--active__color: var(--rui-color-action-primary-active); - --rui-Button--flat--primary--active__background: var(--rui-color-background-primary); - - // Buttons: flat priority: secondary variant - --rui-Button--flat--secondary--default__color: var(--rui-color-action-secondary); - --rui-Button--flat--secondary--default__background: transparent; - --rui-Button--flat--secondary--hover__color: var(--rui-color-action-secondary-hover); - --rui-Button--flat--secondary--hover__background: var(--rui-color-background-secondary); - --rui-Button--flat--secondary--active__color: var(--rui-color-action-secondary-active); - --rui-Button--flat--secondary--active__background: var(--rui-color-background-secondary); - - // Buttons: flat priority: selected variant - --rui-Button--flat--selected--default__color: var(--rui-color-action-selected); - --rui-Button--flat--selected--default__background: var(--rui-color-background-selected); - --rui-Button--flat--selected--hover__color: var(--rui-color-action-selected-hover); - --rui-Button--flat--selected--hover__background: var(--rui-color-background-selected); - --rui-Button--flat--selected--active__color: var(--rui-color-action-selected-active); - --rui-Button--flat--selected--active__background: var(--rui-color-background-selected); - - // Buttons: flat priority: success variant - --rui-Button--flat--success--default__color: var(--rui-color-feedback-success); - --rui-Button--flat--success--default__background: transparent; - --rui-Button--flat--success--hover__color: var(--rui-color-feedback-success-hover); - --rui-Button--flat--success--hover__background: var(--rui-color-background-success); - --rui-Button--flat--success--active__color: var(--rui-color-feedback-success-active); - --rui-Button--flat--success--active__background: var(--rui-color-background-success); - - // Buttons: flat priority: warning variant - --rui-Button--flat--warning--default__color: var(--rui-color-feedback-warning); - --rui-Button--flat--warning--default__background: transparent; - --rui-Button--flat--warning--hover__color: var(--rui-color-feedback-warning-hover); - --rui-Button--flat--warning--hover__background: var(--rui-color-background-warning); - --rui-Button--flat--warning--active__color: var(--rui-color-feedback-warning-active); - --rui-Button--flat--warning--active__background: var(--rui-color-background-warning); - - // Buttons: flat priority: danger variant - --rui-Button--flat--danger--default__color: var(--rui-color-feedback-danger); - --rui-Button--flat--danger--default__background: transparent; - --rui-Button--flat--danger--hover__color: var(--rui-color-feedback-danger-hover); - --rui-Button--flat--danger--hover__background: var(--rui-color-background-danger); - --rui-Button--flat--danger--active__color: var(--rui-color-feedback-danger-active); - --rui-Button--flat--danger--active__background: var(--rui-color-background-danger); - - // Buttons: flat priority: help variant - --rui-Button--flat--help--default__color: var(--rui-color-feedback-help); - --rui-Button--flat--help--default__background: transparent; - --rui-Button--flat--help--hover__color: var(--rui-color-feedback-help-hover); - --rui-Button--flat--help--hover__background: var(--rui-color-background-help); - --rui-Button--flat--help--active__color: var(--rui-color-feedback-help-active); - --rui-Button--flat--help--active__background: var(--rui-color-background-help); - - // Buttons: flat priority: info variant - --rui-Button--flat--info--default__color: var(--rui-color-feedback-info); - --rui-Button--flat--info--default__background: transparent; - --rui-Button--flat--info--hover__color: var(--rui-color-feedback-info-hover); - --rui-Button--flat--info--hover__background: var(--rui-color-background-info); - --rui-Button--flat--info--active__color: var(--rui-color-feedback-info-active); - --rui-Button--flat--info--active__background: var(--rui-color-background-info); - - // Buttons: flat priority: note variant - --rui-Button--flat--note--default__color: var(--rui-color-feedback-note); - --rui-Button--flat--note--default__background: transparent; - --rui-Button--flat--note--hover__color: var(--rui-color-feedback-note-hover); - --rui-Button--flat--note--hover__background: var(--rui-color-background-note); - --rui-Button--flat--note--active__color: var(--rui-color-feedback-note-active); - --rui-Button--flat--note--active__background: var(--rui-color-background-note); - - // Buttons: flat priority: light variant - --rui-Button--flat--light--default__color: var(--rui-color-neutral-light); - --rui-Button--flat--light--default__background: transparent; - --rui-Button--flat--light--hover__color: var(--rui-color-neutral-light-hover); - --rui-Button--flat--light--hover__background: var(--rui-color-background-dark); - --rui-Button--flat--light--active__color: var(--rui-color-neutral-light-active); - --rui-Button--flat--light--active__background: var(--rui-color-background-dark); - - // Buttons: flat priority: dark variant - --rui-Button--flat--dark--default__color: var(--rui-color-neutral-dark); - --rui-Button--flat--dark--default__background: transparent; - --rui-Button--flat--dark--hover__color: var(--rui-color-neutral-dark-hover); - --rui-Button--flat--dark--hover__background: var(--rui-color-background-light); - --rui-Button--flat--dark--active__color: var(--rui-color-neutral-dark-active); - --rui-Button--flat--dark--active__background: var(--rui-color-background-light); - - // Buttons: sizes - - // Buttons: sizes: small - --rui-Button--small__height: 1.75rem; - --rui-Button--small__padding-y: var(--rui-dimension-space-1); - --rui-Button--small__padding-x: var(--rui-dimension-space-3); - --rui-Button--small__font-size: var(--rui-font-size-small); - - // Buttons: sizes: medium - --rui-Button--medium__height: 2.25rem; - --rui-Button--medium__padding-y: var(--rui-dimension-space-1); - --rui-Button--medium__padding-x: var(--rui-dimension-space-4); - --rui-Button--medium__font-size: var(--rui-font-size-1); - - // Buttons: sizes: large - --rui-Button--large__height: 2.75rem; - --rui-Button--large__padding-y: var(--rui-dimension-space-2); - --rui-Button--large__padding-x: var(--rui-dimension-space-5); - --rui-Button--large__font-size: var(--rui-font-size-2); - - // - // ButtonGroup - // =========== - - --rui-ButtonGroup__inner-border-radius: 0; - - // ButtonGroup: filled buttons - --rui-ButtonGroup--filled__gap: calc(-1 * var(--rui-Button__border-width)); - --rui-ButtonGroup--filled__separator__width: var(--rui-Button__border-width); - --rui-ButtonGroup--filled__separator__color: currentcolor; - - // ButtonGroup: outline buttons - --rui-ButtonGroup--outline__gap: calc(-1 * var(--rui-Button__border-width)); - --rui-ButtonGroup--outline__separator__width: 0; - --rui-ButtonGroup--outline__separator__color: transparent; - - // ButtonGroup: flat buttons - --rui-ButtonGroup--flat__gap: var(--rui-Button__border-width); - --rui-ButtonGroup--flat__separator__width: var(--rui-ButtonGroup--flat__gap); - --rui-ButtonGroup--flat__separator__color: currentcolor; - - // - // Card - // ==== - - --rui-Card__padding: var(--rui-dimension-space-4); - --rui-Card__border-width: var(--rui-dimension-border-width-1); - --rui-Card__border-radius: var(--rui-dimension-radius-2); - --rui-Card--dense__padding: var(--rui-dimension-space-2); - --rui-Card--raised__box-shadow: var(--rui-shadow-layer-1); - --rui-Card--disabled__background-color: var(--rui-color-background-disabled); - --rui-Card--disabled__opacity: var(--rui-ratio-disabled-opacity); - - // Card: variant: success - --rui-Card--success__color: var(--rui-color-text-primary); - --rui-Card--success__border-color: var(--rui-color-feedback-success); - --rui-Card--success__background-color: var(--rui-color-background-layer-1); - - // Card: variant: warning - --rui-Card--warning__color: var(--rui-color-text-primary); - --rui-Card--warning__border-color: var(--rui-color-feedback-warning); - --rui-Card--warning__background-color: var(--rui-color-background-layer-1); - - // Card: variant: danger - --rui-Card--danger__color: var(--rui-color-text-primary); - --rui-Card--danger__border-color: var(--rui-color-feedback-danger); - --rui-Card--danger__background-color: var(--rui-color-background-layer-1); - - // Card: variant: info - --rui-Card--info__color: var(--rui-color-text-primary); - --rui-Card--info__border-color: var(--rui-color-feedback-info); - --rui-Card--info__background-color: var(--rui-color-background-layer-1); - - // Card: variant: help - --rui-Card--help__color: var(--rui-color-text-primary); - --rui-Card--help__border-color: var(--rui-color-feedback-help); - --rui-Card--help__background-color: var(--rui-color-background-layer-1); - - // Card: variant: note - --rui-Card--note__color: var(--rui-color-text-primary); - --rui-Card--note__border-color: var(--rui-color-feedback-note); - --rui-Card--note__background-color: var(--rui-color-background-layer-1); - - // Card: variant: light - --rui-Card--light__color: var(--rui-color-text-primary); - --rui-Card--light__border-color: var(--rui-color-neutral-light); - --rui-Card--light__background-color: var(--rui-color-background-layer-1); - - // Card: variant: dark - --rui-Card--dark__color: var(--rui-color-neutral-on-dark); - --rui-Card--dark__border-color: var(--rui-color-neutral-on-dark); - --rui-Card--dark__background-color: var(--rui-color-background-dark); - - // - // Form Fields - // =========== - // - // 1. Please note that `min-width` values under cca 150 px do not take effect due to default input - // width defined in browsers unless `width` (same or smaller) is also defined. - // https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size - // - // 2. Append non-breaking space and asterisk to required filed labels. - // - // 3. Avoid using `fit-content()` for label width, it behaves differently in Chrome vs. FF for - // inline grid. - - // Forms fields: common properties - --rui-FormField__label__color: inherit; - --rui-FormField__label__font-size: var(--rui-font-size-1); - --rui-FormField__help-text__font-size: var(--rui-font-size-small); - --rui-FormField__help-text__font-style: normal; - --rui-FormField__help-text__color: var(--rui-color-text-secondary); - --rui-FormField--required__label__color: inherit; - --rui-FormField--required__sign: "\00a0*"; // 2. - --rui-FormField--required__sign__color: var(--rui-color-text-secondary); - - // Form fields: horizontal layout - --rui-FormField--horizontal__label__text-align: left; - --rui-FormField--horizontal__label__min-width: 0; - --rui-FormField--horizontal__label__width: minmax(auto, 50%); // 3. - --rui-FormField--horizontal__label__vertical-alignment: initial; - --rui-FormField--horizontal__field__vertical-alignment: initial; - --rui-FormField--horizontal--full-width__label__width: fit-content(50%); - - // Forms fields: disabled state - --rui-FormField--disabled__cursor: var(--rui-cursor-not-allowed); - --rui-FormField--disabled__opacity: var(--rui-ratio-disabled-opacity); - - // Form fields: validation states: invalid - --rui-FormField--invalid--default__border-color: var(--rui-color-feedback-danger); - --rui-FormField--invalid--default__background: var(--rui-color-background-danger); - --rui-FormField--invalid--default__check-background-color: var(--rui-FormField--invalid--default__background); - --rui-FormField--invalid--default__surrounding-text-color: var(--rui-color-feedback-danger); - --rui-FormField--invalid--checked__check-background-color: var(--rui-FormField--invalid--default__border-color); - - // Form fields: validation states: valid - --rui-FormField--valid--default__border-color: var(--rui-color-feedback-success); - --rui-FormField--valid--default__background: var(--rui-color-background-success); - --rui-FormField--valid--default__check-background-color: var(--rui-FormField--valid--default__background); - --rui-FormField--valid--default__surrounding-text-color: var(--rui-color-feedback-success); - --rui-FormField--valid--checked__check-background-color: var(--rui-FormField--valid--default__border-color); - - // Form fields: validation states: warning - --rui-FormField--warning--default__border-color: var(--rui-color-feedback-warning-hover); - --rui-FormField--warning--default__background: var(--rui-color-background-warning); - --rui-FormField--warning--default__check-background-color: var(--rui-FormField--warning--default__background); - --rui-FormField--warning--default__surrounding-text-color: var(--rui-color-feedback-warning-active); - --rui-FormField--warning--checked__check-background-color: var(--rui-FormField--warning--default__border-color); - - // Form fields: box fields - --rui-FormField--box__border-width: var(--rui-dimension-border-width-1); - --rui-FormField--box__border-radius: var(--rui-dimension-radius-2); - --rui-FormField--box__input__width: auto; // 1. - --rui-FormField--box__input__min-width: 240px; // 1. - --rui-FormField--box__placeholder__color: var(--rui-color-text-secondary); - --rui-FormField--box--select__caret__border-style: none; - --rui-FormField--box--select__caret__background: transparent; - --rui-FormField--box--select__option--disabled__color: var(--rui-color-text-primary-disabled); - - // Form fields: box field sizes: small - --rui-FormField--box--small__height: var(--rui-Button--small__height); - --rui-FormField--box--small__padding-y: 0.0625rem; - --rui-FormField--box--small__padding-x: var(--rui-dimension-space-2); - --rui-FormField--box--small__font-size: var(--rui-font-size-small); - - // Form fields: box field sizes: medium - --rui-FormField--box--medium__height: var(--rui-Button--medium__height); - --rui-FormField--box--medium__padding-y: 0.3125rem; - --rui-FormField--box--medium__padding-x: var(--rui-dimension-space-3); - --rui-FormField--box--medium__font-size: var(--rui-font-size-1); - - // Form fields: box field sizes: large - --rui-FormField--box--large__height: var(--rui-Button--large__height); - --rui-FormField--box--large__padding-y: 0.5625rem; - --rui-FormField--box--large__padding-x: var(--rui-dimension-space-4); - --rui-FormField--box--large__font-size: var(--rui-font-size-2); - - // Form fields: box field variants: filled variant interaction states - --rui-FormField--box--filled--default__color: var(--rui-color-text-primary); - --rui-FormField--box--filled--default__border-color: var(--rui-color-border-primary); - --rui-FormField--box--filled--default__background: var(--rui-color-background-basic); - --rui-FormField--box--filled--default__box-shadow: none; - --rui-FormField--box--filled--hover__border-color: var(--rui-color-border-primary-hover); - --rui-FormField--box--filled--focus__border-color: var(--rui-color-border-primary-active); - - // Form fields: box field variants: outline variant interaction states - --rui-FormField--box--outline--default__color: var(--rui-color-text-primary); - --rui-FormField--box--outline--default__border-color: var(--rui-color-border-primary); - --rui-FormField--box--outline--default__background: var(--rui-color-background-basic); - --rui-FormField--box--outline--default__box-shadow: none; - --rui-FormField--box--outline--hover__border-color: var(--rui-color-border-primary-hover); - --rui-FormField--box--outline--focus__border-color: var(--rui-color-border-primary-active); - - // Form fields: check fields - --rui-FormField--check__input__size: 1.125rem; - --rui-FormField--check__input__border-width: var(--rui-FormField--box__border-width); - --rui-FormField--check__input--focus__box-shadow: var(--rui-shadow-focus-ring); - --rui-FormField--check__tap-target-size: var(--rui-dimension-tap-target-size); - - // Form fields: check fields, component specific - --rui-FormField--check__input--checkbox__border-radius: var(--rui-FormField--box__border-radius); - --rui-FormField--check__input--checkbox--checked__background-image: #{svg.$checkbox-checked}; - --rui-FormField--check__input--radio__border-radius: 50%; - --rui-FormField--check__input--radio--checked__background-image: #{svg.$radio-checked}; - --rui-FormField--check__input--toggle__width: 2.25rem; - --rui-FormField--check__input--toggle__border-radius: 0.5625rem; - --rui-FormField--check__input--toggle__background-size: contain; - --rui-FormField--check__input--toggle--default__background-image: #{svg.$toggle}; - --rui-FormField--check__input--toggle--default__background-position: left center; - --rui-FormField--check__input--toggle--checked__background-image: #{svg.$toggle-checked}; - --rui-FormField--check__input--toggle--checked__background-position: right center; - - // Form fields: check fields interaction states - --rui-FormField--check--default__border-color: var(--rui-color-border-primary); - --rui-FormField--check--default__check-background-color: var(--rui-color-background-basic); - --rui-FormField--check--checked__border-color: var(--rui-color-action-selected); - --rui-FormField--check--checked__check-background-color: var(--rui-color-action-selected); - - // - // FormLayout - // ========== - - --rui-FormLayout__row-gap: var(--rui-dimension-space-4); - --rui-FormLayout--horizontal__label__width: 10em; - --rui-FormLayout--horizontal__label__width--auto: auto; - --rui-FormLayout--horizontal__label__width--limited: fit-content(50%); - - // - // InputGroup - // ======= - - --rui-InputGroup__gap: var(--rui-dimension-space-1); - --rui-InputGroup__inner-border-radius: var(--rui-dimension-radius-1); - - // - // Modal - // ===== - - --rui-Modal__padding-x: var(--rui-dimension-space-4); - --rui-Modal__padding-y: var(--rui-dimension-space-4); - --rui-Modal__background: var(--rui-color-background-layer-2); - --rui-Modal__box-shadow: var(--rui-shadow-layer-2); - --rui-Modal__separator__width: var(--rui-dimension-border-width-1); - --rui-Modal__separator__color: var(--rui-color-border-secondary); - --rui-Modal__header__gap: var(--rui-dimension-space-2); - --rui-Modal__outer-spacing--xs: var(--rui-dimension-space-2); - --rui-Modal__outer-spacing--sm: var(--rui-dimension-space-6); - --rui-Modal__footer__background: var(--rui-Modal__background); - --rui-Modal__footer__gap: var(--rui-dimension-space-2); - --rui-Modal__backdrop__background: rgb(0 0 0 / 50%); - --rui-Modal--auto__min-width: 18rem; - --rui-Modal--auto__max-width: 60rem; - --rui-Modal--small__width: 20rem; - --rui-Modal--medium__width: 40rem; - --rui-Modal--large__width: 60rem; - --rui-Modal--fullscreen__width: 100%; - --rui-Modal--fullscreen__height: 100%; - - // - // Paper - // ===== - - --rui-Paper__padding: var(--rui-dimension-space-4); - --rui-Paper__border-width: 0; - --rui-Paper__border-color: transparent; - --rui-Paper__border-radius: var(--rui-dimension-radius-2); - --rui-Paper__background-color: var(--rui-color-background-layer-1); - --rui-Paper--muted__background-color: var(--rui-color-background-disabled); - --rui-Paper--muted__opacity: var(--rui-ratio-disabled-opacity); - --rui-Paper--raised__box-shadow: var(--rui-shadow-layer-1); - - // - // Popover - // ======= - - --rui-Popover__max-width: 15rem; - --rui-Popover__padding: var(--rui-dimension-space-3); - --rui-Popover__border-width: 0; - --rui-Popover__border-color: transparent; - --rui-Popover__border-radius: var(--rui-dimension-radius-2); - --rui-Popover__color: var(--rui-color-text-primary); - --rui-Popover__background-color: var(--rui-color-background-layer-2); - --rui-Popover__box-shadow: var(--rui-shadow-layer-2); - - // - // Tabs - // ==== - - --rui-Tabs__border-bottom-width: var(--rui-dimension-border-width-1); - --rui-Tabs__border-bottom-color: var(--rui-color-border-primary); - --rui-Tabs__gap--xs: var(--rui-dimension-space-1); - --rui-Tabs__gap--sm: var(--rui-dimension-space-1); - --rui-Tabs__gap--md: var(--rui-dimension-space-1); - --rui-Tabs__padding-x: 0; - - // Tabs items - --rui-Tabs__item__padding--xs: var(--rui-dimension-space-3); - --rui-Tabs__item__padding--sm: var(--rui-dimension-space-4); - --rui-Tabs__item__padding--md: var(--rui-dimension-space-4); - --rui-Tabs__item__font-weight: inherit; - --rui-Tabs__item__color: var(--rui-color-text-secondary); - --rui-Tabs__item__border-width: var(--rui-dimension-border-width-1); - --rui-Tabs__item__border-color: - var(--rui-color-border-secondary) - var(--rui-color-border-secondary) - transparent - var(--rui-color-border-secondary); - --rui-Tabs__item__border-radius: var(--rui-dimension-radius-2); - --rui-Tabs__item__background-color: var(--rui-color-background-layer-1); - --rui-Tabs__item__box-shadow: none; - --rui-Tabs__item__icon__gap: var(--rui-dimension-space-2); - - // Tabs items: hover - --rui-Tabs__item--hover__font-weight: var(--rui-Tabs__item__font-weight); - --rui-Tabs__item--hover__color: var(--rui-Tabs__item__color); - --rui-Tabs__item--hover__border-width: var(--rui-Tabs__item__border-width); - --rui-Tabs__item--hover__border-color: var(--rui-Tabs__item__border-color); - --rui-Tabs__item--hover__background-color: var(--rui-Tabs__item__background-color); - --rui-Tabs__item--hover__box-shadow: var(--rui-Tabs__item__box-shadow); - --rui-Tabs__item--hover__shift-y: -0.15rem; - --rui-Tabs__item--hover__label__shift-y: 0; - - // Tabs items: active - --rui-Tabs__item--active__font-weight: inherit; - --rui-Tabs__item--active__color: var(--rui-color-text-primary); - --rui-Tabs__item--active__border-width: var(--rui-Tabs__item__border-width); - --rui-Tabs__item--active__border-color: - var(--rui-Tabs__border-bottom-color) - var(--rui-Tabs__border-bottom-color) - transparent - var(--rui-Tabs__border-bottom-color); - --rui-Tabs__item--active__background-color: var(--rui-Tabs__item__background-color); - --rui-Tabs__item--active__box-shadow: var(--rui-Tabs__item__box-shadow); - --rui-Tabs__item--active__shift-y: -0.25em; - --rui-Tabs__item--active__label__shift-y: 0; - - // - // TextLink - // ======== - - --rui-TextLink__color: var(--rui-color-text-link); - --rui-TextLink__text-decoration: var(--rui-text-decoration-link); - --rui-TextLink--hover__color: var(--rui-color-text-link-hover); - --rui-TextLink--hover__text-decoration: var(--rui-text-decoration-link-hover); - --rui-TextLink--active__color: var(--rui-color-text-link-active); - --rui-TextLink--active__text-decoration: var(--rui-text-decoration-link-active); - - // - // Toolbar - // ======= - - --rui-Toolbar__gap: var(--rui-dimension-space-4); - --rui-Toolbar__gap--dense: var(--rui-dimension-space-2); +@layer theme { + :root, + :host { + // ============================================================================================ // + // GLOBAL TOKENS // + // ============================================================================================ // + + // + // Dimensions + // ========== + + // Borders + --rui-dimension-border-width-1: 1px; + + // Breakpoints + // + // ⚠️ Breakpoints are read-only in CSS. Custom properties cannot be used within media queries + // since media query is not a property. + // https://www.w3.org/TR/css-variables-1/#using-variables + --rui-dimension-breakpoint-xs: #{breakpoints.$xs}; + --rui-dimension-breakpoint-sm: #{breakpoints.$sm}; + --rui-dimension-breakpoint-md: #{breakpoints.$md}; + --rui-dimension-breakpoint-lg: #{breakpoints.$lg}; + --rui-dimension-breakpoint-xl: #{breakpoints.$xl}; + --rui-dimension-breakpoint-x2l: #{breakpoints.$x2l}; + --rui-dimension-breakpoint-x3l: #{breakpoints.$x3l}; + + // Radii + --rui-dimension-radius-1: 0.125rem; + --rui-dimension-radius-2: 0.25rem; + + // Spacing + --rui-dimension-space-0: 0; + --rui-dimension-space-1: 0.25rem; + --rui-dimension-space-2: 0.5rem; + --rui-dimension-space-3: 0.75rem; + --rui-dimension-space-4: 1rem; + --rui-dimension-space-5: 1.5rem; + --rui-dimension-space-6: 2rem; + --rui-dimension-space-7: 2.5rem; + + // + // Font Families + // ============= + + --rui-font-family-base: "Titillium Web", helvetica, roboto, arial, sans-serif; + --rui-font-family-monospace: + "SFMono-Regular", + "Menlo", + "Monaco", + "Consolas", + "Liberation Mono", + "Courier New", + monospace; + + // + // Font Weights + // ============ + + --rui-font-weight-base: 400; + --rui-font-weight-light: 300; + --rui-font-weight-bold: 700; + + // + // Ratios + // ====== + + --rui-ratio-opacity-medium: 0.5; + + // + // Shadows + // ======= + + --rui-shadow-1: 0 0.01rem 0.65rem -0.1rem rgb(0 0 0 / 30%); + --rui-shadow-2: 0.2rem 0.25rem 1.2rem -0.1rem rgb(0 0 0 / 15%); + + // + // Other + // ===== + + // ⚠️ Non-standard token types! + // The DTF specification is still in the draft status, and the following token types have proven necessary. + // + // To be honest, some of these tokens are NOT context agnostic as required by the global tokens category. + // These will be probably superseded by semantic typography styles in the future. + + // Font sizes + --rui-font-size-base: 100%; + --rui-font-size-small: 0.889rem; + --rui-font-size-smaller: 0.75rem; + --rui-font-size-code: 85%; + + // Modular scale ratio: 1.125 / 8:9 / major second + --rui-font-size-1: 1rem; + --rui-font-size-2: 1.125rem; + --rui-font-size-3: 1.266rem; + --rui-font-size-4: 1.424rem; + --rui-font-size-5: 1.602rem; + --rui-font-size-6: 1.802rem; + + // Line heights + --rui-line-height-base: 1.5; + --rui-line-height-small: 1.25; + + // Text decorations + --rui-text-decoration-link: none; + --rui-text-decoration-link-hover: underline; + --rui-text-decoration-link-active: underline; + + // List styles + --rui-list-style-unordered: square; + + // Cursors + --rui-cursor-not-allowed: not-allowed; + + // ============================================================================================ // + // SEMANTIC TOKENS // + // ============================================================================================ // + + // + // Borders + // ======= + + --rui-border-focus-ring: var(--rui-dimension-space-1) solid #{colors.$focus}; + + // + // Colors + // ====== + + // 👉 Actual color values are stored in separate SCSS so they can be generated programmatically. + + // Text colors + --rui-color-text-primary: #{colors.$black}; + --rui-color-text-primary-disabled: #{colors.$gray-300}; + --rui-color-text-secondary: #{colors.$gray-500}; + --rui-color-text-secondary-disabled: #{colors.$gray-300}; + --rui-color-text-link: #{colors.$note}; + --rui-color-text-link-hover: #{colors.$note-dark}; + --rui-color-text-link-active: #{colors.$note-darker}; + + // Action colors + --rui-color-action-primary: #{colors.$primary}; + --rui-color-action-primary-hover: #{colors.$primary-dark}; + --rui-color-action-primary-active: #{colors.$primary-darker}; + --rui-color-action-on-primary: #{colors.$on-primary}; + --rui-color-action-secondary: #{colors.$secondary}; + --rui-color-action-secondary-hover: #{colors.$secondary-dark}; + --rui-color-action-secondary-active: #{colors.$secondary-darker}; + --rui-color-action-on-secondary: #{colors.$on-secondary}; + --rui-color-action-selected: #{colors.$selected}; + --rui-color-action-selected-hover: #{colors.$selected-dark}; + --rui-color-action-selected-active: #{colors.$selected-darker}; + --rui-color-action-on-selected: #{colors.$on-selected}; + + // Feedback colors + --rui-color-feedback-success: #{colors.$success}; + --rui-color-feedback-success-hover: #{colors.$success-dark}; + --rui-color-feedback-success-active: #{colors.$success-darker}; + --rui-color-feedback-on-success: #{colors.$on-success}; + --rui-color-feedback-warning: #{colors.$warning}; + --rui-color-feedback-warning-hover: #{colors.$warning-dark}; + --rui-color-feedback-warning-active: #{colors.$warning-darker}; + --rui-color-feedback-on-warning: #{colors.$on-warning}; + --rui-color-feedback-danger: #{colors.$danger}; + --rui-color-feedback-danger-hover: #{colors.$danger-dark}; + --rui-color-feedback-danger-active: #{colors.$danger-darker}; + --rui-color-feedback-on-danger: #{colors.$on-danger}; + --rui-color-feedback-help: #{colors.$help}; + --rui-color-feedback-help-hover: #{colors.$help-dark}; + --rui-color-feedback-help-active: #{colors.$help-darker}; + --rui-color-feedback-on-help: #{colors.$on-help}; + --rui-color-feedback-info: #{colors.$info}; + --rui-color-feedback-info-hover: #{colors.$info-dark}; + --rui-color-feedback-info-active: #{colors.$info-darker}; + --rui-color-feedback-on-info: #{colors.$on-info}; + --rui-color-feedback-note: #{colors.$note}; + --rui-color-feedback-note-hover: #{colors.$note-dark}; + --rui-color-feedback-note-active: #{colors.$note-darker}; + --rui-color-feedback-on-note: #{colors.$on-note}; + + // Neutral colors + --rui-color-neutral-light: #{colors.$white}; + --rui-color-neutral-light-hover: #{colors.$gray-50}; + --rui-color-neutral-light-active: #{colors.$gray-100}; + --rui-color-neutral-on-light: #{colors.$gray-700}; + --rui-color-neutral-dark: #{colors.$gray-700}; + --rui-color-neutral-dark-hover: #{colors.$gray-800}; + --rui-color-neutral-dark-active: #{colors.$gray-900}; + --rui-color-neutral-on-dark: #{colors.$white}; + + // Background colors + --rui-color-background-base: #{colors.$gray-50}; + --rui-color-background-layer-1: #{colors.$white}; + --rui-color-background-layer-2: #{colors.$white}; + --rui-color-background-basic: #{colors.$white}; + --rui-color-background-disabled: #{colors.$gray-50}; + --rui-color-background-interactive: #{colors.$transparent}; + --rui-color-background-interactive-hover: #{colors.$gray-50}; + --rui-color-background-interactive-active: #{colors.$gray-100}; + --rui-color-background-primary: #{colors.$primary-light}; + --rui-color-background-secondary: #{colors.$secondary-light}; + --rui-color-background-selected: #{colors.$selected-light}; + --rui-color-background-success: #{colors.$success-light}; + --rui-color-background-warning: #{colors.$warning-light}; + --rui-color-background-danger: #{colors.$danger-light}; + --rui-color-background-help: #{colors.$help-light}; + --rui-color-background-info: #{colors.$info-light}; + --rui-color-background-note: #{colors.$note-light}; + --rui-color-background-light: #{colors.$gray-100}; + --rui-color-background-dark: #{colors.$gray-600}; + + // Border colors + --rui-color-border-primary: #{colors.$gray-200}; + --rui-color-border-primary-hover: #{colors.$gray-500}; + --rui-color-border-primary-active: #{colors.$selected-darker}; + --rui-color-border-secondary: #{colors.$gray-100}; + + // + // Dimensions + // ========== + + // Accessibility + --rui-dimension-focus-ring-offset: var(--rui-dimension-border-width-1); + --rui-dimension-tap-target-size: var(--rui-dimension-space-7); + + // Shared bottom spacings + --rui-dimension-space-bottom-base: var(--rui-dimension-space-5); + --rui-dimension-space-bottom-headings: var(--rui-dimension-space-5); + --rui-dimension-space-bottom-layouts: var(--rui-dimension-space-5); + + // + // Ratios + // ====== + + --rui-ratio-disabled-opacity: var(--rui-ratio-opacity-medium); + + // + // Shadows + // ======= + + // 1. Use `initial`, `revert` or `unset` to keep the original box shadow of the component. + + --rui-shadow-layer-1: var(--rui-shadow-1); + --rui-shadow-layer-2: var(--rui-shadow-2); + --rui-shadow-focus-ring: initial; // 1. + + // ============================================================================================ // + // COMPONENT TOKENS // + // ============================================================================================ // + + // + // Alert + // ===== + + // Alert: common properties + --rui-Alert__padding: var(--rui-dimension-space-3); + --rui-Alert__font-weight: var(--rui-font-weight-base); + --rui-Alert__border-width: var(--rui-dimension-border-width-1); + --rui-Alert__border-radius: var(--rui-dimension-radius-2); + --rui-Alert__emphasis__font-weight: var(--rui-font-weight-bold); + --rui-Alert__stripe__width: var(--rui-dimension-border-width-1); + + // Alert: variant: success + --rui-Alert--success__color: var(--rui-color-text-primary); + --rui-Alert--success__foreground-color: var(--rui-color-feedback-success); + --rui-Alert--success__background-color: var(--rui-color-background-success); + + // Alert: variant: warning + --rui-Alert--warning__color: var(--rui-color-text-primary); + --rui-Alert--warning__foreground-color: var(--rui-color-feedback-warning); + --rui-Alert--warning__background-color: var(--rui-color-background-warning); + + // Alert: variant: danger + --rui-Alert--danger__color: var(--rui-color-text-primary); + --rui-Alert--danger__foreground-color: var(--rui-color-feedback-danger); + --rui-Alert--danger__background-color: var(--rui-color-background-danger); + + // Alert: variant: info + --rui-Alert--info__color: var(--rui-color-text-primary); + --rui-Alert--info__foreground-color: var(--rui-color-feedback-info); + --rui-Alert--info__background-color: var(--rui-color-background-info); + + // Alert: variant: help + --rui-Alert--help__color: var(--rui-color-text-primary); + --rui-Alert--help__foreground-color: var(--rui-color-feedback-help); + --rui-Alert--help__background-color: var(--rui-color-background-help); + + // Alert: variant: note + --rui-Alert--note__color: var(--rui-color-text-primary); + --rui-Alert--note__foreground-color: var(--rui-color-feedback-note); + --rui-Alert--note__background-color: var(--rui-color-background-note); + + // Alert: variant: light + --rui-Alert--light__color: var(--rui-color-neutral-on-light); + --rui-Alert--light__foreground-color: var(--rui-color-neutral-on-light); + --rui-Alert--light__background-color: var(--rui-color-background-light); + + // Alert: variant: dark + --rui-Alert--dark__color: var(--rui-color-neutral-on-dark); + --rui-Alert--dark__foreground-color: var(--rui-color-neutral-on-dark); + --rui-Alert--dark__background-color: var(--rui-color-background-dark); + + // + // Button + // ====== + + // Buttons: common properties + --rui-Button__font-weight: var(--rui-font-weight-base); + --rui-Button__letter-spacing: 0; + --rui-Button__text-transform: none; + --rui-Button__border-width: var(--rui-dimension-border-width-1); + --rui-Button__border-radius: var(--rui-dimension-radius-2); + --rui-Button--disabled__opacity: var(--rui-ratio-disabled-opacity); + --rui-Button--disabled__cursor: var(--rui-cursor-not-allowed); + --rui-Button--feedback__opacity: 1; + --rui-Button--feedback__cursor: var(--rui-cursor-not-allowed); + + // Buttons: filled priority + + // Buttons: filled priority: primary variant + --rui-Button--filled--primary--default__color: var(--rui-color-action-on-primary); + --rui-Button--filled--primary--default__border-color: var(--rui-color-action-primary); + --rui-Button--filled--primary--default__background: var(--rui-color-action-primary); + --rui-Button--filled--primary--default__box-shadow: none; + --rui-Button--filled--primary--hover__color: var(--rui-color-action-on-primary); + --rui-Button--filled--primary--hover__border-color: var(--rui-color-action-primary-hover); + --rui-Button--filled--primary--hover__background: var(--rui-color-action-primary-hover); + --rui-Button--filled--primary--hover__box-shadow: none; + --rui-Button--filled--primary--active__color: var(--rui-color-action-on-primary); + --rui-Button--filled--primary--active__border-color: var(--rui-color-action-primary-active); + --rui-Button--filled--primary--active__background: var(--rui-color-action-primary-active); + --rui-Button--filled--primary--active__box-shadow: none; + + // Buttons: filled priority: secondary variant + --rui-Button--filled--secondary--default__color: var(--rui-color-action-on-secondary); + --rui-Button--filled--secondary--default__border-color: var(--rui-color-action-secondary); + --rui-Button--filled--secondary--default__background: var(--rui-color-action-secondary); + --rui-Button--filled--secondary--default__box-shadow: none; + --rui-Button--filled--secondary--hover__color: var(--rui-color-action-on-secondary); + --rui-Button--filled--secondary--hover__border-color: var(--rui-color-action-secondary-hover); + --rui-Button--filled--secondary--hover__background: var(--rui-color-action-secondary-hover); + --rui-Button--filled--secondary--hover__box-shadow: none; + --rui-Button--filled--secondary--active__color: var(--rui-color-action-on-secondary); + --rui-Button--filled--secondary--active__border-color: var(--rui-color-action-secondary-active); + --rui-Button--filled--secondary--active__background: var(--rui-color-action-secondary-active); + --rui-Button--filled--secondary--active__box-shadow: none; + + // Buttons: filled priority: selected variant + --rui-Button--filled--selected--default__color: var(--rui-color-action-on-selected); + --rui-Button--filled--selected--default__border-color: var(--rui-color-action-selected); + --rui-Button--filled--selected--default__background: var(--rui-color-action-selected); + --rui-Button--filled--selected--default__box-shadow: none; + --rui-Button--filled--selected--hover__color: var(--rui-color-action-on-selected); + --rui-Button--filled--selected--hover__border-color: var(--rui-color-action-selected-hover); + --rui-Button--filled--selected--hover__background: var(--rui-color-action-selected-hover); + --rui-Button--filled--selected--hover__box-shadow: none; + --rui-Button--filled--selected--active__color: var(--rui-color-action-on-selected); + --rui-Button--filled--selected--active__border-color: var(--rui-color-action-selected-active); + --rui-Button--filled--selected--active__background: var(--rui-color-action-selected-active); + --rui-Button--filled--selected--active__box-shadow: none; + + // Buttons: filled priority: success variant + --rui-Button--filled--success--default__color: var(--rui-color-feedback-on-success); + --rui-Button--filled--success--default__border-color: var(--rui-color-feedback-success); + --rui-Button--filled--success--default__background: var(--rui-color-feedback-success); + --rui-Button--filled--success--default__box-shadow: none; + --rui-Button--filled--success--hover__color: var(--rui-color-feedback-on-success); + --rui-Button--filled--success--hover__border-color: var(--rui-color-feedback-success-hover); + --rui-Button--filled--success--hover__background: var(--rui-color-feedback-success-hover); + --rui-Button--filled--success--hover__box-shadow: none; + --rui-Button--filled--success--active__color: var(--rui-color-feedback-on-success); + --rui-Button--filled--success--active__border-color: var(--rui-color-feedback-success-active); + --rui-Button--filled--success--active__background: var(--rui-color-feedback-success-active); + --rui-Button--filled--success--active__box-shadow: none; + + // Buttons: filled priority: warning variant + --rui-Button--filled--warning--default__color: var(--rui-color-feedback-on-warning); + --rui-Button--filled--warning--default__border-color: var(--rui-color-feedback-warning); + --rui-Button--filled--warning--default__background: var(--rui-color-feedback-warning); + --rui-Button--filled--warning--default__box-shadow: none; + --rui-Button--filled--warning--hover__color: var(--rui-color-feedback-on-warning); + --rui-Button--filled--warning--hover__border-color: var(--rui-color-feedback-warning-hover); + --rui-Button--filled--warning--hover__background: var(--rui-color-feedback-warning-hover); + --rui-Button--filled--warning--hover__box-shadow: none; + --rui-Button--filled--warning--active__color: var(--rui-color-feedback-on-warning); + --rui-Button--filled--warning--active__border-color: var(--rui-color-feedback-warning-active); + --rui-Button--filled--warning--active__background: var(--rui-color-feedback-warning-active); + --rui-Button--filled--warning--active__box-shadow: none; + + // Buttons: filled priority: danger variant + --rui-Button--filled--danger--default__color: var(--rui-color-feedback-on-danger); + --rui-Button--filled--danger--default__border-color: var(--rui-color-feedback-danger); + --rui-Button--filled--danger--default__background: var(--rui-color-feedback-danger); + --rui-Button--filled--danger--default__box-shadow: none; + --rui-Button--filled--danger--hover__color: var(--rui-color-feedback-on-danger); + --rui-Button--filled--danger--hover__border-color: var(--rui-color-feedback-danger-hover); + --rui-Button--filled--danger--hover__background: var(--rui-color-feedback-danger-hover); + --rui-Button--filled--danger--hover__box-shadow: none; + --rui-Button--filled--danger--active__color: var(--rui-color-feedback-on-danger); + --rui-Button--filled--danger--active__border-color: var(--rui-color-feedback-danger-active); + --rui-Button--filled--danger--active__background: var(--rui-color-feedback-danger-active); + --rui-Button--filled--danger--active__box-shadow: none; + + // Buttons: filled priority: help variant + --rui-Button--filled--help--default__color: var(--rui-color-feedback-on-help); + --rui-Button--filled--help--default__border-color: var(--rui-color-feedback-help); + --rui-Button--filled--help--default__background: var(--rui-color-feedback-help); + --rui-Button--filled--help--default__box-shadow: none; + --rui-Button--filled--help--hover__color: var(--rui-color-feedback-on-help); + --rui-Button--filled--help--hover__border-color: var(--rui-color-feedback-help-hover); + --rui-Button--filled--help--hover__background: var(--rui-color-feedback-help-hover); + --rui-Button--filled--help--hover__box-shadow: none; + --rui-Button--filled--help--active__color: var(--rui-color-feedback-on-help); + --rui-Button--filled--help--active__border-color: var(--rui-color-feedback-help-active); + --rui-Button--filled--help--active__background: var(--rui-color-feedback-help-active); + --rui-Button--filled--help--active__box-shadow: none; + + // Buttons: filled priority: info variant + --rui-Button--filled--info--default__color: var(--rui-color-feedback-on-info); + --rui-Button--filled--info--default__border-color: var(--rui-color-feedback-info); + --rui-Button--filled--info--default__background: var(--rui-color-feedback-info); + --rui-Button--filled--info--default__box-shadow: none; + --rui-Button--filled--info--hover__color: var(--rui-color-feedback-on-info); + --rui-Button--filled--info--hover__border-color: var(--rui-color-feedback-info-hover); + --rui-Button--filled--info--hover__background: var(--rui-color-feedback-info-hover); + --rui-Button--filled--info--hover__box-shadow: none; + --rui-Button--filled--info--active__color: var(--rui-color-feedback-on-info); + --rui-Button--filled--info--active__border-color: var(--rui-color-feedback-info-active); + --rui-Button--filled--info--active__background: var(--rui-color-feedback-info-active); + --rui-Button--filled--info--active__box-shadow: none; + + // Buttons: filled priority: note variant + --rui-Button--filled--note--default__color: var(--rui-color-feedback-on-note); + --rui-Button--filled--note--default__border-color: var(--rui-color-feedback-note); + --rui-Button--filled--note--default__background: var(--rui-color-feedback-note); + --rui-Button--filled--note--default__box-shadow: none; + --rui-Button--filled--note--hover__color: var(--rui-color-feedback-on-note); + --rui-Button--filled--note--hover__border-color: var(--rui-color-feedback-note-hover); + --rui-Button--filled--note--hover__background: var(--rui-color-feedback-note-hover); + --rui-Button--filled--note--hover__box-shadow: none; + --rui-Button--filled--note--active__color: var(--rui-color-feedback-on-note); + --rui-Button--filled--note--active__border-color: var(--rui-color-feedback-note-active); + --rui-Button--filled--note--active__background: var(--rui-color-feedback-note-active); + --rui-Button--filled--note--active__box-shadow: none; + + // Buttons: filled priority: light variant + --rui-Button--filled--light--default__color: var(--rui-color-neutral-on-light); + --rui-Button--filled--light--default__border-color: var(--rui-color-neutral-light); + --rui-Button--filled--light--default__background: var(--rui-color-neutral-light); + --rui-Button--filled--light--default__box-shadow: none; + --rui-Button--filled--light--hover__color: var(--rui-color-neutral-on-light); + --rui-Button--filled--light--hover__border-color: var(--rui-color-neutral-light-hover); + --rui-Button--filled--light--hover__background: var(--rui-color-neutral-light-hover); + --rui-Button--filled--light--hover__box-shadow: none; + --rui-Button--filled--light--active__color: var(--rui-color-neutral-on-light); + --rui-Button--filled--light--active__border-color: var(--rui-color-neutral-light-active); + --rui-Button--filled--light--active__background: var(--rui-color-neutral-light-active); + --rui-Button--filled--light--active__box-shadow: none; + + // Buttons: filled priority: dark variant + --rui-Button--filled--dark--default__color: var(--rui-color-neutral-on-dark); + --rui-Button--filled--dark--default__border-color: var(--rui-color-neutral-dark); + --rui-Button--filled--dark--default__background: var(--rui-color-neutral-dark); + --rui-Button--filled--dark--default__box-shadow: none; + --rui-Button--filled--dark--hover__color: var(--rui-color-neutral-on-dark); + --rui-Button--filled--dark--hover__border-color: var(--rui-color-neutral-dark-hover); + --rui-Button--filled--dark--hover__background: var(--rui-color-neutral-dark-hover); + --rui-Button--filled--dark--hover__box-shadow: none; + --rui-Button--filled--dark--active__color: var(--rui-color-neutral-on-dark); + --rui-Button--filled--dark--active__border-color: var(--rui-color-neutral-dark-active); + --rui-Button--filled--dark--active__background: var(--rui-color-neutral-dark-active); + --rui-Button--filled--dark--active__box-shadow: none; + + // Buttons: outline priority + + // Buttons: outline priority: primary variant + --rui-Button--outline--primary--default__color: var(--rui-color-action-primary); + --rui-Button--outline--primary--default__border-color: var(--rui-color-action-primary); + --rui-Button--outline--primary--default__background: transparent; + --rui-Button--outline--primary--hover__color: var(--rui-color-action-on-primary); + --rui-Button--outline--primary--hover__border-color: var(--rui-color-action-primary-hover); + --rui-Button--outline--primary--hover__background: var(--rui-color-action-primary-hover); + --rui-Button--outline--primary--active__color: var(--rui-color-action-on-primary); + --rui-Button--outline--primary--active__border-color: var(--rui-color-action-primary-active); + --rui-Button--outline--primary--active__background: var(--rui-color-action-primary-active); + + // Buttons: outline priority: secondary variant + --rui-Button--outline--secondary--default__color: var(--rui-color-action-secondary); + --rui-Button--outline--secondary--default__border-color: var(--rui-color-action-secondary); + --rui-Button--outline--secondary--default__background: transparent; + --rui-Button--outline--secondary--hover__color: var(--rui-color-action-on-secondary); + --rui-Button--outline--secondary--hover__border-color: var(--rui-color-action-secondary-hover); + --rui-Button--outline--secondary--hover__background: var(--rui-color-action-secondary-hover); + --rui-Button--outline--secondary--active__color: var(--rui-color-action-on-secondary); + --rui-Button--outline--secondary--active__border-color: var(--rui-color-action-secondary-active); + --rui-Button--outline--secondary--active__background: var(--rui-color-action-secondary-active); + + // Buttons: outline priority: selected variant + --rui-Button--outline--selected--default__color: var(--rui-color-action-selected); + --rui-Button--outline--selected--default__border-color: var(--rui-color-action-selected); + --rui-Button--outline--selected--default__background: var(--rui-color-background-selected); + --rui-Button--outline--selected--hover__color: var(--rui-color-action-on-selected); + --rui-Button--outline--selected--hover__border-color: var(--rui-color-action-selected-hover); + --rui-Button--outline--selected--hover__background: var(--rui-color-action-selected-hover); + --rui-Button--outline--selected--active__color: var(--rui-color-action-on-selected); + --rui-Button--outline--selected--active__border-color: var(--rui-color-action-selected-active); + --rui-Button--outline--selected--active__background: var(--rui-color-action-selected-active); + + // Buttons: outline priority: success variant + --rui-Button--outline--success--default__color: var(--rui-color-feedback-success); + --rui-Button--outline--success--default__border-color: var(--rui-color-feedback-success); + --rui-Button--outline--success--default__background: transparent; + --rui-Button--outline--success--hover__color: var(--rui-color-feedback-on-success); + --rui-Button--outline--success--hover__border-color: var(--rui-color-feedback-success-hover); + --rui-Button--outline--success--hover__background: var(--rui-color-feedback-success-hover); + --rui-Button--outline--success--active__color: var(--rui-color-feedback-on-success); + --rui-Button--outline--success--active__border-color: var(--rui-color-feedback-success-active); + --rui-Button--outline--success--active__background: var(--rui-color-feedback-success-active); + + // Buttons: outline priority: warning variant + --rui-Button--outline--warning--default__color: var(--rui-color-feedback-warning); + --rui-Button--outline--warning--default__border-color: var(--rui-color-feedback-warning); + --rui-Button--outline--warning--default__background: transparent; + --rui-Button--outline--warning--hover__color: var(--rui-color-feedback-on-warning); + --rui-Button--outline--warning--hover__border-color: var(--rui-color-feedback-warning-hover); + --rui-Button--outline--warning--hover__background: var(--rui-color-feedback-warning-hover); + --rui-Button--outline--warning--active__color: var(--rui-color-feedback-on-warning); + --rui-Button--outline--warning--active__border-color: var(--rui-color-feedback-warning-active); + --rui-Button--outline--warning--active__background: var(--rui-color-feedback-warning-active); + + // Buttons: outline priority: danger variant + --rui-Button--outline--danger--default__color: var(--rui-color-feedback-danger); + --rui-Button--outline--danger--default__border-color: var(--rui-color-feedback-danger); + --rui-Button--outline--danger--default__background: transparent; + --rui-Button--outline--danger--hover__color: var(--rui-color-feedback-on-danger); + --rui-Button--outline--danger--hover__border-color: var(--rui-color-feedback-danger-hover); + --rui-Button--outline--danger--hover__background: var(--rui-color-feedback-danger-hover); + --rui-Button--outline--danger--active__color: var(--rui-color-feedback-on-danger); + --rui-Button--outline--danger--active__border-color: var(--rui-color-feedback-danger-active); + --rui-Button--outline--danger--active__background: var(--rui-color-feedback-danger-active); + + // Buttons: outline priority: help variant + --rui-Button--outline--help--default__color: var(--rui-color-feedback-help); + --rui-Button--outline--help--default__border-color: var(--rui-color-feedback-help); + --rui-Button--outline--help--default__background: transparent; + --rui-Button--outline--help--hover__color: var(--rui-color-feedback-on-help); + --rui-Button--outline--help--hover__border-color: var(--rui-color-feedback-help-hover); + --rui-Button--outline--help--hover__background: var(--rui-color-feedback-help-hover); + --rui-Button--outline--help--active__color: var(--rui-color-feedback-on-help); + --rui-Button--outline--help--active__border-color: var(--rui-color-feedback-help-active); + --rui-Button--outline--help--active__background: var(--rui-color-feedback-help-active); + + // Buttons: outline priority: info variant + --rui-Button--outline--info--default__color: var(--rui-color-feedback-info); + --rui-Button--outline--info--default__border-color: var(--rui-color-feedback-info); + --rui-Button--outline--info--default__background: transparent; + --rui-Button--outline--info--hover__color: var(--rui-color-feedback-on-info); + --rui-Button--outline--info--hover__border-color: var(--rui-color-feedback-info-hover); + --rui-Button--outline--info--hover__background: var(--rui-color-feedback-info-hover); + --rui-Button--outline--info--active__color: var(--rui-color-feedback-on-info); + --rui-Button--outline--info--active__border-color: var(--rui-color-feedback-info-active); + --rui-Button--outline--info--active__background: var(--rui-color-feedback-info-active); + + // Buttons: outline priority: note variant + --rui-Button--outline--note--default__color: var(--rui-color-feedback-note); + --rui-Button--outline--note--default__border-color: var(--rui-color-feedback-note); + --rui-Button--outline--note--default__background: transparent; + --rui-Button--outline--note--hover__color: var(--rui-color-feedback-on-note); + --rui-Button--outline--note--hover__border-color: var(--rui-color-feedback-note-hover); + --rui-Button--outline--note--hover__background: var(--rui-color-feedback-note-hover); + --rui-Button--outline--note--active__color: var(--rui-color-feedback-on-note); + --rui-Button--outline--note--active__border-color: var(--rui-color-feedback-note-active); + --rui-Button--outline--note--active__background: var(--rui-color-feedback-note-active); + + // Buttons: outline priority: light variant + --rui-Button--outline--light--default__color: var(--rui-color-neutral-light); + --rui-Button--outline--light--default__border-color: var(--rui-color-neutral-light); + --rui-Button--outline--light--default__background: transparent; + --rui-Button--outline--light--hover__color: var(--rui-color-neutral-on-light); + --rui-Button--outline--light--hover__border-color: var(--rui-color-neutral-light-hover); + --rui-Button--outline--light--hover__background: var(--rui-color-neutral-light-hover); + --rui-Button--outline--light--active__color: var(--rui-color-neutral-on-light); + --rui-Button--outline--light--active__border-color: var(--rui-color-neutral-light-active); + --rui-Button--outline--light--active__background: var(--rui-color-neutral-light-active); + + // Buttons: outline priority: dark variant + --rui-Button--outline--dark--default__color: var(--rui-color-neutral-dark); + --rui-Button--outline--dark--default__border-color: var(--rui-color-neutral-dark); + --rui-Button--outline--dark--default__background: transparent; + --rui-Button--outline--dark--hover__color: var(--rui-color-neutral-on-dark); + --rui-Button--outline--dark--hover__border-color: var(--rui-color-neutral-dark-hover); + --rui-Button--outline--dark--hover__background: var(--rui-color-neutral-dark-hover); + --rui-Button--outline--dark--active__color: var(--rui-color-neutral-on-dark); + --rui-Button--outline--dark--active__border-color: var(--rui-color-neutral-dark-active); + --rui-Button--outline--dark--active__background: var(--rui-color-neutral-dark-active); + + // Buttons: flat + + // Buttons: flat priority: primary variant + --rui-Button--flat--primary--default__color: var(--rui-color-action-primary); + --rui-Button--flat--primary--default__background: transparent; + --rui-Button--flat--primary--hover__color: var(--rui-color-action-primary-hover); + --rui-Button--flat--primary--hover__background: var(--rui-color-background-primary); + --rui-Button--flat--primary--active__color: var(--rui-color-action-primary-active); + --rui-Button--flat--primary--active__background: var(--rui-color-background-primary); + + // Buttons: flat priority: secondary variant + --rui-Button--flat--secondary--default__color: var(--rui-color-action-secondary); + --rui-Button--flat--secondary--default__background: transparent; + --rui-Button--flat--secondary--hover__color: var(--rui-color-action-secondary-hover); + --rui-Button--flat--secondary--hover__background: var(--rui-color-background-secondary); + --rui-Button--flat--secondary--active__color: var(--rui-color-action-secondary-active); + --rui-Button--flat--secondary--active__background: var(--rui-color-background-secondary); + + // Buttons: flat priority: selected variant + --rui-Button--flat--selected--default__color: var(--rui-color-action-selected); + --rui-Button--flat--selected--default__background: var(--rui-color-background-selected); + --rui-Button--flat--selected--hover__color: var(--rui-color-action-selected-hover); + --rui-Button--flat--selected--hover__background: var(--rui-color-background-selected); + --rui-Button--flat--selected--active__color: var(--rui-color-action-selected-active); + --rui-Button--flat--selected--active__background: var(--rui-color-background-selected); + + // Buttons: flat priority: success variant + --rui-Button--flat--success--default__color: var(--rui-color-feedback-success); + --rui-Button--flat--success--default__background: transparent; + --rui-Button--flat--success--hover__color: var(--rui-color-feedback-success-hover); + --rui-Button--flat--success--hover__background: var(--rui-color-background-success); + --rui-Button--flat--success--active__color: var(--rui-color-feedback-success-active); + --rui-Button--flat--success--active__background: var(--rui-color-background-success); + + // Buttons: flat priority: warning variant + --rui-Button--flat--warning--default__color: var(--rui-color-feedback-warning); + --rui-Button--flat--warning--default__background: transparent; + --rui-Button--flat--warning--hover__color: var(--rui-color-feedback-warning-hover); + --rui-Button--flat--warning--hover__background: var(--rui-color-background-warning); + --rui-Button--flat--warning--active__color: var(--rui-color-feedback-warning-active); + --rui-Button--flat--warning--active__background: var(--rui-color-background-warning); + + // Buttons: flat priority: danger variant + --rui-Button--flat--danger--default__color: var(--rui-color-feedback-danger); + --rui-Button--flat--danger--default__background: transparent; + --rui-Button--flat--danger--hover__color: var(--rui-color-feedback-danger-hover); + --rui-Button--flat--danger--hover__background: var(--rui-color-background-danger); + --rui-Button--flat--danger--active__color: var(--rui-color-feedback-danger-active); + --rui-Button--flat--danger--active__background: var(--rui-color-background-danger); + + // Buttons: flat priority: help variant + --rui-Button--flat--help--default__color: var(--rui-color-feedback-help); + --rui-Button--flat--help--default__background: transparent; + --rui-Button--flat--help--hover__color: var(--rui-color-feedback-help-hover); + --rui-Button--flat--help--hover__background: var(--rui-color-background-help); + --rui-Button--flat--help--active__color: var(--rui-color-feedback-help-active); + --rui-Button--flat--help--active__background: var(--rui-color-background-help); + + // Buttons: flat priority: info variant + --rui-Button--flat--info--default__color: var(--rui-color-feedback-info); + --rui-Button--flat--info--default__background: transparent; + --rui-Button--flat--info--hover__color: var(--rui-color-feedback-info-hover); + --rui-Button--flat--info--hover__background: var(--rui-color-background-info); + --rui-Button--flat--info--active__color: var(--rui-color-feedback-info-active); + --rui-Button--flat--info--active__background: var(--rui-color-background-info); + + // Buttons: flat priority: note variant + --rui-Button--flat--note--default__color: var(--rui-color-feedback-note); + --rui-Button--flat--note--default__background: transparent; + --rui-Button--flat--note--hover__color: var(--rui-color-feedback-note-hover); + --rui-Button--flat--note--hover__background: var(--rui-color-background-note); + --rui-Button--flat--note--active__color: var(--rui-color-feedback-note-active); + --rui-Button--flat--note--active__background: var(--rui-color-background-note); + + // Buttons: flat priority: light variant + --rui-Button--flat--light--default__color: var(--rui-color-neutral-light); + --rui-Button--flat--light--default__background: transparent; + --rui-Button--flat--light--hover__color: var(--rui-color-neutral-light-hover); + --rui-Button--flat--light--hover__background: var(--rui-color-background-dark); + --rui-Button--flat--light--active__color: var(--rui-color-neutral-light-active); + --rui-Button--flat--light--active__background: var(--rui-color-background-dark); + + // Buttons: flat priority: dark variant + --rui-Button--flat--dark--default__color: var(--rui-color-neutral-dark); + --rui-Button--flat--dark--default__background: transparent; + --rui-Button--flat--dark--hover__color: var(--rui-color-neutral-dark-hover); + --rui-Button--flat--dark--hover__background: var(--rui-color-background-light); + --rui-Button--flat--dark--active__color: var(--rui-color-neutral-dark-active); + --rui-Button--flat--dark--active__background: var(--rui-color-background-light); + + // Buttons: sizes + + // Buttons: sizes: small + --rui-Button--small__height: 1.75rem; + --rui-Button--small__padding-y: var(--rui-dimension-space-1); + --rui-Button--small__padding-x: var(--rui-dimension-space-3); + --rui-Button--small__font-size: var(--rui-font-size-small); + + // Buttons: sizes: medium + --rui-Button--medium__height: 2.25rem; + --rui-Button--medium__padding-y: var(--rui-dimension-space-1); + --rui-Button--medium__padding-x: var(--rui-dimension-space-4); + --rui-Button--medium__font-size: var(--rui-font-size-1); + + // Buttons: sizes: large + --rui-Button--large__height: 2.75rem; + --rui-Button--large__padding-y: var(--rui-dimension-space-2); + --rui-Button--large__padding-x: var(--rui-dimension-space-5); + --rui-Button--large__font-size: var(--rui-font-size-2); + + // + // ButtonGroup + // =========== + + --rui-ButtonGroup__inner-border-radius: 0; + + // ButtonGroup: filled buttons + --rui-ButtonGroup--filled__gap: calc(-1 * var(--rui-Button__border-width)); + --rui-ButtonGroup--filled__separator__width: var(--rui-Button__border-width); + --rui-ButtonGroup--filled__separator__color: currentcolor; + + // ButtonGroup: outline buttons + --rui-ButtonGroup--outline__gap: calc(-1 * var(--rui-Button__border-width)); + --rui-ButtonGroup--outline__separator__width: 0; + --rui-ButtonGroup--outline__separator__color: transparent; + + // ButtonGroup: flat buttons + --rui-ButtonGroup--flat__gap: var(--rui-Button__border-width); + --rui-ButtonGroup--flat__separator__width: var(--rui-ButtonGroup--flat__gap); + --rui-ButtonGroup--flat__separator__color: currentcolor; + + // + // Card + // ==== + + --rui-Card__padding: var(--rui-dimension-space-4); + --rui-Card__border-width: var(--rui-dimension-border-width-1); + --rui-Card__border-radius: var(--rui-dimension-radius-2); + --rui-Card--dense__padding: var(--rui-dimension-space-2); + --rui-Card--raised__box-shadow: var(--rui-shadow-layer-1); + --rui-Card--disabled__background-color: var(--rui-color-background-disabled); + --rui-Card--disabled__opacity: var(--rui-ratio-disabled-opacity); + + // Card: variant: success + --rui-Card--success__color: var(--rui-color-text-primary); + --rui-Card--success__border-color: var(--rui-color-feedback-success); + --rui-Card--success__background-color: var(--rui-color-background-layer-1); + + // Card: variant: warning + --rui-Card--warning__color: var(--rui-color-text-primary); + --rui-Card--warning__border-color: var(--rui-color-feedback-warning); + --rui-Card--warning__background-color: var(--rui-color-background-layer-1); + + // Card: variant: danger + --rui-Card--danger__color: var(--rui-color-text-primary); + --rui-Card--danger__border-color: var(--rui-color-feedback-danger); + --rui-Card--danger__background-color: var(--rui-color-background-layer-1); + + // Card: variant: info + --rui-Card--info__color: var(--rui-color-text-primary); + --rui-Card--info__border-color: var(--rui-color-feedback-info); + --rui-Card--info__background-color: var(--rui-color-background-layer-1); + + // Card: variant: help + --rui-Card--help__color: var(--rui-color-text-primary); + --rui-Card--help__border-color: var(--rui-color-feedback-help); + --rui-Card--help__background-color: var(--rui-color-background-layer-1); + + // Card: variant: note + --rui-Card--note__color: var(--rui-color-text-primary); + --rui-Card--note__border-color: var(--rui-color-feedback-note); + --rui-Card--note__background-color: var(--rui-color-background-layer-1); + + // Card: variant: light + --rui-Card--light__color: var(--rui-color-text-primary); + --rui-Card--light__border-color: var(--rui-color-neutral-light); + --rui-Card--light__background-color: var(--rui-color-background-layer-1); + + // Card: variant: dark + --rui-Card--dark__color: var(--rui-color-neutral-on-dark); + --rui-Card--dark__border-color: var(--rui-color-neutral-on-dark); + --rui-Card--dark__background-color: var(--rui-color-background-dark); + + // + // Form Fields + // =========== + // + // 1. Please note that `min-width` values under cca 150 px do not take effect due to default input + // width defined in browsers unless `width` (same or smaller) is also defined. + // https://stackoverflow.com/questions/36247140/why-dont-flex-items-shrink-past-content-size + // + // 2. Append non-breaking space and asterisk to required filed labels. + // + // 3. Avoid using `fit-content()` for label width, it behaves differently in Chrome vs. FF for + // inline grid. + + // Forms fields: common properties + --rui-FormField__label__color: inherit; + --rui-FormField__label__font-size: var(--rui-font-size-1); + --rui-FormField__help-text__font-size: var(--rui-font-size-small); + --rui-FormField__help-text__font-style: normal; + --rui-FormField__help-text__color: var(--rui-color-text-secondary); + --rui-FormField--required__label__color: inherit; + --rui-FormField--required__sign: "\00a0*"; // 2. + --rui-FormField--required__sign__color: var(--rui-color-text-secondary); + + // Form fields: horizontal layout + --rui-FormField--horizontal__label__text-align: left; + --rui-FormField--horizontal__label__min-width: 0; + --rui-FormField--horizontal__label__width: minmax(auto, 50%); // 3. + --rui-FormField--horizontal__label__vertical-alignment: initial; + --rui-FormField--horizontal__field__vertical-alignment: initial; + --rui-FormField--horizontal--full-width__label__width: fit-content(50%); + + // Forms fields: disabled state + --rui-FormField--disabled__cursor: var(--rui-cursor-not-allowed); + --rui-FormField--disabled__opacity: var(--rui-ratio-disabled-opacity); + + // Form fields: validation states: invalid + --rui-FormField--invalid--default__border-color: var(--rui-color-feedback-danger); + --rui-FormField--invalid--default__background: var(--rui-color-background-danger); + --rui-FormField--invalid--default__check-background-color: var(--rui-FormField--invalid--default__background); + --rui-FormField--invalid--default__surrounding-text-color: var(--rui-color-feedback-danger); + --rui-FormField--invalid--checked__check-background-color: var(--rui-FormField--invalid--default__border-color); + + // Form fields: validation states: valid + --rui-FormField--valid--default__border-color: var(--rui-color-feedback-success); + --rui-FormField--valid--default__background: var(--rui-color-background-success); + --rui-FormField--valid--default__check-background-color: var(--rui-FormField--valid--default__background); + --rui-FormField--valid--default__surrounding-text-color: var(--rui-color-feedback-success); + --rui-FormField--valid--checked__check-background-color: var(--rui-FormField--valid--default__border-color); + + // Form fields: validation states: warning + --rui-FormField--warning--default__border-color: var(--rui-color-feedback-warning-hover); + --rui-FormField--warning--default__background: var(--rui-color-background-warning); + --rui-FormField--warning--default__check-background-color: var(--rui-FormField--warning--default__background); + --rui-FormField--warning--default__surrounding-text-color: var(--rui-color-feedback-warning-active); + --rui-FormField--warning--checked__check-background-color: var(--rui-FormField--warning--default__border-color); + + // Form fields: box fields + --rui-FormField--box__border-width: var(--rui-dimension-border-width-1); + --rui-FormField--box__border-radius: var(--rui-dimension-radius-2); + --rui-FormField--box__input__width: auto; // 1. + --rui-FormField--box__input__min-width: 240px; // 1. + --rui-FormField--box__placeholder__color: var(--rui-color-text-secondary); + --rui-FormField--box--select__caret__border-style: none; + --rui-FormField--box--select__caret__background: transparent; + --rui-FormField--box--select__option--disabled__color: var(--rui-color-text-primary-disabled); + + // Form fields: box field sizes: small + --rui-FormField--box--small__height: var(--rui-Button--small__height); + --rui-FormField--box--small__padding-y: 0.0625rem; + --rui-FormField--box--small__padding-x: var(--rui-dimension-space-2); + --rui-FormField--box--small__font-size: var(--rui-font-size-small); + + // Form fields: box field sizes: medium + --rui-FormField--box--medium__height: var(--rui-Button--medium__height); + --rui-FormField--box--medium__padding-y: 0.3125rem; + --rui-FormField--box--medium__padding-x: var(--rui-dimension-space-3); + --rui-FormField--box--medium__font-size: var(--rui-font-size-1); + + // Form fields: box field sizes: large + --rui-FormField--box--large__height: var(--rui-Button--large__height); + --rui-FormField--box--large__padding-y: 0.5625rem; + --rui-FormField--box--large__padding-x: var(--rui-dimension-space-4); + --rui-FormField--box--large__font-size: var(--rui-font-size-2); + + // Form fields: box field variants: filled variant interaction states + --rui-FormField--box--filled--default__color: var(--rui-color-text-primary); + --rui-FormField--box--filled--default__border-color: var(--rui-color-border-primary); + --rui-FormField--box--filled--default__background: var(--rui-color-background-basic); + --rui-FormField--box--filled--default__box-shadow: none; + --rui-FormField--box--filled--hover__border-color: var(--rui-color-border-primary-hover); + --rui-FormField--box--filled--focus__border-color: var(--rui-color-border-primary-active); + + // Form fields: box field variants: outline variant interaction states + --rui-FormField--box--outline--default__color: var(--rui-color-text-primary); + --rui-FormField--box--outline--default__border-color: var(--rui-color-border-primary); + --rui-FormField--box--outline--default__background: var(--rui-color-background-basic); + --rui-FormField--box--outline--default__box-shadow: none; + --rui-FormField--box--outline--hover__border-color: var(--rui-color-border-primary-hover); + --rui-FormField--box--outline--focus__border-color: var(--rui-color-border-primary-active); + + // Form fields: check fields + --rui-FormField--check__input__size: 1.125rem; + --rui-FormField--check__input__border-width: var(--rui-FormField--box__border-width); + --rui-FormField--check__input--focus__box-shadow: var(--rui-shadow-focus-ring); + --rui-FormField--check__tap-target-size: var(--rui-dimension-tap-target-size); + + // Form fields: check fields, component specific + --rui-FormField--check__input--checkbox__border-radius: var(--rui-FormField--box__border-radius); + --rui-FormField--check__input--checkbox--checked__background-image: #{svg.$checkbox-checked}; + --rui-FormField--check__input--radio__border-radius: 50%; + --rui-FormField--check__input--radio--checked__background-image: #{svg.$radio-checked}; + --rui-FormField--check__input--toggle__width: 2.25rem; + --rui-FormField--check__input--toggle__border-radius: 0.5625rem; + --rui-FormField--check__input--toggle__background-size: contain; + --rui-FormField--check__input--toggle--default__background-image: #{svg.$toggle}; + --rui-FormField--check__input--toggle--default__background-position: left center; + --rui-FormField--check__input--toggle--checked__background-image: #{svg.$toggle-checked}; + --rui-FormField--check__input--toggle--checked__background-position: right center; + + // Form fields: check fields interaction states + --rui-FormField--check--default__border-color: var(--rui-color-border-primary); + --rui-FormField--check--default__check-background-color: var(--rui-color-background-basic); + --rui-FormField--check--checked__border-color: var(--rui-color-action-selected); + --rui-FormField--check--checked__check-background-color: var(--rui-color-action-selected); + + // + // FormLayout + // ========== + + --rui-FormLayout__row-gap: var(--rui-dimension-space-4); + --rui-FormLayout--horizontal__label__width: 10em; + --rui-FormLayout--horizontal__label__width--auto: auto; + --rui-FormLayout--horizontal__label__width--limited: fit-content(50%); + + // + // InputGroup + // ======= + + --rui-InputGroup__gap: var(--rui-dimension-space-1); + --rui-InputGroup__inner-border-radius: var(--rui-dimension-radius-1); + + // + // Modal + // ===== + + --rui-Modal__padding-x: var(--rui-dimension-space-4); + --rui-Modal__padding-y: var(--rui-dimension-space-4); + --rui-Modal__background: var(--rui-color-background-layer-2); + --rui-Modal__box-shadow: var(--rui-shadow-layer-2); + --rui-Modal__separator__width: var(--rui-dimension-border-width-1); + --rui-Modal__separator__color: var(--rui-color-border-secondary); + --rui-Modal__header__gap: var(--rui-dimension-space-2); + --rui-Modal__outer-spacing--xs: var(--rui-dimension-space-2); + --rui-Modal__outer-spacing--sm: var(--rui-dimension-space-6); + --rui-Modal__footer__background: var(--rui-Modal__background); + --rui-Modal__footer__gap: var(--rui-dimension-space-2); + --rui-Modal__backdrop__background: rgb(0 0 0 / 50%); + --rui-Modal--auto__min-width: 18rem; + --rui-Modal--auto__max-width: 60rem; + --rui-Modal--small__width: 20rem; + --rui-Modal--medium__width: 40rem; + --rui-Modal--large__width: 60rem; + --rui-Modal--fullscreen__width: 100%; + --rui-Modal--fullscreen__height: 100%; + + // + // Paper + // ===== + + --rui-Paper__padding: var(--rui-dimension-space-4); + --rui-Paper__border-width: 0; + --rui-Paper__border-color: transparent; + --rui-Paper__border-radius: var(--rui-dimension-radius-2); + --rui-Paper__background-color: var(--rui-color-background-layer-1); + --rui-Paper--muted__background-color: var(--rui-color-background-disabled); + --rui-Paper--muted__opacity: var(--rui-ratio-disabled-opacity); + --rui-Paper--raised__box-shadow: var(--rui-shadow-layer-1); + + // + // Popover + // ======= + + --rui-Popover__max-width: 15rem; + --rui-Popover__padding: var(--rui-dimension-space-3); + --rui-Popover__border-width: 0; + --rui-Popover__border-color: transparent; + --rui-Popover__border-radius: var(--rui-dimension-radius-2); + --rui-Popover__color: var(--rui-color-text-primary); + --rui-Popover__background-color: var(--rui-color-background-layer-2); + --rui-Popover__box-shadow: var(--rui-shadow-layer-2); + + // + // Tabs + // ==== + + --rui-Tabs__border-bottom-width: var(--rui-dimension-border-width-1); + --rui-Tabs__border-bottom-color: var(--rui-color-border-primary); + --rui-Tabs__gap--xs: var(--rui-dimension-space-1); + --rui-Tabs__gap--sm: var(--rui-dimension-space-1); + --rui-Tabs__gap--md: var(--rui-dimension-space-1); + --rui-Tabs__padding-x: 0; + + // Tabs items + --rui-Tabs__item__padding--xs: var(--rui-dimension-space-3); + --rui-Tabs__item__padding--sm: var(--rui-dimension-space-4); + --rui-Tabs__item__padding--md: var(--rui-dimension-space-4); + --rui-Tabs__item__font-weight: inherit; + --rui-Tabs__item__color: var(--rui-color-text-secondary); + --rui-Tabs__item__border-width: var(--rui-dimension-border-width-1); + --rui-Tabs__item__border-color: + var(--rui-color-border-secondary) + var(--rui-color-border-secondary) + transparent + var(--rui-color-border-secondary); + --rui-Tabs__item__border-radius: var(--rui-dimension-radius-2); + --rui-Tabs__item__background-color: var(--rui-color-background-layer-1); + --rui-Tabs__item__box-shadow: none; + --rui-Tabs__item__icon__gap: var(--rui-dimension-space-2); + + // Tabs items: hover + --rui-Tabs__item--hover__font-weight: var(--rui-Tabs__item__font-weight); + --rui-Tabs__item--hover__color: var(--rui-Tabs__item__color); + --rui-Tabs__item--hover__border-width: var(--rui-Tabs__item__border-width); + --rui-Tabs__item--hover__border-color: var(--rui-Tabs__item__border-color); + --rui-Tabs__item--hover__background-color: var(--rui-Tabs__item__background-color); + --rui-Tabs__item--hover__box-shadow: var(--rui-Tabs__item__box-shadow); + --rui-Tabs__item--hover__shift-y: -0.15rem; + --rui-Tabs__item--hover__label__shift-y: 0; + + // Tabs items: active + --rui-Tabs__item--active__font-weight: inherit; + --rui-Tabs__item--active__color: var(--rui-color-text-primary); + --rui-Tabs__item--active__border-width: var(--rui-Tabs__item__border-width); + --rui-Tabs__item--active__border-color: + var(--rui-Tabs__border-bottom-color) + var(--rui-Tabs__border-bottom-color) + transparent + var(--rui-Tabs__border-bottom-color); + --rui-Tabs__item--active__background-color: var(--rui-Tabs__item__background-color); + --rui-Tabs__item--active__box-shadow: var(--rui-Tabs__item__box-shadow); + --rui-Tabs__item--active__shift-y: -0.25em; + --rui-Tabs__item--active__label__shift-y: 0; + + // + // TextLink + // ======== + + --rui-TextLink__color: var(--rui-color-text-link); + --rui-TextLink__text-decoration: var(--rui-text-decoration-link); + --rui-TextLink--hover__color: var(--rui-color-text-link-hover); + --rui-TextLink--hover__text-decoration: var(--rui-text-decoration-link-hover); + --rui-TextLink--active__color: var(--rui-color-text-link-active); + --rui-TextLink--active__text-decoration: var(--rui-text-decoration-link-active); + + // + // Toolbar + // ======= + + --rui-Toolbar__gap: var(--rui-dimension-space-4); + --rui-Toolbar__gap--dense: var(--rui-dimension-space-2); + } } diff --git a/webpack.config.babel.js b/webpack.config.babel.js index 17f8bc0b..6130f7e7 100644 --- a/webpack.config.babel.js +++ b/webpack.config.babel.js @@ -45,6 +45,7 @@ module.exports = (env, argv) => ({ loader: 'css-loader', options: { modules: { + auto: true, // Enable CSS Modules only for files with `.module.*` extension localIdentName: argv.mode === 'production' ? '[hash:base64:8]' : '[name]__[local]__[hash:base64:8]',