@evolve.ui/theme-system 1.0.1 → 1.1.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.
@@ -0,0 +1,301 @@
1
+ /**
2
+ * CSS variable name constants for the theme system
3
+ *
4
+ * Central registry of all CSS custom property names used across brand themes.
5
+ * These constants are imported by Tailwind config modules (colors.ts, boxShadow.ts, etc.)
6
+ * to provide type-safe, refactor-friendly variable references.
7
+ *
8
+ * Internal reference: Hammer UI patterns
9
+ * Ported from the upstream theme system.
10
+ */
11
+
12
+ // shadow
13
+
14
+ export const shadow01 = '--box-shadow-01';
15
+ export const shadow02 = '--box-shadow-02';
16
+ export const shadow03 = '--box-shadow-03';
17
+ export const shadow04 = '--box-shadow-04';
18
+ export const shadow05 = '--box-shadow-05';
19
+
20
+ // fonts
21
+
22
+ export const fontFamilyPrimary = '--font-family-primary';
23
+ export const fontFamilySecondary = '--font-family-secondary';
24
+
25
+ // radii
26
+
27
+ export const buttonBorderRadius = '--button-border-radius';
28
+ export const checkboxBorderRadius = '--checkbox-border-radius';
29
+ export const inputBorderRadius = '--input-border-radius';
30
+ export const searchInputBorderRadius = '--search-input-border-radius';
31
+ export const containerBorderRadius = '--container-border-radius';
32
+
33
+ // widths
34
+
35
+ export const widthPage = '--width-page';
36
+ export const widthDense = '--width-dense';
37
+
38
+ // text
39
+
40
+ export const fontSizeButton100 = '--font-size-button-100';
41
+ export const fontSizeButton200 = '--font-size-button-200';
42
+
43
+ export const fontWeightH1 = '--font-weight-h1';
44
+ export const fontWeightH2 = '--font-weight-h2';
45
+ export const fontWeightH3 = '--font-weight-h3';
46
+ export const fontWeightH4 = '--font-weight-h4';
47
+ export const fontWeightH5 = '--font-weight-h5';
48
+ export const fontWeightH6 = '--font-weight-h6';
49
+ export const fontWeightBodyPrimary = '--font-weight-body-primary';
50
+ export const fontWeightBodySecondary = '--font-weight-body-secondary';
51
+ export const fontWeightLabelStrong = '--font-weight-label-strong';
52
+ export const fontWeightLabelMini = '--font-weight-label-mini';
53
+ export const fontWeightCaption = '--font-weight-caption';
54
+ export const fontWeightButton = '--font-weight-button';
55
+
56
+ export const letterSpacingH1 = '--letter-spacing-h1';
57
+ export const letterSpacingH1Mobile = '--letter-spacing-h1-mobile';
58
+ export const letterSpacingH2 = '--letter-spacing-h2';
59
+ export const letterSpacingH2Mobile = '--letter-spacing-h2-mobile';
60
+ export const letterSpacingH3 = '--letter-spacing-h3';
61
+ export const letterSpacingH3Mobile = '--letter-spacing-h3-mobile';
62
+ export const letterSpacingH4 = '--letter-spacing-h4';
63
+ export const letterSpacingH5 = '--letter-spacing-h5';
64
+ export const letterSpacingH6 = '--letter-spacing-h6';
65
+ export const letterSpacingBodyPrimary = '--letter-spacing-body-primary';
66
+ export const letterSpacingBodySecondary = '--letter-spacing-body-secondary';
67
+ export const letterSpacingLabelStrong = '--letter-spacing-label-strong';
68
+ export const letterSpacingLabelMini = '--letter-spacing-label-mini';
69
+ export const letterSpacingCaption = '--letter-spacing-caption';
70
+ export const letterSpacingButton = '--letter-spacing-button';
71
+
72
+ export const textTransformH6 = '--text-transform-h6';
73
+ export const textTransformLabelMini = '--text-transform-label-mini';
74
+ export const textTransformButton = '--text-transform-button';
75
+
76
+ // colors
77
+ export type ColorAliases =
78
+ | 'primary'
79
+ | 'secondary'
80
+ | 'tertiary'
81
+ | 'info'
82
+ | 'success'
83
+ | 'critical'
84
+ | 'warning'
85
+ | 'surface';
86
+
87
+ export const colorPrimary50 = '--color-primary-50';
88
+ export const colorPrimary100 = '--color-primary-100';
89
+ export const colorPrimary200 = '--color-primary-200';
90
+ export const colorPrimary300 = '--color-primary-300';
91
+ export const colorPrimary400 = '--color-primary-400';
92
+ export const colorPrimary500 = '--color-primary-500';
93
+ export const colorPrimary600 = '--color-primary-600';
94
+ export const colorPrimary700 = '--color-primary-700';
95
+ export const colorPrimary800 = '--color-primary-800';
96
+ export const colorPrimary900 = '--color-primary-900';
97
+ export const colorSecondary50 = '--color-secondary-50';
98
+ export const colorSecondary100 = '--color-secondary-100';
99
+ export const colorSecondary200 = '--color-secondary-200';
100
+ export const colorSecondary300 = '--color-secondary-300';
101
+ export const colorSecondary400 = '--color-secondary-400';
102
+ export const colorSecondary500 = '--color-secondary-500';
103
+ export const colorSecondary600 = '--color-secondary-600';
104
+ export const colorSecondary700 = '--color-secondary-700';
105
+ export const colorSecondary800 = '--color-secondary-800';
106
+ export const colorSecondary900 = '--color-secondary-900';
107
+ export const colorTertiary50 = '--color-tertiary-50';
108
+ export const colorTertiary100 = '--color-tertiary-100';
109
+ export const colorTertiary200 = '--color-tertiary-200';
110
+ export const colorTertiary300 = '--color-tertiary-300';
111
+ export const colorTertiary400 = '--color-tertiary-400';
112
+ export const colorTertiary500 = '--color-tertiary-500';
113
+ export const colorTertiary600 = '--color-tertiary-600';
114
+ export const colorTertiary700 = '--color-tertiary-700';
115
+ export const colorTertiary800 = '--color-tertiary-800';
116
+ export const colorTertiary900 = '--color-tertiary-900';
117
+ export const colorInfo50 = '--color-info-50';
118
+ export const colorInfo100 = '--color-info-100';
119
+ export const colorInfo200 = '--color-info-200';
120
+ export const colorInfo300 = '--color-info-300';
121
+ export const colorInfo400 = '--color-info-400';
122
+ export const colorInfo500 = '--color-info-500';
123
+ export const colorInfo600 = '--color-info-600';
124
+ export const colorInfo700 = '--color-info-700';
125
+ export const colorInfo800 = '--color-info-800';
126
+ export const colorInfo900 = '--color-info-900';
127
+ export const colorSuccess50 = '--color-success-50';
128
+ export const colorSuccess100 = '--color-success-100';
129
+ export const colorSuccess200 = '--color-success-200';
130
+ export const colorSuccess300 = '--color-success-300';
131
+ export const colorSuccess400 = '--color-success-400';
132
+ export const colorSuccess500 = '--color-success-500';
133
+ export const colorSuccess600 = '--color-success-600';
134
+ export const colorSuccess700 = '--color-success-700';
135
+ export const colorSuccess800 = '--color-success-800';
136
+ export const colorSuccess900 = '--color-success-900';
137
+ export const colorCritical50 = '--color-critical-50';
138
+ export const colorCritical100 = '--color-critical-100';
139
+ export const colorCritical200 = '--color-critical-200';
140
+ export const colorCritical300 = '--color-critical-300';
141
+ export const colorCritical400 = '--color-critical-400';
142
+ export const colorCritical500 = '--color-critical-500';
143
+ export const colorCritical600 = '--color-critical-600';
144
+ export const colorCritical700 = '--color-critical-700';
145
+ export const colorCritical800 = '--color-critical-800';
146
+ export const colorCritical900 = '--color-critical-900';
147
+ export const colorWarning50 = '--color-warning-50';
148
+ export const colorWarning100 = '--color-warning-100';
149
+ export const colorWarning200 = '--color-warning-200';
150
+ export const colorWarning300 = '--color-warning-300';
151
+ export const colorWarning400 = '--color-warning-400';
152
+ export const colorWarning500 = '--color-warning-500';
153
+ export const colorWarning600 = '--color-warning-600';
154
+ export const colorWarning700 = '--color-warning-700';
155
+ export const colorWarning800 = '--color-warning-800';
156
+ export const colorWarning900 = '--color-warning-900';
157
+ export const colorSurface50 = '--color-surface-50';
158
+ export const colorSurface100 = '--color-surface-100';
159
+ export const colorSurface200 = '--color-surface-200';
160
+ export const colorSurface300 = '--color-surface-300';
161
+ export const colorSurface400 = '--color-surface-400';
162
+ export const colorSurface500 = '--color-surface-500';
163
+ export const colorSurface600 = '--color-surface-600';
164
+ export const colorSurface700 = '--color-surface-700';
165
+ export const colorSurface800 = '--color-surface-800';
166
+ export const colorSurface900 = '--color-surface-900';
167
+
168
+ // text colors
169
+
170
+ export type TextColorAliases =
171
+ | 'primary'
172
+ | 'secondary'
173
+ | 'inverse'
174
+ | 'info'
175
+ | 'success'
176
+ | 'warning'
177
+ | 'critical'
178
+ | 'disabled'
179
+ | 'inactive';
180
+
181
+ export const colorTextPrimary = '--color-text-primary';
182
+ export const colorTextSecondary = '--color-text-secondary';
183
+ export const colorTextInverse = '--color-text-inverse';
184
+ export const colorTextCritical = '--color-text-critical';
185
+ export const colorTextInfo = '--color-text-info';
186
+ export const colorTextSuccess = '--color-text-success';
187
+ export const colorTextInactive = '--color-text-inactive';
188
+ export const colorTextDisabled = '--color-text-disabled';
189
+ export const colorTextWarning = '--color-text-warning';
190
+
191
+ // icon colors
192
+
193
+ export type IconColorAliases =
194
+ | 'primary'
195
+ | 'secondary'
196
+ | 'inverse'
197
+ | 'info'
198
+ | 'success'
199
+ | 'warning'
200
+ | 'critical'
201
+ | 'disabled';
202
+
203
+ export const colorIconPrimary = '--color-icon-primary';
204
+ export const colorIconSecondary = '--color-icon-secondary';
205
+ export const colorIconInverse = '--color-icon-inverse';
206
+ export const colorIconInfo = '--color-icon-info';
207
+ export const colorIconSuccess = '--color-icon-success';
208
+ export const colorIconWarning = '--color-icon-warning';
209
+ export const colorIconCritical = '--color-icon-critical';
210
+ export const colorIconDisabled = '--color-icon-disabled';
211
+
212
+ // link colors
213
+
214
+ export type LinkColorAliases = 'primary' | 'secondary' | 'monochrome' | 'hover' | 'pressed' | 'disabled' | 'inverse';
215
+
216
+ export const colorLinkPrimary = '--color-link-primary';
217
+ export const colorLinkSecondary = '--color-link-secondary';
218
+ export const colorLinkMonochrome = '--color-link-monochrome';
219
+ export const colorLinkHover = '--color-link-hover';
220
+ export const colorLinkPressed = '--color-link-pressed';
221
+ export const colorLinkDisabled = '--color-link-disabled';
222
+ export const colorLinkInverse = '--color-link-inverse';
223
+ export const colorLinkInverseHover = '--color-link-inverse-hover';
224
+ export const colorLinkInversePressed = '--color-link-inverse-pressed';
225
+ export const colorLinkInverseDisabled = '--color-link-inverse-disabled';
226
+
227
+ // background colors
228
+
229
+ export type BackgroundColorAliases =
230
+ | 'primary'
231
+ | 'secondary'
232
+ | 'tertiary'
233
+ | 'inverse'
234
+ | 'subdued'
235
+ | 'hover'
236
+ | 'pressed'
237
+ | 'disabled'
238
+ | 'infoLight'
239
+ | 'infoDark'
240
+ | 'successLight'
241
+ | 'successDark'
242
+ | 'criticalLight'
243
+ | 'criticalDark'
244
+ | 'warningLight'
245
+ | 'warningDark';
246
+
247
+ export const colorBackgroundPrimary = '--color-background-primary';
248
+ export const colorBackgroundSecondary = '--color-background-secondary';
249
+ export const colorBackgroundTertiary = '--color-background-tertiary';
250
+ export const colorBackgroundInverse = '--color-background-inverse';
251
+ export const colorBackgroundSubdued = '--color-background-subdued';
252
+ export const colorBackgroundHover = '--color-background-hover';
253
+ export const colorBackgroundOverlay = '--color-background-overlay';
254
+ export const colorBackgroundPressed = '--color-background-pressed';
255
+ export const colorBackgroundDisabled = '--color-background-disabled';
256
+ export const colorBackgroundInfoLight = '--color-background-info-light';
257
+ export const colorBackgroundInfoDark = '--color-background-info-dark';
258
+ export const colorBackgroundSuccessLight = '--color-background-success-light';
259
+ export const colorBackgroundSuccessDark = '--color-background-success-dark';
260
+ export const colorBackgroundCriticalLight = '--color-background-critical-light';
261
+ export const colorBackgroundCriticalDark = '--color-background-critical-dark';
262
+ export const colorBackgroundWarningLight = '--color-background-warning-light';
263
+ export const colorBackgroundWarningDark = '--color-background-warning-dark';
264
+ export const colorBackgroundHoverInverse = '--color-background-hover-inverse';
265
+ export const colorBackgroundPressedInverse = '--color-background-pressed-inverse';
266
+
267
+ // border colors
268
+
269
+ export type BorderColorAliases =
270
+ | 'primary'
271
+ | 'secondary'
272
+ | 'tertiary'
273
+ | 'inverse'
274
+ | 'black'
275
+ | 'info'
276
+ | 'success'
277
+ | 'critical'
278
+ | 'warning'
279
+ | 'disabled'
280
+ | 'hover'
281
+ | 'selected';
282
+
283
+ export const colorBorderPrimary = '--color-border-primary';
284
+ export const colorBorderSecondary = '--color-border-secondary';
285
+ export const colorBorderTertiary = '--color-border-tertiary';
286
+ export const colorBorderInverse = '--color-border-inverse';
287
+ export const colorBorderBlack = '--color-border-black';
288
+ export const colorBorderInfo = '--color-border-info';
289
+ export const colorBorderSuccess = '--color-border-success';
290
+ export const colorBorderCritical = '--color-border-critical';
291
+ export const colorBorderWarning = '--color-border-warning';
292
+ export const colorBorderDisabled = '--color-border-disabled';
293
+ export const colorBorderHover = '--color-border-hover';
294
+ export const colorBorderSelected = '--color-border-selected';
295
+
296
+ // focus colors
297
+
298
+ export type FocusColorAliases = 'primary' | 'inverse';
299
+
300
+ export const colorFocusPrimary = '--color-focus-primary';
301
+ export const colorFocusInverse = '--color-focus-inverse';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Font family configuration for Tailwind CSS
3
+ *
4
+ * Internal reference: Hammer UI patterns
5
+ * Ported from the upstream theme system.
6
+ */
7
+
8
+ import { wrapVar } from '../utils/wrapVar';
9
+ import { fontFamilyPrimary, fontFamilySecondary } from './cssVars';
10
+
11
+ export const fontFamily = {
12
+ primary: wrapVar(fontFamilyPrimary),
13
+ secondary: wrapVar(fontFamilySecondary),
14
+ };
@@ -0,0 +1,308 @@
1
+ /**
2
+ * Main Tailwind CSS plugin for the theme system
3
+ *
4
+ * Composes all theme configuration modules (colors, spacing, typography, etc.)
5
+ * into a single Tailwind plugin. The plugin's second argument defines the complete
6
+ * theme, so consumers only need `plugins: [themePlugin]` — no separate theme extension.
7
+ *
8
+ * Internal reference: Hammer UI patterns
9
+ * Ported from the upstream theme system.
10
+ */
11
+
12
+ import plugin from 'tailwindcss/plugin';
13
+
14
+ import { borderRadius } from './borderRadius';
15
+ import { boxShadow } from './boxShadow';
16
+ import { colors } from './colors';
17
+ import { fontFamily } from './fontFamily';
18
+ import { screens } from './screens';
19
+ import { spacing } from './spacing';
20
+ import { textComponents } from './text';
21
+ import { width } from './width';
22
+
23
+ const autofillStyles = {
24
+ '-webkit-box-shadow': '0 0 0 12px rgb(var(--color-background-primary)) inset !important',
25
+ 'box-shadow': '0 0 0 12px rgb(var(--color-background-primary)) inset !important',
26
+ };
27
+
28
+ export const themePlugin = plugin(
29
+ ({ addBase, addComponents, matchUtilities }) => {
30
+ // https://tailwindcss.com/docs/plugins#css-in-js-syntax
31
+ addComponents(textComponents);
32
+ addComponents({
33
+ '.hui-autofill-transparent': {
34
+ '&:-webkit-autofill': autofillStyles,
35
+ '&:-webkit-autofill:active': autofillStyles,
36
+ '&:-webkit-autofill:focus': autofillStyles,
37
+ '&:-webkit-autofill:hover': autofillStyles,
38
+ },
39
+ '.hui-focus-visible-outline': {
40
+ '@apply focus-visible:outline-focus-primary focus-visible:outline focus-visible:outline-4': {},
41
+ },
42
+ '.hui-focus-visible-outline-inverse': {
43
+ '@apply focus-visible:outline-focus-inverse focus-visible:outline focus-visible:outline-4': {},
44
+ },
45
+ '.scrollbar-default': {
46
+ /* Safari and Chrome */
47
+ '&::-webkit-scrollbar': {
48
+ display: 'block',
49
+ },
50
+ /* IE and Edge */
51
+ '-ms-overflow-style': 'auto',
52
+ /* Firefox */
53
+ 'scrollbar-width': 'auto',
54
+ },
55
+ '.scrollbar-hide': {
56
+ /* Safari and Chrome */
57
+ '&::-webkit-scrollbar': {
58
+ display: 'none',
59
+ },
60
+ /* IE and Edge */
61
+ '-ms-overflow-style': 'none',
62
+ /* Firefox */
63
+ 'scrollbar-width': 'none',
64
+ },
65
+ });
66
+
67
+ // Save/Favorite button keyframes — emitted unconditionally via addBase so they are
68
+ // available in all consumer builds regardless of Tailwind content scanning.
69
+ // The corresponding animate-* utilities are registered in theme.extend.animation below.
70
+ addBase({
71
+ '@keyframes saveButtonWiggle': {
72
+ '0%, 100%': { transform: 'rotate(0deg) scale(1)' },
73
+ '10%': { transform: 'rotate(-6deg) scale(1.03)' },
74
+ '25%': { transform: 'rotate(5deg) scale(1.03)' },
75
+ '40%': { transform: 'rotate(-4deg) scale(1.02)' },
76
+ '55%': { transform: 'rotate(3deg) scale(1.02)' },
77
+ '70%': { transform: 'rotate(-1.5deg) scale(1.01)' },
78
+ '85%': { transform: 'rotate(0.5deg) scale(1)' },
79
+ },
80
+ '@keyframes saveHeartTwirlBloom': {
81
+ '0%': { transform: 'rotateY(0deg) scale(1)' },
82
+ '50%': { transform: 'rotateY(180deg) scale(1.35)' },
83
+ '100%': { transform: 'rotateY(360deg) scale(1)' },
84
+ },
85
+ '@keyframes saveHeartColorFlash': {
86
+ '0%': {
87
+ fill: 'rgb(var(--hui-save-color-critical-500, var(--color-critical-500)))',
88
+ },
89
+ '40%': {
90
+ fill: 'rgb(var(--hui-save-color-critical-300, var(--color-critical-300)))',
91
+ },
92
+ '60%': {
93
+ fill: 'rgb(var(--hui-save-color-critical-500, var(--color-critical-500)))',
94
+ },
95
+ '100%': {
96
+ fill: 'rgb(var(--hui-save-color-critical-500, var(--color-critical-500)))',
97
+ },
98
+ },
99
+ '@keyframes saveLabelShimmer': {
100
+ '0%': { backgroundPosition: '200% center' },
101
+ '100%': { backgroundPosition: '-200% center' },
102
+ },
103
+ '@keyframes saveButtonPulse': {
104
+ '0%': { transform: 'scale(1)' },
105
+ '35%': { transform: 'scale(1.08)' },
106
+ '65%': { transform: 'scale(0.97)' },
107
+ '100%': { transform: 'scale(1)' },
108
+ },
109
+ '@keyframes saveHeartPop': {
110
+ '0%': { transform: 'scale(1)' },
111
+ '20%': { transform: 'scale(0.6)' },
112
+ '60%': { transform: 'scale(1.35)' },
113
+ '100%': { transform: 'scale(1)' },
114
+ },
115
+ // Save/Favorite button animated variant — shimmer and color-flash helpers.
116
+ // Placed in addBase (not addComponents) so Vite's PostCSS pipeline emits
117
+ // them unconditionally. addComponents is subject to caching discrepancies
118
+ // in this monorepo's Storybook build that prevent new rules from landing.
119
+ '.hui-fb-shimmer': {
120
+ lineHeight: 'normal',
121
+ backgroundImage:
122
+ 'linear-gradient(90deg, currentColor 0%, currentColor 20%, rgb(var(--hui-save-color-critical-200, var(--color-critical-200))) 33%, rgb(var(--hui-save-color-critical-500, var(--color-critical-500))) 50%, rgb(var(--hui-save-color-tertiary-400, var(--color-tertiary-400))) 67%, currentColor 80%, currentColor 100%)',
123
+ backgroundSize: '200% 100%',
124
+ backgroundClip: 'text',
125
+ '-webkit-background-clip': 'text',
126
+ '-webkit-text-fill-color': 'transparent',
127
+ '@media (prefers-reduced-motion: reduce)': {
128
+ backgroundImage: 'none !important',
129
+ '-webkit-text-fill-color': 'currentColor !important',
130
+ },
131
+ },
132
+ '.hui-fb-color-flash .hui-fb-icon-frame svg path': {
133
+ animation: 'saveHeartColorFlash 1100ms cubic-bezier(0.45, 0, 0.55, 1) 1',
134
+ animationFillMode: 'forwards',
135
+ },
136
+ '@media (prefers-reduced-motion: reduce)': {
137
+ '.hui-fb-color-flash .hui-fb-icon-frame svg path': {
138
+ animation: 'none !important',
139
+ },
140
+ },
141
+ });
142
+
143
+ matchUtilities({
144
+ 'grid-area': (value) => {
145
+ return {
146
+ 'grid-area': value,
147
+ };
148
+ },
149
+ });
150
+ },
151
+ {
152
+ theme: {
153
+ borderRadius,
154
+ boxShadow,
155
+ colors,
156
+ extend: {
157
+ animation: {
158
+ fadeIn: 'fadeIn .2s ease-in-out',
159
+ fadeInOpacity: 'fadeInOpacity 0.5s ease-in-out',
160
+ fadeInScaled: 'fadeInScaled .2s ease-in',
161
+ fadeOut: 'fadeOut .2s ease-in-out',
162
+ loading: 'loading 1.4s infinite ease-in-out',
163
+ 'progress-completion': 'shrink 0.15s ease-in-out both, grow 0.15s ease-in-out 0.15s both',
164
+ 'progress-icon-fade-in': 'fadeInOpacity 0.15s ease-in-out 0.15s both',
165
+ 'progress-wave':
166
+ 'progressWave 1333ms cubic-bezier(0.4, 0, 0.2, 1) infinite both, progressWaveRotate 1568ms linear infinite both',
167
+ saveButtonPulse: 'saveButtonPulse 500ms cubic-bezier(0.34, 1.56, 0.64, 1)',
168
+ saveButtonWiggle: 'saveButtonWiggle 1.3s cubic-bezier(0.36, 0, 0.66, -0.56)',
169
+ saveHeartColorFlash: 'saveHeartColorFlash 1100ms cubic-bezier(0.45, 0, 0.55, 1)',
170
+ saveHeartPop: 'saveHeartPop 480ms cubic-bezier(0.34, 1.56, 0.64, 1)',
171
+ saveHeartTwirlBloom: 'saveHeartTwirlBloom 1100ms cubic-bezier(0.45, 0, 0.55, 1)',
172
+ saveLabelShimmer: 'saveLabelShimmer 1100ms ease-in-out',
173
+ slideDown: 'slideDown 0.3s ease-in forwards',
174
+ slideUp: 'slideUp 0.3s ease-out forwards',
175
+ },
176
+ keyframes: {
177
+ fadeIn: {
178
+ from: {
179
+ opacity: '0',
180
+ },
181
+ to: {
182
+ opacity: '1',
183
+ },
184
+ },
185
+ fadeInOpacity: {
186
+ from: {
187
+ opacity: '0',
188
+ visibility: 'hidden',
189
+ },
190
+ to: {
191
+ opacity: '1',
192
+ visibility: 'visible',
193
+ },
194
+ },
195
+ fadeInScaled: {
196
+ from: {
197
+ opacity: '0',
198
+ transform: 'scale(0.7)',
199
+ },
200
+ to: {
201
+ opacity: '1',
202
+ transform: 'scale(1)',
203
+ },
204
+ },
205
+ fadeOut: {
206
+ from: {
207
+ opacity: '1',
208
+ transform: 'scale(1)',
209
+ },
210
+ to: {
211
+ opacity: '0',
212
+ transform: 'scale(0.7)',
213
+ },
214
+ },
215
+ grow: {
216
+ from: { transform: 'scale(0.5)' },
217
+ to: { transform: 'scale(1)' },
218
+ },
219
+ loading: {
220
+ '0%, 100%, 80%': { transform: 'scale(0)' },
221
+ '40%': { transform: 'scale(1)' },
222
+ },
223
+ progressWave: {
224
+ '0%': {
225
+ strokeDasharray: 'var(--progress-wave-start)',
226
+ strokeDashoffset: '0',
227
+ },
228
+ '100%': {
229
+ strokeDasharray: 'var(--progress-wave-end)',
230
+ strokeDashoffset: 'var(--progress-wave-full)',
231
+ },
232
+ '50%': {
233
+ strokeDasharray: 'var(--progress-wave-mid)',
234
+ strokeDashoffset: 'var(--progress-wave-offset)',
235
+ },
236
+ },
237
+ progressWaveRotate: {
238
+ '0%': { transform: 'rotate(-90deg)' },
239
+ '100%': { transform: 'rotate(270deg)' },
240
+ },
241
+ saveButtonPulse: {
242
+ '0%': { transform: 'scale(1)' },
243
+ '35%': { transform: 'scale(1.08)' },
244
+ '65%': { transform: 'scale(0.97)' },
245
+ '100%': { transform: 'scale(1)' },
246
+ },
247
+ saveButtonWiggle: {
248
+ '0%, 100%': { transform: 'rotate(0deg) scale(1)' },
249
+ '10%': { transform: 'rotate(-6deg) scale(1.03)' },
250
+ '25%': { transform: 'rotate(5deg) scale(1.03)' },
251
+ '40%': { transform: 'rotate(-4deg) scale(1.02)' },
252
+ '55%': { transform: 'rotate(3deg) scale(1.02)' },
253
+ '70%': { transform: 'rotate(-1.5deg) scale(1.01)' },
254
+ '85%': { transform: 'rotate(0.5deg) scale(1)' },
255
+ },
256
+ saveHeartColorFlash: {
257
+ '0%': {
258
+ fill: 'rgb(var(--hui-save-color-critical-500, var(--color-critical-500)))',
259
+ },
260
+ '40%': {
261
+ fill: 'rgb(var(--hui-save-color-critical-300, var(--color-critical-300)))',
262
+ },
263
+ '60%': {
264
+ fill: 'rgb(var(--hui-save-color-critical-500, var(--color-critical-500)))',
265
+ },
266
+ '100%': {
267
+ fill: 'rgb(var(--hui-save-color-critical-500, var(--color-critical-500)))',
268
+ },
269
+ },
270
+ saveHeartPop: {
271
+ '0%': { transform: 'scale(1)' },
272
+ '20%': { transform: 'scale(0.6)' },
273
+ '60%': { transform: 'scale(1.35)' },
274
+ '100%': { transform: 'scale(1)' },
275
+ },
276
+ saveHeartTwirlBloom: {
277
+ '0%': { transform: 'rotateY(0deg) scale(1)' },
278
+ '50%': { transform: 'rotateY(180deg) scale(1.35)' },
279
+ '100%': { transform: 'rotateY(360deg) scale(1)' },
280
+ },
281
+ saveLabelShimmer: {
282
+ '0%': { backgroundPosition: '200% center' },
283
+ '100%': { backgroundPosition: '-200% center' },
284
+ },
285
+ shrink: {
286
+ from: { transform: 'scale(1)' },
287
+ to: { transform: 'scale(0.5)' },
288
+ },
289
+ slideDown: {
290
+ '0%': { opacity: '1', transform: 'translateY(0)' },
291
+ '100%': { opacity: '0', transform: 'translateY(100%)' },
292
+ },
293
+ slideUp: {
294
+ '0%': { opacity: '0', transform: 'translateY(100%)' },
295
+ '100%': { opacity: '1', transform: 'translateY(0)' },
296
+ },
297
+ },
298
+
299
+ maxWidth: width,
300
+ minWidth: width,
301
+ spacing,
302
+ width,
303
+ },
304
+ fontFamily,
305
+ screens,
306
+ },
307
+ }
308
+ );
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Responsive breakpoints for Tailwind CSS
3
+ *
4
+ * These breakpoints mirror the Hammer UI responsive system.
5
+ * Usage: mobile:gap-[2px], mdMin:max-w-[786px], desktop:text-lg
6
+ */
7
+ export const screens = {
8
+ desktop: { min: '769px' },
9
+ lgMax: { max: '1644px' },
10
+ lgMin: { min: '1249px' },
11
+ mdMax: { max: '1248px' },
12
+ mdMin: { min: '1024px' },
13
+ mobile: { max: '480px' },
14
+ mobileSmall: { max: '380px' },
15
+ print: { raw: 'print' },
16
+ smMax: { max: '1023px' },
17
+ smMin: { min: '769px' },
18
+ tabletMax: { max: '954px' },
19
+ tabletMin: { min: '954px' },
20
+ xlMin: { min: '1645px' },
21
+ xsMax: { max: '768px' },
22
+ } as const;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Spacing scale for Tailwind CSS
3
+ *
4
+ * Fixed pixel values that don't change per brand.
5
+ *
6
+ * Internal reference: Hammer UI patterns
7
+ * Ported from the upstream theme system.
8
+ */
9
+
10
+ export const spacing = {
11
+ '2xl': '64px',
12
+ '2xs': '4px',
13
+ '3xl': '128px',
14
+ '3xs': '2px',
15
+ lg: '32px',
16
+ md: '24px',
17
+ sm: '16px',
18
+ xl: '48px',
19
+ xs: '8px',
20
+ } as const;