@crisp-ui-kit/crisp 0.33.0 → 0.33.1

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 (105) hide show
  1. package/README.md +33 -1
  2. package/dist/appshell.css +1 -4
  3. package/dist/appshell.layered.css +1 -4
  4. package/dist/authshell.css +4 -19
  5. package/dist/authshell.layered.css +4 -19
  6. package/dist/avatar.css +2 -1
  7. package/dist/avatar.layered.css +2 -1
  8. package/dist/board.css +1 -4
  9. package/dist/board.layered.css +1 -4
  10. package/dist/breadcrumb.css +0 -1
  11. package/dist/breadcrumb.layered.css +0 -1
  12. package/dist/button.css +14 -6
  13. package/dist/button.layered.css +14 -6
  14. package/dist/card.css +2 -1
  15. package/dist/card.layered.css +2 -1
  16. package/dist/checkbox.css +6 -9
  17. package/dist/checkbox.layered.css +6 -9
  18. package/dist/cjs/components/avatar/avatar.recipe.js +38 -19
  19. package/dist/cjs/components/button/button.recipe.js +109 -18
  20. package/dist/cjs/components/switch/switch.recipe.js +48 -18
  21. package/dist/columncalc.css +2 -6
  22. package/dist/columncalc.layered.css +2 -6
  23. package/dist/command.css +9 -11
  24. package/dist/command.layered.css +9 -11
  25. package/dist/datatable.css +9 -19
  26. package/dist/datatable.layered.css +9 -19
  27. package/dist/datepicker.css +15 -80
  28. package/dist/datepicker.layered.css +15 -80
  29. package/dist/datepickerfield.css +3 -18
  30. package/dist/datepickerfield.layered.css +3 -18
  31. package/dist/donutchart.css +1 -2
  32. package/dist/donutchart.layered.css +1 -2
  33. package/dist/entitycard.css +1 -7
  34. package/dist/entitycard.layered.css +1 -7
  35. package/dist/esm/components/avatar/avatar.recipe.js +38 -19
  36. package/dist/esm/components/button/button.recipe.js +109 -18
  37. package/dist/esm/components/switch/switch.recipe.js +48 -18
  38. package/dist/fileupload.css +10 -60
  39. package/dist/fileupload.layered.css +10 -60
  40. package/dist/inbox.css +1 -7
  41. package/dist/inbox.layered.css +1 -7
  42. package/dist/input.css +9 -20
  43. package/dist/input.layered.css +9 -20
  44. package/dist/listpage.css +2 -12
  45. package/dist/listpage.layered.css +2 -12
  46. package/dist/menu.css +3 -19
  47. package/dist/menu.layered.css +3 -19
  48. package/dist/multiselect.css +4 -25
  49. package/dist/multiselect.layered.css +4 -25
  50. package/dist/navitem.css +5 -13
  51. package/dist/navitem.layered.css +5 -13
  52. package/dist/onboarding.css +1 -8
  53. package/dist/onboarding.layered.css +1 -8
  54. package/dist/quantitypicker.css +15 -50
  55. package/dist/quantitypicker.layered.css +15 -50
  56. package/dist/radiogroup.css +1 -6
  57. package/dist/radiogroup.layered.css +1 -6
  58. package/dist/recordpage.css +2 -10
  59. package/dist/recordpage.layered.css +2 -10
  60. package/dist/recordpanel.css +1 -13
  61. package/dist/recordpanel.layered.css +1 -13
  62. package/dist/recordstable.css +2 -11
  63. package/dist/recordstable.layered.css +2 -11
  64. package/dist/resizablepanel.css +4 -15
  65. package/dist/resizablepanel.layered.css +4 -15
  66. package/dist/richtext.css +1 -5
  67. package/dist/richtext.layered.css +1 -5
  68. package/dist/select.css +7 -30
  69. package/dist/select.layered.css +7 -30
  70. package/dist/settingsshell.css +2 -7
  71. package/dist/settingsshell.layered.css +2 -7
  72. package/dist/sidebar.css +23 -28
  73. package/dist/sidebar.layered.css +23 -28
  74. package/dist/slider.css +1 -8
  75. package/dist/slider.layered.css +1 -8
  76. package/dist/statcard.css +1 -2
  77. package/dist/statcard.layered.css +1 -2
  78. package/dist/styles.css +194 -652
  79. package/dist/styles.layered.css +194 -652
  80. package/dist/switch.css +1 -5
  81. package/dist/switch.layered.css +1 -5
  82. package/dist/table.css +2 -1
  83. package/dist/table.layered.css +2 -1
  84. package/dist/tabletoolbar.css +1 -3
  85. package/dist/tabletoolbar.layered.css +1 -3
  86. package/dist/tabs.css +1 -5
  87. package/dist/tabs.layered.css +1 -5
  88. package/dist/tasklist.css +1 -8
  89. package/dist/tasklist.layered.css +1 -8
  90. package/dist/textarea.css +2 -13
  91. package/dist/textarea.layered.css +2 -13
  92. package/dist/tooltip.css +2 -1
  93. package/dist/tooltip.layered.css +2 -1
  94. package/dist/trialbanner.css +2 -11
  95. package/dist/trialbanner.layered.css +2 -11
  96. package/dist/types/components/avatar/avatar.d.ts +30 -30
  97. package/dist/types/components/avatar/avatar.recipe.d.ts +136 -49
  98. package/dist/types/components/button/button.d.ts +30 -30
  99. package/dist/types/components/button/button.recipe.d.ts +193 -45
  100. package/dist/types/components/switch/switch.recipe.d.ts +57 -3
  101. package/dist/viewtoggle.css +3 -9
  102. package/dist/viewtoggle.layered.css +3 -9
  103. package/dist/wheelpicker.css +14 -59
  104. package/dist/wheelpicker.layered.css +14 -59
  105. package/package.json +1 -1
@@ -1,74 +1,27 @@
1
1
  @layer crisp-components {
2
2
  .crisp-datepicker {
3
-
4
- position: relative; box-sizing: border-box; width: 100%; min-width: 0;
5
- font-family: var(--crisp-font-sans); color: var(--crisp-fg-primary); background: var(--crisp-bg-surface);
6
-
7
- & .crisp-datepicker-header {
8
- display: flex; align-items: center; justify-content: space-between;
9
- height: var(--crisp-size-menuRow);
10
- }
11
- & .crisp-datepicker-header-label {
12
- display: inline-flex; align-items: center; gap: var(--crisp-space-1);
13
- height: 100%; min-width: 0; border: 0; padding: 0 var(--crisp-space-1);
14
- border-radius: var(--crisp-radius-md); background: transparent; cursor: pointer;
15
- color: var(--crisp-fg-primary); font-family: inherit;
16
- font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium);
17
- white-space: nowrap;
18
- outline: 2px solid transparent; outline-offset: -2px;
19
- transition: outline-color .2s ease;
20
- }
3
+ position: relative; box-sizing: border-box; width: 100%; min-width: 0; font-family: var(--crisp-font-sans); color: var(--crisp-fg-primary); background: var(--crisp-bg-surface);
4
+ & .crisp-datepicker-header { display: flex; align-items: center; justify-content: space-between; height: var(--crisp-size-menuRow); }
5
+ & .crisp-datepicker-header-label { display: inline-flex; align-items: center; gap: var(--crisp-space-1); height: 100%; min-width: 0; border: 0; padding: 0 var(--crisp-space-1); border-radius: var(--crisp-radius-md); background: transparent; cursor: pointer; color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); white-space: nowrap; outline: 2px solid transparent; outline-offset: -2px; transition: outline-color .2s ease; }
21
6
  & .crisp-datepicker-header-label:focus-visible { outline-color: var(--crisp-stroke-focus-ring); }
22
7
  & .crisp-datepicker-header-chevron { display: inline-flex; transition: transform .2s ease; }
23
8
  & .crisp-datepicker-header-chevron[data-open] { transform: rotate(180deg); }
24
-
25
9
  & .crisp-datepicker-nav { display: flex; align-items: center; }
26
- & .crisp-datepicker-nav-button {
27
- display: inline-flex; align-items: center; justify-content: center;
28
- width: var(--crisp-size-menuRow); height: var(--crisp-size-menuRow); padding: 0;
29
- border: none; border-radius: var(--crisp-radius-md); background: none;
30
- color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer;
31
- outline: 2px solid transparent; outline-offset: -2px;
32
- transition: background-color .12s, outline-color .2s ease;
33
- }
10
+ & .crisp-datepicker-nav-button { display: inline-flex; align-items: center; justify-content: center; width: var(--crisp-size-menuRow); height: var(--crisp-size-menuRow); padding: 0; border: none; border-radius: var(--crisp-radius-md); background: none; color: var(--crisp-fg-muted); font-family: inherit; cursor: pointer; outline: 2px solid transparent; outline-offset: -2px; transition: background-color .12s, outline-color .2s ease; }
34
11
  & .crisp-datepicker-nav-button:hover { background: var(--crisp-bg-raised); }
35
12
  & .crisp-datepicker-nav-button:focus-visible { outline-color: var(--crisp-stroke-focus-ring); }
36
13
  & .crisp-datepicker-nav-button:disabled { opacity: .4; cursor: not-allowed; }
37
-
38
- & .crisp-datepicker-weekday-row {
39
- display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
40
- position: relative; z-index: 2; background: var(--crisp-bg-surface);
41
- }
42
- & .crisp-datepicker-weekday {
43
- display: flex; align-items: center; justify-content: center;
44
- height: var(--crisp-size-calendarCell); color: var(--crisp-fg-neutral-subtle);
45
- font-size: var(--crisp-text-sm); line-height: 16px; font-weight: var(--crisp-weight-medium);
46
- }
47
-
14
+ & .crisp-datepicker-weekday-row { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); position: relative; z-index: 2; background: var(--crisp-bg-surface); }
15
+ & .crisp-datepicker-weekday { display: flex; align-items: center; justify-content: center; height: var(--crisp-size-calendarCell); color: var(--crisp-fg-neutral-subtle); font-size: var(--crisp-text-sm); line-height: 16px; font-weight: var(--crisp-weight-medium); }
48
16
  & .crisp-datepicker-months { display: grid; grid-template-columns: minmax(0, 1fr); align-items: start; min-width: 0; }
49
17
  & .crisp-datepicker-months[data-wheel-open] { visibility: hidden; }
50
18
  & .crisp-datepicker-month { min-width: 0; }
51
- & .crisp-datepicker-month-label {
52
- display: flex; align-items: center; height: 24px;
53
- color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px;
54
- font-weight: var(--crisp-weight-medium);
55
- }
56
-
19
+ & .crisp-datepicker-month-label { display: flex; align-items: center; height: 24px; color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); }
57
20
  & .crisp-datepicker-grid { display: grid; min-width: 0; }
58
21
  & .crisp-datepicker-week-row { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); }
59
-
60
- & .crisp-datepicker-cell {
61
- position: relative; min-width: 0; min-height: var(--crisp-size-calendarCell);
62
- isolation: isolate;
63
- }
22
+ & .crisp-datepicker-cell { position: relative; min-width: 0; min-height: var(--crisp-size-calendarCell); isolation: isolate; }
64
23
  & .crisp-datepicker-empty-cell { min-height: var(--crisp-size-calendarCell); }
65
-
66
- /* The bridge joining days inside a completed range.
67
- The endpoints do NOT carry data-in-range -- only the interior days do --
68
- so these are three independent rules, not a base plus two modifiers. A
69
- modifier that sets only inset-inline-start never generates a pseudo
70
- element on an endpoint, which leaves a half-cell of white between the
71
- endpoint's pill and the run of grey beside it. Each rule declares its
24
+ /* The bridge joining days inside a completed range. The endpoints do NOT carry data-in-range -- only the interior days do -- so these are three independent rules, not a base plus two modifiers. A modifier that sets only inset-inline-start never generates a pseudo element on an endpoint, which leaves a half-cell of white between the endpoint's pill and the run of grey beside it. Each rule declares its
72
25
  own content. */
73
26
  & .crisp-datepicker-cell[data-range-complete][data-in-range]::before {
74
27
  content: ""; position: absolute; z-index: -1; inset-inline: 0;
@@ -126,41 +79,23 @@
126
79
  Without this the content column top-aligns the glyph and the pill reads
127
80
  as offset — the cell is 48px, the pill 42px inset 3px, and only a
128
81
  42px-tall numeral box shares the pill's centre line. */
129
- & .crisp-datepicker-date-content > [data-date-picker-day] {
130
- display: flex; min-height: var(--crisp-size-calendarPill); flex-shrink: 0;
131
- align-items: center; justify-content: center;
132
- }
133
-
82
+ & .crisp-datepicker-date-content > [data-date-picker-day] { display: flex; min-height: var(--crisp-size-calendarPill); flex-shrink: 0; align-items: center; justify-content: center; }
134
83
  /* the year/month wheel, laid over the grid it replaces */
135
- & .crisp-datepicker-wheel-container {
136
- position: absolute; z-index: 1; inset-inline: 0;
137
- top: var(--crisp-size-menuRow); bottom: 0;
138
- display: flex; align-items: center; overflow: hidden;
139
- background: var(--crisp-bg-surface);
140
- }
84
+ & .crisp-datepicker-wheel-container { position: absolute; z-index: 1; inset-inline: 0; top: var(--crisp-size-menuRow); bottom: 0; display: flex; align-items: center; overflow: hidden; background: var(--crisp-bg-surface); }
141
85
  & .crisp-datepicker-wheel { width: 100%; }
142
-
143
- & .crisp-datepicker-continuous-scroll {
144
- height: 100%; min-height: 0; overflow-y: auto;
145
- overscroll-behavior: contain; scrollbar-width: none;
146
- }
86
+ & .crisp-datepicker-continuous-scroll { height: 100%; min-height: 0; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: none; }
147
87
  & .crisp-datepicker-continuous-scroll::-webkit-scrollbar { display: none; }
148
88
  & .crisp-datepicker-continuous-content { display: flex; flex-direction: column; }
149
-
150
89
  /* announced, never drawn */
151
- & .crisp-datepicker-live-region {
152
- position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
153
- overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
154
- }
155
-
90
+ & .crisp-datepicker-live-region { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
156
91
  }
157
92
  .crisp-datepicker--visibleRange_month {
158
93
 
159
94
  }
160
95
  .crisp-datepicker--visibleRange_twoMonths {
161
96
  & .crisp-datepicker-months { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--crisp-space-6); }
162
- & .crisp-datepicker-two-month-header { display: flex; align-items: center; justify-content: space-between; height: var(--crisp-size-menuRow); }
163
- & .crisp-datepicker-two-month-label { color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); }
97
+ & .crisp-datepicker-two-month-header { display: flex; align-items: center; justify-content: space-between; height: var(--crisp-size-menuRow); }
98
+ & .crisp-datepicker-two-month-label { color: var(--crisp-fg-primary); font-size: var(--crisp-text-lg); line-height: 20px; font-weight: var(--crisp-weight-medium); }
164
99
  }
165
100
  .crisp-datepicker--visibleRange_week {
166
101
 
@@ -1,27 +1,12 @@
1
1
  .crisp-datepickerfield {
2
-
3
- display: inline-flex; font-family: var(--crisp-font-sans);
4
-
5
- & .crisp-datepickerfield-trigger {
6
- display: inline-flex; align-items: center; gap: var(--crisp-space-2);
7
- box-sizing: border-box; height: 32px; padding: 0 var(--crisp-space-2-5); margin: 0;
8
- border: none; border-radius: var(--crisp-radius-md); background: transparent;
9
- box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent);
10
- color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg);
11
- white-space: nowrap; cursor: pointer;
12
- }
2
+ display: inline-flex; font-family: var(--crisp-font-sans);
3
+ & .crisp-datepickerfield-trigger { display: inline-flex; align-items: center; gap: var(--crisp-space-2); box-sizing: border-box; height: 32px; padding: 0 var(--crisp-space-2-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); white-space: nowrap; cursor: pointer; }
13
4
  & .crisp-datepickerfield-trigger[data-ghost] { background: transparent; box-shadow: none; }
14
5
  & .crisp-datepickerfield-trigger[data-ghost]:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
15
6
  & .crisp-datepickerfield-trigger[data-placeholder] { color: var(--crisp-fg-muted); }
16
7
  & .crisp-datepickerfield-trigger svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
17
-
18
8
  & .crisp-datepickerfield-panel { padding: var(--crisp-space-2); width: 300px; }
19
9
  & .crisp-datepickerfield-presets { display: flex; flex-wrap: wrap; gap: var(--crisp-space-1); margin-top: var(--crisp-space-2); }
20
- & .crisp-datepickerfield-preset {
21
- height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none;
22
- border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary);
23
- font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer;
24
- }
10
+ & .crisp-datepickerfield-preset { height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer; }
25
11
  & .crisp-datepickerfield-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
26
-
27
12
  }
@@ -1,29 +1,14 @@
1
1
  @layer crisp-components {
2
2
  .crisp-datepickerfield {
3
-
4
- display: inline-flex; font-family: var(--crisp-font-sans);
5
-
6
- & .crisp-datepickerfield-trigger {
7
- display: inline-flex; align-items: center; gap: var(--crisp-space-2);
8
- box-sizing: border-box; height: 32px; padding: 0 var(--crisp-space-2-5); margin: 0;
9
- border: none; border-radius: var(--crisp-radius-md); background: transparent;
10
- box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent);
11
- color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg);
12
- white-space: nowrap; cursor: pointer;
13
- }
3
+ display: inline-flex; font-family: var(--crisp-font-sans);
4
+ & .crisp-datepickerfield-trigger { display: inline-flex; align-items: center; gap: var(--crisp-space-2); box-sizing: border-box; height: 32px; padding: 0 var(--crisp-space-2-5); margin: 0; border: none; border-radius: var(--crisp-radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--crisp-fg-primary) 7%, transparent); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-lg); white-space: nowrap; cursor: pointer; }
14
5
  & .crisp-datepickerfield-trigger[data-ghost] { background: transparent; box-shadow: none; }
15
6
  & .crisp-datepickerfield-trigger[data-ghost]:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 4%, transparent); }
16
7
  & .crisp-datepickerfield-trigger[data-placeholder] { color: var(--crisp-fg-muted); }
17
8
  & .crisp-datepickerfield-trigger svg { flex-shrink: 0; color: var(--crisp-fg-muted); }
18
-
19
9
  & .crisp-datepickerfield-panel { padding: var(--crisp-space-2); width: 300px; }
20
10
  & .crisp-datepickerfield-presets { display: flex; flex-wrap: wrap; gap: var(--crisp-space-1); margin-top: var(--crisp-space-2); }
21
- & .crisp-datepickerfield-preset {
22
- height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none;
23
- border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary);
24
- font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer;
25
- }
11
+ & .crisp-datepickerfield-preset { height: var(--crisp-size-chip); padding: 0 var(--crisp-space-2); border: none; border-radius: var(--crisp-radius-chip); background: var(--crisp-bg-raised); color: var(--crisp-fg-primary); font-family: inherit; font-size: var(--crisp-text-sm); cursor: pointer; }
26
12
  & .crisp-datepickerfield-preset:hover { background: color-mix(in srgb, var(--crisp-fg-primary) 8%, transparent); }
27
-
28
13
  }
29
14
  }
@@ -1,6 +1,5 @@
1
1
  .crisp-donutchart {
2
- display: inline-flex; align-items: center; gap: var(--crisp-space-4); box-sizing: border-box; font-family: var(--crisp-font-sans);
3
- -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
2
+ display: inline-flex; align-items: center; gap: var(--crisp-space-4); box-sizing: border-box; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
4
3
  & .crisp-donutchart-ring { position: relative; flex-shrink: 0; }
5
4
  & .crisp-donutchart-svg { display: block; }
6
5
  & .crisp-donutchart-seg { fill: none; transition: stroke-dasharray 0.3s ease; }
@@ -1,7 +1,6 @@
1
1
  @layer crisp-components {
2
2
  .crisp-donutchart {
3
- display: inline-flex; align-items: center; gap: var(--crisp-space-4); box-sizing: border-box; font-family: var(--crisp-font-sans);
4
- -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
3
+ display: inline-flex; align-items: center; gap: var(--crisp-space-4); box-sizing: border-box; font-family: var(--crisp-font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
5
4
  & .crisp-donutchart-ring { position: relative; flex-shrink: 0; }
6
5
  & .crisp-donutchart-svg { display: block; }
7
6
  & .crisp-donutchart-seg { fill: none; transition: stroke-dasharray 0.3s ease; }
@@ -1,13 +1,7 @@
1
1
  .crisp-entitycard {
2
- display: flex; flex-direction: column; box-sizing: border-box; width: 100%; min-width: 0; text-align: start;
3
- padding: var(--crisp-space-3) var(--crisp-space-4); margin: 0; border: none; border-radius: var(--crisp-radius-xl);
4
- background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); color: var(--crisp-fg-primary);
5
- font-family: var(--crisp-font-sans); cursor: pointer; transition: box-shadow .12s ease, background-color .12s ease;
6
- -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
7
-
2
+ display: flex; flex-direction: column; box-sizing: border-box; width: 100%; min-width: 0; text-align: start; padding: var(--crisp-space-3) var(--crisp-space-4); margin: 0; border: none; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); color: var(--crisp-fg-primary); font-family: var(--crisp-font-sans); cursor: pointer; transition: box-shadow .12s ease, background-color .12s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
8
3
  &:hover { box-shadow: inset 0 0 0 1px var(--crisp-border-default), 0 1px 2px rgba(0,0,0,0.04), 0 6px 16px -6px rgba(28,40,64,0.12); }
9
4
  &:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 2px; }
10
-
11
5
  & .crisp-entitycard-author { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
12
6
  & .crisp-entitycard-title { margin-top: var(--crisp-space-2); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.1px; color: var(--crisp-fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
13
7
  & .crisp-entitycard-excerpt { margin-top: var(--crisp-space-1); font-size: var(--crisp-text-md); line-height: 18px; color: var(--crisp-fg-muted); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
@@ -1,14 +1,8 @@
1
1
  @layer crisp-components {
2
2
  .crisp-entitycard {
3
- display: flex; flex-direction: column; box-sizing: border-box; width: 100%; min-width: 0; text-align: start;
4
- padding: var(--crisp-space-3) var(--crisp-space-4); margin: 0; border: none; border-radius: var(--crisp-radius-xl);
5
- background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); color: var(--crisp-fg-primary);
6
- font-family: var(--crisp-font-sans); cursor: pointer; transition: box-shadow .12s ease, background-color .12s ease;
7
- -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
8
-
3
+ display: flex; flex-direction: column; box-sizing: border-box; width: 100%; min-width: 0; text-align: start; padding: var(--crisp-space-3) var(--crisp-space-4); margin: 0; border: none; border-radius: var(--crisp-radius-xl); background: var(--crisp-bg-surface); box-shadow: inset 0 0 0 1px var(--crisp-border-subtle); color: var(--crisp-fg-primary); font-family: var(--crisp-font-sans); cursor: pointer; transition: box-shadow .12s ease, background-color .12s ease; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
9
4
  &:hover { box-shadow: inset 0 0 0 1px var(--crisp-border-default), 0 1px 2px rgba(0,0,0,0.04), 0 6px 16px -6px rgba(28,40,64,0.12); }
10
5
  &:focus-visible { outline: 2px solid var(--crisp-bg-brand-solid); outline-offset: 2px; }
11
-
12
6
  & .crisp-entitycard-author { display: inline-flex; align-items: center; gap: var(--crisp-space-1-5); font-size: var(--crisp-text-md); font-weight: var(--crisp-weight-medium); color: var(--crisp-fg-muted); }
13
7
  & .crisp-entitycard-title { margin-top: var(--crisp-space-2); font-size: var(--crisp-text-lg); font-weight: var(--crisp-weight-semibold); letter-spacing: -0.1px; color: var(--crisp-fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
14
8
  & .crisp-entitycard-excerpt { margin-top: var(--crisp-space-1); font-size: var(--crisp-text-md); line-height: 18px; color: var(--crisp-fg-muted); display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden; }
@@ -1,32 +1,51 @@
1
- import { defineRecipe, resolveRecipe } from "../../core/index.js";
1
+ import { defineSpec, resolveRecipe, specToRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
- const config = defineRecipe({
3
+ const spec = defineSpec({
4
4
  name: "avatar",
5
- base: `display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; font-family: ${c.font.sans}; font-weight: ${c.weight.semibold}; overflow: hidden; user-select: none; & img { width: 100%; height: 100%; object-fit: cover; }`,
5
+ base: {
6
+ display: "inline-flex",
7
+ alignItems: "center",
8
+ justifyContent: "center",
9
+ flexShrink: 0,
10
+ fontFamily: c.font.sans,
11
+ fontWeight: c.weight.semibold,
12
+ overflow: "hidden",
13
+ userSelect: "none",
14
+ },
15
+ parts: [
16
+ {
17
+ slot: "image",
18
+ selector: "& img",
19
+ decls: { width: "100%", height: "100%", objectFit: "cover" },
20
+ },
21
+ ],
6
22
  variants: {
7
23
  size: {
8
- sm: `height: 16px; width: 16px; font-size: 9px;`,
9
- md: `height: 20px; width: 20px; font-size: 10px;`,
10
- lg: `height: 24px; width: 24px; font-size: ${c.text.sm};`,
11
- xl: `height: 32px; width: 32px; font-size: ${c.text.lg};`,
24
+ sm: { height: "16px", width: "16px", fontSize: "9px" },
25
+ md: { height: "20px", width: "20px", fontSize: "10px" },
26
+ lg: { height: "24px", width: "24px", fontSize: c.text.sm },
27
+ xl: { height: "32px", width: "32px", fontSize: c.text.lg },
12
28
  },
13
29
  shape: {
14
- circle: `border-radius: ${c.radius.full};`,
15
- rounded: `border-radius: 30%;`,
30
+ circle: { borderRadius: c.radius.full },
31
+ rounded: { borderRadius: "30%" },
16
32
  },
17
33
  tone: {
18
- neutral: `background: ${c.bgRaised}; color: ${c.fgMuted}; box-shadow: inset 0 0 0 1px ${c.borderDefault};`,
19
- brand: `background: ${c.bgBrandSolid}; color: #fff;`,
20
- orange: `background: ${c.bgOrange}; color: #fff;`,
21
- cyan: `background: ${c.bgCyan}; color: #fff;`,
22
- purple: `background: ${c.bgPurple}; color: #fff;`,
23
- green: `background: ${c.bgSuccess}; color: #fff;`,
34
+ neutral: {
35
+ background: c.bgRaised,
36
+ color: c.fgMuted,
37
+ boxShadow: `inset 0 0 0 1px ${c.borderDefault}`,
38
+ },
39
+ brand: { background: c.bgBrandSolid, color: "#fff" },
40
+ orange: { background: c.bgOrange, color: "#fff" },
41
+ cyan: { background: c.bgCyan, color: "#fff" },
42
+ purple: { background: c.bgPurple, color: "#fff" },
43
+ green: { background: c.bgSuccess, color: "#fff" },
24
44
  },
25
45
  },
26
46
  defaultVariants: { size: "md", shape: "circle", tone: "neutral" },
27
- compoundVariants: [],
28
- });
29
- export const avatarRecipe = Object.assign(resolveRecipe(config), {
30
- config,
31
47
  });
48
+ const config = specToRecipe(spec);
49
+ export const avatarRecipe = Object.assign(resolveRecipe(config), { config });
50
+ export { spec };
32
51
  export default config;
@@ -1,23 +1,96 @@
1
- import { defineRecipe, resolveRecipe } from "../../core/index.js";
1
+ import { defineSpec, resolveRecipe, specToRecipe } from "../../core/index.js";
2
2
  import { contract as c, elevation as e } from "../../tokens/index.js";
3
- const config = defineRecipe({
3
+ const spec = defineSpec({
4
4
  name: "button",
5
- base: `display: inline-flex; align-items: center; justify-content: center; gap: ${c.space["1.5"]}; font-family: ${c.font.sans}; font-weight: ${c.weight.medium}; letter-spacing: -0.14px; line-height: 20px; white-space: nowrap; border: none; cursor: pointer; transition: background-color .2s, box-shadow .2s, color .2s; &:disabled { opacity: 0.5; cursor: not-allowed; }`,
5
+ base: {
6
+ display: "inline-flex",
7
+ alignItems: "center",
8
+ justifyContent: "center",
9
+ gap: c.space["1.5"],
10
+ fontFamily: c.font.sans,
11
+ fontWeight: c.weight.medium,
12
+ letterSpacing: "-0.14px",
13
+ lineHeight: "20px",
14
+ whiteSpace: "nowrap",
15
+ border: "none",
16
+ cursor: "pointer",
17
+ transition: "background-color .2s, box-shadow .2s, color .2s",
18
+ },
19
+ parts: [
20
+ { selector: "&:disabled", decls: { opacity: 0.5, cursor: "not-allowed" } },
21
+ ],
6
22
  variants: {
7
23
  intent: {
8
- primary: `background: ${c.bgBrandSolid}; color: ${c.fgOnBrand}; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.07), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08); &:hover { background: ${c.bgBrandSolidPressed}; } &:active { background: ${c.bgBrandSolidPressed}; }`,
9
- neutral: `background: ${c.bgSurface}; color: ${c.fgPrimary}; box-shadow: ${e.field}; &:hover { background: ${c.bgRaised}; }`,
10
- danger: `background: ${c.bgDangerSolid}; color: ${c.fgOnBrand}; box-shadow: inset 0 0 0 1px rgba(255,255,255,0.07), 0 2px 4px -2px rgba(186,37,37,0.20), 0 3px 6px -2px rgba(186,37,37,0.12); &:hover { filter: brightness(0.96); } &:active { filter: brightness(0.92); }`,
11
- ghost: `background: transparent; color: ${c.fgMuted}; box-shadow: none; &:hover { background: ${c.bgRaised}; color: ${c.fgPrimary}; }`,
24
+ primary: {
25
+ decls: {
26
+ background: c.bgBrandSolid,
27
+ color: c.fgOnBrand,
28
+ boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.07), 0 2px 4px -2px rgba(38,109,240,0.12), 0 3px 6px -2px rgba(38,109,240,0.08)",
29
+ },
30
+ parts: [
31
+ { selector: "&:hover", decls: { background: c.bgBrandSolidPressed } },
32
+ {
33
+ selector: "&:active",
34
+ decls: { background: c.bgBrandSolidPressed },
35
+ },
36
+ ],
37
+ },
38
+ neutral: {
39
+ decls: {
40
+ background: c.bgSurface,
41
+ color: c.fgPrimary,
42
+ boxShadow: e.field,
43
+ },
44
+ parts: [{ selector: "&:hover", decls: { background: c.bgRaised } }],
45
+ },
46
+ danger: {
47
+ decls: {
48
+ background: c.bgDangerSolid,
49
+ color: c.fgOnBrand,
50
+ boxShadow: "inset 0 0 0 1px rgba(255,255,255,0.07), 0 2px 4px -2px rgba(186,37,37,0.20), 0 3px 6px -2px rgba(186,37,37,0.12)",
51
+ },
52
+ parts: [
53
+ { selector: "&:hover", decls: { filter: "brightness(0.96)" } },
54
+ { selector: "&:active", decls: { filter: "brightness(0.92)" } },
55
+ ],
56
+ },
57
+ ghost: {
58
+ decls: {
59
+ background: "transparent",
60
+ color: c.fgMuted,
61
+ boxShadow: "none",
62
+ },
63
+ parts: [
64
+ {
65
+ selector: "&:hover",
66
+ decls: { background: c.bgRaised, color: c.fgPrimary },
67
+ },
68
+ ],
69
+ },
12
70
  },
13
71
  size: {
14
- sm: `height: 24px; padding-inline: ${c.space["1.5"]}; font-size: ${c.text.md}; border-radius: ${c.radius.md};`,
15
- md: `height: 28px; padding-inline: ${c.space["2"]}; font-size: ${c.text.lg}; border-radius: ${c.radius.md};`,
16
- lg: `height: 40px; padding-inline: 14px; font-size: ${c.text.lg}; border-radius: 10px;`,
72
+ sm: {
73
+ height: "24px",
74
+ paddingInline: c.space["1.5"],
75
+ fontSize: c.text.md,
76
+ borderRadius: c.radius.md,
77
+ },
78
+ md: {
79
+ height: "28px",
80
+ paddingInline: c.space["2"],
81
+ fontSize: c.text.lg,
82
+ borderRadius: c.radius.md,
83
+ },
84
+ lg: {
85
+ height: "40px",
86
+ paddingInline: "14px",
87
+ fontSize: c.text.lg,
88
+ borderRadius: "10px",
89
+ },
17
90
  },
18
91
  shape: {
19
- text: ``,
20
- icon: `padding-inline: 0; aspect-ratio: 1 / 1;`,
92
+ text: {},
93
+ icon: { paddingInline: 0, aspectRatio: "1 / 1" },
21
94
  },
22
95
  // Opt-in hit-area expansion (crisp/#62): none of sm/md/lg reaches the
23
96
  // 44x44 touch-target minimum (Apple HIG / Material), and enlarging the
@@ -27,8 +100,27 @@ const config = defineRecipe({
27
100
  // Opt-in rather than always-on: an always-on overlay would swallow
28
101
  // clicks meant for a neighbour in a toolbar packed tighter than 44px.
29
102
  touchTarget: {
30
- true: `position: relative; &::after { content: ""; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 100%; height: 100%; min-width: 44px; min-height: 44px; }`,
31
- false: ``,
103
+ true: {
104
+ decls: { position: "relative" },
105
+ parts: [
106
+ {
107
+ slot: "hitArea",
108
+ selector: "&::after",
109
+ decls: {
110
+ content: '""',
111
+ position: "absolute",
112
+ top: "50%",
113
+ left: "50%",
114
+ transform: "translate(-50%, -50%)",
115
+ width: "100%",
116
+ height: "100%",
117
+ minWidth: "44px",
118
+ minHeight: "44px",
119
+ },
120
+ },
121
+ ],
122
+ },
123
+ false: {},
32
124
  },
33
125
  },
34
126
  defaultVariants: {
@@ -37,9 +129,8 @@ const config = defineRecipe({
37
129
  shape: "text",
38
130
  touchTarget: false,
39
131
  },
40
- compoundVariants: [],
41
- });
42
- export const buttonRecipe = Object.assign(resolveRecipe(config), {
43
- config,
44
132
  });
133
+ const config = specToRecipe(spec);
134
+ export const buttonRecipe = Object.assign(resolveRecipe(config), { config });
135
+ export { spec };
45
136
  export default config;
@@ -1,25 +1,55 @@
1
- import { defineRecipe, resolveRecipe } from "../../core/index.js";
1
+ import { defineSpec, resolveRecipe, specToRecipe } from "../../core/index.js";
2
2
  import { contract as c } from "../../tokens/index.js";
3
3
  // A settings toggle, measured from the live app: a 24×16 pill track that
4
4
  // flips from a muted grey to brand blue (#266df0), with a 12px white thumb
5
5
  // (2px inset) that slides 8px across. background + transform both animate .2s.
6
- const config = defineRecipe({
6
+ const spec = defineSpec({
7
7
  name: "switch",
8
- base: `
9
- display: inline-flex; align-items: center; flex-shrink: 0; width: 24px; height: 16px; padding: 0; margin: 0;
10
- border: none; border-radius: ${c.radius.full}; background: color-mix(in srgb, ${c.fgPrimary} 9%, transparent);
11
- cursor: pointer; transition: background-color .2s ease; -webkit-tap-highlight-color: transparent;
12
- & .crisp-switch-thumb { width: 12px; height: 12px; margin: 0 2px; border-radius: ${c.radius.full}; background: #fff; transition: transform .2s ease; }
13
- &[data-checked] { background: ${c.bgBrandSolid}; }
14
- &[data-checked] .crisp-switch-thumb { transform: translateX(8px); }
15
- &:focus-visible { outline: 2px solid ${c.bgBrandSolid}; outline-offset: 2px; }
16
- &:disabled { opacity: 0.5; cursor: not-allowed; }
17
- `,
18
- variants: {},
19
- defaultVariants: {},
20
- compoundVariants: [],
21
- });
22
- export const switchRecipe = Object.assign(resolveRecipe(config), {
23
- config,
8
+ base: {
9
+ display: "inline-flex",
10
+ alignItems: "center",
11
+ flexShrink: 0,
12
+ width: "24px",
13
+ height: "16px",
14
+ padding: 0,
15
+ margin: 0,
16
+ border: "none",
17
+ borderRadius: c.radius.full,
18
+ background: `color-mix(in srgb, ${c.fgPrimary} 9%, transparent)`,
19
+ cursor: "pointer",
20
+ transition: "background-color .2s ease",
21
+ WebkitTapHighlightColor: "transparent",
22
+ },
23
+ parts: [
24
+ {
25
+ slot: "thumb",
26
+ selector: "& .crisp-switch-thumb",
27
+ decls: {
28
+ width: "12px",
29
+ height: "12px",
30
+ margin: "0 2px",
31
+ borderRadius: c.radius.full,
32
+ background: "#fff",
33
+ transition: "transform .2s ease",
34
+ },
35
+ },
36
+ { selector: "&[data-checked]", decls: { background: c.bgBrandSolid } },
37
+ {
38
+ slot: "thumb",
39
+ selector: "&[data-checked] .crisp-switch-thumb",
40
+ decls: { transform: "translateX(8px)" },
41
+ },
42
+ {
43
+ selector: "&:focus-visible",
44
+ decls: {
45
+ outline: `2px solid ${c.bgBrandSolid}`,
46
+ outlineOffset: "2px",
47
+ },
48
+ },
49
+ { selector: "&:disabled", decls: { opacity: 0.5, cursor: "not-allowed" } },
50
+ ],
24
51
  });
52
+ const config = specToRecipe(spec);
53
+ export const switchRecipe = Object.assign(resolveRecipe(config), { config });
54
+ export { spec };
25
55
  export default config;