import type { Meta, StoryObj } from '@storybook/vue3-vite'
import type { ProbeProperty, Token } from '@/stories/tokenUtils'
import {
copyableClass,
copyableCopiedClass,
getTokenPixels,
readTokens,
sortTokensBySize,
splitRemPx,
tokenTableClass,
useCopier,
} from '@/stories/tokenUtils'
const meta: Meta = {
title: 'Foundations/Typography',
tags: ['!dev'],
parameters: {
layout: 'padded',
controls: { disable: true },
docs: { source: { code: null } },
},
}
export default meta
type Story = StoryObj
type PreviewKind = 'letter-spacing' | 'line-height' | 'text-size'
const previewStyle = (kind: PreviewKind, tokenName: string): string => {
const ref = `var(${tokenName})`
switch (kind) {
case 'text-size':
return `font-size: ${ref}; line-height: 1.1; color: #36384d;`
case 'line-height':
return `font-size: 14px; line-height: ${ref}; color: #36384d; max-width: 280px; width:280px; display:block; white-space: initial;`
case 'letter-spacing':
return `font-size: 14px; letter-spacing: ${ref}; color: #36384d;`
}
}
const sampleForKind = (kind: PreviewKind): string => {
switch (kind) {
case 'text-size':
return 'The quick brown fox'
case 'line-height':
return 'Cras mattis consectetur purus sit amet fermentum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.'
case 'letter-spacing':
return 'AVERAGE spacing sample'
}
}
/**
* Raw text sizes, sorted from the biggest to the smallest. Prefer the
* semantic `--cp-text-*-size` tokens (Text scale) in application code.
*/
export const TextSize: Story = {
render: () => ({
setup() {
const tokens = sortTokensBySize(readTokens(['--cp-text-size-']))
const { copiedKey, copy } = useCopier()
return {
tokens,
copiedKey,
copy,
tableClass: tokenTableClass,
copyClass: copyableClass,
copiedClass: copyableCopiedClass,
preview: (tokenName: string) => previewStyle('text-size', tokenName),
sample: sampleForKind('text-size'),
split: (token: Token) => splitRemPx(token),
}
},
template: `
| Token |
rem |
px |
Preview |
|
{{ copiedKey === token.name ? 'Copied!' : token.name }}
|
{{ split(token).rem }} |
{{ split(token).px }} |
{{ sample }}
|
No tokens
`,
}),
}
type ValueSectionArgs = { kind: 'letter-spacing' | 'line-height'; loader: () => Token[] }
const makeValueStory = ({ kind, loader }: ValueSectionArgs): Story => ({
render: () => ({
setup() {
const { copiedKey, copy } = useCopier()
const probeProperty: ProbeProperty = kind
return {
kind,
tokens: loader(),
copiedKey,
copy,
tableClass: tokenTableClass,
copyClass: copyableClass,
copiedClass: copyableCopiedClass,
preview: (k: PreviewKind, tokenName: string) => previewStyle(k, tokenName),
sample: (k: PreviewKind) => sampleForKind(k),
px: (tokenName: string) => getTokenPixels(tokenName, probeProperty) ?? '—',
}
},
template: `
| Token |
Value |
px |
Preview |
|
{{ copiedKey === token.name ? 'Copied!' : token.name }}
|
{{ token.value }} |
{{ px(token.name) }} |
{{ sample(kind) }}
|
No tokens
`,
}),
})
/**
* Raw line-heights. The gradient line marks the baseline of each sample.
*/
export const LineHeight: Story = makeValueStory({
kind: 'line-height',
loader: () => sortTokensBySize(readTokens(['--cp-line-height-'])),
})
/**
* Letter-spacing (tracking) scale.
*/
export const LetterSpacing: Story = makeValueStory({
kind: 'letter-spacing',
loader: () => sortTokensBySize(readTokens(['--cp-letter-spacing-'])),
})