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:
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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} />
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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} />
|
||||
@@ -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} />
|
||||
@@ -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} />
|
||||
@@ -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} />
|
||||
@@ -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} />
|
||||
@@ -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} />
|
||||
@@ -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} />
|
||||
@@ -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} />
|
||||
Reference in New Issue
Block a user