@crisp-ui-kit/crisp 0.2.0 → 0.5.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.
Files changed (244) hide show
  1. package/README.md +6 -0
  2. package/dist/base.css +25 -0
  3. package/dist/button.css +1 -1
  4. package/dist/command.css +1 -1
  5. package/dist/contextmenu.css +1 -1
  6. package/dist/datatable.css +60 -0
  7. package/dist/datatable.d.ts +7 -0
  8. package/dist/datepicker.css +1 -1
  9. package/dist/dialog.css +1 -1
  10. package/dist/esm/components/accordion/accordion.js +32 -0
  11. package/dist/esm/components/accordion/accordion.recipe.js +23 -0
  12. package/dist/esm/components/accordion/index.js +2 -0
  13. package/dist/esm/components/avatar/avatar.js +8 -0
  14. package/dist/esm/components/avatar/avatar.recipe.js +39 -0
  15. package/dist/esm/components/avatar/index.js +2 -0
  16. package/dist/esm/components/avatargroup/avatargroup.js +16 -0
  17. package/dist/esm/components/avatargroup/avatargroup.recipe.js +15 -0
  18. package/dist/esm/components/avatargroup/index.js +2 -0
  19. package/dist/esm/components/badge/badge.js +8 -0
  20. package/dist/esm/components/badge/badge.recipe.js +65 -0
  21. package/dist/esm/components/badge/index.js +2 -0
  22. package/dist/esm/components/barchart/barchart.js +29 -0
  23. package/dist/esm/components/barchart/barchart.recipe.js +26 -0
  24. package/dist/esm/components/barchart/index.js +2 -0
  25. package/dist/esm/components/breadcrumb/breadcrumb.js +17 -0
  26. package/dist/esm/components/breadcrumb/breadcrumb.recipe.js +18 -0
  27. package/dist/esm/components/breadcrumb/index.js +2 -0
  28. package/dist/esm/components/bulkbar/bulkbar.js +16 -0
  29. package/dist/esm/components/bulkbar/bulkbar.recipe.js +28 -0
  30. package/dist/esm/components/bulkbar/index.js +2 -0
  31. package/dist/esm/components/button/button.js +15 -0
  32. package/dist/esm/components/button/button.recipe.js +39 -0
  33. package/dist/esm/components/button/index.js +2 -0
  34. package/dist/esm/components/callout/callout.js +22 -0
  35. package/dist/esm/components/callout/callout.recipe.js +26 -0
  36. package/dist/esm/components/callout/index.js +2 -0
  37. package/dist/esm/components/card/card.js +15 -0
  38. package/dist/esm/components/card/card.recipe.js +28 -0
  39. package/dist/esm/components/card/index.js +2 -0
  40. package/dist/esm/components/checkbox/checkbox.js +20 -0
  41. package/dist/esm/components/checkbox/checkbox.recipe.js +23 -0
  42. package/dist/esm/components/checkbox/index.js +2 -0
  43. package/dist/esm/components/contextmenu/contextmenu.js +42 -0
  44. package/dist/esm/components/contextmenu/contextmenu.recipe.js +21 -0
  45. package/dist/esm/components/contextmenu/index.js +2 -0
  46. package/dist/esm/components/datatable/datatable.js +245 -0
  47. package/dist/esm/components/datatable/datatable.recipe.js +72 -0
  48. package/dist/esm/components/datatable/index.js +2 -0
  49. package/dist/esm/components/datepicker/datepicker.js +57 -0
  50. package/dist/esm/components/datepicker/datepicker.recipe.js +32 -0
  51. package/dist/esm/components/datepicker/index.js +2 -0
  52. package/dist/esm/components/dialog/dialog.js +48 -0
  53. package/dist/esm/components/dialog/dialog.recipe.js +32 -0
  54. package/dist/esm/components/dialog/index.js +2 -0
  55. package/dist/esm/components/divider/divider.js +7 -0
  56. package/dist/esm/components/divider/divider.recipe.js +14 -0
  57. package/dist/esm/components/divider/index.js +2 -0
  58. package/dist/esm/components/donutchart/donutchart.js +38 -0
  59. package/dist/esm/components/donutchart/donutchart.recipe.js +27 -0
  60. package/dist/esm/components/donutchart/index.js +2 -0
  61. package/dist/esm/components/drawer/drawer.js +42 -0
  62. package/dist/esm/components/drawer/drawer.recipe.js +27 -0
  63. package/dist/esm/components/drawer/index.js +2 -0
  64. package/dist/esm/components/emptystate/emptystate.js +7 -0
  65. package/dist/esm/components/emptystate/emptystate.recipe.js +31 -0
  66. package/dist/esm/components/emptystate/index.js +2 -0
  67. package/dist/esm/components/formfield/formfield.js +14 -0
  68. package/dist/esm/components/formfield/formfield.recipe.js +19 -0
  69. package/dist/esm/components/formfield/index.js +2 -0
  70. package/dist/esm/components/input/index.js +2 -0
  71. package/dist/esm/components/input/input.js +8 -0
  72. package/dist/esm/components/input/input.recipe.js +23 -0
  73. package/dist/esm/components/kbd/index.js +2 -0
  74. package/dist/esm/components/kbd/kbd.js +8 -0
  75. package/dist/esm/components/kbd/kbd.recipe.js +20 -0
  76. package/dist/esm/components/linechart/index.js +2 -0
  77. package/dist/esm/components/linechart/linechart.js +41 -0
  78. package/dist/esm/components/linechart/linechart.recipe.js +27 -0
  79. package/dist/esm/components/menu/index.js +2 -0
  80. package/dist/esm/components/menu/menu.js +137 -0
  81. package/dist/esm/components/menu/menu.recipe.js +51 -0
  82. package/dist/esm/components/multiselect/index.js +2 -0
  83. package/dist/esm/components/multiselect/multiselect.js +118 -0
  84. package/dist/esm/components/multiselect/multiselect.recipe.js +68 -0
  85. package/dist/esm/components/popover/index.js +2 -0
  86. package/dist/esm/components/popover/popover.js +70 -0
  87. package/dist/esm/components/popover/popover.recipe.js +18 -0
  88. package/dist/esm/components/progress/index.js +2 -0
  89. package/dist/esm/components/progress/progress.js +23 -0
  90. package/dist/esm/components/progress/progress.recipe.js +17 -0
  91. package/dist/esm/components/radiogroup/index.js +2 -0
  92. package/dist/esm/components/radiogroup/radiogroup.js +46 -0
  93. package/dist/esm/components/radiogroup/radiogroup.recipe.js +37 -0
  94. package/dist/esm/components/segmented/index.js +2 -0
  95. package/dist/esm/components/segmented/segmented.js +59 -0
  96. package/dist/esm/components/segmented/segmented.recipe.js +20 -0
  97. package/dist/esm/components/select/index.js +2 -0
  98. package/dist/esm/components/select/select.js +144 -0
  99. package/dist/esm/components/select/select.recipe.js +76 -0
  100. package/dist/esm/components/skeleton/index.js +2 -0
  101. package/dist/esm/components/skeleton/skeleton.js +7 -0
  102. package/dist/esm/components/skeleton/skeleton.recipe.js +14 -0
  103. package/dist/esm/components/spinner/index.js +2 -0
  104. package/dist/esm/components/spinner/spinner.js +11 -0
  105. package/dist/esm/components/spinner/spinner.recipe.js +13 -0
  106. package/dist/esm/components/stagebar/index.js +2 -0
  107. package/dist/esm/components/stagebar/stagebar.js +23 -0
  108. package/dist/esm/components/stagebar/stagebar.recipe.js +14 -0
  109. package/dist/esm/components/statcard/index.js +2 -0
  110. package/dist/esm/components/statcard/statcard.js +12 -0
  111. package/dist/esm/components/statcard/statcard.recipe.js +34 -0
  112. package/dist/esm/components/switch/index.js +2 -0
  113. package/dist/esm/components/switch/switch.js +22 -0
  114. package/dist/esm/components/switch/switch.recipe.js +26 -0
  115. package/dist/esm/components/table/index.js +2 -0
  116. package/dist/esm/components/table/table.js +30 -0
  117. package/dist/esm/components/table/table.recipe.js +40 -0
  118. package/dist/esm/components/tabletoolbar/index.js +2 -0
  119. package/dist/esm/components/tabletoolbar/tabletoolbar.chrome.js +79 -0
  120. package/dist/esm/components/tabletoolbar/tabletoolbar.js +191 -0
  121. package/dist/esm/components/tabletoolbar/tabletoolbar.recipe.js +23 -0
  122. package/dist/esm/components/tabs/index.js +2 -0
  123. package/dist/esm/components/tabs/tabs.js +70 -0
  124. package/dist/esm/components/tabs/tabs.recipe.js +33 -0
  125. package/dist/esm/components/textarea/index.js +2 -0
  126. package/dist/esm/components/textarea/textarea.js +20 -0
  127. package/dist/esm/components/textarea/textarea.recipe.js +31 -0
  128. package/dist/esm/components/toast/index.js +2 -0
  129. package/dist/esm/components/toast/toast.js +58 -0
  130. package/dist/esm/components/toast/toast.recipe.js +28 -0
  131. package/dist/esm/components/tooltip/index.js +2 -0
  132. package/dist/esm/components/tooltip/tooltip.js +45 -0
  133. package/dist/esm/components/tooltip/tooltip.recipe.js +13 -0
  134. package/dist/esm/core/cx.js +1 -0
  135. package/dist/esm/core/define.js +3 -0
  136. package/dist/esm/core/index.js +4 -0
  137. package/dist/esm/core/primitive.js +13 -0
  138. package/dist/esm/core/resolve.js +41 -0
  139. package/dist/esm/core/types.js +1 -0
  140. package/dist/esm/index.js +71 -0
  141. package/dist/esm/product/appshell/appshell.js +44 -0
  142. package/dist/esm/product/appshell/appshell.recipe.js +27 -0
  143. package/dist/esm/product/appshell/index.js +2 -0
  144. package/dist/esm/product/board/board.js +42 -0
  145. package/dist/esm/product/board/board.recipe.js +28 -0
  146. package/dist/esm/product/board/index.js +2 -0
  147. package/dist/esm/product/command/command.js +188 -0
  148. package/dist/esm/product/command/command.recipe.js +19 -0
  149. package/dist/esm/product/command/index.js +2 -0
  150. package/dist/esm/product/entitycard/entitycard.js +11 -0
  151. package/dist/esm/product/entitycard/entitycard.recipe.js +29 -0
  152. package/dist/esm/product/entitycard/index.js +2 -0
  153. package/dist/esm/product/flowcanvas/flowcanvas.js +85 -0
  154. package/dist/esm/product/flowcanvas/flowcanvas.recipe.js +25 -0
  155. package/dist/esm/product/flowcanvas/index.js +2 -0
  156. package/dist/esm/product/inbox/inbox.js +13 -0
  157. package/dist/esm/product/inbox/inbox.recipe.js +43 -0
  158. package/dist/esm/product/inbox/index.js +2 -0
  159. package/dist/esm/product/listpage/index.js +2 -0
  160. package/dist/esm/product/listpage/listpage.js +21 -0
  161. package/dist/esm/product/listpage/listpage.recipe.js +43 -0
  162. package/dist/esm/product/navitem/index.js +1 -0
  163. package/dist/esm/product/navitem/navitem.js +8 -0
  164. package/dist/esm/product/navitem/navitem.recipe.js +21 -0
  165. package/dist/esm/product/onboarding/index.js +2 -0
  166. package/dist/esm/product/onboarding/onboarding.js +14 -0
  167. package/dist/esm/product/onboarding/onboarding.recipe.js +41 -0
  168. package/dist/esm/product/recordpage/index.js +2 -0
  169. package/dist/esm/product/recordpage/recordpage.js +286 -0
  170. package/dist/esm/product/recordpage/recordpage.recipe.js +157 -0
  171. package/dist/esm/product/recordpanel/index.js +2 -0
  172. package/dist/esm/product/recordpanel/recordpanel.js +47 -0
  173. package/dist/esm/product/recordpanel/recordpanel.recipe.js +52 -0
  174. package/dist/esm/product/recordstable/company-logos.js +26 -0
  175. package/dist/esm/product/recordstable/index.js +2 -0
  176. package/dist/esm/product/recordstable/recordstable.js +963 -0
  177. package/dist/esm/product/recordstable/recordstable.recipe.js +149 -0
  178. package/dist/esm/product/richtext/index.js +2 -0
  179. package/dist/esm/product/richtext/richtext.js +111 -0
  180. package/dist/esm/product/richtext/richtext.recipe.js +40 -0
  181. package/dist/esm/product/settingssection/index.js +2 -0
  182. package/dist/esm/product/settingssection/settingssection.js +11 -0
  183. package/dist/esm/product/settingssection/settingssection.recipe.js +20 -0
  184. package/dist/esm/product/settingsshell/index.js +2 -0
  185. package/dist/esm/product/settingsshell/settingsshell.js +23 -0
  186. package/dist/esm/product/settingsshell/settingsshell.recipe.js +38 -0
  187. package/dist/esm/product/sidebar/index.js +2 -0
  188. package/dist/esm/product/sidebar/sidebar.js +112 -0
  189. package/dist/esm/product/sidebar/sidebar.recipe.js +18 -0
  190. package/dist/esm/product/tasklist/index.js +2 -0
  191. package/dist/esm/product/tasklist/tasklist.js +16 -0
  192. package/dist/esm/product/tasklist/tasklist.recipe.js +35 -0
  193. package/dist/esm/product/trialbanner/index.js +2 -0
  194. package/dist/esm/product/trialbanner/trialbanner.js +10 -0
  195. package/dist/esm/product/trialbanner/trialbanner.recipe.js +29 -0
  196. package/dist/esm/product/viewtoggle/index.js +2 -0
  197. package/dist/esm/product/viewtoggle/viewtoggle.js +11 -0
  198. package/dist/esm/product/viewtoggle/viewtoggle.recipe.js +24 -0
  199. package/dist/esm/tokens/contract.js +18 -0
  200. package/dist/esm/tokens/index.js +4 -0
  201. package/dist/esm/tokens/palette.js +30 -0
  202. package/dist/esm/tokens/scale.js +60 -0
  203. package/dist/esm/tokens/semantic.js +30 -0
  204. package/dist/menu.css +2 -2
  205. package/dist/multiselect.css +3 -3
  206. package/dist/popover.css +1 -1
  207. package/dist/recordpage.css +5 -5
  208. package/dist/recordstable.css +4 -4
  209. package/dist/select.css +10 -4
  210. package/dist/select.d.ts +2 -1
  211. package/dist/sidebar.css +1 -1
  212. package/dist/statcard.css +6 -0
  213. package/dist/statcard.d.ts +2 -2
  214. package/dist/styles.css +222 -27
  215. package/dist/table.css +26 -0
  216. package/dist/table.d.ts +8 -0
  217. package/dist/tabletoolbar.css +70 -0
  218. package/dist/tabletoolbar.d.ts +7 -0
  219. package/dist/tokens.css +24 -0
  220. package/dist/types/components/datatable/datatable.d.ts +98 -0
  221. package/dist/types/components/datatable/datatable.recipe.d.ts +3 -0
  222. package/dist/types/components/datatable/index.d.ts +2 -0
  223. package/dist/types/components/select/select.d.ts +3 -1
  224. package/dist/types/components/select/select.recipe.d.ts +12 -0
  225. package/dist/types/components/statcard/statcard.d.ts +6 -1
  226. package/dist/types/components/statcard/statcard.recipe.d.ts +12 -2
  227. package/dist/types/components/table/index.d.ts +2 -0
  228. package/dist/types/components/table/table.d.ts +53 -0
  229. package/dist/types/components/table/table.recipe.d.ts +21 -0
  230. package/dist/types/components/tabletoolbar/index.d.ts +2 -0
  231. package/dist/types/components/tabletoolbar/tabletoolbar.chrome.d.ts +2 -0
  232. package/dist/types/components/tabletoolbar/tabletoolbar.d.ts +63 -0
  233. package/dist/types/components/tabletoolbar/tabletoolbar.recipe.d.ts +3 -0
  234. package/dist/types/index.d.ts +3 -0
  235. package/dist/types/product/recordstable/company-logos.d.ts +1 -0
  236. package/dist/types/product/recordstable/recordstable.d.ts +42 -1
  237. package/dist/types/product/sidebar/index.d.ts +1 -1
  238. package/dist/types/product/sidebar/sidebar.d.ts +85 -0
  239. package/dist/types/tokens/contract.d.ts +12 -0
  240. package/dist/types/tokens/palette.d.ts +48 -0
  241. package/dist/types/tokens/semantic.d.ts +12 -0
  242. package/dist/viewtoggle.css +2 -2
  243. package/package.json +259 -9
  244. package/dist/index.js +0 -9690
@@ -0,0 +1,35 @@
1
+ import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
+ import { contract as c } from "../../tokens/index.js";
3
+ // A task list — measured from Attio's Tasks page: optional group headers, then
4
+ // rows of a round complete-checkbox + title + trailing meta (due date, record,
5
+ // assignee). Completed rows strike through; overdue due-dates go red.
6
+ const config = defineRecipe({
7
+ name: "tasklist",
8
+ base: `display: flex; flex-direction: column; box-sizing: border-box; font-family: ${c.font.sans};
9
+ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
10
+
11
+ & .tasklist-group { display: flex; align-items: center; gap: ${c.space["1.5"]}; height: 36px; padding: 0 ${c.space["2"]}; font-size: ${c.text.md}; font-weight: ${c.weight.medium}; color: ${c.fgMuted}; }
12
+ & .tasklist-group-count { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 ${c.space["1"]}; border-radius: ${c.radius.sm}; background: color-mix(in srgb, ${c.fgPrimary} 6%, transparent); font-size: ${c.text.xs}; color: ${c.fgMuted}; }
13
+
14
+ & .tasklist-row { display: flex; align-items: center; gap: ${c.space["2.5"]}; height: 52px; padding: 0 ${c.space["2"]}; border-top: 1px solid ${c.borderSubtle}; }
15
+ & .tasklist-row:first-child { border-top: none; }
16
+
17
+ & .tasklist-check { appearance: none; -webkit-appearance: none; box-sizing: border-box; flex-shrink: 0; margin: 0; width: 16px; height: 16px; border: none; border-radius: ${c.radius.full}; background: ${c.bgSurface}; box-shadow: inset 0 0 0 1px color-mix(in srgb, ${c.fgPrimary} 9%, transparent); cursor: pointer; transition: background-color .12s, box-shadow .12s; }
18
+ & .tasklist-check:hover { box-shadow: inset 0 0 0 1px color-mix(in srgb, ${c.fgPrimary} 30%, transparent); }
19
+ & .tasklist-check:checked { background: ${c.bgBrandSolid} center / 10px no-repeat; box-shadow: none; background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='10' viewBox='0 0 12 12' fill='none' stroke='white' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 6.5 5 9l4.5-5'/%3E%3C/svg%3E"); }
20
+ & .tasklist-check:focus-visible { outline: 2px solid ${c.bgBrandSolid}; outline-offset: 1px; }
21
+
22
+ & .tasklist-title { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: ${c.text.lg}; font-weight: ${c.weight.medium}; color: ${c.fgPrimary}; }
23
+ & .tasklist-row[data-done] .tasklist-title { color: ${c.fgMuted}; text-decoration: line-through; }
24
+
25
+ & .tasklist-meta { display: inline-flex; align-items: center; gap: ${c.space["3"]}; flex-shrink: 0; }
26
+ & .tasklist-due { font-size: ${c.text.lg}; color: ${c.fgMuted}; white-space: nowrap; }
27
+ & .tasklist-due[data-overdue] { color: ${c.bgDanger}; }
28
+
29
+ & .tasklist-empty { padding: ${c.space["4"]} ${c.space["2"]}; text-align: center; font-size: ${c.text.md}; color: ${c.fgMuted}; }`,
30
+ variants: {},
31
+ defaultVariants: {},
32
+ compoundVariants: [],
33
+ });
34
+ export const tasklistRecipe = resolveRecipe(config);
35
+ export default config;
@@ -0,0 +1,2 @@
1
+ export { TrialBanner } from "./trialbanner.js";
2
+ export { trialbannerRecipe } from "./trialbanner.recipe.js";
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { trialbannerRecipe } from "./trialbanner.recipe.js";
3
+ /**
4
+ * A compact trial / upgrade banner — measured from Attio's sidebar footer.
5
+ * Icon + message + an optional small action pill (soft-glow outlined button).
6
+ */
7
+ export function TrialBanner({ icon, children, action, onAction, tone = "neutral", className, }) {
8
+ return (_jsxs("div", { className: trialbannerRecipe({ className }), "data-tone": tone === "neutral" ? undefined : tone, children: [icon != null && _jsx("span", { className: "trialbanner-icon", children: icon }), _jsx("span", { className: "trialbanner-msg", children: children }), action != null && (_jsx("button", { type: "button", className: "trialbanner-action", onClick: onAction, children: action }))] }));
9
+ }
10
+ TrialBanner.displayName = "TrialBanner";
@@ -0,0 +1,29 @@
1
+ import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
+ import { contract as c } from "../../tokens/index.js";
3
+ // A compact trial / upgrade banner — measured from Attio's sidebar footer: an
4
+ // icon + a message on the left and a small action pill on the right, in a 28px
5
+ // row. The action uses Attio's soft-glow outlined-button shadow.
6
+ const config = defineRecipe({
7
+ name: "trialbanner",
8
+ base: `display: flex; align-items: center; gap: ${c.space["1.5"]}; box-sizing: border-box; min-height: 28px;
9
+ padding: 0 ${c.space["1"]}; border-radius: ${c.radius.lg}; font-family: ${c.font.sans};
10
+ font-size: ${c.text.lg}; color: ${c.fgPrimary};
11
+ -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
12
+
13
+ & .trialbanner-icon { display: inline-flex; flex-shrink: 0; color: ${c.fgMuted}; }
14
+ & .trialbanner-msg { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
15
+ & .trialbanner-action { display: inline-flex; align-items: center; gap: ${c.space["1"]}; height: 20px; flex-shrink: 0;
16
+ padding: 0 ${c.space["1.5"]}; margin: 0; border: none; border-radius: ${c.radius.sm}; background: ${c.bgSurface};
17
+ box-shadow: 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04);
18
+ font-family: inherit; font-size: ${c.text.md}; font-weight: ${c.weight.medium}; color: ${c.fgPrimary};
19
+ white-space: nowrap; cursor: pointer; transition: background-color .12s; }
20
+ & .trialbanner-action:hover { background: ${c.bgRaised}; }
21
+
22
+ &[data-tone="warning"] .trialbanner-icon { color: ${c.bgWarning}; }
23
+ &[data-tone="danger"] .trialbanner-icon { color: ${c.bgDanger}; }`,
24
+ variants: {},
25
+ defaultVariants: {},
26
+ compoundVariants: [],
27
+ });
28
+ export const trialbannerRecipe = resolveRecipe(config);
29
+ export default config;
@@ -0,0 +1,2 @@
1
+ export { ViewToggle, } from "./viewtoggle.js";
2
+ export { viewtoggleRecipe } from "./viewtoggle.recipe.js";
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { viewtoggleRecipe } from "./viewtoggle.recipe.js";
3
+ /**
4
+ * A compact icon toggle — measured from Attio's list/grid switch. A padded track
5
+ * of icon tiles; the selected tile is raised. Use for view-mode switches (list ⇄
6
+ * grid) or any small mutually-exclusive icon choice.
7
+ */
8
+ export function ViewToggle({ options, value, onChange, "aria-label": ariaLabel, className, }) {
9
+ return (_jsx("div", { className: viewtoggleRecipe({ className }), role: "group", "aria-label": ariaLabel, children: options.map((o) => (_jsx("button", { type: "button", className: "viewtoggle-tile", "aria-pressed": o.value === value, "aria-label": o.label, title: o.label, "data-active": o.value === value ? "" : undefined, onClick: () => onChange(o.value), children: o.icon }, o.value))) }));
10
+ }
11
+ ViewToggle.displayName = "ViewToggle";
@@ -0,0 +1,24 @@
1
+ import { defineRecipe, resolveRecipe } from "../../core/index.js";
2
+ import { contract as c } from "../../tokens/index.js";
3
+ // A compact icon toggle — measured from Attio's list/grid switch: a 28px track
4
+ // (radius 10, ~5% ink) padded 2px, holding 24px icon tiles (radius 8). The
5
+ // selected tile gets a raised surface with a soft shadow.
6
+ const config = defineRecipe({
7
+ name: "viewtoggle",
8
+ base: `display: inline-flex; align-items: center; gap: 2px; box-sizing: border-box; padding: 2px;
9
+ border-radius: ${c.radius.lg}; background: color-mix(in srgb, ${c.fgPrimary} 5%, transparent);
10
+ font-family: ${c.font.sans};
11
+
12
+ & .viewtoggle-tile { display: inline-flex; align-items: center; justify-content: center; width: 24px; height: 24px;
13
+ padding: 0; margin: 0; border: none; border-radius: ${c.radius.md}; background: none; color: ${c.fgMuted};
14
+ cursor: pointer; transition: background-color .12s, color .12s, box-shadow .12s; }
15
+ & .viewtoggle-tile:hover { color: ${c.fgPrimary}; }
16
+ & .viewtoggle-tile[data-active] { background: ${c.bgTileActive}; color: ${c.fgPrimary};
17
+ box-shadow: 0 1px 2px -1px ${c.shadowTileActive}; }
18
+ & .viewtoggle-tile:focus-visible { outline: 2px solid ${c.bgBrandSolid}; outline-offset: 1px; }`,
19
+ variants: {},
20
+ defaultVariants: {},
21
+ compoundVariants: [],
22
+ });
23
+ export const viewtoggleRecipe = resolveRecipe(config);
24
+ export default config;
@@ -0,0 +1,18 @@
1
+ import { font as fontScale, radius as radiusScale, size as sizeScale, space as spaceScale, text as textScale, weight as weightScale, } from "./scale.js";
2
+ import { semantic } from "./semantic.js";
3
+ const kebab = (s) => s.replace(/[A-Z]/g, (m) => `-${m.toLowerCase()}`);
4
+ const toVar = (key) => `var(--${kebab(key)})`;
5
+ // dots aren't valid in a CSS custom-property name → "2.5" becomes "2-5"
6
+ const scaleVar = (prefix, key) => `var(--${prefix}-${key.replace(/\./g, "-")})`;
7
+ const mapScale = (prefix, scale) => Object.fromEntries(Object.keys(scale).map((k) => [k, scaleVar(prefix, k)]));
8
+ const colors = Object.fromEntries(Object.keys(semantic).map((k) => [k, toVar(k)]));
9
+ // contract = color tokens (theme-flipping) + the dimensional scale
10
+ // (theme-invariant). Recipes read everything through this one import.
11
+ export const contract = Object.assign(colors, {
12
+ space: mapScale("space", spaceScale),
13
+ radius: mapScale("radius", radiusScale),
14
+ size: mapScale("size", sizeScale),
15
+ font: mapScale("font", fontScale),
16
+ text: mapScale("text", textScale),
17
+ weight: mapScale("weight", weightScale),
18
+ });
@@ -0,0 +1,4 @@
1
+ export { contract } from "./contract.js";
2
+ export { palette } from "./palette.js";
3
+ export { font, radius, size, space, text, weight, } from "./scale.js";
4
+ export { semantic } from "./semantic.js";
@@ -0,0 +1,30 @@
1
+ export const palette = {
2
+ gray00: { light: "#ffffff", dark: "#0a0a0a" },
3
+ white: { light: "#ffffff", dark: "#ffffff" },
4
+ gray50: { light: "#f4f4f5", dark: "#101112" },
5
+ gray900: { light: "#101112", dark: "#f5f5f5" },
6
+ line200: { light: "#e4e4e7", dark: "#212224" },
7
+ line100: { light: "#eeeff1", dark: "#1c1d1f" },
8
+ ringNeutral: { light: "transparent", dark: "#212224" },
9
+ tileActive: { light: "#ffffff", dark: "#101112" },
10
+ tileActiveShadow: { light: "rgba(0,0,0,0.04)", dark: "rgba(0,0,0,0)" },
11
+ overlayFrost: { light: "#ffffff", dark: "#1c1d1f" },
12
+ shadowOverlay1: { light: "rgba(28,40,64,0.12)", dark: "rgba(0,0,0,0.48)" },
13
+ shadowOverlay2: { light: "rgba(28,40,64,0.16)", dark: "rgba(0,0,0,0.64)" },
14
+ shadowOverlay3: { light: "rgba(28,40,64,0.16)", dark: "rgba(0,0,0,0)" },
15
+ popoverBg: { light: "#ffffff", dark: "#17181a" },
16
+ ringPopover: { light: "rgba(0,0,0,0)", dark: "#212224" },
17
+ shadowPopover1: { light: "rgba(28,40,64,0.04)", dark: "rgba(0,0,0,0.16)" },
18
+ shadowPopover2: { light: "rgba(28,40,64,0.12)", dark: "rgba(0,0,0,0.24)" },
19
+ shadowPopover3: { light: "rgba(24,41,75,0.16)", dark: "rgba(0,0,0,0.32)" },
20
+ gray400: { light: "#71717a", dark: "#9a9aa2" },
21
+ brand600: { light: "#266df0", dark: "#266df0" },
22
+ brand700: { light: "#1f5fd6", dark: "#1f5fd6" },
23
+ red600: { light: "#e5484d", dark: "#ff5a5f" },
24
+ green600: { light: "#1f9d57", dark: "#2ea968" },
25
+ amber600: { light: "#b5730f", dark: "#e0982a" },
26
+ orange600: { light: "#f97514", dark: "#f97514" },
27
+ cyan600: { light: "#00b9eb", dark: "#00b9eb" },
28
+ purple600: { light: "#9b69ff", dark: "#9b69ff" },
29
+ graySidebar: { light: "#fbfbfb", dark: "#0e0f10" },
30
+ };
@@ -0,0 +1,60 @@
1
+ // Dimensional scale — the single source of raw px for spacing, radius, and
2
+ // component sizing. Theme-invariant (identical in light/dark), so it is emitted
3
+ // once into :root, unlike the color tokens which flip per theme.
4
+ //
5
+ // Derived by measuring the live Attio app (not taste): its spacing is a
6
+ // 2px-granular / 4px-base scale — the values 1,2,4,6,8,10,12,16 account for
7
+ // nearly every gap/pad/margin in the sidebar. Radii cluster at 6/8/9 + a pill.
8
+ // Recipes MUST reference these through the contract (`c.space[...]`), never a
9
+ // literal px — this file is the only exception.
10
+ // Spacing: gaps, padding, margins. Keys follow the Tailwind step convention
11
+ // (0.5 = half a 4px step = 2px) so the numbers stay legible to consumers.
12
+ export const space = {
13
+ px: "1px", // hairline — the 1px gap between rows in a dense nav list
14
+ "0.5": "2px",
15
+ "1": "4px",
16
+ "1.5": "6px",
17
+ "2": "8px",
18
+ "2.5": "10px",
19
+ "3": "12px",
20
+ "4": "16px",
21
+ "5": "20px",
22
+ "6": "24px",
23
+ "8": "32px", // overlay / empty-state padding
24
+ };
25
+ // Corner radius. sm/md/lg are the three Attio uses on stacked surfaces
26
+ // (inputs, rows, tiles); full is the pill.
27
+ export const radius = {
28
+ sm: "6px", // chips, badges
29
+ md: "8px", // inputs, search box
30
+ lg: "9px", // rows, tiles, list items
31
+ xl: "12px", // overlay items (command rows)
32
+ "2xl": "16px", // overlay panels (command surface)
33
+ full: "999px", // pills
34
+ };
35
+ // Component sizing — recurring measured dimensions that are neither spacing nor
36
+ // radius (row height, header height, the nav icon box).
37
+ export const size = {
38
+ icon: "16px", // nav / control glyph box
39
+ row: "28px", // nav item · search · control height
40
+ tableRow: "36px", // data-grid row height
41
+ header: "48px", // workspace-switcher header height
42
+ };
43
+ // Typography — Attio's UI runs entirely on Inter. Sizes measured in the sidebar
44
+ // collapse onto 11/12/13/14/16 (lg = 14px is the default body/label size);
45
+ // weights are 400/500/600 with 500 the UI default.
46
+ export const font = {
47
+ sans: '"Inter", system-ui, -apple-system, "Segoe UI", sans-serif',
48
+ };
49
+ export const text = {
50
+ xs: "11px",
51
+ sm: "12px",
52
+ md: "13px",
53
+ lg: "14px", // default body / nav-label size
54
+ xl: "16px",
55
+ };
56
+ export const weight = {
57
+ regular: "400",
58
+ medium: "500", // default UI weight
59
+ semibold: "600",
60
+ };
@@ -0,0 +1,30 @@
1
+ export const semantic = {
2
+ bgBrandSolid: "brand600",
3
+ bgBrandSolidPressed: "brand700",
4
+ fgOnBrand: "white",
5
+ bgSurface: "gray00",
6
+ bgRaised: "gray50",
7
+ borderDefault: "line200",
8
+ borderSubtle: "line100",
9
+ ringNeutral: "ringNeutral",
10
+ bgTileActive: "tileActive",
11
+ shadowTileActive: "tileActiveShadow",
12
+ bgOverlayFrost: "overlayFrost",
13
+ shadowOverlay1: "shadowOverlay1",
14
+ shadowOverlay2: "shadowOverlay2",
15
+ shadowOverlay3: "shadowOverlay3",
16
+ bgPopover: "popoverBg",
17
+ ringPopover: "ringPopover",
18
+ shadowPopover1: "shadowPopover1",
19
+ shadowPopover2: "shadowPopover2",
20
+ shadowPopover3: "shadowPopover3",
21
+ fgPrimary: "gray900",
22
+ fgMuted: "gray400",
23
+ bgDanger: "red600",
24
+ bgSuccess: "green600",
25
+ bgWarning: "amber600",
26
+ bgOrange: "orange600",
27
+ bgCyan: "cyan600",
28
+ bgPurple: "purple600",
29
+ bgSidebar: "graySidebar",
30
+ };
package/dist/menu.css CHANGED
@@ -6,8 +6,8 @@
6
6
  & .menu-content {
7
7
  position: fixed; z-index: 60; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--space-px);
8
8
  min-width: 200px; max-height: 360px; overflow-y: auto; padding: var(--space-1);
9
- border-radius: var(--radius-xl); background: var(--bg-surface);
10
- box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg-primary) 5%, transparent), 0 8px 28px -6px rgba(28,40,64,0.16), 0 2px 6px -2px rgba(28,40,64,0.10);
9
+ border-radius: var(--radius-xl); background: var(--bg-popover);
10
+ box-shadow: inset 0 0 0 1px var(--ring-popover), 0 0 0 1px var(--shadow-popover1), 0 4px 8px -4px var(--shadow-popover2), 0 4px 12px -2px var(--shadow-popover3);
11
11
  transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease;
12
12
  }
13
13
  & .menu-content[data-align="end"] { transform-origin: top right; }
@@ -6,7 +6,7 @@
6
6
  & .multiselect-trigger {
7
7
  box-sizing: border-box; display: flex; align-items: center; gap: var(--space-1); width: 100%; min-width: 0; min-height: 32px;
8
8
  margin: 0; padding: var(--space-0-5) var(--space-1-5) var(--space-0-5) var(--space-2);
9
- border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04);
9
+ border: none; border-radius: var(--radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg-primary) 7%, transparent);
10
10
  font-family: inherit; font-size: var(--text-lg); color: var(--fg-primary); cursor: pointer; text-align: left;
11
11
  transition: background-color .12s ease, box-shadow .12s ease;
12
12
  }
@@ -21,8 +21,8 @@
21
21
  & .multiselect-listbox {
22
22
  position: fixed; z-index: 60; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--space-px);
23
23
  max-height: 300px; overflow-y: auto; padding: var(--space-1);
24
- border-radius: var(--radius-xl); background: var(--bg-surface);
25
- box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg-primary) 5%, transparent), 0 8px 28px -6px rgba(28,40,64,0.16), 0 2px 6px -2px rgba(28,40,64,0.10);
24
+ border-radius: var(--radius-xl); background: var(--bg-popover);
25
+ box-shadow: inset 0 0 0 1px var(--ring-popover), 0 0 0 1px var(--shadow-popover1), 0 4px 8px -4px var(--shadow-popover2), 0 4px 12px -2px var(--shadow-popover3);
26
26
  transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease;
27
27
  }
28
28
  & .multiselect-listbox[data-up] { transform-origin: bottom left; }
package/dist/popover.css CHANGED
@@ -1,6 +1,6 @@
1
1
  .popover {
2
2
  display: contents; font-family: var(--font-sans);
3
- & .popover-content { position: fixed; z-index: 60; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: var(--space-1); border-radius: var(--radius-xl); background: var(--bg-raised); color: var(--fg-primary); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg-primary) 5%, transparent), 0 8px 28px -6px rgba(28,40,64,0.16), 0 2px 6px -2px rgba(28,40,64,0.10); opacity: 1; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
3
+ & .popover-content { position: fixed; z-index: 60; box-sizing: border-box; min-width: 200px; max-width: min(360px, 92vw); padding: var(--space-1); border-radius: var(--radius-xl); background: var(--bg-popover); color: var(--fg-primary); box-shadow: inset 0 0 0 1px var(--ring-popover), 0 0 0 1px var(--shadow-popover1), 0 4px 8px -4px var(--shadow-popover2), 0 4px 12px -2px var(--shadow-popover3); opacity: 1; transform: none; transition: opacity 0.08s ease, transform 0.08s ease; transform-origin: top left; @starting-style { opacity: 0; transform: scale(0.97) translateY(-1px); } }
4
4
  & .popover-content[data-align="end"] { transform-origin: top right; }
5
5
  & .popover-content[data-up] { transform-origin: bottom left; }
6
6
  }
@@ -12,7 +12,7 @@
12
12
  & .recordpage-crumb-sep { color: var(--fg-muted); font-size: var(--text-lg); }
13
13
  & .recordpage-crumb-name { font-size: var(--text-lg); font-weight: var(--weight-medium); color: var(--fg-primary); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
14
14
  & .recordpage-actions { margin-left: auto; display: flex; align-items: center; gap: var(--space-1); }
15
- & .recordpage-action { display: inline-flex; align-items: center; gap: var(--space-1-5); height: 28px; padding: 0 var(--space-2) 0 var(--space-1-5); margin: 0; border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--text-lg); font-weight: var(--weight-medium); color: var(--fg-primary); cursor: pointer; white-space: nowrap; }
15
+ & .recordpage-action { display: inline-flex; align-items: center; gap: var(--space-1-5); height: 28px; padding: 0 var(--space-2) 0 var(--space-1-5); margin: 0; border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: inset 0 0 0 1px var(--ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--text-lg); font-weight: var(--weight-medium); color: var(--fg-primary); cursor: pointer; white-space: nowrap; }
16
16
  & .recordpage-action:hover { background: var(--bg-raised); }
17
17
  & .recordpage-action--ghost { box-shadow: none; color: var(--fg-muted); }
18
18
  & .recordpage-action--icon { width: 28px; padding: 0; justify-content: center; box-shadow: none; color: var(--fg-muted); }
@@ -33,10 +33,10 @@
33
33
  & .recordpage-entity-iconbtn:hover { background: var(--bg-raised); color: var(--fg-primary); }
34
34
  & .recordpage-entity-iconbtn[data-active] svg { color: #f5b83d; fill: #f5b83d; }
35
35
  & .recordpage-quickactions { display: flex; align-items: center; gap: var(--space-2); padding: 0 var(--space-1) var(--space-3); }
36
- & .recordpage-compose { display: inline-flex; align-items: center; gap: var(--space-1-5); height: 28px; padding: 0 var(--space-4) 0 var(--space-3); margin: 0; border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--text-lg); font-weight: var(--weight-medium); color: var(--fg-primary); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
36
+ & .recordpage-compose { display: inline-flex; align-items: center; gap: var(--space-1-5); height: 28px; padding: 0 var(--space-4) 0 var(--space-3); margin: 0; border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: inset 0 0 0 1px var(--ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--text-lg); font-weight: var(--weight-medium); color: var(--fg-primary); white-space: nowrap; cursor: pointer; transition: background-color .12s; }
37
37
  & .recordpage-compose:hover { background: var(--bg-raised); }
38
38
  & .recordpage-compose svg { flex-shrink: 0; color: var(--fg-muted); }
39
- & .recordpage-quickbtn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; margin: 0; border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--fg-muted); cursor: pointer; transition: background-color .12s, color .12s; }
39
+ & .recordpage-quickbtn { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; margin: 0; border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: inset 0 0 0 1px var(--ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--fg-muted); cursor: pointer; transition: background-color .12s, color .12s; }
40
40
  & .recordpage-quickbtn:hover { background: var(--bg-raised); color: var(--fg-primary); }
41
41
  & .recordpage-section { padding-top: var(--space-2); }
42
42
  & .recordpage-section-title { font-size: var(--text-sm); font-weight: var(--weight-medium); letter-spacing: -0.12px; color: color-mix(in srgb, var(--fg-primary) 63%, transparent); padding: var(--space-1); }
@@ -100,7 +100,7 @@
100
100
  & .recordpage-section-head .recordpage-section-title { padding: 0; }
101
101
  & .recordpage-section-count { display: inline-flex; align-items: center; justify-content: center; min-width: 16px; height: 16px; padding: 0 var(--space-1); border-radius: var(--radius-sm); background: color-mix(in srgb, var(--fg-primary) 6%, transparent); font-size: var(--text-xs); font-weight: var(--weight-medium); color: var(--fg-muted); }
102
102
  & .recordpage-section-spacer { flex: 1; }
103
- & .recordpage-addbtn { display: inline-flex; align-items: center; gap: var(--space-1); height: 26px; padding: 0 var(--space-1-5); margin: 0; border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--fg-primary); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); cursor: pointer; }
103
+ & .recordpage-addbtn { display: inline-flex; align-items: center; gap: var(--space-1); height: 26px; padding: 0 var(--space-1-5); margin: 0; border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: inset 0 0 0 1px var(--ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--fg-primary); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); cursor: pointer; }
104
104
  & .recordpage-addbtn:hover { background: var(--bg-raised); }
105
105
  & .recordpage-addbtn svg { flex-shrink: 0; }
106
106
 
@@ -108,7 +108,7 @@
108
108
  & .recordpage-composer textarea { width: 100%; min-height: 56px; resize: vertical; border: none; outline: none; background: none; font-family: inherit; font-size: var(--text-lg); color: var(--fg-primary); }
109
109
  & .recordpage-composer textarea::placeholder { color: var(--fg-muted); }
110
110
  & .recordpage-composer-actions { display: flex; justify-content: flex-end; align-items: center; gap: var(--space-1-5); }
111
- & .recordpage-btn { display: inline-flex; align-items: center; height: 28px; padding: 0 var(--space-2-5); margin: 0; border: none; border-radius: var(--radius-md); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); cursor: pointer; box-shadow: 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); background: var(--bg-surface); color: var(--fg-primary); }
111
+ & .recordpage-btn { display: inline-flex; align-items: center; height: 28px; padding: 0 var(--space-2-5); margin: 0; border: none; border-radius: var(--radius-md); font-family: inherit; font-size: var(--text-md); font-weight: var(--weight-medium); cursor: pointer; box-shadow: inset 0 0 0 1px var(--ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); background: var(--bg-surface); color: var(--fg-primary); }
112
112
  & .recordpage-btn:hover { background: var(--bg-raised); }
113
113
  & .recordpage-btn--primary { box-shadow: none; background: var(--bg-brand-solid); color: var(--fg-on-brand); }
114
114
  & .recordpage-btn--primary:disabled { opacity: 0.5; cursor: not-allowed; }
@@ -16,7 +16,7 @@
16
16
  & .recordstable-tool--ghost { box-shadow: none; background: color-mix(in srgb, var(--fg-primary) 3%, transparent); color: var(--fg-muted); }
17
17
  & .recordstable-tool--ghost:hover { background: color-mix(in srgb, var(--fg-primary) 6%, transparent); }
18
18
  & .recordstable-toolgroup { position: relative; display: inline-flex; }
19
- & .recordstable-menu { position: absolute; top: calc(100% + var(--space-1)); left: 0; z-index: 30; min-width: 232px; padding: var(--space-1); border-radius: var(--radius-lg); background: var(--bg-surface); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg-primary) 5%, transparent), 0 8px 28px -6px rgba(28,40,64,0.16), 0 2px 6px -2px rgba(28,40,64,0.10); display: flex; flex-direction: column; gap: var(--space-px); transform-origin: top; opacity: 1; transform: none; transition: opacity .13s ease, transform .13s ease; }
19
+ & .recordstable-menu { position: absolute; top: calc(100% + var(--space-1)); left: 0; z-index: 30; min-width: 232px; padding: var(--space-1); border-radius: var(--radius-lg); background: var(--bg-popover); box-shadow: inset 0 0 0 1px var(--ring-popover), 0 0 0 1px var(--shadow-popover1), 0 4px 8px -4px var(--shadow-popover2), 0 4px 12px -2px var(--shadow-popover3); display: flex; flex-direction: column; gap: var(--space-px); transform-origin: top; opacity: 1; transform: none; transition: opacity .13s ease, transform .13s ease; }
20
20
  & .recordstable-menu { @starting-style { opacity: 0; transform: scale(0.96); } }
21
21
  & .recordstable-ctx { z-index: 60; }
22
22
  & .recordstable-th[data-drop] { box-shadow: inset 2px 0 0 var(--bg-brand-solid); }
@@ -36,7 +36,7 @@
36
36
  & .recordstable-sort-remove { display: inline-flex; align-items: center; justify-content: center; width: 28px; height: 28px; flex-shrink: 0; padding: 0; margin: 0; border: none; border-radius: var(--radius-md); background: none; color: var(--fg-muted); cursor: pointer; transition: background-color .12s, color .12s; }
37
37
  & .recordstable-sort-remove:hover { background: var(--bg-raised); color: var(--fg-primary); }
38
38
  & .recordstable-sort-addrow { display: flex; padding: var(--space-0-5) 0; }
39
- & .recordstable-sort-add { display: inline-flex; align-items: center; gap: var(--space-1-5); height: 28px; padding: 0 var(--space-2) 0 var(--space-1-5); margin: 0; border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--text-lg); font-weight: var(--weight-regular); color: var(--fg-primary); cursor: pointer; transition: background-color .12s; }
39
+ & .recordstable-sort-add { display: inline-flex; align-items: center; gap: var(--space-1-5); height: 28px; padding: 0 var(--space-2) 0 var(--space-1-5); margin: 0; border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: inset 0 0 0 1px var(--ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); font-family: inherit; font-size: var(--text-lg); font-weight: var(--weight-regular); color: var(--fg-primary); cursor: pointer; transition: background-color .12s; }
40
40
  & .recordstable-sort-add:hover { background: var(--bg-raised); }
41
41
  & .recordstable-sort-add svg { flex-shrink: 0; color: var(--fg-muted); }
42
42
  & .recordstable-sort-foot { display: flex; padding: var(--space-1-5) var(--space-1) var(--space-0-5); }
@@ -96,8 +96,8 @@
96
96
  & .recordstable-resize:hover::after, & .recordstable-resize[data-resizing]::after { opacity: 1; }
97
97
 
98
98
  /* add-column header */
99
- & .recordstable-addcol { width: 44px; min-width: 44px; }
100
- & .recordstable-addcol button { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; border: none; background: none; color: var(--fg-muted); cursor: pointer; }
99
+ & .recordstable-addcol { min-width: 44px; }
100
+ & .recordstable-addcol button { display: flex; align-items: center; justify-content: center; width: 44px; height: 100%; border: none; background: none; color: var(--fg-muted); cursor: pointer; }
101
101
  & .recordstable-addcol button:hover { background: var(--bg-raised); color: var(--fg-primary); }
102
102
 
103
103
  /* cells */
package/dist/select.css CHANGED
@@ -1,12 +1,12 @@
1
1
  .select {
2
2
 
3
- position: relative; display: inline-flex; width: 100%; font-family: var(--font-sans);
3
+ position: relative; display: inline-flex; font-family: var(--font-sans);
4
4
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
5
5
 
6
6
  & .select-trigger {
7
7
  box-sizing: border-box; display: inline-flex; align-items: center; gap: var(--space-1-5);
8
8
  height: 32px; width: 100%; min-width: 0; margin: 0; padding: 0 var(--space-1-5) 0 var(--space-2);
9
- border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04);
9
+ border: none; border-radius: var(--radius-md); background: transparent; box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg-primary) 7%, transparent);
10
10
  font-family: inherit; font-size: var(--text-lg); color: var(--fg-primary); cursor: pointer;
11
11
  transition: background-color .12s ease, box-shadow .12s ease;
12
12
  }
@@ -21,8 +21,8 @@
21
21
  & .select-listbox {
22
22
  position: fixed; z-index: 60; box-sizing: border-box; display: flex; flex-direction: column; gap: var(--space-px);
23
23
  max-height: 280px; overflow-y: auto; padding: var(--space-1);
24
- border-radius: var(--radius-xl); background: var(--bg-surface);
25
- box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg-primary) 5%, transparent), 0 8px 28px -6px rgba(28,40,64,0.16), 0 2px 6px -2px rgba(28,40,64,0.10);
24
+ border-radius: var(--radius-xl); background: var(--bg-popover);
25
+ box-shadow: inset 0 0 0 1px var(--ring-popover), 0 0 0 1px var(--shadow-popover1), 0 4px 8px -4px var(--shadow-popover2), 0 4px 12px -2px var(--shadow-popover3);
26
26
  transform-origin: top left; opacity: 1; transform: none; transition: opacity .08s ease, transform .08s ease;
27
27
  }
28
28
  & .select-listbox[data-up] { transform-origin: bottom; }
@@ -54,3 +54,9 @@
54
54
  & .select-trigger[data-open], & .select-trigger:focus-visible { background: transparent; box-shadow: inset 0 0 0 1px var(--bg-brand-solid); }
55
55
 
56
56
  }
57
+ .select--width_full {
58
+ width: 100%;
59
+ }
60
+ .select--width_auto {
61
+ width: auto;
62
+ }
package/dist/select.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { RecipeFn } from "../core/types";
2
2
 
3
3
  export interface SelectVariants {
4
4
  variant?: "default" | "ghost";
5
+ width?: "full" | "auto";
5
6
  }
6
7
 
7
- export declare const selectRecipe: RecipeFn<{ variant: { default: string; ghost: string } }>;
8
+ export declare const selectRecipe: RecipeFn<{ variant: { default: string; ghost: string }; width: { full: string; auto: string } }>;
package/dist/sidebar.css CHANGED
@@ -1,3 +1,3 @@
1
1
  .sidebar {
2
- box-sizing: border-box; display: flex; flex-direction: column; width: 275px; height: 100%; background: var(--bg-sidebar); border-right: 1px solid var(--border-subtle); padding: var(--space-2); font-family: var(--font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-y: auto; & .sidebar-section { display: flex; flex-direction: column; gap: var(--space-px); margin-top: var(--space-2); } & .sidebar-section[data-collapsed] { display: none; } & .sidebar-label { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--fg-muted); padding: var(--space-1-5) var(--space-2) var(--space-0-5); } & .sidebar-section-header { display: flex; align-items: center; gap: var(--space-1); width: 100%; margin: 0; border: none; background: none; padding: var(--space-1-5) var(--space-2) var(--space-0-5); font-family: var(--font-sans); font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--fg-muted); cursor: pointer; } & .sidebar-section-header svg { flex-shrink: 0; transition: transform .15s ease; } & .sidebar-section-header[data-collapsed] svg { transform: rotate(-90deg); } & .sidebar-ws { display: flex; align-items: center; gap: var(--space-2); height: var(--size-header); padding: 0 var(--space-2); border-radius: var(--radius-lg); cursor: pointer; transition: background-color 0.16s; } & .sidebar-ws:hover { background: color-mix(in srgb, var(--fg-primary) 5%, transparent); } & .sidebar-ws-name { font-size: var(--text-lg); font-weight: var(--weight-semibold); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } & .sidebar-ws-collapse { margin-left: auto; } & .sidebar-searchrow { display: flex; align-items: center; gap: var(--space-1-5); margin-top: var(--space-2-5); padding-right: var(--space-2); } & .sidebar-footer { margin-top: auto; display: flex; flex-direction: column; gap: var(--space-0-5); } & .sidebar-trial { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: var(--space-1-5) var(--space-2); font-size: var(--text-sm); color: var(--fg-muted); } & .sidebar-search { box-sizing: border-box; flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--space-2); height: var(--size-row); margin: 0; padding: 0 var(--space-1) 0 var(--space-2); border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--fg-muted); font-family: inherit; font-size: var(--text-lg); text-align: left; cursor: pointer; transition: background-color 0.14s; } & .sidebar-search:hover { background: var(--bg-raised); } & .sidebar-search-label { flex: 1; color: var(--fg-primary); font-weight: var(--weight-medium); } & .sidebar-search-kbd { margin-left: auto; display: inline-flex; align-items: center; height: 18px; padding: 0 var(--space-1); border-radius: var(--radius-sm); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg-primary) 8%, transparent); color: color-mix(in srgb, var(--fg-primary) 50%, transparent); font-size: var(--text-xs); } & .sidebar-pill { border-radius: var(--radius-full); align-self: center; width: auto; height: 32px; padding-inline: var(--space-4); } & .sidebar-divider { height: 0; border: none; border-top: 1px solid var(--border-subtle); margin: var(--space-2) calc(-1 * var(--space-2)) 0; } & .sidebar-newlist { box-sizing: border-box; display: flex; align-items: center; justify-content: center; width: 100%; height: var(--size-row); border-radius: var(--radius-md); border: 1px dashed var(--border-default); background: transparent; color: var(--fg-muted); font-family: var(--font-sans); font-size: var(--text-md); font-weight: var(--weight-medium); cursor: pointer; } & .sidebar-newlist:hover { background: var(--bg-raised); color: var(--fg-primary); }
2
+ box-sizing: border-box; display: flex; flex-direction: column; width: 275px; height: 100%; background: var(--bg-sidebar); border-right: 1px solid var(--border-subtle); padding: var(--space-2); font-family: var(--font-sans); -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; overflow-y: auto; & .sidebar-section { display: flex; flex-direction: column; gap: var(--space-px); margin-top: var(--space-2); } & .sidebar-section[data-collapsed] { display: none; } & .sidebar-label { font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--fg-muted); padding: var(--space-1-5) var(--space-2) var(--space-0-5); } & .sidebar-section-header { display: flex; align-items: center; gap: var(--space-1); width: 100%; margin: 0; border: none; background: none; padding: var(--space-1-5) var(--space-2) var(--space-0-5); font-family: var(--font-sans); font-size: var(--text-sm); font-weight: var(--weight-medium); color: var(--fg-muted); cursor: pointer; } & .sidebar-section-header svg { flex-shrink: 0; transition: transform .15s ease; } & .sidebar-section-header[data-collapsed] svg { transform: rotate(-90deg); } & .sidebar-ws { display: flex; align-items: center; gap: var(--space-2); height: var(--size-header); padding: 0 var(--space-2); border-radius: var(--radius-lg); cursor: pointer; transition: background-color 0.16s; } & .sidebar-ws:hover { background: color-mix(in srgb, var(--fg-primary) 5%, transparent); } & .sidebar-ws-name { font-size: var(--text-lg); font-weight: var(--weight-semibold); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } & .sidebar-ws-collapse { margin-left: auto; } & .sidebar-searchrow { display: flex; align-items: center; gap: var(--space-1-5); margin-top: var(--space-2-5); padding-right: var(--space-2); } & .sidebar-footer { margin-top: auto; display: flex; flex-direction: column; gap: var(--space-0-5); } & .sidebar-trial { display: flex; align-items: center; justify-content: space-between; gap: var(--space-2); padding: var(--space-1-5) var(--space-2); font-size: var(--text-sm); color: var(--fg-muted); } & .sidebar-search { box-sizing: border-box; flex: 1; min-width: 0; display: flex; align-items: center; gap: var(--space-2); height: var(--size-row); margin: 0; padding: 0 var(--space-1) 0 var(--space-2); border: none; border-radius: var(--radius-md); background: var(--bg-surface); box-shadow: inset 0 0 0 1px var(--ring-neutral), 0 0 2px rgba(28,40,64,0.18), 0 1px 3px rgba(0,0,0,0.04); color: var(--fg-muted); font-family: inherit; font-size: var(--text-lg); text-align: left; cursor: pointer; transition: background-color 0.14s; } & .sidebar-search:hover { background: var(--bg-raised); } & .sidebar-search-label { flex: 1; color: var(--fg-primary); font-weight: var(--weight-medium); } & .sidebar-search-kbd { margin-left: auto; display: inline-flex; align-items: center; height: 18px; padding: 0 var(--space-1); border-radius: var(--radius-sm); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--fg-primary) 8%, transparent); color: color-mix(in srgb, var(--fg-primary) 50%, transparent); font-size: var(--text-xs); } & .sidebar-pill { border-radius: var(--radius-full); align-self: center; width: auto; height: 32px; padding-inline: var(--space-4); } & .sidebar-divider { height: 0; border: none; border-top: 1px solid var(--border-subtle); margin: var(--space-2) calc(-1 * var(--space-2)) 0; } & .sidebar-newlist { box-sizing: border-box; display: flex; align-items: center; justify-content: center; width: 100%; height: var(--size-row); border-radius: var(--radius-md); border: 1px dashed var(--border-default); background: transparent; color: var(--fg-muted); font-family: var(--font-sans); font-size: var(--text-md); font-weight: var(--weight-medium); cursor: pointer; } & .sidebar-newlist:hover { background: var(--bg-raised); color: var(--fg-primary); }
3
3
  }
package/dist/statcard.css CHANGED
@@ -11,3 +11,9 @@
11
11
  & .statcard-delta[data-trend="down"] { background: color-mix(in srgb, var(--bg-danger) 15%, transparent); color: color-mix(in srgb, var(--bg-danger) 80%, var(--fg-primary)); }
12
12
  & .statcard-delta[data-trend="flat"] { background: color-mix(in srgb, var(--fg-primary) 6%, transparent); color: var(--fg-muted); }
13
13
  }
14
+ .statcard--card_true {
15
+ padding: var(--space-4); border-radius: var(--radius-xl); background: var(--bg-surface); box-shadow: inset 0 0 0 1px var(--border-subtle);
16
+ }
17
+ .statcard--card_false {
18
+
19
+ }
@@ -1,7 +1,7 @@
1
1
  import type { RecipeFn } from "../core/types";
2
2
 
3
3
  export interface StatcardVariants {
4
-
4
+ card?: boolean;
5
5
  }
6
6
 
7
- export declare const statcardRecipe: RecipeFn<{ }>;
7
+ export declare const statcardRecipe: RecipeFn<{ card: { true: string; false: string } }>;