Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce theming of Badge color variants #562

Merged
merged 2 commits into from
Sep 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions src/components/Alert/__tests__/Alert.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import {
within,
} from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { colorPropTest } from '../../../../tests/propTests/colorPropTest';
import { feedbackColorPropTest } from '../../../../tests/propTests/feedbackColorPropTest';
import { neutralColorPropTest } from '../../../../tests/propTests/neutralColorPropTest';
import defaultTranslations from '../../../translations/en';
import { Alert } from '../Alert';

Expand All @@ -20,7 +21,8 @@ describe('rendering', () => {
{ children: <div>content text</div> },
(rootElement) => expect(within(rootElement).getByText('content text')),
],
...colorPropTest,
...feedbackColorPropTest,
...neutralColorPropTest,
[
{ icon: (<div>icon</div>) },
(rootElement) => expect(within(rootElement).getByText('icon')),
Expand Down
3 changes: 2 additions & 1 deletion src/components/Badge/Badge.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ Badge.defaultProps = {

Badge.propTypes = {
/**
* [Color variant](/docs/foundation/colors#component-colors) to clarify importance and meaning of the badge.
* Color to clarify importance and meaning of the badge. Implements
* [Feedback and Neutral color collections](/docs/foundation/collections#colors).
*/
color: PropTypes.oneOf(['success', 'warning', 'danger', 'help', 'info', 'note', 'light', 'dark']),
/**
Expand Down
97 changes: 26 additions & 71 deletions src/components/Badge/Badge.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
@use "sass:math";
@use "../../styles/theme/borders";
@use "../../styles/theme/typography";

$_badge-size: 1.25rem;
@use "../../styles/tools/collections";
@use "settings";

@layer components.badge {
.root {
display: inline-block;
min-width: $_badge-size;
height: $_badge-size;
min-width: settings.$badge-size;
height: settings.$badge-size;
padding: 0.25rem 0.35rem;
overflow: hidden;
font-weight: map.get(typography.$font-weight-values, bold);
Expand All @@ -19,53 +19,28 @@ $_badge-size: 1.25rem;
white-space: nowrap;
vertical-align: baseline;
color: var(--rui-local-color);
border-radius: math.div($_badge-size, 2);
border-radius: math.div(settings.$badge-size, 2);
}

.isRootPriorityFilled {
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;
@each $color in settings.$colors {
@include collections.generate-properties(
$prefix: "rui-",
$component-name: "Badge",
$modifier-name: "priority",
$modifier-value: "filled",
$variant-name: "color",
$variant-value: $color,
$properties: settings.$themeable-properties-filled,
);
}

.isRootColorLight,
.isRootColorDark {
--rui-local-color: var(--rui-color-neutral-on-dark);
--rui-local-background-color: var(--rui-color-neutral-dark);
--rui-local-box-shadow: none;
}

Expand All @@ -75,35 +50,15 @@ $_badge-size: 1.25rem;
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);
@each $color in settings.$colors {
@include collections.generate-properties(
$prefix: "rui-",
$component-name: "Badge",
$modifier-name: "priority",
$modifier-value: "outline",
$variant-name: "color",
$variant-value: $color,
$properties: settings.$themeable-properties-outline,
);
}
}
21 changes: 19 additions & 2 deletions src/components/Badge/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ lowest:
1. filled
2. outline

All priorities come in supported
[component colors](/docs/foundation/colors#component-colors).
All priorities are available in colors from supported
[color collections](/docs/foundation/collections#colors).
Check [API](#api) to see which collections are supported.

### Filled

Expand Down Expand Up @@ -102,5 +103,21 @@ helps to improve its accessibility.

<docoff-react-props src="/components/Badge/Badge.jsx" />

## Theming
bedrich-schindler marked this conversation as resolved.
Show resolved Hide resolved

It's possible to adjust the theme of specific badge color variant. Naming
convention looks as follows:

`--rui-Badge--<PRIORITY>--<COLOR>__<PROPERTY>`

Where:

- `<PRIORITY>` is one of `filled` or `outline`,
- `<COLOR>` is a value from supported
[color collections](/docs/foundation/collections#colors)
(check [API](#api) to see which collections are supported),
- `<PROPERTY>` is one of `color` (color of text) or `background-color` for the
filled priority, or just `color` for the outline priority.

[div-attributes]: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/div#attributes
[React common props]: https://react.dev/reference/react-dom/components/common#common-props
6 changes: 4 additions & 2 deletions src/components/Badge/__tests__/Badge.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {
render,
within,
} from '@testing-library/react';
import { colorPropTest } from '../../../../tests/propTests/colorPropTest';
import { feedbackColorPropTest } from '../../../../tests/propTests/feedbackColorPropTest';
import { neutralColorPropTest } from '../../../../tests/propTests/neutralColorPropTest';
import { Badge } from '../Badge';

const mandatoryProps = {
Expand All @@ -12,7 +13,8 @@ const mandatoryProps = {

describe('rendering', () => {
it.each([
...colorPropTest,
...feedbackColorPropTest,
...neutralColorPropTest,
[
{ label: 'label text' },
(rootElement) => expect(within(rootElement).getByText('label text')),
Expand Down
8 changes: 8 additions & 0 deletions src/components/Badge/_settings.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
@use "sass:list";
@use "../../styles/settings/collections";

$badge-size: 1.25rem;

$colors: list.join(collections.$feedback-colors, collections.$neutral-colors);
$themeable-properties-filled: color, background-color;
$themeable-properties-outline: color;
6 changes: 4 additions & 2 deletions src/components/Button/__tests__/Button.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
import userEvent from '@testing-library/user-event';
import { actionColorPropTest } from '../../../../tests/propTests/actionColorPropTest';
import { blockPropTest } from '../../../../tests/propTests/blockPropTest';
import { colorPropTest } from '../../../../tests/propTests/colorPropTest';
import { feedbackColorPropTest } from '../../../../tests/propTests/feedbackColorPropTest';
import { neutralColorPropTest } from '../../../../tests/propTests/neutralColorPropTest';
import { refPropTest } from '../../../../tests/propTests/refPropTest';
import { labelPropTest } from '../../../../tests/propTests/labelPropTest';
import { sizePropTest } from '../../../../tests/propTests/sizePropTest';
Expand Down Expand Up @@ -67,7 +68,8 @@ describe('rendering', () => {
],
...actionColorPropTest,
...blockPropTest,
...colorPropTest,
...feedbackColorPropTest,
...neutralColorPropTest,
[
{ disabled: true },
(rootElement) => expect(rootElement).toBeDisabled(),
Expand Down
6 changes: 4 additions & 2 deletions src/components/Card/__tests__/Card.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import {
render,
within,
} from '@testing-library/react';
import { colorPropTest } from '../../../../tests/propTests/colorPropTest';
import { feedbackColorPropTest } from '../../../../tests/propTests/feedbackColorPropTest';
import { neutralColorPropTest } from '../../../../tests/propTests/neutralColorPropTest';
import { raisedPropTest } from '../../../../tests/propTests/raisedPropTest';
import { ScrollView } from '../../ScrollView';
import { Card } from '../Card';
Expand Down Expand Up @@ -33,7 +34,8 @@ describe('rendering', () => {
{ children: <ScrollView>scroll view content</ScrollView> },
(rootElement) => expect(within(rootElement).getByText('scroll view content')),
],
...colorPropTest,
...feedbackColorPropTest,
...neutralColorPropTest,
...densePropTest('Root'),
[
{ disabled: true },
Expand Down
36 changes: 36 additions & 0 deletions src/styles/tools/_collections.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@use "string" as rui-string;

@mixin generate-properties(
$prefix,
$component-name,
$modifier-name: null,
$modifier-value: null,
$variant-name,
$variant-value,
$properties,
) {
$combined-class-name:
if(
$modifier-name and $modifier-value,
".isRoot#{rui-string.capitalize($modifier-name)}#{rui-string.capitalize($modifier-value)}",
""
);

#{$combined-class-name}.isRoot#{rui-string.capitalize($variant-name)}#{rui-string.capitalize($variant-value)} {
@each $property in $properties {
--#{$prefix}local-#{$property}:
var(
#{
"--"
+ $prefix
+ $component-name
+ if($modifier-value, "--" + $modifier-value, "")
+ "--"
+ $variant-value
+ "__"
+ $property
}
);
}
}
}
7 changes: 5 additions & 2 deletions src/styles/tools/_string.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
// Author: Hugo Giraudel

@use "sass:string";

@function capitalize($string) {
@return string.to-upper-case(string.slice($string, 1, 1)) + string.slice($string, 2);
}

// Author: Hugo Giraudel
@function replace($string, $search, $replace: "") {
$index: string.index($string, $search);

Expand Down
64 changes: 64 additions & 0 deletions src/theme.scss
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,70 @@
--rui-Alert--dark__foreground-color: var(--rui-color-neutral-on-dark);
--rui-Alert--dark__background-color: var(--rui-color-background-dark);

//
// Badge
// =====

// Badge: filled priority

// Badge: filled priority: success variant
--rui-Badge--filled--success__color: var(--rui-color-feedback-on-success);
--rui-Badge--filled--success__background-color: var(--rui-color-feedback-success);

// Badge: filled priority: warning variant
--rui-Badge--filled--warning__color: var(--rui-color-feedback-on-warning);
--rui-Badge--filled--warning__background-color: var(--rui-color-feedback-warning);

// Badge: filled priority: danger variant
--rui-Badge--filled--danger__color: var(--rui-color-feedback-on-danger);
--rui-Badge--filled--danger__background-color: var(--rui-color-feedback-danger);

// Badge: filled priority: help variant
--rui-Badge--filled--help__color: var(--rui-color-feedback-on-help);
--rui-Badge--filled--help__background-color: var(--rui-color-feedback-help);

// Badge: filled priority: info variant
--rui-Badge--filled--info__color: var(--rui-color-feedback-on-info);
--rui-Badge--filled--info__background-color: var(--rui-color-feedback-info);

// Badge: filled priority: note variant
--rui-Badge--filled--note__color: var(--rui-color-feedback-on-note);
--rui-Badge--filled--note__background-color: var(--rui-color-feedback-note);

// Badge: filled priority: light variant
--rui-Badge--filled--light__color: var(--rui-color-neutral-on-light);
--rui-Badge--filled--light__background-color: var(--rui-color-neutral-light);

// Badge: filled priority: dark variant
--rui-Badge--filled--dark__color: var(--rui-color-neutral-on-dark);
--rui-Badge--filled--dark__background-color: var(--rui-color-neutral-dark);

// Badge: outline priority

// Badge: outline priority: success variant
--rui-Badge--outline--success__color: var(--rui-color-feedback-success);

// Badge: outline priority: warning variant
--rui-Badge--outline--warning__color: var(--rui-color-feedback-warning);

// Badge: outline priority: danger variant
--rui-Badge--outline--danger__color: var(--rui-color-feedback-danger);

// Badge: outline priority: help variant
--rui-Badge--outline--help__color: var(--rui-color-feedback-help);

// Badge: outline priority: info variant
--rui-Badge--outline--info__color: var(--rui-color-feedback-info);

// Badge: outline priority: note variant
--rui-Badge--outline--note__color: var(--rui-color-feedback-note);

// Badge: outline priority: light variant
--rui-Badge--outline--light__color: var(--rui-color-neutral-light);

// Badge: outline priority: dark variant
--rui-Badge--outline--dark__color: var(--rui-color-neutral-dark);

//
// Button
// ======
Expand Down
Loading