@sanity/ui 2.0.0-alpha.13 → 2.0.0-alpha.14

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.
Files changed (32) hide show
  1. package/dist/index.cjs.mjs +27 -0
  2. package/dist/index.d.ts +337 -7
  3. package/dist/index.esm.js +745 -58
  4. package/dist/index.esm.js.map +1 -1
  5. package/dist/index.js +772 -58
  6. package/dist/index.js.map +1 -1
  7. package/package.json +2 -2
  8. package/src/theme/_internal/__workshop__/build/story.tsx +178 -0
  9. package/src/theme/_internal/__workshop__/build/theme.ts +3 -0
  10. package/src/theme/_internal/__workshop__/index.ts +14 -0
  11. package/src/theme/_internal/build/buildTheme.test.ts +78 -0
  12. package/src/theme/_internal/build/buildTheme.ts +15 -0
  13. package/src/theme/_internal/build/colorTheme/buildColorTheme.test.ts +185 -0
  14. package/src/theme/_internal/build/colorTheme/buildColorTheme.ts +222 -0
  15. package/src/theme/_internal/build/colorTheme/renderColorTheme.ts +226 -0
  16. package/src/theme/_internal/build/defaults/colorPalette.ts +8 -0
  17. package/src/theme/_internal/build/defaults/colorTokens.ts +124 -0
  18. package/src/theme/_internal/build/helpers.ts +64 -0
  19. package/src/theme/_internal/build/index.ts +1 -0
  20. package/src/theme/_internal/config/helpers.ts +47 -0
  21. package/src/theme/_internal/config/index.ts +3 -0
  22. package/src/theme/_internal/config/token/index.ts +2 -0
  23. package/src/theme/_internal/config/token/parseTokenKey.test.ts +72 -0
  24. package/src/theme/_internal/config/token/parseTokenKey.ts +88 -0
  25. package/src/theme/_internal/config/token/parseTokenValue.test.ts +45 -0
  26. package/src/theme/_internal/config/token/parseTokenValue.ts +123 -0
  27. package/src/theme/_internal/config/types.ts +126 -0
  28. package/src/theme/_internal/constants.ts +48 -0
  29. package/src/theme/_internal/helpers.ts +19 -0
  30. package/src/theme/_internal/index.ts +5 -0
  31. package/src/theme/_internal/types.ts +72 -0
  32. package/src/theme/index.ts +1 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/ui",
3
- "version": "2.0.0-alpha.13",
3
+ "version": "2.0.0-alpha.14",
4
4
  "sideEffects": false,
5
5
  "types": "./dist/index.d.ts",
6
6
  "source": "./src/index.ts",
@@ -52,7 +52,7 @@
52
52
  },
53
53
  "dependencies": {
54
54
  "@floating-ui/react-dom": "2.0.0",
55
- "@sanity/color": "3.0.0-beta.5",
55
+ "@sanity/color": "3.0.0-beta.6",
56
56
  "@sanity/icons": "^2.4.1",
57
57
  "csstype": "^3.1.2",
58
58
  "framer-motion": "^10.16.2",
@@ -0,0 +1,178 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any */
2
+
3
+ import {ReactElement} from 'react'
4
+ import styled from 'styled-components'
5
+ import {COLOR_BASE_TONES, COLOR_BUTTON_MODES, COLOR_STATE_TONES} from '../../constants'
6
+ import {ColorBaseTone, TMP_Theme} from '../../types'
7
+ import {theme} from './theme'
8
+
9
+ const Root = styled.div`
10
+ background: #000;
11
+ font-family:
12
+ system-ui,
13
+ -apple-system,
14
+ BlinkMacSystemFont,
15
+ 'Segoe UI',
16
+ Roboto,
17
+ Oxygen,
18
+ Ubuntu,
19
+ Cantarell,
20
+ 'Open Sans',
21
+ 'Helvetica Neue',
22
+ sans-serif;
23
+ font-size: 13px;
24
+ line-height: 9px;
25
+ margin: 0;
26
+ -webkit-font-smoothing: antialiased;
27
+ user-select: none;
28
+
29
+ pre {
30
+ font: inherit;
31
+ font-family: 'SF Mono', Menlo, monospace;
32
+ margin: 0;
33
+ padding: 0;
34
+ }
35
+
36
+ .button {
37
+ background-color: var(--button-enabled-bg);
38
+ color: var(--button-enabled-fg);
39
+ box-shadow:
40
+ inset 0 0 0 1px var(--border-color),
41
+ 0 1px 0 0 color-mix(in srgb, var(--border-color), transparent 75%);
42
+ text-align: center;
43
+ border-radius: 3px;
44
+ font-weight: 500;
45
+ cursor: default;
46
+ transition: box-shadow 80ms ease-in-out;
47
+
48
+ --border-color: var(--button-enabled-border);
49
+ }
50
+
51
+ .button:hover {
52
+ background-color: var(--button-hovered-bg);
53
+ color: var(--button-hovered-fg);
54
+ --border-color: var(--button-hovered-border);
55
+ }
56
+
57
+ .button:active {
58
+ background-color: var(--button-pressed-bg);
59
+ color: var(--button-pressed-fg);
60
+ --border-color: var(--button-pressed-border);
61
+ box-shadow: inset 0 0 0 1px var(--border-color);
62
+ }
63
+
64
+ .button.selected {
65
+ background-color: var(--button-selected-bg);
66
+ color: var(--button-selected-fg);
67
+ --border-color: var(--button-selected-border);
68
+ box-shadow: inset 0 0 0 1px var(--border-color);
69
+ }
70
+
71
+ .button.disabled {
72
+ background-color: var(--button-disabled-bg);
73
+ color: var(--button-disabled-fg);
74
+ --border-color: var(--button-disabled-border);
75
+ box-shadow: inset 0 0 0 1px var(--border-color);
76
+ }
77
+ `
78
+
79
+ export default function BuildStory(): ReactElement {
80
+ return (
81
+ <Root>
82
+ <div style={{display: 'flex'}}>
83
+ <div style={{flex: 1}}>
84
+ {COLOR_BASE_TONES.map((baseTone) => (
85
+ <BaseTonePreview baseTone={baseTone} key={baseTone} scheme="light" theme={theme} />
86
+ ))}
87
+ </div>
88
+ <div style={{flex: 1}}>
89
+ {COLOR_BASE_TONES.map((baseTone) => (
90
+ <BaseTonePreview baseTone={baseTone} key={baseTone} scheme="dark" theme={theme} />
91
+ ))}
92
+ </div>
93
+ </div>
94
+ </Root>
95
+ )
96
+ }
97
+
98
+ function BaseTonePreview(props: {
99
+ baseTone: ColorBaseTone
100
+ scheme: 'light' | 'dark'
101
+ theme: TMP_Theme
102
+ }) {
103
+ const {baseTone, scheme, theme} = props
104
+ const color = theme.color[scheme]
105
+
106
+ return (
107
+ <div
108
+ style={
109
+ {
110
+ backgroundColor: color[baseTone].base.bg,
111
+ color: color[baseTone].base.fg,
112
+ '--border-color': color[baseTone].base.border,
113
+ } as any
114
+ }
115
+ >
116
+ <div style={{maxWidth: 540, margin: 'auto', padding: '20px 0'}}>
117
+ <pre style={{padding: 12}}>
118
+ color/{scheme}/{baseTone}
119
+ </pre>
120
+ <div style={{padding: '1px 12px 12px 12px'}}>
121
+ {COLOR_BUTTON_MODES.map((mode) => (
122
+ <div key={mode} style={{display: 'flex', flexDirection: 'column'}}>
123
+ {COLOR_STATE_TONES.map((tone) => {
124
+ const button = color[baseTone].button[tone][mode]
125
+
126
+ return (
127
+ <div
128
+ key={tone}
129
+ style={
130
+ {
131
+ border: '1px solid var(--border-color)',
132
+ padding: 4,
133
+ display: 'flex',
134
+ marginTop: -1,
135
+ gap: 4,
136
+
137
+ '--button-enabled-bg': button.enabled.bg,
138
+ '--button-enabled-fg': button.enabled.fg,
139
+ '--button-enabled-border': button.enabled.border,
140
+
141
+ '--button-hovered-bg': button.hovered.bg,
142
+ '--button-hovered-fg': button.hovered.fg,
143
+ '--button-hovered-border': button.hovered.border,
144
+
145
+ '--button-pressed-bg': button.pressed.bg,
146
+ '--button-pressed-fg': button.pressed.fg,
147
+ '--button-pressed-border': button.pressed.border,
148
+
149
+ '--button-selected-bg': button.selected.bg,
150
+ '--button-selected-fg': button.selected.fg,
151
+ '--button-selected-border': button.selected.border,
152
+
153
+ '--button-disabled-bg': button.disabled.bg,
154
+ '--button-disabled-fg': button.disabled.fg,
155
+ '--button-disabled-border': button.disabled.border,
156
+ } as any
157
+ }
158
+ >
159
+ <pre style={{flex: 2, padding: 8}}>{`mode="${mode}" tone="${tone}"`}</pre>
160
+ <div className="button" style={{flex: 'none', padding: 8}}>
161
+ Button
162
+ </div>
163
+ <div className="button selected" style={{flex: 'none', padding: 8}}>
164
+ Button
165
+ </div>
166
+ <div className="button disabled" style={{flex: 'none', padding: 8}}>
167
+ Button
168
+ </div>
169
+ </div>
170
+ )
171
+ })}
172
+ </div>
173
+ ))}
174
+ </div>
175
+ </div>
176
+ </div>
177
+ )
178
+ }
@@ -0,0 +1,3 @@
1
+ import {buildTheme} from '../../build'
2
+
3
+ export const theme = buildTheme()
@@ -0,0 +1,14 @@
1
+ import {defineScope} from '@sanity/ui-workshop'
2
+ import {lazy} from 'react'
3
+
4
+ export default defineScope({
5
+ name: '_internal/theme',
6
+ title: 'Theming',
7
+ stories: [
8
+ {
9
+ name: 'build',
10
+ title: 'Build theme',
11
+ component: lazy(() => import('./build/story')),
12
+ },
13
+ ],
14
+ })
@@ -0,0 +1,78 @@
1
+ import {buildTheme} from './buildTheme'
2
+
3
+ test('build theme', () => {
4
+ const {color} = buildTheme({
5
+ color: {
6
+ tokens: {
7
+ default: {
8
+ bg: ['white/0', 'black/0'],
9
+ },
10
+ button: {
11
+ default: {
12
+ ghost: {
13
+ '*': {
14
+ border: ['white/0', 'black/0'],
15
+ },
16
+ },
17
+ },
18
+ },
19
+ },
20
+ },
21
+ })
22
+
23
+ expect({
24
+ light: {
25
+ bg: color.light.default.base.bg,
26
+ fg: color.light.default.base.fg,
27
+ default: {
28
+ button: {
29
+ ghost: {
30
+ enabled: {
31
+ border: color.light.default.button.default.ghost.enabled.border,
32
+ },
33
+ },
34
+ },
35
+ },
36
+ },
37
+ dark: {
38
+ bg: color.dark.default.base.bg,
39
+ fg: color.dark.default.base.fg,
40
+ default: {
41
+ button: {
42
+ ghost: {
43
+ enabled: {
44
+ border: color.dark.default.button.default.ghost.enabled.border,
45
+ },
46
+ },
47
+ },
48
+ },
49
+ },
50
+ }).toEqual({
51
+ light: {
52
+ bg: 'rgba(255,255,255,0)',
53
+ fg: '#ffffff',
54
+ default: {
55
+ button: {
56
+ ghost: {
57
+ enabled: {
58
+ border: 'rgba(255,255,255,0)',
59
+ },
60
+ },
61
+ },
62
+ },
63
+ },
64
+ dark: {
65
+ bg: 'rgba(0,0,0,0)',
66
+ fg: '#000000',
67
+ default: {
68
+ button: {
69
+ ghost: {
70
+ enabled: {
71
+ border: 'rgba(0,0,0,0)',
72
+ },
73
+ },
74
+ },
75
+ },
76
+ },
77
+ })
78
+ })
@@ -0,0 +1,15 @@
1
+ import {ThemeConfig} from '../config'
2
+ import {TMP_Theme} from '../types'
3
+ import {buildColorTheme} from './colorTheme/buildColorTheme'
4
+ import {renderColorTheme} from './colorTheme/renderColorTheme'
5
+ import {defaultColorPalette} from './defaults/colorPalette'
6
+
7
+ /** @internal */
8
+ export function buildTheme(config?: ThemeConfig): TMP_Theme {
9
+ return {
10
+ color: renderColorTheme(config?.color?.palette ?? defaultColorPalette, {
11
+ light: buildColorTheme({scheme: 'light'}, config),
12
+ dark: buildColorTheme({scheme: 'dark'}, config),
13
+ }),
14
+ }
15
+ }
@@ -0,0 +1,185 @@
1
+ import {ColorThemeConfig} from '../../config'
2
+ import {buildColorTheme} from './buildColorTheme'
3
+
4
+ test('buildColorTheme: base', () => {
5
+ const colorConfig: ColorThemeConfig = {
6
+ tokens: {
7
+ '*': {
8
+ bg: ['50', '900'],
9
+ fg: ['800', '200'],
10
+ },
11
+ transparent: {
12
+ bg: ['50', 'black'],
13
+ },
14
+ default: {
15
+ bg: ['white', '950'],
16
+ fg: ['black', '200'],
17
+ },
18
+ primary: {
19
+ _hue: 'purple',
20
+ },
21
+ positive: {
22
+ _hue: 'cyan',
23
+ },
24
+ caution: {
25
+ _hue: 'yellow',
26
+ },
27
+ critical: {
28
+ _hue: 'red',
29
+ },
30
+ },
31
+ }
32
+
33
+ const light = buildColorTheme({scheme: 'light'}, {color: colorConfig})
34
+ const dark = buildColorTheme({scheme: 'dark'}, {color: colorConfig})
35
+
36
+ expect({
37
+ light: {
38
+ transparent: {
39
+ bg: light.transparent.base.bg,
40
+ fg: light.transparent.base.fg,
41
+ },
42
+ default: {
43
+ bg: light.default.base.bg,
44
+ fg: light.default.base.fg,
45
+ },
46
+ primary: {
47
+ bg: light.primary.base.bg,
48
+ fg: light.primary.base.fg,
49
+ },
50
+ },
51
+ dark: {
52
+ transparent: {
53
+ bg: dark.transparent.base.bg,
54
+ fg: dark.transparent.base.fg,
55
+ },
56
+ default: {
57
+ bg: dark.default.base.bg,
58
+ fg: dark.default.base.fg,
59
+ },
60
+ primary: {
61
+ bg: dark.primary.base.bg,
62
+ fg: dark.primary.base.fg,
63
+ },
64
+ },
65
+ }).toEqual({
66
+ light: {
67
+ transparent: {
68
+ bg: 'gray/50',
69
+ fg: 'gray/800',
70
+ },
71
+ default: {
72
+ bg: 'white',
73
+ fg: 'black',
74
+ },
75
+ primary: {
76
+ bg: 'purple/50',
77
+ fg: 'purple/800',
78
+ },
79
+ },
80
+ dark: {
81
+ transparent: {
82
+ bg: 'black',
83
+ fg: 'gray/200',
84
+ },
85
+ default: {
86
+ bg: 'gray/950',
87
+ fg: 'gray/200',
88
+ },
89
+ primary: {
90
+ bg: 'purple/900',
91
+ fg: 'purple/200',
92
+ },
93
+ },
94
+ })
95
+ })
96
+
97
+ test('buildColorTheme: button', () => {
98
+ const colorConfig: ColorThemeConfig = {
99
+ tokens: {
100
+ '*': {
101
+ bg: ['50', '900'],
102
+ fg: ['800', '200'],
103
+ },
104
+ transparent: {
105
+ bg: ['50', 'black'],
106
+ },
107
+ default: {
108
+ bg: ['white', '950'],
109
+ fg: ['black', '200'],
110
+ },
111
+ primary: {
112
+ _hue: 'purple',
113
+ },
114
+ positive: {
115
+ _hue: 'cyan',
116
+ },
117
+ caution: {
118
+ _hue: 'yellow',
119
+ },
120
+ critical: {
121
+ _hue: 'red',
122
+ },
123
+ button: {
124
+ '*': {
125
+ default: {
126
+ '*': {
127
+ bg: ['500', '400'],
128
+ fg: ['white', 'black'],
129
+ },
130
+ hovered: {
131
+ bg: ['600', '300'],
132
+ },
133
+ },
134
+ },
135
+ },
136
+ },
137
+ }
138
+
139
+ const light = buildColorTheme({scheme: 'light'}, {color: colorConfig})
140
+ const dark = buildColorTheme({scheme: 'dark'}, {color: colorConfig})
141
+
142
+ expect({
143
+ light: {
144
+ enabled: {
145
+ bg: light.default.button.primary.default.enabled.bg,
146
+ fg: light.default.button.primary.default.enabled.fg,
147
+ },
148
+ hovered: {
149
+ bg: light.default.button.primary.default.hovered.bg,
150
+ fg: light.default.button.primary.default.hovered.fg,
151
+ },
152
+ },
153
+ dark: {
154
+ enabled: {
155
+ bg: dark.default.button.primary.default.enabled.bg,
156
+ fg: dark.default.button.primary.default.enabled.fg,
157
+ },
158
+ hovered: {
159
+ bg: dark.default.button.primary.default.hovered.bg,
160
+ fg: dark.default.button.primary.default.hovered.fg,
161
+ },
162
+ },
163
+ }).toEqual({
164
+ light: {
165
+ enabled: {
166
+ bg: 'purple/500',
167
+ fg: 'white',
168
+ },
169
+ hovered: {
170
+ bg: 'purple/600',
171
+ fg: 'white',
172
+ },
173
+ },
174
+ dark: {
175
+ enabled: {
176
+ bg: 'purple/400',
177
+ fg: 'black',
178
+ },
179
+ hovered: {
180
+ bg: 'purple/300',
181
+ fg: 'black',
182
+ },
183
+ },
184
+ })
185
+ })