diff --git a/second-gen/packages/core/components/badge/Badge.base.ts b/second-gen/packages/core/components/badge/Badge.base.ts index d360ada0387..4a9f272dc15 100644 --- a/second-gen/packages/core/components/badge/Badge.base.ts +++ b/second-gen/packages/core/components/badge/Badge.base.ts @@ -16,13 +16,16 @@ import { SizedMixin, SpectrumElement } from '@swc/core/shared/base'; import { ObserveSlotPresence } from '@swc/core/shared/observe-slot-presence'; import { ObserveSlotText } from '@swc/core/shared/observe-slot-text'; -export const BADGE_VARIANTS = [ +export const BADGE_VARIANTS_SEMANTIC = [ 'accent', 'neutral', 'informative', 'positive', 'negative', 'notice', +] as const; + +export const BADGE_VARIANTS_COLOR = [ 'fuchsia', 'indigo', 'magenta', @@ -38,6 +41,11 @@ export const BADGE_VARIANTS = [ 'cyan', 'blue', ] as const; + +export const BADGE_VARIANTS = [ + ...BADGE_VARIANTS_SEMANTIC, + ...BADGE_VARIANTS_COLOR, +] as const; export type BadgeVariant = (typeof BADGE_VARIANTS)[number]; export const FIXED_VALUES = [ 'inline-start', @@ -49,8 +57,9 @@ export type FixedValues = (typeof FIXED_VALUES)[number]; /** * @element sp-badge-base - * @slot - The text label to display in the badge. - * @slot icon - The icon to display in the badge. + * @attribute {ElementSize} size - The size of the badge. + * @attribute {BadgeVariant} variant - The variant of the badge. + * @attribute {FixedValues} fixed - The fixed position of the badge. */ export abstract class BadgeBase extends SizedMixin( ObserveSlotText(ObserveSlotPresence(SpectrumElement, '[slot="icon"]'), ''), @@ -61,27 +70,12 @@ export abstract class BadgeBase extends SizedMixin( @property({ type: String, reflect: true }) public variant: BadgeVariant = 'informative'; - @property({ reflect: true }) - public get fixed(): FixedValues | undefined { - return this._fixed; - } - - public set fixed(fixed: FixedValues | undefined) { - if (fixed === this.fixed) { - return; - } - const oldValue = this.fixed; - this._fixed = fixed; - if (fixed) { - this.setAttribute('fixed', fixed); - } else { - this.removeAttribute('fixed'); - } - this.requestUpdate('fixed', oldValue); - } - - private _fixed?: FixedValues; + @property({ type: String, reflect: true }) + public fixed?: FixedValues; + /** + * @internal Used for rendering gap when the badge has an icon. + */ protected get hasIcon(): boolean { return this.slotContentIsPresent; } diff --git a/second-gen/packages/swc/components/badge/Badge.ts b/second-gen/packages/swc/components/badge/Badge.ts index 950baf098d0..359eef1a9b2 100644 --- a/second-gen/packages/swc/components/badge/Badge.ts +++ b/second-gen/packages/swc/components/badge/Badge.ts @@ -10,15 +10,40 @@ * governing permissions and limitations under the License. */ -import { CSSResultArray, html, nothing, TemplateResult } from 'lit'; +import { CSSResultArray, html, PropertyValues, TemplateResult } from 'lit'; +import { property } from 'lit/decorators.js'; +import { classMap } from 'lit/directives/class-map.js'; +import { when } from 'lit/directives/when.js'; -import { BadgeBase } from '@swc/core/components/badge'; +import { + BADGE_VARIANTS_COLOR as BADGE_VARIANTS_COLOR_BASE, + BADGE_VARIANTS_SEMANTIC, + BadgeBase, +} from '@swc/core/components/badge'; + +export const BADGE_VARIANTS_COLOR = [ + ...BADGE_VARIANTS_COLOR_BASE, + 'pink', + 'turquoise', + 'brown', + 'cinnamon', + 'silver', +] as const; + +export const BADGE_VARIANTS = [ + ...BADGE_VARIANTS_SEMANTIC, + ...BADGE_VARIANTS_COLOR, +] as const; +export type BadgeVariant = (typeof BADGE_VARIANTS)[number]; import styles from './badge.css'; // Export types and values to avoid breaking changes -export { BADGE_VARIANTS, FIXED_VALUES } from '@swc/core/components/badge'; -export type { BadgeVariant, FixedValues } from '@swc/core/components/badge'; +export { + BADGE_VARIANTS_SEMANTIC, + FIXED_VALUES, +} from '@swc/core/components/badge'; +export type { FixedValues } from '@swc/core/components/badge'; /** * A badge component that displays short, descriptive information about an element. @@ -28,14 +53,16 @@ export type { BadgeVariant, FixedValues } from '@swc/core/components/badge'; * @since 1.0.0 * @status stable * @github https://github.com/adobe/spectrum-web-components/tree/main/... - * @figma https://www.figma.com/design/... + * @figma https://www.figma.com/design/Mngz9H7WZLbrCvGQf3GnsY/S2-%2F-Desktop?node-id=36806-6551 + * + * @attribute {BadgeVariant} variant - The variant of the badge. + * @attribute {boolean} subtle - Whether the badge is subtle. + * @attribute {boolean} outline - Whether the badge is outlined. + * @attribute {FixedValues} fixed - The fixed position of the badge. * * @slot - Text label of the badge * @slot icon - Optional icon that appears to the left of the label * - * @csspart label - The text content area of the badge - * @csspart icon - The icon area of the badge (when present) - * * @example * New * @@ -46,23 +73,68 @@ export type { BadgeVariant, FixedValues } from '@swc/core/components/badge'; * */ export class Badge extends BadgeBase { + @property({ type: Boolean, reflect: true }) + public subtle: boolean = false; + + @property({ type: Boolean, reflect: true }) + public outline: boolean = false; + public static override get styles(): CSSResultArray { return [styles]; } protected override render(): TemplateResult { return html` - ${this.hasIcon - ? html` - - ` - : nothing} -
- +
+ ${when( + this.hasIcon, + () => html` +
+ +
+ ` + )} +
+ +
`; } + + protected override update(changedProperties: PropertyValues): void { + super.update(changedProperties); + if (window.__swc?.DEBUG) { + if ( + this.outline && + !BADGE_VARIANTS_SEMANTIC.includes(this.variant) + ) { + window.__swc.warn( + this, + `<${this.localName}> element only supports the outline styling if the variant is a semantic color variant.`, + 'https://opensource.adobe.com/spectrum-web-components/components/badge/#variants', + { + issues: [...BADGE_VARIANTS_SEMANTIC], + } + ); + } + } + } } diff --git a/second-gen/packages/swc/components/badge/badge.css b/second-gen/packages/swc/components/badge/badge.css index 4c7871aa0bc..2a4997ba46e 100644 --- a/second-gen/packages/swc/components/badge/badge.css +++ b/second-gen/packages/swc/components/badge/badge.css @@ -1,8 +1,9 @@ -/** - * Copyright 2025 Adobe. All rights reserved. +/*! + * Copyright 2024 Adobe. All rights reserved. + * * This file is licensed to you under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. You may obtain a copy - * of the License at http://www.apache.org/licenses/LICENSE-2.0 + * of the License at * * Unless required by applicable law or agreed to in writing, software distributed under * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS @@ -11,9 +12,15 @@ */ :host { - --spectrum-badge-corner-radius: var(--spectrum-corner-radius-100); + display: inline-flex; +} + +.spectrum-Badge { + --spectrum-badge-border-width: var(--spectrum-border-width-200); + --spectrum-badge-border-color: transparent; --spectrum-badge-line-height: var(--spectrum-line-height-100); --spectrum-badge-line-height-cjk: var(--spectrum-cjk-line-height-100); + --spectrum-badge-font-weight: var(--spectrum-medium-font-weight); --spectrum-badge-label-icon-color: var(--spectrum-white); --spectrum-badge-background-color-default: var( --spectrum-neutral-subdued-background-color-default @@ -75,6 +82,122 @@ --spectrum-badge-background-color-magenta: var( --spectrum-magenta-background-color-default ); + --spectrum-badge-background-color-pink: var( + --spectrum-pink-background-color-default + ); + --spectrum-badge-background-color-turquoise: var( + --spectrum-turquoise-background-color-default + ); + --spectrum-badge-background-color-brown: var( + --spectrum-brown-background-color-default + ); + --spectrum-badge-background-color-cinnamon: var( + --spectrum-cinnamon-background-color-default + ); + --spectrum-badge-background-color-silver: var( + --spectrum-silver-background-color-default + ); + --spectrum-badge-subtle-label-icon-color: var(--spectrum-gray-1000); + --spectrum-badge-subtle-background-color-default: var( + --spectrum-neutral-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-accent: var( + --spectrum-accent-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-informative: var( + --spectrum-informative-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-negative: var( + --spectrum-negative-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-positive: var( + --spectrum-positive-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-notice: var( + --spectrum-notice-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-gray: var( + --spectrum-gray-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-red: var( + --spectrum-red-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-orange: var( + --spectrum-orange-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-yellow: var( + --spectrum-yellow-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-chartreuse: var( + --spectrum-chartreuse-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-celery: var( + --spectrum-celery-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-green: var( + --spectrum-green-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-seafoam: var( + --spectrum-seafoam-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-cyan: var( + --spectrum-cyan-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-blue: var( + --spectrum-blue-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-indigo: var( + --spectrum-indigo-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-purple: var( + --spectrum-purple-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-fuchsia: var( + --spectrum-fuchsia-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-magenta: var( + --spectrum-magenta-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-pink: var( + --spectrum-pink-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-turquoise: var( + --spectrum-turquoise-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-brown: var( + --spectrum-brown-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-cinnamon: var( + --spectrum-cinnamon-subtle-background-color-default + ); + --spectrum-badge-subtle-background-color-silver: var( + --spectrum-silver-subtle-background-color-default + ); + --spectrum-badge-outline-label-icon-color: var(--spectrum-gray-1000); + --spectrum-badge-outline-background-color: var( + --spectrum-background-layer-2-color + ); + --spectrum-badge-outline-border-color-neutral: var( + --spectrum-neutral-visual-color + ); + --spectrum-badge-outline-border-color-accent: var( + --spectrum-accent-visual-color + ); + --spectrum-badge-outline-border-color-informative: var( + --spectrum-informative-visual-color + ); + --spectrum-badge-outline-border-color-negative: var( + --spectrum-negative-visual-color + ); + --spectrum-badge-outline-border-color-notice: var( + --spectrum-notice-visual-color + ); + --spectrum-badge-outline-border-color-positive: var( + --spectrum-positive-visual-color + ); + --spectrum-badge-corner-radius: var( + --spectrum-corner-radius-medium-size-medium + ); --spectrum-badge-height: var(--spectrum-component-height-100); --spectrum-badge-font-size: var(--spectrum-font-size-100); --spectrum-badge-label-spacing-vertical-top: var( @@ -100,29 +223,18 @@ --highcontrast-badge-border-color: CanvasText; } -:host([variant='celery']), -:host([variant='chartreuse']), -:host([variant='orange']), -:host([variant='yellow']) { +.spectrum-Badge--celery, +.spectrum-Badge--chartreuse, +.spectrum-Badge--notice, +.spectrum-Badge--orange, +.spectrum-Badge--yellow { --spectrum-badge-label-icon-color: var(--spectrum-black); } -:host([variant='blue']), -:host([variant='cyan']), -:host([variant='fuchsia']), -:host([variant='gray']), -:host([variant='green']), -:host([variant='indigo']), -:host([variant='magenta']), -:host([variant='purple']), -:host([variant='red']), -:host([variant='seafoam']) { - --spectrum-badge-label-icon-color: var( - --spectrum-badge-label-icon-color-primary +.spectrum-Badge--sizeS { + --spectrum-badge-corner-radius: var( + --spectrum-corner-radius-medium-size-small ); -} - -:host([size='s']) { --spectrum-badge-height: var(--spectrum-component-height-75); --spectrum-badge-font-size: var(--spectrum-font-size-75); --spectrum-badge-label-spacing-vertical-top: var( @@ -147,7 +259,10 @@ ); } -:host([size='l']) { +.spectrum-Badge--sizeL { + --spectrum-badge-corner-radius: var( + --spectrum-corner-radius-medium-size-large + ); --spectrum-badge-height: var(--spectrum-component-height-100); --spectrum-badge-font-size: var(--spectrum-font-size-200); --spectrum-badge-label-spacing-vertical-top: var( @@ -172,7 +287,10 @@ ); } -:host([size='xl']) { +.spectrum-Badge--sizeXL { + --spectrum-badge-corner-radius: var( + --spectrum-corner-radius-medium-size-extra-large + ); --spectrum-badge-height: var(--spectrum-component-height-100); --spectrum-badge-font-size: var(--spectrum-font-size-300); --spectrum-badge-label-spacing-vertical-top: var( @@ -198,328 +316,348 @@ } @media (forced-colors: active) { - :host { + .spectrum-Badge { border-color: var(--highcontrast-badge-border-color); } } -:host { - min-block-size: var(--mod-badge-height, var(--spectrum-badge-height)); +.spectrum-Badge { + min-block-size: var(--spectrum-badge-height); inline-size: auto; - vertical-align: middle; - cursor: default; - -webkit-font-smoothing: subpixel-antialiased; - -moz-osx-font-smoothing: auto; - border-radius: var( - --mod-badge-corner-radius, - var(--spectrum-badge-corner-radius) - ); - color: var( - --mod-badge-label-icon-color, - var(--spectrum-badge-label-icon-color) - ); - border: 1px solid #0000; display: inline-flex; + vertical-align: middle; position: relative; + cursor: default; + border: var(--spectrum-badge-border-width) solid + var(--spectrum-badge-border-color); + border-radius: var(--spectrum-badge-corner-radius); + background: var(--spectrum-badge-background-color-default); + color: var(--spectrum-badge-label-icon-color); + background-origin: border-box; + align-self: start; } -:host, -:host([variant='neutral']) { - background: var( - --mod-badge-background-color-default, - var(--spectrum-badge-background-color-default) - ); +.spectrum-Badge--neutral { + background: var(--spectrum-badge-background-color-default); } -:host([variant='accent']) { - background: var( - --mod-badge-background-color-accent, - var(--spectrum-badge-background-color-accent) - ); +.spectrum-Badge--accent { + background: var(--spectrum-badge-background-color-accent); } -:host([variant='informative']) { - background: var( - --mod-badge-background-color-informative, - var(--spectrum-badge-background-color-informative) - ); +.spectrum-Badge--informative { + background: var(--spectrum-badge-background-color-informative); } -:host([variant='negative']) { - background: var( - --mod-badge-background-color-negative, - var(--spectrum-badge-background-color-negative) - ); +.spectrum-Badge--negative { + background: var(--spectrum-badge-background-color-negative); } -:host([variant='positive']) { - background: var( - --mod-badge-background-color-positive, - var(--spectrum-badge-background-color-positive) - ); +.spectrum-Badge--positive { + background: var(--spectrum-badge-background-color-positive); } -:host([variant='notice']) { - background: var( - --mod-badge-background-color-notice, - var(--spectrum-badge-background-color-notice) - ); +.spectrum-Badge--notice { + background: var(--spectrum-badge-background-color-notice); } -:host([variant='gray']) { - background: var( - --mod-badge-background-color-gray, - var(--spectrum-badge-background-color-gray) - ); +.spectrum-Badge--gray { + background: var(--spectrum-badge-background-color-gray); } -:host([variant='red']) { - background: var( - --mod-badge-background-color-red, - var(--spectrum-badge-background-color-red) - ); +.spectrum-Badge--red { + background: var(--spectrum-badge-background-color-red); } -:host([variant='orange']) { - background: var( - --mod-badge-background-color-orange, - var(--spectrum-badge-background-color-orange) - ); +.spectrum-Badge--orange { + background: var(--spectrum-badge-background-color-orange); } -:host([variant='yellow']) { - background: var( - --mod-badge-background-color-yellow, - var(--spectrum-badge-background-color-yellow) - ); +.spectrum-Badge--yellow { + background: var(--spectrum-badge-background-color-yellow); } -:host([variant='chartreuse']) { - background: var( - --mod-badge-background-color-chartreuse, - var(--spectrum-badge-background-color-chartreuse) - ); +.spectrum-Badge--chartreuse { + background: var(--spectrum-badge-background-color-chartreuse); } -:host([variant='celery']) { - background: var( - --mod-badge-background-color-celery, - var(--spectrum-badge-background-color-celery) - ); +.spectrum-Badge--celery { + background: var(--spectrum-badge-background-color-celery); } -:host([variant='green']) { - background: var( - --mod-badge-background-color-green, - var(--spectrum-badge-background-color-green) - ); +.spectrum-Badge--green { + background: var(--spectrum-badge-background-color-green); } -:host([variant='seafoam']) { - background: var( - --mod-badge-background-color-seafoam, - var(--spectrum-badge-background-color-seafoam) - ); +.spectrum-Badge--seafoam { + background: var(--spectrum-badge-background-color-seafoam); } -:host([variant='cyan']) { - background: var( - --mod-badge-background-color-cyan, - var(--spectrum-badge-background-color-cyan) - ); +.spectrum-Badge--cyan { + background: var(--spectrum-badge-background-color-cyan); } -:host([variant='blue']) { - background: var( - --mod-badge-background-color-blue, - var(--spectrum-badge-background-color-blue) - ); +.spectrum-Badge--blue { + background: var(--spectrum-badge-background-color-blue); } -:host([variant='indigo']) { - background: var( - --mod-badge-background-color-indigo, - var(--spectrum-badge-background-color-indigo) - ); +.spectrum-Badge--indigo { + background: var(--spectrum-badge-background-color-indigo); } -:host([variant='purple']) { - background: var( - --mod-badge-background-color-purple, - var(--spectrum-badge-background-color-purple) - ); +.spectrum-Badge--purple { + background: var(--spectrum-badge-background-color-purple); } -:host([variant='fuchsia']) { - background: var( - --mod-badge-background-color-fuchsia, - var(--spectrum-badge-background-color-fuchsia) - ); +.spectrum-Badge--fuchsia { + background: var(--spectrum-badge-background-color-fuchsia); } -:host([variant='magenta']) { - background: var( - --mod-badge-background-color-magenta, - var(--spectrum-badge-background-color-magenta) - ); +.spectrum-Badge--magenta { + background: var(--spectrum-badge-background-color-magenta); } -:host([fixed='inline-start']) { - border-start-start-radius: 0; - border-end-start-radius: 0; +.spectrum-Badge--pink { + background: var(--spectrum-badge-background-color-pink); } -:host([fixed='inline-end']) { - border-start-end-radius: 0; - border-end-end-radius: 0; +.spectrum-Badge--turquoise { + background: var(--spectrum-badge-background-color-turquoise); } -:host([fixed='block-start']) { - border-start-start-radius: 0; - border-start-end-radius: 0; +.spectrum-Badge--brown { + background: var(--spectrum-badge-background-color-brown); } -:host([fixed='block-end']) { - border-end-end-radius: 0; - border-end-start-radius: 0; +.spectrum-Badge--cinnamon { + background: var(--spectrum-badge-background-color-cinnamon); } -.label { - font-size: var(--mod-badge-font-size, var(--spectrum-badge-font-size)); - line-height: var( - --mod-badge-line-height, - var(--spectrum-badge-line-height) - ); - color: var( - --mod-badge-label-icon-color, - var(--spectrum-badge-label-icon-color) - ); - padding-block-start: var( - --mod-badge-label-spacing-vertical-top, - var(--spectrum-badge-label-spacing-vertical-top) - ); - padding-block-end: var( - --mod-badge-label-spacing-vertical-bottom, - var(--spectrum-badge-label-spacing-vertical-bottom) - ); - padding-inline-start: var( - --mod-badge-label-spacing-horizontal, - var(--spectrum-badge-label-spacing-horizontal) - ); - padding-inline-end: var( - --mod-badge-label-spacing-horizontal, - var(--spectrum-badge-label-spacing-horizontal) - ); +.spectrum-Badge--silver { + background: var(--spectrum-badge-background-color-silver); } -.label:lang(ja), -.label:lang(ko), -.label:lang(zh) { - line-height: var( - --mod-badge-line-height-cjk, - var(--spectrum-badge-line-height-cjk) - ); +.spectrum-Badge--subtle { + color: var(--spectrum-badge-subtle-label-icon-color); } -[name='icon'] + .label { - padding-inline-start: 0; +.spectrum-Badge--subtle.spectrum-Badge--neutral { + background: var(--spectrum-badge-subtle-background-color-default); } -::slotted([slot='icon']) { - block-size: var( - --mod-badge-workflow-icon-size, - var(--spectrum-badge-workflow-icon-size) - ); - inline-size: var( - --mod-badge-workflow-icon-size, - var(--spectrum-badge-workflow-icon-size) - ); - flex: 0 0 - var( - --mod-badge-workflow-icon-size, - var(--spectrum-badge-workflow-icon-size) - ); - color: var( - --mod-badge-label-icon-color, - var(--spectrum-badge-label-icon-color) - ); - padding-block-start: var( - --mod-badge-icon-spacing-vertical-top, - var(--spectrum-badge-icon-spacing-vertical-top) - ); - padding-block-end: var( - --mod-badge-icon-spacing-vertical-top, - var(--spectrum-badge-icon-spacing-vertical-top) - ); - padding-inline-start: var( - --mod-badge-icon-spacing-horizontal, - var(--spectrum-badge-icon-spacing-horizontal) - ); - padding-inline-end: var( - --mod-badge-icon-text-spacing, - var(--spectrum-badge-icon-text-spacing) - ); +.spectrum-Badge--subtle.spectrum-Badge--accent { + background: var(--spectrum-badge-subtle-background-color-accent); } -[icon-only]::slotted(*) { - padding-inline-start: var( - --mod-badge-icon-only-spacing-horizontal, - var(--spectrum-badge-icon-only-spacing-horizontal) - ); - padding-inline-end: var( - --mod-badge-icon-only-spacing-horizontal, - var(--spectrum-badge-icon-only-spacing-horizontal) - ); +.spectrum-Badge--subtle.spectrum-Badge--informative { + background: var(--spectrum-badge-subtle-background-color-informative); } -/* center align icons and text */ +.spectrum-Badge--subtle.spectrum-Badge--negative { + background: var(--spectrum-badge-subtle-background-color-negative); +} -:host { - align-items: center; +.spectrum-Badge--subtle.spectrum-Badge--positive { + background: var(--spectrum-badge-subtle-background-color-positive); +} + +.spectrum-Badge--subtle.spectrum-Badge--notice { + background: var(--spectrum-badge-subtle-background-color-notice); +} + +.spectrum-Badge--subtle.spectrum-Badge--gray { + background: var(--spectrum-badge-subtle-background-color-gray); +} + +.spectrum-Badge--subtle.spectrum-Badge--red { + background: var(--spectrum-badge-subtle-background-color-red); +} + +.spectrum-Badge--subtle.spectrum-Badge--orange { + background: var(--spectrum-badge-subtle-background-color-orange); +} + +.spectrum-Badge--subtle.spectrum-Badge--yellow { + background: var(--spectrum-badge-subtle-background-color-yellow); +} + +.spectrum-Badge--subtle.spectrum-Badge--chartreuse { + background: var(--spectrum-badge-subtle-background-color-chartreuse); +} + +.spectrum-Badge--subtle.spectrum-Badge--celery { + background: var(--spectrum-badge-subtle-background-color-celery); +} + +.spectrum-Badge--subtle.spectrum-Badge--green { + background: var(--spectrum-badge-subtle-background-color-green); +} + +.spectrum-Badge--subtle.spectrum-Badge--seafoam { + background: var(--spectrum-badge-subtle-background-color-seafoam); +} + +.spectrum-Badge--subtle.spectrum-Badge--cyan { + background: var(--spectrum-badge-subtle-background-color-cyan); +} + +.spectrum-Badge--subtle.spectrum-Badge--blue { + background: var(--spectrum-badge-subtle-background-color-blue); +} + +.spectrum-Badge--subtle.spectrum-Badge--indigo { + background: var(--spectrum-badge-subtle-background-color-indigo); +} + +.spectrum-Badge--subtle.spectrum-Badge--purple { + background: var(--spectrum-badge-subtle-background-color-purple); +} + +.spectrum-Badge--subtle.spectrum-Badge--fuchsia { + background: var(--spectrum-badge-subtle-background-color-fuchsia); +} + +.spectrum-Badge--subtle.spectrum-Badge--magenta { + background: var(--spectrum-badge-subtle-background-color-magenta); +} + +.spectrum-Badge--subtle.spectrum-Badge--pink { + background: var(--spectrum-badge-subtle-background-color-pink); +} + +.spectrum-Badge--subtle.spectrum-Badge--turquoise { + background: var(--spectrum-badge-subtle-background-color-turquoise); +} + +.spectrum-Badge--subtle.spectrum-Badge--brown { + background: var(--spectrum-badge-subtle-background-color-brown); +} + +.spectrum-Badge--subtle.spectrum-Badge--cinnamon { + background: var(--spectrum-badge-subtle-background-color-cinnamon); +} + +.spectrum-Badge--subtle.spectrum-Badge--silver { + background: var(--spectrum-badge-subtle-background-color-silver); +} + +.spectrum-Badge--outline:is( + .spectrum-Badge--neutral, + .spectrum-Badge--accent, + .spectrum-Badge--informative, + .spectrum-Badge--negative, + .spectrum-Badge--positive, + .spectrum-Badge--notice + ) { + background: var(--spectrum-badge-outline-background-color); + color: var(--spectrum-badge-outline-label-icon-color); +} + +.spectrum-Badge--outline.spectrum-Badge--neutral { + border-color: var(--spectrum-badge-outline-border-color-neutral); +} + +.spectrum-Badge--outline.spectrum-Badge--accent { + border-color: var(--spectrum-badge-outline-border-color-accent); +} + +.spectrum-Badge--outline.spectrum-Badge--informative { + border-color: var(--spectrum-badge-outline-border-color-informative); } -/* cascade badge's size to its icon */ +.spectrum-Badge--outline.spectrum-Badge--negative { + border-color: var(--spectrum-badge-outline-border-color-negative); +} -:host([size='xs']) { - --spectrum-icon-size: var(--spectrum-workflow-icon-size-50); +.spectrum-Badge--outline.spectrum-Badge--positive { + border-color: var(--spectrum-badge-outline-border-color-positive); } -:host([size='s']) { - --spectrum-icon-size: var(--spectrum-workflow-icon-size-75); +.spectrum-Badge--outline.spectrum-Badge--notice { + border-color: var(--spectrum-badge-outline-border-color-notice); } -:host([size='m']) { - --spectrum-icon-size: var(--spectrum-workflow-icon-size-100); +.spectrum-Badge--fixed-inline-start { + border-start-start-radius: 0; + border-end-start-radius: 0; } -:host([size='l']) { - --spectrum-icon-size: var(--spectrum-workflow-icon-size-200); +.spectrum-Badge--fixed-inline-end { + border-start-end-radius: 0; + border-end-end-radius: 0; } -:host([size='xl']) { - --spectrum-icon-size: var(--spectrum-workflow-icon-size-300); +.spectrum-Badge--fixed-block-start { + border-start-start-radius: 0; + border-start-end-radius: 0; } -:host([size='xxl']) { - --spectrum-icon-size: var(--spectrum-workflow-icon-size-400); +.spectrum-Badge--fixed-block-end { + border-end-start-radius: 0; + border-end-end-radius: 0; } -/* don't shrink icons and ensure they're separated from labels */ +.spectrum-Badge-label { + font-size: var(--spectrum-badge-font-size); + font-weight: var(--spectrum-badge-font-weight); + line-height: var(--spectrum-badge-line-height); + padding-inline-end: calc( + var(--spectrum-badge-label-spacing-horizontal) - + var(--spectrum-badge-border-width) + ); + padding-inline-start: var(--spectrum-badge-label-spacing-horizontal); + padding-block-start: calc( + var(--spectrum-badge-label-spacing-vertical-top) - + var(--spectrum-badge-border-width) + ); + padding-block-end: calc( + var(--spectrum-badge-label-spacing-vertical-bottom) - + var(--spectrum-badge-border-width) + ); +} -::slotted([slot='icon']) { - flex-shrink: 0; +.spectrum-Badge-label:lang(ja), +.spectrum-Badge-label:lang(ko), +.spectrum-Badge-label:lang(zh) { + line-height: var(--spectrum-badge-line-height-cjk); +} + +.spectrum-Badge-icon + .spectrum-Badge-label { + padding-inline-start: 0; } -/* limit badge size to two lines */ +.spectrum-Badge-icon { + block-size: var(--spectrum-badge-workflow-icon-size); + inline-size: var(--spectrum-badge-workflow-icon-size); + flex: 0 0 var(--spectrum-badge-workflow-icon-size); + margin-inline-start: calc( + var(--spectrum-badge-icon-spacing-horizontal) - + var(--spectrum-badge-border-width) + ); + margin-inline-end: var(--spectrum-badge-icon-text-spacing); + margin-block-start: calc( + var(--spectrum-badge-icon-spacing-vertical-top) - + var(--spectrum-badge-border-width) + ); + margin-block-end: calc( + var(--spectrum-badge-icon-spacing-vertical-top) - + var(--spectrum-badge-border-width) + ); +} -.label slot { - display: block; - max-height: calc( - var(--spectrum-badge-line-height) * var(--spectrum-badge-font-size) * 2 +.spectrum-Badge-icon--no-label { + margin-inline-start: calc( + var(--spectrum-badge-icon-only-spacing-horizontal) - + var(--spectrum-badge-border-width) + ); + margin-inline-end: calc( + var(--spectrum-badge-icon-only-spacing-horizontal) - + var(--spectrum-badge-border-width) ); - overflow: hidden; } -[icon-only] + .label { - display: none; +.spectrum-Badge, +.spectrum-Badge-icon, +.spectrum-Badge-label { + box-sizing: border-box; } diff --git a/second-gen/packages/swc/components/badge/stories/badge.stories.ts b/second-gen/packages/swc/components/badge/stories/badge.stories.ts index 814880f8a9e..bb6cc5b129d 100644 --- a/second-gen/packages/swc/components/badge/stories/badge.stories.ts +++ b/second-gen/packages/swc/components/badge/stories/badge.stories.ts @@ -10,81 +10,233 @@ * governing permissions and limitations under the License. */ -import { html } from 'lit'; +import { html, nothing, TemplateResult } from 'lit'; +import { styleMap } from 'lit/directives/style-map.js'; import type { Meta, StoryObj } from '@storybook/web-components'; -import { BADGE_VARIANTS, FIXED_VALUES } from '@swc/components/badge'; +import { + BADGE_VARIANTS, + BADGE_VARIANTS_COLOR, + BADGE_VARIANTS_SEMANTIC, + FIXED_VALUES, +} from '@swc/components/badge'; import '@swc/components/badge'; +/** @todo Pull this up into a utility function for all components to leverage */ +function capitalize(str?: string): string { + if (typeof str !== 'string') { + return ''; + } + return str.charAt(0).toUpperCase() + str.slice(1); +} + +/** @todo Pull this up into a decorator for all stories to leverage */ +const CONTAINER = (content: TemplateResult<1>[]) => + html`
+ ${content} +
`; + +/** + * Badges are for showing a small amount of color-categorized metadata. They're ideal for getting a user's attention. There are two additional styles - subtle fill and outline - in addition to the default, bold fill style. + * + * Because outline and subtle fill styles draw a similar level of attention, choose only one to use consistently within a single product. Bold fill can be paired with either style, and is reserved for high-attention badging only. + */ const meta: Meta = { title: 'Components/Badge', component: 'swc-badge', argTypes: { + size: { + name: 'Size', + control: { type: 'select' }, + options: ['s', 'm', 'l', 'xl'], + }, variant: { + name: 'Variant', control: { type: 'select' }, options: BADGE_VARIANTS, }, + subtle: { + name: 'Subtle', + control: { type: 'boolean' }, + }, + outline: { + name: 'Outline', + control: { type: 'boolean' }, + }, fixed: { + name: 'Fixed', control: { type: 'select' }, - options: [undefined, ...FIXED_VALUES], + options: [...FIXED_VALUES], }, - size: { - control: { type: 'select' }, - options: ['s', 'm', 'l', 'xl'], + label: { + name: 'Label', + control: { type: 'text' }, + table: { category: 'Slots' }, + }, + icon: { + name: 'Icon', + control: { type: 'text' }, + table: { category: 'Slots' }, }, }, args: { + label: 'Badge', + // updating this to make the options more readable as a demo + size: 'l', variant: 'informative', + subtle: false, + outline: false, }, + parameters: { + design: { + type: 'figma', + url: 'https://www.figma.com/design/Mngz9H7WZLbrCvGQf3GnsY/S2-%2F-Desktop?node-id=36806-6551', + }, + }, + tags: ['migrated'], }; export default meta; type Story = StoryObj; +type StoryArgs = StoryObj['args']; + +/** + * @param args - The arguments for the badge as sourced from the storybook args. + * @returns A lightweight template for to render a single badge with bindings to the args. + * @todo could also surface a knob to select an icon from our icon library and use that instead of the string. + * @todo is there stronger typing we can use for the args? + */ +const BASE_TEMPLATE = (args: StoryArgs = {}) => html` + + ${args.icon ? html`${args.icon}` : nothing} + ${args.label} + +`; +/** + * Badges can contain label, icon, or label and icon. Text wrapping is also included when a `max-inline-size` is applied to the badge. + */ export const Default: Story = { args: { - variant: 'informative', + size: 'm', + }, + render: BASE_TEMPLATE, +}; + +/** + * Badges can be rendered with or without an icon. Icons can be passed to the component using the `icon` slot and can be sourced from either the Spectrum icon library or a custom icon library as needed. + */ +export const WithIcon: Story = { + args: { + icon: '✓', + }, + render: BASE_TEMPLATE, + // Removes the story from the side navigation while keeping in the docs view + tags: ['!dev'], +}; + +/** + * Semantic variants allow you to render the badge with a descriptive name that maps to a design-system-aligned color. This is the preferred way to assign color to a badge because it will align more consistently with other components in your UI with the same meaning. + */ +export const SemanticVariants: Story = { + render: (args) => + CONTAINER( + BADGE_VARIANTS_SEMANTIC.map((variant) => + BASE_TEMPLATE({ + ...args, + variant, + label: capitalize(variant), + }) + ) + ), + tags: ['!dev'], +}; + +/** + * The `outline` style is only valid for semantic color variants. + */ +export const Outline: Story = { + argTypes: { + variant: { + control: { type: 'select' }, + options: BADGE_VARIANTS_SEMANTIC, + }, }, - render: (args) => html` - - Badge - - `, + render: (args) => + CONTAINER( + BADGE_VARIANTS_SEMANTIC.map((variant) => + BASE_TEMPLATE({ + ...args, + variant, + label: capitalize(variant), + outline: true, + }) + ) + ), + tags: ['!dev'], }; -export const Variants: Story = { - render: () => html` -
- ${BADGE_VARIANTS.map( - (variant) => html` - ${variant} - ` - )} -
- `, +/** + * Color variants are available for the badge component and provide a more granular access to the full color palette in the design system. + */ +export const ColorVariants: Story = { + render: (args) => + CONTAINER( + BADGE_VARIANTS_COLOR.map((variant) => + BASE_TEMPLATE({ + ...args, + variant, + label: capitalize(variant), + }) + ) + ), + tags: ['!dev'], }; export const Sizes: Story = { - render: () => html` -
- Small - Medium - Large - Extra Large -
- `, + render: (args) => + CONTAINER( + ['s', 'm', 'l', 'xl'].map((size) => + BASE_TEMPLATE({ + ...args, + size, + label: capitalize(size), + }) + ) + ), + tags: ['!dev'], }; -export const WithIcon: Story = { - render: () => html` - - - With icon - - `, +/** + * The `subtle` style is available for all variants. It is useful when you want to reduce the visual prominence of the badge while still mapping to the design system color palette. + */ +export const Subtle: Story = { + render: (args) => + CONTAINER( + BADGE_VARIANTS.map((variant) => + BASE_TEMPLATE({ + ...args, + variant, + label: capitalize(variant), + subtle: true, + }) + ) + ), + tags: ['!dev'], };