@citizenplane/pimp 16.0.3 → 16.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pimp.es.js +781 -757
- package/dist/pimp.umd.js +21 -21
- package/dist/style.css +1 -1
- package/package.json +10 -8
- package/src/components/CpDate.vue +3 -1
- package/src/components/CpHeading.vue +4 -5
- package/src/components/CpMultiselect.vue +2 -5
- package/src/components/CpTable.vue +4 -2
- package/src/components/CpTelInput.vue +18 -12
- package/src/components/CpText.vue +141 -0
- package/src/components/CpToast.vue +1 -1
- package/src/components/CpTransitionExpand.vue +23 -20
- package/src/components/index.ts +2 -0
- package/src/libs/CoreDatepicker.vue +1 -0
- package/src/stories/BaseInputLabel.stories.ts +36 -9
- package/src/stories/Colors.mdx +9 -0
- package/src/stories/Colors.stories.ts +177 -0
- package/src/stories/CpAccordion.stories.ts +188 -159
- package/src/stories/CpAccordionGroup.stories.ts +51 -95
- package/src/stories/CpAirlineLogo.stories.ts +52 -28
- package/src/stories/CpAlert.stories.ts +196 -159
- package/src/stories/CpBadge.stories.ts +260 -194
- package/src/stories/CpButton.stories.ts +257 -426
- package/src/stories/CpCheckbox.stories.ts +102 -30
- package/src/stories/CpContextualMenu.stories.ts +14 -9
- package/src/stories/CpDate.stories.ts +53 -26
- package/src/stories/CpDatepicker.stories.ts +53 -80
- package/src/stories/CpDialog.stories.ts +23 -2
- package/src/stories/CpHeading.stories.ts +60 -20
- package/src/stories/CpIcon.stories.ts +98 -31
- package/src/stories/CpInput.stories.ts +164 -73
- package/src/stories/CpItemActions.stories.ts +23 -12
- package/src/stories/CpLoader.stories.ts +55 -7
- package/src/stories/CpMenuItem.stories.ts +53 -27
- package/src/stories/CpMultiselect.stories.ts +53 -72
- package/src/stories/CpPartnerBadge.stories.ts +58 -76
- package/src/stories/CpRadio.stories.ts +45 -49
- package/src/stories/CpRadioGroup.stories.ts +47 -40
- package/src/stories/CpSelect.stories.ts +108 -34
- package/src/stories/CpSelectMenu.stories.ts +66 -55
- package/src/stories/CpSelectableButton.stories.ts +170 -81
- package/src/stories/CpSwitch.stories.ts +136 -134
- package/src/stories/CpTable.stories.ts +69 -13
- package/src/stories/CpTableEmptyState.stories.ts +11 -7
- package/src/stories/CpTabs.stories.ts +23 -5
- package/src/stories/CpTelInput.stories.ts +28 -19
- package/src/stories/CpText.stories.ts +131 -0
- package/src/stories/CpTextarea.stories.ts +74 -27
- package/src/stories/CpToast.stories.ts +75 -109
- package/src/stories/CpTooltip.stories.ts +82 -77
- package/src/stories/CpTransitionCounter.stories.ts +5 -1
- package/src/stories/CpTransitionExpand.stories.ts +12 -7
- package/src/stories/CpTransitionListItems.stories.ts +6 -1
- package/src/stories/CpTransitionSize.stories.ts +9 -1
- package/src/stories/CpTransitionSlide.stories.ts +5 -1
- package/src/stories/CpTransitionTabContent.stories.ts +5 -1
- package/src/stories/Dimensions.mdx +9 -0
- package/src/stories/Dimensions.stories.ts +119 -0
- package/src/stories/Easings.mdx +9 -0
- package/src/stories/Easings.stories.ts +101 -0
- package/src/stories/FocusRings.mdx +9 -0
- package/src/stories/FocusRings.stories.ts +74 -0
- package/src/stories/Shadows.mdx +9 -0
- package/src/stories/Shadows.stories.ts +100 -0
- package/src/stories/Typography.mdx +9 -0
- package/src/stories/Typography.stories.ts +181 -0
- package/src/stories/documentationStyles.ts +2 -10
- package/src/stories/tokenUtils.ts +259 -0
- package/src/types/primevue-toasteventbus.d.ts +14 -0
- package/tsconfig.json +1 -0
- package/.lintstagedrc.json +0 -4
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ref } from 'vue'
|
|
2
2
|
|
|
3
|
-
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
3
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
4
4
|
|
|
5
5
|
import CpTabs from '@/components/CpTabs.vue'
|
|
6
6
|
import CpTransitionTabContent from '@/components/CpTransitionTabContent.vue'
|
|
@@ -36,6 +36,10 @@ const layoutStyle = 'display: flex; flex-direction: column; gap: 20px; min-width
|
|
|
36
36
|
const panelStyle =
|
|
37
37
|
'min-height: 120px; padding: 20px; border-radius: 12px; background: #f3f4f6; font-size: 15px; line-height: 1.5;'
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Directional slide between tab panels. `direction` is driven by the
|
|
41
|
+
* current vs. previous tab index to slide forward or backward.
|
|
42
|
+
*/
|
|
39
43
|
export const Default: Story = {
|
|
40
44
|
args: {
|
|
41
45
|
duration: 300,
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
2
|
+
|
|
3
|
+
import type { Token } from '@/stories/tokenUtils'
|
|
4
|
+
import {
|
|
5
|
+
copyableClass,
|
|
6
|
+
copyableCopiedClass,
|
|
7
|
+
readTokens,
|
|
8
|
+
sortTokensBySize,
|
|
9
|
+
splitRemPx,
|
|
10
|
+
tokenTableClass,
|
|
11
|
+
useCopier,
|
|
12
|
+
} from '@/stories/tokenUtils'
|
|
13
|
+
|
|
14
|
+
const meta: Meta = {
|
|
15
|
+
title: 'Foundations/Dimensions',
|
|
16
|
+
tags: ['!dev'],
|
|
17
|
+
parameters: {
|
|
18
|
+
layout: 'padded',
|
|
19
|
+
controls: { disable: true },
|
|
20
|
+
docs: { source: { code: null } },
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default meta
|
|
25
|
+
|
|
26
|
+
type Story = StoryObj
|
|
27
|
+
|
|
28
|
+
type DimensionKind = 'bar' | 'none' | 'radius' | 'square'
|
|
29
|
+
|
|
30
|
+
const previewStyle = (kind: DimensionKind, tokenName: string): string => {
|
|
31
|
+
const ref = `var(${tokenName})`
|
|
32
|
+
switch (kind) {
|
|
33
|
+
case 'bar':
|
|
34
|
+
return `height: 12px; width: ${ref}; max-width: 100%; background: var(--cp-background-accent-solid, #603dfd); border-radius: 4px;`
|
|
35
|
+
case 'radius':
|
|
36
|
+
return `width: 56px; height: 56px; background: var(--cp-background-accent-primary, #eaecff); border: 1px solid var(--cp-border-accent-primary, #ccd0ff); border-radius: ${ref};`
|
|
37
|
+
case 'square':
|
|
38
|
+
return `width: ${ref}; height: ${ref}; background: var(--cp-background-accent-solid, #603dfd); border-radius: 2px;`
|
|
39
|
+
case 'none':
|
|
40
|
+
return ''
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
type SectionArgs = { kind: DimensionKind; prefix: string }
|
|
45
|
+
|
|
46
|
+
const makeSectionStory = (section: SectionArgs): Story => ({
|
|
47
|
+
render: () => ({
|
|
48
|
+
setup() {
|
|
49
|
+
const tokens = sortTokensBySize(readTokens([section.prefix]))
|
|
50
|
+
const { copiedKey, copy } = useCopier()
|
|
51
|
+
return {
|
|
52
|
+
kind: section.kind,
|
|
53
|
+
tokens,
|
|
54
|
+
copiedKey,
|
|
55
|
+
copy,
|
|
56
|
+
tableClass: tokenTableClass,
|
|
57
|
+
copyClass: copyableClass,
|
|
58
|
+
copiedClass: copyableCopiedClass,
|
|
59
|
+
preview: (kind: DimensionKind, tokenName: string) => previewStyle(kind, tokenName),
|
|
60
|
+
split: (token: Token) => splitRemPx(token),
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
template: `
|
|
64
|
+
<table v-if="tokens.length > 0" :class="tableClass">
|
|
65
|
+
<thead>
|
|
66
|
+
<tr>
|
|
67
|
+
<th scope="col">Token</th>
|
|
68
|
+
<th scope="col">rem</th>
|
|
69
|
+
<th scope="col">px</th>
|
|
70
|
+
<th scope="col">Preview</th>
|
|
71
|
+
</tr>
|
|
72
|
+
</thead>
|
|
73
|
+
<tbody>
|
|
74
|
+
<tr v-for="token in tokens" :key="token.name">
|
|
75
|
+
<td>
|
|
76
|
+
<span
|
|
77
|
+
:class="[copyClass, copiedKey === token.name ? copiedClass : '']"
|
|
78
|
+
role="button"
|
|
79
|
+
tabindex="0"
|
|
80
|
+
:title="'Click to copy ' + token.name"
|
|
81
|
+
@click="copy(token.name)"
|
|
82
|
+
@keydown.enter.prevent="copy(token.name)"
|
|
83
|
+
@keydown.space.prevent="copy(token.name)"
|
|
84
|
+
>{{ copiedKey === token.name ? 'Copied!' : token.name }}</span>
|
|
85
|
+
</td>
|
|
86
|
+
<td>{{ split(token).rem }}</td>
|
|
87
|
+
<td>{{ split(token).px }}</td>
|
|
88
|
+
<td class="cp-token-table__preview">
|
|
89
|
+
<div :style="preview(kind, token.name)"></div>
|
|
90
|
+
</td>
|
|
91
|
+
</tr>
|
|
92
|
+
</tbody>
|
|
93
|
+
</table>
|
|
94
|
+
<div v-else style="padding: 12px 0; color: #9ca3af; font-size: 12px;">No tokens</div>
|
|
95
|
+
`,
|
|
96
|
+
}),
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Responsive breakpoints. These values match the `min-width` media queries
|
|
101
|
+
* the design system uses to adapt layouts.
|
|
102
|
+
*/
|
|
103
|
+
export const Breakpoint: Story = makeSectionStory({ prefix: '--cp-breakpoint-', kind: 'none' })
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Border radius scale, from sharp corners to fully rounded pill shapes.
|
|
107
|
+
*/
|
|
108
|
+
export const Radius: Story = makeSectionStory({ prefix: '--cp-radius-', kind: 'radius' })
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Spacing scale used for padding, margin and gap. Rendered as horizontal
|
|
112
|
+
* bars to compare relative widths.
|
|
113
|
+
*/
|
|
114
|
+
export const Spacing: Story = makeSectionStory({ prefix: '--cp-spacing-', kind: 'bar' })
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Width tokens used for icons, avatars and small fixed-size surfaces.
|
|
118
|
+
*/
|
|
119
|
+
export const Width: Story = makeSectionStory({ prefix: '--cp-width-', kind: 'square' })
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
2
|
+
|
|
3
|
+
import { copyableClass, copyableCopiedClass, readTokens, tokenTableClass, useCopier } from '@/stories/tokenUtils'
|
|
4
|
+
|
|
5
|
+
const meta: Meta = {
|
|
6
|
+
title: 'Foundations/Easings',
|
|
7
|
+
tags: ['!dev'],
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'padded',
|
|
10
|
+
controls: { disable: true },
|
|
11
|
+
docs: { source: { code: null } },
|
|
12
|
+
},
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default meta
|
|
16
|
+
|
|
17
|
+
type Story = StoryObj
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Cubic-bezier curves used for the design-system transitions. Hover (or
|
|
21
|
+
* focus) any track to play the animation and compare curves side by side.
|
|
22
|
+
*/
|
|
23
|
+
export const Curves: Story = {
|
|
24
|
+
render: () => ({
|
|
25
|
+
setup() {
|
|
26
|
+
const easings = readTokens(['--cp-easing-'])
|
|
27
|
+
const { copiedKey, copy } = useCopier()
|
|
28
|
+
return {
|
|
29
|
+
easings,
|
|
30
|
+
copiedKey,
|
|
31
|
+
copy,
|
|
32
|
+
tableClass: tokenTableClass,
|
|
33
|
+
copyClass: copyableClass,
|
|
34
|
+
copiedClass: copyableCopiedClass,
|
|
35
|
+
ballStyle: (tokenName: string) => `transition-timing-function: var(${tokenName});`,
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
template: `
|
|
39
|
+
<div>
|
|
40
|
+
<style>
|
|
41
|
+
.cp-easing-track {
|
|
42
|
+
position: relative;
|
|
43
|
+
width: 220px;
|
|
44
|
+
height: 36px;
|
|
45
|
+
background: #f3f4f6;
|
|
46
|
+
border-radius: 18px;
|
|
47
|
+
overflow: hidden;
|
|
48
|
+
}
|
|
49
|
+
.cp-easing-ball {
|
|
50
|
+
position: absolute;
|
|
51
|
+
top: 4px;
|
|
52
|
+
left: 4px;
|
|
53
|
+
width: 28px;
|
|
54
|
+
height: 28px;
|
|
55
|
+
border-radius: 50%;
|
|
56
|
+
background: var(--cp-background-accent-solid, #603dfd);
|
|
57
|
+
transition-property: transform;
|
|
58
|
+
transition-duration: 900ms;
|
|
59
|
+
transform: translateX(0);
|
|
60
|
+
}
|
|
61
|
+
.cp-easing-track:hover .cp-easing-ball,
|
|
62
|
+
.cp-easing-track:focus-within .cp-easing-ball {
|
|
63
|
+
transform: translateX(184px);
|
|
64
|
+
}
|
|
65
|
+
</style>
|
|
66
|
+
<p style="margin: 0 0 12px 0; color: #6b7280; font-size: 12px;">Hover a track to play the transition.</p>
|
|
67
|
+
<table v-if="easings.length > 0" :class="tableClass">
|
|
68
|
+
<thead>
|
|
69
|
+
<tr>
|
|
70
|
+
<th scope="col">Token</th>
|
|
71
|
+
<th scope="col">Value</th>
|
|
72
|
+
<th scope="col">Preview</th>
|
|
73
|
+
</tr>
|
|
74
|
+
</thead>
|
|
75
|
+
<tbody>
|
|
76
|
+
<tr v-for="token in easings" :key="token.name">
|
|
77
|
+
<td>
|
|
78
|
+
<span
|
|
79
|
+
:class="[copyClass, copiedKey === token.name ? copiedClass : '']"
|
|
80
|
+
role="button"
|
|
81
|
+
tabindex="0"
|
|
82
|
+
:title="'Click to copy ' + token.name"
|
|
83
|
+
@click="copy(token.name)"
|
|
84
|
+
@keydown.enter.prevent="copy(token.name)"
|
|
85
|
+
@keydown.space.prevent="copy(token.name)"
|
|
86
|
+
>{{ copiedKey === token.name ? 'Copied!' : token.name }}</span>
|
|
87
|
+
</td>
|
|
88
|
+
<td>{{ token.value }}</td>
|
|
89
|
+
<td class="cp-token-table__preview">
|
|
90
|
+
<div class="cp-easing-track" tabindex="0">
|
|
91
|
+
<div class="cp-easing-ball" :style="ballStyle(token.name)"></div>
|
|
92
|
+
</div>
|
|
93
|
+
</td>
|
|
94
|
+
</tr>
|
|
95
|
+
</tbody>
|
|
96
|
+
</table>
|
|
97
|
+
<div v-else style="padding: 12px 0; color: #9ca3af; font-size: 12px;">No tokens</div>
|
|
98
|
+
</div>
|
|
99
|
+
`,
|
|
100
|
+
}),
|
|
101
|
+
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
2
|
+
|
|
3
|
+
import { copyableClass, copyableCopiedClass, readTokens, tokenTableClass, useCopier } from '@/stories/tokenUtils'
|
|
4
|
+
|
|
5
|
+
const meta: Meta = {
|
|
6
|
+
title: 'Foundations/Focus Rings',
|
|
7
|
+
tags: ['!dev'],
|
|
8
|
+
parameters: {
|
|
9
|
+
layout: 'padded',
|
|
10
|
+
controls: { disable: true },
|
|
11
|
+
docs: { source: { code: null } },
|
|
12
|
+
},
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export default meta
|
|
16
|
+
|
|
17
|
+
type Story = StoryObj
|
|
18
|
+
|
|
19
|
+
const previewStyle = (tokenName: string): string =>
|
|
20
|
+
`display: inline-flex; align-items: center; justify-content: center; height: 40px; padding: 0 18px; border-radius: 8px; background: #ffffff; border: 1px solid #e9eaf6; color: #36384d; font-size: 14px; box-shadow: var(${tokenName});`
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Composite focus-ring tokens (one token per color role). Each token is a
|
|
24
|
+
* multi-layered `box-shadow` that produces a consistent, accessible focus
|
|
25
|
+
* outline when applied to an element.
|
|
26
|
+
*/
|
|
27
|
+
export const Composite: Story = {
|
|
28
|
+
render: () => ({
|
|
29
|
+
setup() {
|
|
30
|
+
const composites = readTokens([/^--cp-shadow-focus-ring-[^-]+$/])
|
|
31
|
+
const { copiedKey, copy } = useCopier()
|
|
32
|
+
return {
|
|
33
|
+
composites,
|
|
34
|
+
copiedKey,
|
|
35
|
+
copy,
|
|
36
|
+
tableClass: tokenTableClass,
|
|
37
|
+
copyClass: copyableClass,
|
|
38
|
+
copiedClass: copyableCopiedClass,
|
|
39
|
+
preview: (tokenName: string) => previewStyle(tokenName),
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
template: `
|
|
43
|
+
<table v-if="composites.length > 0" :class="tableClass">
|
|
44
|
+
<thead>
|
|
45
|
+
<tr>
|
|
46
|
+
<th scope="col">Token</th>
|
|
47
|
+
<th scope="col">Value</th>
|
|
48
|
+
<th scope="col">Preview</th>
|
|
49
|
+
</tr>
|
|
50
|
+
</thead>
|
|
51
|
+
<tbody>
|
|
52
|
+
<tr v-for="token in composites" :key="token.name">
|
|
53
|
+
<td>
|
|
54
|
+
<span
|
|
55
|
+
:class="[copyClass, copiedKey === token.name ? copiedClass : '']"
|
|
56
|
+
role="button"
|
|
57
|
+
tabindex="0"
|
|
58
|
+
:title="'Click to copy ' + token.name"
|
|
59
|
+
@click="copy(token.name)"
|
|
60
|
+
@keydown.enter.prevent="copy(token.name)"
|
|
61
|
+
@keydown.space.prevent="copy(token.name)"
|
|
62
|
+
>{{ copiedKey === token.name ? 'Copied!' : token.name }}</span>
|
|
63
|
+
</td>
|
|
64
|
+
<td>{{ token.value }}</td>
|
|
65
|
+
<td class="cp-token-table__preview">
|
|
66
|
+
<span :style="preview(token.name)">Focused</span>
|
|
67
|
+
</td>
|
|
68
|
+
</tr>
|
|
69
|
+
</tbody>
|
|
70
|
+
</table>
|
|
71
|
+
<div v-else style="padding: 12px 0; color: #9ca3af; font-size: 12px;">No tokens</div>
|
|
72
|
+
`,
|
|
73
|
+
}),
|
|
74
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
2
|
+
|
|
3
|
+
import type { Token } from '@/stories/tokenUtils'
|
|
4
|
+
import {
|
|
5
|
+
copyableClass,
|
|
6
|
+
copyableCopiedClass,
|
|
7
|
+
readTokens,
|
|
8
|
+
sortTokensBySize,
|
|
9
|
+
tokenTableClass,
|
|
10
|
+
useCopier,
|
|
11
|
+
} from '@/stories/tokenUtils'
|
|
12
|
+
|
|
13
|
+
const meta: Meta = {
|
|
14
|
+
title: 'Foundations/Shadows',
|
|
15
|
+
tags: ['!dev'],
|
|
16
|
+
parameters: {
|
|
17
|
+
layout: 'padded',
|
|
18
|
+
controls: { disable: true },
|
|
19
|
+
docs: { source: { code: null } },
|
|
20
|
+
},
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export default meta
|
|
24
|
+
|
|
25
|
+
type Story = StoryObj
|
|
26
|
+
|
|
27
|
+
const previewStyle = (tokenName: string): string =>
|
|
28
|
+
`width: 160px; height: 80px; background: #ffffff; border-radius: 8px; box-shadow: var(${tokenName});`
|
|
29
|
+
|
|
30
|
+
const makeSectionStory = (loader: () => Token[]): Story => ({
|
|
31
|
+
render: () => ({
|
|
32
|
+
setup() {
|
|
33
|
+
const { copiedKey, copy } = useCopier()
|
|
34
|
+
return {
|
|
35
|
+
tokens: loader(),
|
|
36
|
+
copiedKey,
|
|
37
|
+
copy,
|
|
38
|
+
tableClass: tokenTableClass,
|
|
39
|
+
copyClass: copyableClass,
|
|
40
|
+
copiedClass: copyableCopiedClass,
|
|
41
|
+
preview: (tokenName: string) => previewStyle(tokenName),
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
template: `
|
|
45
|
+
<table v-if="tokens.length > 0" :class="tableClass">
|
|
46
|
+
<thead>
|
|
47
|
+
<tr>
|
|
48
|
+
<th scope="col">Token</th>
|
|
49
|
+
<th scope="col">Value</th>
|
|
50
|
+
<th scope="col">Preview</th>
|
|
51
|
+
</tr>
|
|
52
|
+
</thead>
|
|
53
|
+
<tbody>
|
|
54
|
+
<tr v-for="token in tokens" :key="token.name">
|
|
55
|
+
<td>
|
|
56
|
+
<span
|
|
57
|
+
:class="[copyClass, copiedKey === token.name ? copiedClass : '']"
|
|
58
|
+
role="button"
|
|
59
|
+
tabindex="0"
|
|
60
|
+
:title="'Click to copy ' + token.name"
|
|
61
|
+
@click="copy(token.name)"
|
|
62
|
+
@keydown.enter.prevent="copy(token.name)"
|
|
63
|
+
@keydown.space.prevent="copy(token.name)"
|
|
64
|
+
>{{ copiedKey === token.name ? 'Copied!' : token.name }}</span>
|
|
65
|
+
</td>
|
|
66
|
+
<td>{{ token.value }}</td>
|
|
67
|
+
<td class="cp-token-table__preview">
|
|
68
|
+
<div :style="preview(token.name)"></div>
|
|
69
|
+
</td>
|
|
70
|
+
</tr>
|
|
71
|
+
</tbody>
|
|
72
|
+
</table>
|
|
73
|
+
<div v-else style="padding: 12px 0; color: #9ca3af; font-size: 12px;">No tokens</div>
|
|
74
|
+
`,
|
|
75
|
+
}),
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Drop shadows ordered from the most to the least prominent. Use them to
|
|
80
|
+
* lift cards, popovers and menus off the surface.
|
|
81
|
+
*/
|
|
82
|
+
export const DropShadows: Story = makeSectionStory(() =>
|
|
83
|
+
sortTokensBySize(readTokens(['--cp-shadows-'], [/-inset$/, /^--cp-shadows-overlay$/, /^--cp-shadows-side-panel$/])),
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Inset shadows sit inside the element. Useful for pressed states and
|
|
88
|
+
* recessed surfaces like form fields.
|
|
89
|
+
*/
|
|
90
|
+
export const InsetShadows: Story = makeSectionStory(() => sortTokensBySize(readTokens([/^--cp-shadows-.*-inset$/])))
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Dedicated shadow for the side panel container.
|
|
94
|
+
*/
|
|
95
|
+
export const SidePanel: Story = makeSectionStory(() => readTokens(['--cp-shadows-side-panel']))
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Multi-layered shadow used for modals and full-screen overlays.
|
|
99
|
+
*/
|
|
100
|
+
export const Overlay: Story = makeSectionStory(() => readTokens(['--cp-shadows-overlay']))
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3-vite'
|
|
2
|
+
|
|
3
|
+
import type { ProbeProperty, Token } from '@/stories/tokenUtils'
|
|
4
|
+
import {
|
|
5
|
+
copyableClass,
|
|
6
|
+
copyableCopiedClass,
|
|
7
|
+
getTokenPixels,
|
|
8
|
+
readTokens,
|
|
9
|
+
sortTokensBySize,
|
|
10
|
+
splitRemPx,
|
|
11
|
+
tokenTableClass,
|
|
12
|
+
useCopier,
|
|
13
|
+
} from '@/stories/tokenUtils'
|
|
14
|
+
|
|
15
|
+
const meta: Meta = {
|
|
16
|
+
title: 'Foundations/Typography',
|
|
17
|
+
tags: ['!dev'],
|
|
18
|
+
parameters: {
|
|
19
|
+
layout: 'padded',
|
|
20
|
+
controls: { disable: true },
|
|
21
|
+
docs: { source: { code: null } },
|
|
22
|
+
},
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export default meta
|
|
26
|
+
|
|
27
|
+
type Story = StoryObj
|
|
28
|
+
|
|
29
|
+
type PreviewKind = 'letter-spacing' | 'line-height' | 'text-size'
|
|
30
|
+
|
|
31
|
+
const previewStyle = (kind: PreviewKind, tokenName: string): string => {
|
|
32
|
+
const ref = `var(${tokenName})`
|
|
33
|
+
switch (kind) {
|
|
34
|
+
case 'text-size':
|
|
35
|
+
return `font-size: ${ref}; line-height: 1.1; color: #36384d;`
|
|
36
|
+
case 'line-height':
|
|
37
|
+
return `font-size: 14px; line-height: ${ref}; color: #36384d; max-width: 280px; width:280px; display:block; white-space: initial;`
|
|
38
|
+
case 'letter-spacing':
|
|
39
|
+
return `font-size: 14px; letter-spacing: ${ref}; color: #36384d;`
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const sampleForKind = (kind: PreviewKind): string => {
|
|
44
|
+
switch (kind) {
|
|
45
|
+
case 'text-size':
|
|
46
|
+
return 'The quick brown fox'
|
|
47
|
+
case 'line-height':
|
|
48
|
+
return 'Cras mattis consectetur purus sit amet fermentum. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.'
|
|
49
|
+
case 'letter-spacing':
|
|
50
|
+
return 'AVERAGE spacing sample'
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Raw text sizes, sorted from the biggest to the smallest. Prefer the
|
|
56
|
+
* semantic `--cp-text-*-size` tokens (Text scale) in application code.
|
|
57
|
+
*/
|
|
58
|
+
export const TextSize: Story = {
|
|
59
|
+
render: () => ({
|
|
60
|
+
setup() {
|
|
61
|
+
const tokens = sortTokensBySize(readTokens(['--cp-text-size-']))
|
|
62
|
+
const { copiedKey, copy } = useCopier()
|
|
63
|
+
return {
|
|
64
|
+
tokens,
|
|
65
|
+
copiedKey,
|
|
66
|
+
copy,
|
|
67
|
+
tableClass: tokenTableClass,
|
|
68
|
+
copyClass: copyableClass,
|
|
69
|
+
copiedClass: copyableCopiedClass,
|
|
70
|
+
preview: (tokenName: string) => previewStyle('text-size', tokenName),
|
|
71
|
+
sample: sampleForKind('text-size'),
|
|
72
|
+
split: (token: Token) => splitRemPx(token),
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
template: `
|
|
76
|
+
<table v-if="tokens.length > 0" :class="tableClass">
|
|
77
|
+
<thead>
|
|
78
|
+
<tr>
|
|
79
|
+
<th scope="col">Token</th>
|
|
80
|
+
<th scope="col">rem</th>
|
|
81
|
+
<th scope="col">px</th>
|
|
82
|
+
<th scope="col">Preview</th>
|
|
83
|
+
</tr>
|
|
84
|
+
</thead>
|
|
85
|
+
<tbody>
|
|
86
|
+
<tr v-for="token in tokens" :key="token.name">
|
|
87
|
+
<td>
|
|
88
|
+
<span
|
|
89
|
+
:class="[copyClass, copiedKey === token.name ? copiedClass : '']"
|
|
90
|
+
role="button"
|
|
91
|
+
tabindex="0"
|
|
92
|
+
:title="'Click to copy ' + token.name"
|
|
93
|
+
@click="copy(token.name)"
|
|
94
|
+
@keydown.enter.prevent="copy(token.name)"
|
|
95
|
+
@keydown.space.prevent="copy(token.name)"
|
|
96
|
+
>{{ copiedKey === token.name ? 'Copied!' : token.name }}</span>
|
|
97
|
+
</td>
|
|
98
|
+
<td>{{ split(token).rem }}</td>
|
|
99
|
+
<td>{{ split(token).px }}</td>
|
|
100
|
+
<td class="cp-token-table__preview">
|
|
101
|
+
<span :style="preview(token.name)">{{ sample }}</span>
|
|
102
|
+
</td>
|
|
103
|
+
</tr>
|
|
104
|
+
</tbody>
|
|
105
|
+
</table>
|
|
106
|
+
<div v-else style="padding: 12px 0; color: #9ca3af; font-size: 12px;">No tokens</div>
|
|
107
|
+
`,
|
|
108
|
+
}),
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
type ValueSectionArgs = { kind: 'letter-spacing' | 'line-height'; loader: () => Token[] }
|
|
112
|
+
|
|
113
|
+
const makeValueStory = ({ kind, loader }: ValueSectionArgs): Story => ({
|
|
114
|
+
render: () => ({
|
|
115
|
+
setup() {
|
|
116
|
+
const { copiedKey, copy } = useCopier()
|
|
117
|
+
const probeProperty: ProbeProperty = kind
|
|
118
|
+
return {
|
|
119
|
+
kind,
|
|
120
|
+
tokens: loader(),
|
|
121
|
+
copiedKey,
|
|
122
|
+
copy,
|
|
123
|
+
tableClass: tokenTableClass,
|
|
124
|
+
copyClass: copyableClass,
|
|
125
|
+
copiedClass: copyableCopiedClass,
|
|
126
|
+
preview: (k: PreviewKind, tokenName: string) => previewStyle(k, tokenName),
|
|
127
|
+
sample: (k: PreviewKind) => sampleForKind(k),
|
|
128
|
+
px: (tokenName: string) => getTokenPixels(tokenName, probeProperty) ?? '—',
|
|
129
|
+
}
|
|
130
|
+
},
|
|
131
|
+
template: `
|
|
132
|
+
<table v-if="tokens.length > 0" :class="tableClass">
|
|
133
|
+
<thead>
|
|
134
|
+
<tr>
|
|
135
|
+
<th scope="col">Token</th>
|
|
136
|
+
<th scope="col">Value</th>
|
|
137
|
+
<th scope="col">px</th>
|
|
138
|
+
<th scope="col">Preview</th>
|
|
139
|
+
</tr>
|
|
140
|
+
</thead>
|
|
141
|
+
<tbody>
|
|
142
|
+
<tr v-for="token in tokens" :key="token.name">
|
|
143
|
+
<td>
|
|
144
|
+
<span
|
|
145
|
+
:class="[copyClass, copiedKey === token.name ? copiedClass : '']"
|
|
146
|
+
role="button"
|
|
147
|
+
tabindex="0"
|
|
148
|
+
:title="'Click to copy ' + token.name"
|
|
149
|
+
@click="copy(token.name)"
|
|
150
|
+
@keydown.enter.prevent="copy(token.name)"
|
|
151
|
+
@keydown.space.prevent="copy(token.name)"
|
|
152
|
+
>{{ copiedKey === token.name ? 'Copied!' : token.name }}</span>
|
|
153
|
+
</td>
|
|
154
|
+
<td>{{ token.value }}</td>
|
|
155
|
+
<td>{{ px(token.name) }}</td>
|
|
156
|
+
<td class="cp-token-table__preview">
|
|
157
|
+
<span :style="preview(kind, token.name)">{{ sample(kind) }}</span>
|
|
158
|
+
</td>
|
|
159
|
+
</tr>
|
|
160
|
+
</tbody>
|
|
161
|
+
</table>
|
|
162
|
+
<div v-else style="padding: 12px 0; color: #9ca3af; font-size: 12px;">No tokens</div>
|
|
163
|
+
`,
|
|
164
|
+
}),
|
|
165
|
+
})
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Raw line-heights. The gradient line marks the baseline of each sample.
|
|
169
|
+
*/
|
|
170
|
+
export const LineHeight: Story = makeValueStory({
|
|
171
|
+
kind: 'line-height',
|
|
172
|
+
loader: () => sortTokensBySize(readTokens(['--cp-line-height-'])),
|
|
173
|
+
})
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Letter-spacing (tracking) scale.
|
|
177
|
+
*/
|
|
178
|
+
export const LetterSpacing: Story = makeValueStory({
|
|
179
|
+
kind: 'letter-spacing',
|
|
180
|
+
loader: () => sortTokensBySize(readTokens(['--cp-letter-spacing-'])),
|
|
181
|
+
})
|
|
@@ -1,16 +1,8 @@
|
|
|
1
|
-
export const docPageStyle =
|
|
2
|
-
'padding: 24px; background: #f3f4f6; min-height: 100vh; width: 70vw; box-sizing: border-box;'
|
|
3
|
-
|
|
4
|
-
export const docSectionStyle =
|
|
5
|
-
'background: #fff; border-radius: 8px; padding: 24px; margin-bottom: 28px; box-shadow: 0 1px 3px rgba(0,0,0,0.08);'
|
|
6
|
-
|
|
7
|
-
export const docTitleStyle =
|
|
8
|
-
'margin: 0 0 16px 0; font-size: 12px; font-weight: 600; color: #6b7280; text-transform: uppercase; letter-spacing: 0.05em;'
|
|
9
|
-
|
|
10
1
|
export const docRowWrapStyle = 'display: flex; flex-wrap: wrap; gap: 24px 32px; align-items: flex-end;'
|
|
11
2
|
|
|
12
3
|
export const docRowColumnStyle = 'display: flex; flex-direction: column; gap: 24px;'
|
|
13
4
|
|
|
14
|
-
export const docCellStyle =
|
|
5
|
+
export const docCellStyle =
|
|
6
|
+
'display: flex; flex-direction: column; gap: 10px; align-items: flex-start; justify-content: space-between; align-self: stretch;'
|
|
15
7
|
|
|
16
8
|
export const docLabelStyle = 'font-size: 12px; color: #6b7280;'
|