From ff626cc7cd8efd786c65491db2861d4d99489be0 Mon Sep 17 00:00:00 2001 From: Adam Kudrna Date: Fri, 21 Mar 2025 18:38:20 +0100 Subject: [PATCH 1/2] Add description of our color collections so it's clearer when they can be used --- src/docs/foundation/collections.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/docs/foundation/collections.md b/src/docs/foundation/collections.md index 62a6e08bf..3029778a5 100644 --- a/src/docs/foundation/collections.md +++ b/src/docs/foundation/collections.md @@ -17,8 +17,8 @@ used to ensure consistency across the design system. The following color names are designed for use in components that support the `color` prop: -| Collection | Available values | -|------------|--------------------------------------------------------| -| Action | `primary`, `secondary`, `selected` | -| Feedback | `success`, `warning`, `danger`, `info`, `help`, `note` | -| Neutral | `light`, `dark` | +| Collection | Available values | Description | +|------------|--------------------------------------------------------|----------------------------------------------------------------------------------| +| Action | `primary`, `secondary`, `selected` | Reserved for actionable elements, such as buttons and navigation links | +| Feedback | `success`, `warning`, `danger`, `info`, `help`, `note` | For components with feedback state, such as alerts and badges | +| Neutral | `light`, `dark` | For components that require a neutral background color, such as cards and badges | From 30286316f550fcec59cb3fb7863ed1e3dcbda54a Mon Sep 17 00:00:00 2001 From: Adam Kudrna Date: Mon, 24 Mar 2025 12:34:37 +0100 Subject: [PATCH 2/2] Introduce `color` property to the `Modal` component (#468) `Modal` can now be colored via the `color` prop, using a value from the Feedback Colors collection. --- src/components/Modal/Modal.jsx | 12 +++ src/components/Modal/Modal.module.scss | 11 +++ src/components/Modal/ModalBody.module.scss | 18 ++++ src/components/Modal/ModalFooter.module.scss | 8 +- src/components/Modal/ModalHeader.module.scss | 9 +- src/components/Modal/README.md | 99 +++++++++++++++++++ src/components/Modal/__tests__/Modal.test.jsx | 2 + src/components/Modal/_settings.scss | 4 + src/theme.scss | 24 +++++ 9 files changed, 184 insertions(+), 3 deletions(-) diff --git a/src/components/Modal/Modal.jsx b/src/components/Modal/Modal.jsx index fded1f0b0..19e95ef3e 100644 --- a/src/components/Modal/Modal.jsx +++ b/src/components/Modal/Modal.jsx @@ -9,6 +9,7 @@ import { createPortal } from 'react-dom'; import { classNames } from '../../helpers/classNames'; import { transferProps } from '../../helpers/transferProps'; import { withGlobalProps } from '../../providers/globalProps'; +import { getRootColorClassName } from '../_helpers/getRootColorClassName'; import { dialogOnCancelHandler } from './_helpers/dialogOnCancelHandler'; import { dialogOnClickHandler } from './_helpers/dialogOnClickHandler'; import { dialogOnCloseHandler } from './_helpers/dialogOnCloseHandler'; @@ -21,6 +22,7 @@ import styles from './Modal.module.scss'; const preRender = ( children, + color, dialogRef, position, size, @@ -32,6 +34,7 @@ const preRender = ( {...transferProps(events)} className={classNames( styles.root, + color && getRootColorClassName(color, styles), getSizeClassName(size, styles), getPositionClassName(position, styles), )} @@ -48,6 +51,7 @@ export const Modal = ({ autoFocus, children, closeButtonRef, + color, dialogRef, portalId, position, @@ -107,6 +111,7 @@ export const Modal = ({ if (portalId === null) { return preRender( children, + color, internalDialogRef, position, size, @@ -118,6 +123,7 @@ export const Modal = ({ return createPortal( preRender( children, + color, internalDialogRef, position, size, @@ -135,6 +141,7 @@ Modal.defaultProps = { autoFocus: true, children: null, closeButtonRef: null, + color: undefined, dialogRef: null, portalId: null, position: 'center', @@ -180,6 +187,11 @@ Modal.propTypes = { // eslint-disable-next-line react/forbid-prop-types current: PropTypes.any, }), + /** + * Color to clarify importance and meaning of the modal. Implements + * [Feedback color collection](/docs/foundation/collections#colors). + */ + color: PropTypes.oneOf(['success', 'warning', 'danger', 'help', 'info', 'note']), /** * Reference to dialog element */ diff --git a/src/components/Modal/Modal.module.scss b/src/components/Modal/Modal.module.scss index a340ac766..4afb7d0fb 100644 --- a/src/components/Modal/Modal.module.scss +++ b/src/components/Modal/Modal.module.scss @@ -7,6 +7,7 @@ @use "../../styles/theme/typography"; @use "../../styles/tools/accessibility"; @use "../../styles/tools/breakpoint"; +@use "../../styles/tools/collections"; @use "../../styles/tools/reset"; @use "../../styles/tools/spacing"; @use "animations"; @@ -82,4 +83,14 @@ top: var(--rui-local-outer-spacing); bottom: auto; } + + @each $color in settings.$colors { + @include collections.generate-class( + $prefix: "rui-", + $component-name: "Modal", + $variant-name: "color", + $variant-value: $color, + $properties: settings.$themeable-properties, + ); + } } diff --git a/src/components/Modal/ModalBody.module.scss b/src/components/Modal/ModalBody.module.scss index 06f2340c8..5cdecbd2d 100644 --- a/src/components/Modal/ModalBody.module.scss +++ b/src/components/Modal/ModalBody.module.scss @@ -1,6 +1,24 @@ +// 1. Intentionally do not provide a fallback value for the border color. Setting a fallback value (e.g. `transparent`) +// will result in the border being skewed at both ends. + +@use "settings"; + @layer components.modal { .root { flex: 1 1 auto; + border-inline: settings.$border-width solid var(--rui-local-border-color); // 1. + + &:first-child { + border-top: settings.$border-width solid var(--rui-local-border-color); // 1. + border-top-left-radius: settings.$border-radius; + border-top-right-radius: settings.$border-radius; + } + + &:last-child { + border-bottom: settings.$border-width solid var(--rui-local-border-color); // 1. + border-bottom-right-radius: settings.$border-radius; + border-bottom-left-radius: settings.$border-radius; + } } .isRootScrollingAuto, diff --git a/src/components/Modal/ModalFooter.module.scss b/src/components/Modal/ModalFooter.module.scss index 922d2c195..4702d028b 100644 --- a/src/components/Modal/ModalFooter.module.scss +++ b/src/components/Modal/ModalFooter.module.scss @@ -1,3 +1,6 @@ +// 1. Intentionally do not provide a fallback value for the border color. Setting a fallback value (e.g. `transparent`) +// will result in the border being skewed at both ends. + @use "settings"; @use "theme"; @@ -9,10 +12,11 @@ gap: theme.$footer-gap; align-items: center; padding: theme.$padding-y theme.$padding-x; - border-top: theme.$separator-width solid theme.$separator-color; + border: settings.$border-width solid var(--rui-local-border-color); // 1. + border-top: theme.$separator-width solid var(--rui-local-border-color, #{theme.$separator-color}); border-bottom-right-radius: settings.$border-radius; border-bottom-left-radius: settings.$border-radius; - background: theme.$footer-background; + background: var(--rui-local-background-color, #{theme.$footer-background}); } .isRootJustifiedToStart { diff --git a/src/components/Modal/ModalHeader.module.scss b/src/components/Modal/ModalHeader.module.scss index 116d55d59..a11ec02fa 100644 --- a/src/components/Modal/ModalHeader.module.scss +++ b/src/components/Modal/ModalHeader.module.scss @@ -1,3 +1,7 @@ +// 1. Intentionally do not provide a fallback value for the border color. Setting a fallback value (e.g. `transparent`) +// will result in the border being skewed at both ends. + +@use "settings"; @use "theme"; @layer components.modal { @@ -7,7 +11,10 @@ gap: theme.$header-gap; align-items: baseline; padding: theme.$padding-y theme.$padding-x; - border-bottom: theme.$separator-width solid theme.$separator-color; + border: settings.$border-width solid var(--rui-local-border-color); // 1. + border-bottom: theme.$separator-width solid var(--rui-local-border-color, #{theme.$separator-color}); + border-top-left-radius: settings.$border-radius; + border-top-right-radius: settings.$border-radius; } .isRootJustifiedToStart { diff --git a/src/components/Modal/README.md b/src/components/Modal/README.md index b2e7376e0..77fb431b2 100644 --- a/src/components/Modal/README.md +++ b/src/components/Modal/README.md @@ -690,6 +690,90 @@ React.createElement(() => { }); ``` +## Color Variants + +Modal can be colored using the `color` prop. The `color` prop implements the +[Feedback color collection](/docs/foundation/collections#colors) +and is applied to the border of the modal and the modal footer. + +```docoff-react-preview +React.createElement(() => { + const [modalOpen, setModalOpen] = React.useState(false); + const [modalColor, setModalColor] = React.useState('success'); + const modalCloseButtonRef = React.useRef(); + {/* + The `preventScrollUnderneath` feature is necessary for Modals to work in + React UI docs. You may not need it in your application. + */} + return ( + +