From 4bcc9f711ed19da82e0f300ef76af6842c2dece0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Aliz=C3=A9=20Debray?=
<33580481+alizedebray@users.noreply.github.com>
Date: Fri, 5 Apr 2024 10:25:44 +0200
Subject: [PATCH] feat(styles, docs): update badges (#2860)
---
.changeset/dry-wasps-film.md | 6 +
.../background-colors.module.scss} | 0
.../src/shared/decorators/dark-background.ts | 10 +
.../stories/components/badge/badge.docs.mdx | 37 ++-
.../badge/badge.snapshot.stories.ts | 12 +-
.../stories/components/badge/badge.stories.ts | 241 ++++++------------
.../card-control/card-control.stories.ts | 11 +-
.../cards/card-button/card-button.stories.ts | 4 +-
packages/styles/src/components/badge.scss | 100 ++------
packages/styles/src/placeholders/_badge.scss | 2 +-
.../src/variables/components/_badge.scss | 37 ++-
11 files changed, 157 insertions(+), 303 deletions(-)
create mode 100644 .changeset/dry-wasps-film.md
rename packages/documentation/src/{stories/components/cards/card-button/card-button.module.scss => shared/background-colors.module.scss} (100%)
create mode 100644 packages/documentation/src/shared/decorators/dark-background.ts
diff --git a/.changeset/dry-wasps-film.md b/.changeset/dry-wasps-film.md
new file mode 100644
index 0000000000..335ab35008
--- /dev/null
+++ b/.changeset/dry-wasps-film.md
@@ -0,0 +1,6 @@
+---
+'@swisspost/design-system-styles': major
+'@swisspost/design-system-documentation': patch
+---
+
+Restricted the badge to showing counts only and updated the styles accordingly.
diff --git a/packages/documentation/src/stories/components/cards/card-button/card-button.module.scss b/packages/documentation/src/shared/background-colors.module.scss
similarity index 100%
rename from packages/documentation/src/stories/components/cards/card-button/card-button.module.scss
rename to packages/documentation/src/shared/background-colors.module.scss
diff --git a/packages/documentation/src/shared/decorators/dark-background.ts b/packages/documentation/src/shared/decorators/dark-background.ts
new file mode 100644
index 0000000000..73b82b8680
--- /dev/null
+++ b/packages/documentation/src/shared/decorators/dark-background.ts
@@ -0,0 +1,10 @@
+import { StoryContext, StoryFn } from '@storybook/web-components';
+import { html } from 'lit';
+
+export function coloredBackground(story: StoryFn, context: StoryContext, color: string) {
+ return html`
+
- Documentation and examples for badges, our small count and labeling component.
+ Highlight a numerical characteristic or mark an item with a status.
-
@@ -31,17 +20,23 @@ import StylesPackageImport from '../../../shared/styles-package-import.mdx';
## Examples
-### Checkable
+### Colors
+
+You can change the badge color simply by applying a `.bg-*` class to it.
+See all available classes in the [background utilities documentation](/?path=/docs/60852fac-a861-4415-8276-bd38d68653bb--docs).
+
+
+
+### Large number
-Checkable badges are nothing more than personalized checkboxes.
-Therefore, you can handle then like standard checkboxes.
+A large number will extend the badge with.
+To prevent the badge from being too large you can simply use the `+` notation as shown hereafter.
-
+
-### Dismissible
+### Position
-Dismissible badges include a close button, allowing users to easily clear them from the page.
-Because the close button does not have a visible text,
-it should always include a visually hidden label to ensure accessibility for assistive technology users.
+As inline elements, the badges can be placed inside other element such as tags.
+They can also be place absolutely to appear above other elements such as icons for example.
-
+
diff --git a/packages/documentation/src/stories/components/badge/badge.snapshot.stories.ts b/packages/documentation/src/stories/components/badge/badge.snapshot.stories.ts
index 3a90dca504..2181c8b0c6 100644
--- a/packages/documentation/src/stories/components/badge/badge.snapshot.stories.ts
+++ b/packages/documentation/src/stories/components/badge/badge.snapshot.stories.ts
@@ -20,17 +20,11 @@ export const Badge: Story = {
bg => html`
${bombArgs({
- text: [
- 'Malakceptebla Insigno',
- 'Contentus momentus vero siteos et accusam iretea et justo.',
- ],
+ showNumber: [true, false],
size: context.argTypes.size.options,
- interactionType: context.argTypes.interactionType.options,
- nestedBadge: [false, true],
- checked: [false, true],
- dismissed: [false],
+ background: context.argTypes.background.options,
})
- .filter(args => !(args.interactionType !== 'checkable' && args.checked === true))
+ .filter(args => !(!args.showNumber && args.size === 'small'))
.map((args: Args) => meta.render?.({ ...context.args, ...args }, context))}
`,
diff --git a/packages/documentation/src/stories/components/badge/badge.stories.ts b/packages/documentation/src/stories/components/badge/badge.stories.ts
index 2be92512ef..1173ce76e2 100644
--- a/packages/documentation/src/stories/components/badge/badge.stories.ts
+++ b/packages/documentation/src/stories/components/badge/badge.stories.ts
@@ -1,32 +1,41 @@
-import { useArgs } from '@storybook/preview-api';
-import type { Args, StoryContext, StoryObj } from '@storybook/web-components';
+import { Args, StoryContext, StoryFn, StoryObj } from '@storybook/web-components';
import { html, nothing } from 'lit';
-import { mapClasses } from '../../../utils';
import { MetaComponent } from '../../../../types';
+import backgroundColors from '../../../shared/background-colors.module.scss';
+import { coloredBackground } from '../../../shared/decorators/dark-background';
const meta: MetaComponent = {
id: 'bec68e8b-445e-4760-8bd7-1b9970206d8d',
title: 'Components/Badge',
tags: ['package:HTML'],
render: renderBadge,
- decorators: [externalControl],
- parameters: {
- badges: [],
- },
+ decorators: [adaptiveBackground],
args: {
- text: 'Insigno',
- size: 'default',
- nestedBadge: false,
- interactionType: 'none',
- checked: false,
- dismissed: false,
+ showNumber: true,
+ number: 1,
+ size: 'large',
},
argTypes: {
- text: {
- name: 'Text',
- description: 'The text contained in the badge.',
+ showNumber: {
+ name: 'Show Number',
+ description: 'If `true`, the badge contains a number otherwise it is empty.',
+ control: {
+ type: 'boolean',
+ },
+ table: {
+ category: 'Content',
+ },
+ },
+ number: {
+ name: 'Number',
+ description: 'The number contained in the badge.',
+ if: {
+ arg: 'showNumber',
+ truthy: true,
+ },
control: {
- type: 'text',
+ type: 'number',
+ min: 0,
},
table: {
category: 'Content',
@@ -35,161 +44,51 @@ const meta: MetaComponent = {
size: {
name: 'Size',
description: 'The size of the badge.',
+ if: {
+ arg: 'showNumber',
+ truthy: true,
+ },
control: {
type: 'radio',
labels: {
- 'default': 'Default',
+ 'large': 'Large',
'badge-sm': 'Small',
},
},
- options: ['default', 'badge-sm'],
+ options: ['large', 'badge-sm'],
table: {
category: 'General',
},
},
- nestedBadge: {
- name: 'Nested Badge',
- description: 'If `true`, a nested badge is displayed inside the main badge.',
+ background: {
+ name: 'Backround',
+ description: 'You can use the Background classes to color the cards',
control: {
- type: 'boolean',
+ type: 'select',
},
+ options: Object.keys(backgroundColors),
table: {
category: 'General',
},
},
- interactionType: {
- name: 'Interaction Type',
- description: 'Defines how the badge can be interacted with.',
- control: {
- type: 'inline-radio',
- labels: {
- none: 'None',
- checkable: 'Checkable',
- dismissible: 'Dismissible',
- },
- },
- options: ['none', 'checkable', 'dismissible'],
- table: {
- category: 'Interactions',
- },
- },
- checked: {
- name: 'Checked',
- description: 'If `true`, the badge is checked otherwise it is unchecked.',
- if: {
- arg: 'interactionType',
- eq: 'checkable',
- },
- control: {
- type: 'boolean',
- },
- table: {
- category: 'Interactions',
- },
- },
- dismissed: {
- name: 'Dismissed',
- description: 'If `true`, the badge is removed from the page otherwise it is displayed.',
- if: {
- arg: 'interactionType',
- eq: 'dismissible',
- },
- control: {
- type: 'boolean',
- },
- table: {
- category: 'Interactions',
- },
- },
},
};
export default meta;
// DECORATORS
-function externalControl(story: any, { args }: StoryContext) {
- const [_, updateArgs] = useArgs();
-
- const button = html`
-
{
- e.preventDefault();
- updateArgs({ dismissed: false });
- }}"
- >
- Show badge
-
- `;
-
- return html` ${args.dismissed ? button : nothing} ${story()} `;
+function adaptiveBackground(story: StoryFn, context: StoryContext) {
+ const { args } = context;
+ const isLight = ['bg-white', 'bg-light', 'bg-gray'].includes(args.background as string);
+ return isLight ? coloredBackground(story, context, 'dark') : story(args, context);
}
// RENDERER
-function getDefaultContent(args: Args) {
- return html`
-
${args.text}
- ${args.nestedBadge ? html`
10 ` : nothing}
- `;
-}
-
-function getCheckableContent(args: Args, updateArgs: (args: Args) => void, context: StoryContext) {
- const checkboxId = `badge-example--${context.name.replace(/ /g, '-').toLowerCase()}`;
- const labelClasses = mapClasses({
- 'badge-check-label': true,
- [args.size]: args.size !== 'default',
- });
-
- const handleChange = (e: Event) => {
- updateArgs({ checked: !args.checked });
-
- if (document.activeElement === e.target) {
- setTimeout(() => {
- const element: HTMLInputElement | null = document.querySelector(`#${checkboxId}`);
- if (element) element.focus();
- }, 25);
- }
- };
-
- return html`
-
-
${getDefaultContent(args)}
- `;
-}
-
-function getDismissButton(updateArgs: (args: Args) => void) {
- return html`
-
updateArgs({ dismissed: true })}">
- Forigi insignon
-
- `;
-}
-
-function renderBadge(args: Args, context: StoryContext) {
- const [_, updateArgs] = useArgs();
-
- if (args.dismissed) return html` ${nothing} `;
-
- const isCheckable = args.interactionType === 'checkable';
- const isDismissible = args.interactionType === 'dismissible';
-
- const badgeClasses = mapClasses({
- 'badge': !isCheckable,
- 'badge-check': isCheckable,
- [args.size]: args.size !== 'default' && !isCheckable,
- });
-
+function renderBadge(args: Args) {
+ const sizingClass = args.showNumber && args.size !== 'large' ? ` ${args.size}` : '';
+ const bgClass = args.background && args.background !== 'bg-danger' ? ` ${args.background}` : '';
return html`
-
- ${isCheckable ? getCheckableContent(args, updateArgs, context) : getDefaultContent(args)}
- ${isDismissible ? getDismissButton(updateArgs) : nothing}
-
+
${args.showNumber ? args.number : nothing}
`;
}
@@ -198,26 +97,36 @@ type Story = StoryObj;
export const Default: Story = {};
-export const Checkable: Story = {
- parameters: {
- controls: {
- exclude: ['Interaction Type'],
- },
- },
- args: {
- text: 'Kontrolebla Insigno',
- interactionType: 'checkable',
- },
+export const Colors: Story = {
+ render: args => html`
+ ${renderBadge({ ...args, background: 'bg-info' })}
+ ${renderBadge({ ...args, background: 'bg-success' })}
+ ${renderBadge({ ...args, background: 'bg-warning' })}
+ ${renderBadge({ ...args, background: 'bg-yellow' })}
+ `,
};
-export const Dismissible: Story = {
- parameters: {
- controls: {
- exclude: ['Interaction Type'],
- },
- },
- args: {
- text: 'Malakceptebla Insigno',
- interactionType: 'dismissible',
- },
+export const LargeNumber: Story = {
+ render: args => html`
+ ${renderBadge({ ...args, number: 256 })} ${renderBadge({ ...args, number: '+99' })}
+ `,
+};
+
+export const Position: Story = {
+ render: args => html`
+
+
+
+ `,
+ decorators: [
+ (story: StoryFn, { args, context }: StoryContext) => html`
+
${story(args, context)}
+ `,
+ ],
};
diff --git a/packages/documentation/src/stories/components/card-control/card-control.stories.ts b/packages/documentation/src/stories/components/card-control/card-control.stories.ts
index 7a68ba4ad9..7e78953284 100644
--- a/packages/documentation/src/stories/components/card-control/card-control.stories.ts
+++ b/packages/documentation/src/stories/components/card-control/card-control.stories.ts
@@ -6,6 +6,7 @@ import { unsafeHTML } from 'lit/directives/unsafe-html.js';
import { parse } from '../../../utils/sass-export';
import './card-control.styles.scss';
import scss from './card-control.module.scss';
+import { coloredBackground } from '../../../shared/decorators/dark-background';
const SCSS_VARIABLES: any = parse(scss);
@@ -116,15 +117,7 @@ export const DarkBackground: Story = {
},
},
},
- decorators: [
- (story, context) =>
- html`
- ${story()}
-
`,
- ],
+ decorators: [(story, context) => coloredBackground(story, context, context.args.background)],
args: {
background: 'dark',
icon: '1001',
diff --git a/packages/documentation/src/stories/components/cards/card-button/card-button.stories.ts b/packages/documentation/src/stories/components/cards/card-button/card-button.stories.ts
index 9b9757a4e9..8ea937dff0 100644
--- a/packages/documentation/src/stories/components/cards/card-button/card-button.stories.ts
+++ b/packages/documentation/src/stories/components/cards/card-button/card-button.stories.ts
@@ -1,8 +1,8 @@
import { Args, StoryObj } from '@storybook/web-components';
import { html } from 'lit';
import { useArgs } from '@storybook/preview-api';
-import scss from './card-button.module.scss';
import { MetaComponent } from '../../../../../types';
+import backgroundColors from '../../../../shared/background-colors.module.scss';
const meta: MetaComponent = {
id: '6f8f76ec-a2b5-4eb0-87f7-4021e1a5b8d0',
@@ -64,7 +64,7 @@ const meta: MetaComponent = {
control: {
type: 'select',
},
- options: Object.keys(scss),
+ options: Object.keys(backgroundColors),
table: {
category: 'General',
},
diff --git a/packages/styles/src/components/badge.scss b/packages/styles/src/components/badge.scss
index cc7ed9dbd9..b4c9fcff7e 100644
--- a/packages/styles/src/components/badge.scss
+++ b/packages/styles/src/components/badge.scss
@@ -1,85 +1,33 @@
@forward './../variables/options';
-@use './../lic/bootstrap-license';
-@use './../themes/bootstrap/core' as *;
-@use './../themes/bootstrap/badge' as bb;
-
+@use './../mixins/color' as color-mx;
@use './../variables/components/badge';
-@use './../variables/components/forms';
-@use './../variables/components/form-check';
-@use './../variables/color';
-@use './../mixins/utilities';
-@use './../mixins/forms' as forms-mx;
-@use './../mixins/badge' as badge-mx;
-@use './../placeholders/badge' as badge-ph;
-@use './../functions/icons' as icons-fn;
.badge {
- @extend %badge;
-}
-
-a,
-button {
- &.badge {
- @include forms-mx.focus-outline;
- background-color: transparent;
- text-decoration: none;
- transition: badge.$badge-transition;
-
- @include utilities.not-disabled-focus-hover {
- @include badge-mx.badge-hover-state;
- }
-
- &:active,
- &.active {
- @include badge-mx.badge-active-state;
- }
- }
-}
-
-.badge-check {
- &-label {
- @extend %badge;
- @include forms-mx.focus-outline;
- transition: badge.$badge-transition;
- cursor: pointer;
- }
-
- &-input {
- @include utilities.visuallyhidden;
- }
-
- &-input:focus-visible + &-label {
- outline-offset: forms.$input-focus-outline-thickness;
- outline: forms.$input-focus-outline-thickness solid var(--post-contrast-color);
- }
-
- &-input:not(:checked) + &-label:hover {
- @include badge-mx.badge-hover-state;
- }
-
- &-input:checked + &-label {
- @include badge-mx.badge-active-state;
+ --post-badge-height: #{badge.$badge-height};
+ --post-badge-padding-x: #{badge.$badge-padding-x};
+
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ box-sizing: content-box;
+ height: var(--post-badge-height);
+ min-width: calc(var(--post-badge-height) - 2 * var(--post-badge-padding-x));
+ padding-inline: var(--post-badge-padding-x);
+ border: badge.$badge-border;
+ border-radius: badge.$badge-border-radius;
+ font-size: badge.$badge-font-size;
+ background-color: badge.$badge-bg;
+ color: badge.$badge-color;
+
+ &:empty {
+ --post-badge-height: #{badge.$badge-height-empty};
+ --post-badge-padding-x: #{badge.$badge-padding-x-empty};
}
}
-@include utilities.high-contrast-mode() {
- .badge-check {
- &-input:focus-visible + &-label {
- border-color: Highlight;
- outline-color: Highlight;
- }
-
- &-input:checked + &-label {
- &:hover {
- @include badge-mx.badge-hover-state;
- }
- }
- }
-
- button.badge,
- a.badge,
- .badge-check-label {
- transition: none;
- }
+.badge-sm {
+ --post-badge-height: #{badge.$badge-height-sm};
+ --post-badge-padding-x: #{badge.$badge-padding-x-sm};
+ font-size: badge.$badge-font-size-sm;
}
diff --git a/packages/styles/src/placeholders/_badge.scss b/packages/styles/src/placeholders/_badge.scss
index 8c187aeb71..a98cfd3afa 100644
--- a/packages/styles/src/placeholders/_badge.scss
+++ b/packages/styles/src/placeholders/_badge.scss
@@ -9,7 +9,7 @@
align-items: center;
gap: badge.$badge-gap;
padding: $badge-padding-y $badge-padding-x;
- border: badge.$badge-border-width solid badge.$badge-border-color;
+ border: badge.$badge-border;
height: badge.$badge-height;
font-size: badge.$badge-font-size;
font-weight: $badge-font-weight;
diff --git a/packages/styles/src/variables/components/_badge.scss b/packages/styles/src/variables/components/_badge.scss
index d47f01e4fe..49ea1bfbad 100644
--- a/packages/styles/src/variables/components/_badge.scss
+++ b/packages/styles/src/variables/components/_badge.scss
@@ -1,19 +1,29 @@
-@use 'sass:math';
-
-@use './button';
-@use './../animation';
@use './../color';
@use './../commons';
@use './../spacing';
@use './../type';
+@use './button';
@use './../../functions/sizing';
-// Design System custom variables
-$badge-height: button.$btn-height-rg;
+$badge-border-radius: 50rem;
+$badge-color: color.$white;
+$badge-bg: color.$error;
+$badge-border: color.$white solid commons.$border-thick;
+
+$badge-height: spacing.$size-large;
+$badge-height-sm: spacing.$size-regular;
+$badge-height-empty: spacing.$size-mini;
+
+$badge-padding-x: spacing.$size-mini;
+$badge-padding-x-sm: spacing.$size-micro;
+$badge-padding-x-empty: 0%; // needs a unit for the calculated min-width
+
+$badge-font-size: type.$font-size-12;
+$badge-font-size-sm: 10px;
+
+// DEPRECATED
$badge-gap: spacing.$size-mini;
-$badge-border-color: var(--post-gray-60);
-$badge-border-width: commons.$border-thick;
$badge-transition:
color 250ms,
background-color 250ms,
@@ -22,11 +32,7 @@ $badge-hover-color: color.$black;
$badge-hover-bg-color: color.$gray-10;
$badge-active-color: color.$black;
$badge-active-bg-color: color.$yellow;
-
-$badge-height-sm: button.$btn-height-sm;
$badge-gap-sm: sizing.px-to-rem(6px);
-$badge-font-size-sm: type.$font-size-tiny;
-
$badge-nested-height: sizing.px-to-rem(22px);
$badge-nested-color: color.$gray-60;
$badge-nested-bg-color: color.$gray-10;
@@ -35,14 +41,7 @@ $badge-nested-font-size: sizing.px-to-rem(10px);
$badge-nested-translate-x: ($badge-height - $badge-nested-height) * 0.5;
$badge-nested-active-bg-color: color.$white;
$badge-nested-translate-x-sm: ($badge-height-sm - $badge-nested-height) * 0.5;
-
$badge-check-input-height: spacing.$size-small-large;
$badge-check-input-bg-color: color.$white;
-
-// Bootstrap variables
-$badge-font-size: type.$font-size-small;
$badge-font-weight: type.$font-weight-normal;
-$badge-color: var(--post-gray-80);
$badge-padding-y: 0;
-$badge-padding-x: spacing.$size-regular - sizing.px-to-rem($badge-border-width);
-$badge-border-radius: 50rem;