Merged in feat/SW-3636-storybook-structure (pull request #3309)

feat(SW-3636): Storybook structure

* New sections in Storybook sidebar

* Group Storybook content files and add token files for spacing, border radius and shadows


Approved-by: Joakim Jäderberg
This commit is contained in:
Rasmus Langvad
2025-12-08 12:35:14 +00:00
parent 177c2e7176
commit ca6cc5ab6c
83 changed files with 1272 additions and 525 deletions

View File

@@ -1,153 +0,0 @@
/* eslint-disable formatjs/no-literal-string-in-jsx */
import copy from 'copy-to-clipboard'
import { kebabify } from '../../generate/utils'
export type ThemeValue = Record<'resolved' | 'alias', string | number>
export type Theme = Record<string, ThemeValue>
export type ColorsProps = {
theme: Theme
}
import styles from './colors.module.css'
function getContrastColor(bgColor: string) {
const r = parseInt(bgColor.substring(1, 3), 16)
const g = parseInt(bgColor.substring(3, 5), 16)
const b = parseInt(bgColor.substring(5, 7), 16)
let a = parseInt(bgColor.substring(7, 9), 16)
if (isNaN(a)) {
a = 255
}
const luminance = (0.299 * r + 0.587 * g + 0.114 * b) / 255
if (luminance > 0.5) {
return '#000'
} else {
if (a < 255 / 2) {
return '#000'
}
return '#fff'
}
}
export function Colors({ theme }: ColorsProps) {
const grouping: Record<string, Theme> = {}
for (const [k, v] of Object.entries(theme)) {
if (typeof v.resolved === 'string' && v.resolved.startsWith('#')) {
const key = k.replace(/\/[^/]+$/, '')
if (!grouping[key]) {
grouping[key] = {}
}
grouping[key][k] = v
}
}
return (
<div className={styles.container}>
<div className={styles.jumpTo}>
<label>
Jump to:
<select
onChange={(e) => {
const el = document.getElementById(e.target.value)
el?.scrollIntoView({
behavior: 'smooth',
})
}}
>
<option>- Select a grouping -</option>
{Object.keys(grouping)
.sort((a, b) => a.localeCompare(b))
.map((title) => {
return (
<option key={title} value={kebabify(title)}>
{title}
</option>
)
})}
</select>
</label>
<span className={styles.tip}>
Click on any of the values to copy to clipboard!
</span>
</div>
<div className={styles.groups}>
{Object.entries(grouping)
.sort((a, b) => {
return a[0].localeCompare(b[0])
})
.map(([title, values]) => {
return (
<div className={styles.group} key={title}>
<h2 id={kebabify(title)} className={styles.title}>
{title}
</h2>
<div className={styles.values}>
{Object.entries(values).map(([k, v]) => {
return (
<div className={styles.value} key={k}>
<div className={styles.colorContainer}>
<div
className={styles.color}
style={{
color: getContrastColor(v.resolved.toString()),
backgroundColor: v.resolved.toString(),
}}
onClick={() => {
copy(`var(--${kebabify(k)})`)
}}
>
var(--{kebabify(k)})
</div>
</div>
<div
className={styles.tokenName}
onClick={() => {
copy(k)
}}
>
Figma: {k}
</div>
<div
className={styles.tokenName}
onClick={() => {
copy(kebabify(k))
}}
>
CSS: {kebabify(k)}
</div>
{v.alias ? (
<div
className={styles.tokenAlias}
onClick={() => {
copy(v.alias.toString())
}}
>
Alias: {v.alias}
</div>
) : null}
<div
className={styles.tokenValue}
onClick={() => {
copy(v.resolved.toString())
}}
>
Value: {v.resolved}
</div>
</div>
)
})}
</div>
</div>
)
})}
</div>
</div>
)
}

View File

@@ -1,11 +0,0 @@
import { Meta } from '@storybook/addon-docs/blocks'
import { Colors } from './Colors'
import { base } from '.'
<Meta title="Global/Colors/Base" />
# Colors: Base
<Colors theme={base} />

View File

@@ -1,130 +0,0 @@
.container {
display: grid;
gap: 2em;
}
.jumpTo {
position: sticky;
top: 0;
background: #fff;
padding: 0.5em;
z-index: 100;
border: solid 1px #ccc;
border-radius: 4px;
display: flex;
justify-content: space-between;
align-items: center;
flex-direction: row;
flex-wrap: nowrap;
}
.jumpTo select {
margin-left: 1em;
padding: 0.3em;
border-radius: 3px;
border: solid 1px #ccc;
font-size: 14px;
}
.tip {
font-size: 12px !important;
background: #fffcdd;
padding: 0.5em;
border-radius: 4px;
border: solid 1px #e8db45;
}
.groups {
display: flex;
flex-direction: column;
}
.title {
font-weight: bold;
padding-top: 60px !important; /* jumpTo element height:ish */
}
.values {
display: flex;
flex-wrap: wrap;
}
.value {
box-sizing: border-box;
width: 50%;
min-width: 500px;
padding: 1em;
}
.colorContainer {
--opacity: 0.1;
background:
linear-gradient(
45deg,
rgba(0, 0, 0, var(--opacity)) 25%,
transparent 25%,
transparent 75%,
rgba(0, 0, 0, var(--opacity)) 75%,
rgba(0, 0, 0, var(--opacity)) 0
),
linear-gradient(
45deg,
rgba(0, 0, 0, var(--opacity)) 25%,
transparent 25%,
transparent 75%,
rgba(0, 0, 0, var(--opacity)) 75%,
rgba(0, 0, 0, var(--opacity)) 0
),
white;
background-position:
0px 0,
5px 5px;
background-size:
10px 10px,
10px 10px;
border-radius: 12px;
overflow: hidden;
will-change: transform;
transition: transform 0.2s ease-out;
margin-bottom: 1em;
cursor: pointer;
border: solid 1px #d9d9d9;
}
.color {
display: flex;
justify-content: center;
align-items: center;
height: 4em;
width: 100%;
}
.colorContainer:hover {
transform: scale(1.02);
}
.colorContainer:active {
transform: scale(1.01);
}
.tokenName,
.tokenValue,
.tokenAlias {
cursor: pointer;
padding: 0.1em 0.5em;
white-space: nowrap;
}
.tokenName:hover,
.tokenValue:hover,
.tokenAlias:hover {
transform-origin: left;
font-weight: bold;
word-break: break-all;
}
.tokenName:active,
.tokenValue:active,
.tokenAlias:active {
transform: scale(0.98);
}

View File

@@ -1,11 +0,0 @@
import { Meta } from '@storybook/addon-docs/blocks'
import { Colors } from './Colors'
import { downtownCamper } from '.'
<Meta title="Global/Colors/Downtown Camper" />
# Colors: Downtown Camper
<Colors theme={downtownCamper} />

View File

@@ -1,11 +0,0 @@
import { Meta } from '@storybook/addon-docs/blocks'
import { Colors } from './Colors'
import { grandHotel } from '.'
<Meta title="Global/Colors/Grand Hotel" />
# Colors: Grand Hotel
<Colors theme={grandHotel} />

View File

@@ -1,11 +0,0 @@
import { Meta } from '@storybook/addon-docs/blocks'
import { Colors } from './Colors'
import { haymarket } from '.'
<Meta title="Global/Colors/Haymarket" />
# Colors: Haymarket
<Colors theme={haymarket} />

View File

@@ -1,11 +0,0 @@
import { Meta } from '@storybook/addon-docs/blocks'
import { Colors } from './Colors'
import { hotelNorge } from '.'
<Meta title="Global/Colors/Hotel Norge" />
# Colors: Hotel Norge
<Colors theme={hotelNorge} />

View File

@@ -1,11 +0,0 @@
import { Meta } from '@storybook/addon-docs/blocks'
import { Colors } from './Colors'
import { marski } from '.'
<Meta title="Global/Colors/Marski" />
# Colors: Marski
<Colors theme={marski} />

View File

@@ -1,11 +0,0 @@
import { Meta } from '@storybook/addon-docs/blocks'
import { Colors } from './Colors'
import { scandic } from '.'
<Meta title="Global/Colors/Scandic" />
# Colors: Scandic
<Colors theme={scandic} />

View File

@@ -1,11 +0,0 @@
import { Meta } from '@storybook/addon-docs/blocks'
import { Colors } from './Colors'
import { scandicGo } from '.'
<Meta title="Global/Colors/Scandic Go" />
# Colors: Scandic Go
<Colors theme={scandicGo} />

View File

@@ -1,11 +0,0 @@
import { Meta } from '@storybook/addon-docs/blocks'
import { Colors } from './Colors'
import { theDock } from '.'
<Meta title="Global/Colors/The Dock" />
# Colors: The Dock
<Colors theme={theDock} />