@skewedaspect/sleekspace-ui 0.7.1 → 0.8.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 (243) hide show
  1. package/dist/sleekspace-ui.css +984 -291
  2. package/dist/sleekspace-ui.es.js +31559 -29868
  3. package/dist/sleekspace-ui.umd.js +32210 -30438
  4. package/dist/{components → src/components}/Accordion/SkAccordion.vue.d.ts +1 -1
  5. package/dist/{components → src/components}/Accordion/types.d.ts +1 -1
  6. package/dist/{components → src/components}/Alert/SkAlert.vue.d.ts +1 -1
  7. package/dist/{components → src/components}/Alert/types.d.ts +1 -1
  8. package/dist/{components → src/components}/Avatar/SkAvatar.vue.d.ts +1 -1
  9. package/dist/{components → src/components}/Avatar/types.d.ts +1 -1
  10. package/dist/{components → src/components}/Breadcrumbs/SkBreadcrumbs.vue.d.ts +2 -2
  11. package/dist/{components → src/components}/Breadcrumbs/types.d.ts +1 -1
  12. package/dist/{components → src/components}/Button/SkButton.vue.d.ts +9 -1
  13. package/dist/{components → src/components}/Button/types.d.ts +1 -1
  14. package/dist/{components → src/components}/Card/SkCard.vue.d.ts +1 -1
  15. package/dist/src/components/Card/types.d.ts +2 -0
  16. package/dist/{components → src/components}/Checkbox/SkCheckbox.vue.d.ts +1 -1
  17. package/dist/{components → src/components}/Checkbox/types.d.ts +1 -1
  18. package/dist/{components → src/components}/Collapsible/SkCollapsible.vue.d.ts +1 -1
  19. package/dist/src/components/Collapsible/types.d.ts +2 -0
  20. package/dist/{components → src/components}/ColorPicker/SkColorPicker.vue.d.ts +1 -1
  21. package/dist/{components → src/components}/ColorPicker/types.d.ts +1 -1
  22. package/dist/{components → src/components}/ContextMenu/SkContextMenu.vue.d.ts +1 -1
  23. package/dist/src/components/ContextMenu/types.d.ts +2 -0
  24. package/dist/{components → src/components}/Divider/SkDivider.vue.d.ts +1 -1
  25. package/dist/{components → src/components}/Dropdown/SkDropdown.vue.d.ts +1 -1
  26. package/dist/{components → src/components}/Dropdown/types.d.ts +1 -1
  27. package/dist/{components → src/components}/Input/SkInput.vue.d.ts +1 -1
  28. package/dist/{components → src/components}/Input/types.d.ts +1 -1
  29. package/dist/{components → src/components}/Listbox/SkListbox.vue.d.ts +1 -1
  30. package/dist/{components → src/components}/Listbox/types.d.ts +1 -1
  31. package/dist/{components → src/components}/Modal/SkModal.vue.d.ts +1 -1
  32. package/dist/{components → src/components}/Modal/types.d.ts +1 -1
  33. package/dist/{components → src/components}/NavBar/SkNavBar.vue.d.ts +2 -1
  34. package/dist/src/components/NavBar/context.d.ts +3 -0
  35. package/dist/{components → src/components}/NavBar/types.d.ts +1 -1
  36. package/dist/{components → src/components}/NumberInput/SkNumberInput.vue.d.ts +1 -1
  37. package/dist/{components → src/components}/NumberInput/types.d.ts +1 -1
  38. package/dist/src/components/Page/SkPage.vue.d.ts +161 -0
  39. package/dist/src/components/Page/SkPageSidebarToggle.vue.d.ts +41 -0
  40. package/dist/src/components/Page/index.d.ts +3 -0
  41. package/dist/src/components/Page/types.d.ts +39 -0
  42. package/dist/{components → src/components}/Pagination/SkPagination.vue.d.ts +3 -3
  43. package/dist/{components → src/components}/Pagination/types.d.ts +1 -1
  44. package/dist/{components → src/components}/Panel/SkPanel.vue.d.ts +1 -1
  45. package/dist/{components → src/components}/Panel/types.d.ts +1 -1
  46. package/dist/{components → src/components}/Popover/SkPopover.vue.d.ts +1 -1
  47. package/dist/{components → src/components}/Progress/SkProgress.vue.d.ts +1 -1
  48. package/dist/{components → src/components}/Progress/types.d.ts +1 -1
  49. package/dist/{components → src/components}/Radio/SkRadio.vue.d.ts +1 -1
  50. package/dist/{components → src/components}/Radio/types.d.ts +1 -1
  51. package/dist/{components → src/components}/ScrollArea/SkScrollArea.vue.d.ts +9 -0
  52. package/dist/{components → src/components}/ScrollArea/types.d.ts +1 -1
  53. package/dist/{components → src/components}/Select/SkSelect.vue.d.ts +1 -1
  54. package/dist/{components → src/components}/Select/SkSelectItem.vue.d.ts +6 -18
  55. package/dist/{components → src/components}/Select/types.d.ts +1 -1
  56. package/dist/{components → src/components}/Sidebar/SkSidebar.vue.d.ts +10 -2
  57. package/dist/{components → src/components}/Sidebar/types.d.ts +1 -1
  58. package/dist/{components → src/components}/Slider/SkSlider.vue.d.ts +1 -1
  59. package/dist/{components → src/components}/Slider/types.d.ts +1 -1
  60. package/dist/{components → src/components}/Spinner/SkSpinner.vue.d.ts +1 -1
  61. package/dist/{components → src/components}/Spinner/types.d.ts +1 -1
  62. package/dist/{components → src/components}/Splitter/types.d.ts +1 -1
  63. package/dist/{components → src/components}/Switch/SkSwitch.vue.d.ts +1 -1
  64. package/dist/{components → src/components}/Switch/types.d.ts +1 -1
  65. package/dist/{components → src/components}/Table/SkTable.vue.d.ts +1 -1
  66. package/dist/{components → src/components}/Table/types.d.ts +1 -1
  67. package/dist/{components → src/components}/Tabs/SkTab.vue.d.ts +1 -1
  68. package/dist/{components → src/components}/Tabs/SkTabs.vue.d.ts +2 -2
  69. package/dist/{components → src/components}/Tag/SkTag.vue.d.ts +1 -1
  70. package/dist/{components → src/components}/TagsInput/SkTagsInput.vue.d.ts +1 -1
  71. package/dist/{components → src/components}/TagsInput/types.d.ts +1 -1
  72. package/dist/{components → src/components}/Textarea/SkTextarea.vue.d.ts +1 -1
  73. package/dist/{components → src/components}/Textarea/types.d.ts +1 -1
  74. package/dist/{components → src/components}/Toolbar/types.d.ts +1 -1
  75. package/dist/{components → src/components}/Tooltip/SkTooltip.vue.d.ts +1 -1
  76. package/dist/{components → src/components}/Tooltip/types.d.ts +1 -1
  77. package/dist/{components → src/components}/TreeView/SkTreeView.vue.d.ts +5 -5
  78. package/dist/{components → src/components}/TreeView/types.d.ts +1 -1
  79. package/dist/src/composables/useFocusTrap.d.ts +17 -0
  80. package/dist/src/composables/usePageDrawer.d.ts +35 -0
  81. package/dist/src/composables/usePortalContext.test.d.ts +1 -0
  82. package/dist/{index.d.ts → src/index.d.ts} +2 -0
  83. package/dist/src/styles/mixins/fluidSize.test.d.ts +1 -0
  84. package/dist/tokens.css +60 -0
  85. package/llms-full.txt +6349 -0
  86. package/llms.txt +46 -0
  87. package/package.json +16 -11
  88. package/src/components/Button/SkButton.vue +25 -13
  89. package/src/components/NavBar/SkNavBar.vue +12 -1
  90. package/src/components/NavBar/context.ts +16 -0
  91. package/src/components/Page/SkPage.vue +460 -72
  92. package/src/components/Page/SkPageSidebarToggle.vue +148 -0
  93. package/src/components/Page/index.ts +1 -0
  94. package/src/components/Page/types.ts +30 -5
  95. package/src/components/ScrollArea/SkScrollArea.vue +12 -0
  96. package/src/components/Select/SkSelectItem.vue +2 -2
  97. package/src/components/Sidebar/SkSidebar.vue +10 -0
  98. package/src/components/TreeView/SkTreeView.vue +6 -6
  99. package/src/composables/useFocusTrap.test.ts +184 -0
  100. package/src/composables/useFocusTrap.ts +141 -0
  101. package/src/composables/usePageDrawer.ts +96 -0
  102. package/src/global.d.ts +1 -0
  103. package/src/index.ts +5 -0
  104. package/src/styles/components/_accordion.scss +15 -0
  105. package/src/styles/components/_alert.scss +1 -0
  106. package/src/styles/components/_avatar.scss +1 -0
  107. package/src/styles/components/_breadcrumbs.scss +7 -0
  108. package/src/styles/components/_button.scss +291 -214
  109. package/src/styles/components/_checkbox.scss +9 -1
  110. package/src/styles/components/_collapsible.scss +15 -0
  111. package/src/styles/components/_color-picker.scss +4 -1
  112. package/src/styles/components/_input.scss +1 -0
  113. package/src/styles/components/_listbox.scss +8 -2
  114. package/src/styles/components/_menu.scss +9 -2
  115. package/src/styles/components/_modal.scss +18 -2
  116. package/src/styles/components/_navbar.scss +22 -6
  117. package/src/styles/components/_number-input.scss +1 -0
  118. package/src/styles/components/_page.scss +220 -12
  119. package/src/styles/components/_pagination.scss +10 -1
  120. package/src/styles/components/_panel.scss +8 -3
  121. package/src/styles/components/_popover.scss +15 -2
  122. package/src/styles/components/_progress.scss +14 -0
  123. package/src/styles/components/_radio.scss +8 -1
  124. package/src/styles/components/_scroll-area.scss +56 -0
  125. package/src/styles/components/_select.scss +3 -1
  126. package/src/styles/components/_sidebar.scss +78 -38
  127. package/src/styles/components/_skeleton.scss +18 -0
  128. package/src/styles/components/_slider.scss +1 -0
  129. package/src/styles/components/_spinner.scss +15 -0
  130. package/src/styles/components/_switch.scss +5 -0
  131. package/src/styles/components/_table.scss +1 -0
  132. package/src/styles/components/_tabs.scss +6 -0
  133. package/src/styles/components/_tag.scss +2 -0
  134. package/src/styles/components/_tags-input.scss +1 -0
  135. package/src/styles/components/_textarea.scss +1 -0
  136. package/src/styles/components/_toast.scss +16 -1
  137. package/src/styles/components/_toolbar.scss +2 -0
  138. package/src/styles/components/_tooltip.scss +14 -1
  139. package/src/styles/components/_tree-view.scss +6 -1
  140. package/src/styles/mixins/_index.scss +1 -0
  141. package/src/styles/mixins/_responsive.scss +184 -0
  142. package/src/styles/mixins/fluidSize.test.ts +149 -0
  143. package/src/styles/tokens/_foundation-breakpoints.scss +26 -0
  144. package/src/styles/tokens/_foundation-z-index.scss +38 -0
  145. package/src/styles/tokens/index.scss +2 -0
  146. package/web-types.json +194 -14
  147. package/dist/components/Card/types.d.ts +0 -2
  148. package/dist/components/Collapsible/types.d.ts +0 -2
  149. package/dist/components/ContextMenu/types.d.ts +0 -2
  150. package/dist/components/Page/SkPage.vue.d.ts +0 -64
  151. package/dist/components/Page/index.d.ts +0 -2
  152. package/dist/components/Page/types.d.ts +0 -16
  153. package/dist/{components → src/components}/Accordion/SkAccordionItem.vue.d.ts +0 -0
  154. package/dist/{components → src/components}/Accordion/index.d.ts +0 -0
  155. package/dist/{components → src/components}/Avatar/index.d.ts +0 -0
  156. package/dist/{components → src/components}/Breadcrumbs/SkBreadcrumbItem.vue.d.ts +0 -0
  157. package/dist/{components → src/components}/Breadcrumbs/SkBreadcrumbSeparator.vue.d.ts +0 -0
  158. package/dist/{components → src/components}/Breadcrumbs/index.d.ts +0 -0
  159. package/dist/{components → src/components}/Checkbox/index.d.ts +0 -0
  160. package/dist/{components → src/components}/Collapsible/index.d.ts +0 -0
  161. package/dist/{components → src/components}/ColorPicker/index.d.ts +0 -0
  162. package/dist/{components → src/components}/ContextMenu/SkContextMenuCheckboxItem.vue.d.ts +0 -0
  163. package/dist/{components → src/components}/ContextMenu/SkContextMenuItem.vue.d.ts +0 -0
  164. package/dist/{components → src/components}/ContextMenu/SkContextMenuLabel.vue.d.ts +0 -0
  165. package/dist/{components → src/components}/ContextMenu/SkContextMenuRadioGroup.vue.d.ts +0 -0
  166. package/dist/{components → src/components}/ContextMenu/SkContextMenuRadioItem.vue.d.ts +0 -0
  167. package/dist/{components → src/components}/ContextMenu/SkContextMenuSeparator.vue.d.ts +0 -0
  168. package/dist/{components → src/components}/ContextMenu/SkContextMenuSubmenu.vue.d.ts +0 -0
  169. package/dist/{components → src/components}/ContextMenu/index.d.ts +0 -0
  170. package/dist/{components → src/components}/Divider/types.d.ts +0 -0
  171. package/dist/{components → src/components}/Dropdown/SkDropdownCheckboxItem.vue.d.ts +0 -0
  172. package/dist/{components → src/components}/Dropdown/SkDropdownMenuItem.vue.d.ts +0 -0
  173. package/dist/{components → src/components}/Dropdown/SkDropdownMenuLabel.vue.d.ts +0 -0
  174. package/dist/{components → src/components}/Dropdown/SkDropdownMenuSeparator.vue.d.ts +0 -0
  175. package/dist/{components → src/components}/Dropdown/SkDropdownRadioGroup.vue.d.ts +0 -0
  176. package/dist/{components → src/components}/Dropdown/SkDropdownRadioItem.vue.d.ts +0 -0
  177. package/dist/{components → src/components}/Dropdown/SkDropdownSubmenu.vue.d.ts +0 -0
  178. package/dist/{components → src/components}/Dropdown/index.d.ts +0 -0
  179. package/dist/{components → src/components}/Field/SkField.vue.d.ts +0 -0
  180. package/dist/{components → src/components}/Field/index.d.ts +0 -0
  181. package/dist/{components → src/components}/Field/types.d.ts +0 -0
  182. package/dist/{components → src/components}/Group/SkGroup.vue.d.ts +0 -0
  183. package/dist/{components → src/components}/Group/types.d.ts +0 -0
  184. package/dist/{components → src/components}/Input/index.d.ts +0 -0
  185. package/dist/{components → src/components}/Listbox/SkListboxItem.vue.d.ts +0 -0
  186. package/dist/{components → src/components}/Listbox/SkListboxSeparator.vue.d.ts +0 -0
  187. package/dist/{components → src/components}/Listbox/index.d.ts +0 -0
  188. package/dist/{components → src/components}/Modal/index.d.ts +0 -0
  189. package/dist/{components → src/components}/NavBar/index.d.ts +0 -0
  190. package/dist/{components → src/components}/NumberInput/index.d.ts +0 -0
  191. package/dist/{components → src/components}/Pagination/SkPaginationItem.vue.d.ts +0 -0
  192. package/dist/{components → src/components}/Pagination/index.d.ts +0 -0
  193. package/dist/{components → src/components}/Popover/index.d.ts +0 -0
  194. package/dist/{components → src/components}/Popover/types.d.ts +0 -0
  195. package/dist/{components → src/components}/Progress/index.d.ts +0 -0
  196. package/dist/{components → src/components}/Radio/SkRadioGroup.vue.d.ts +0 -0
  197. package/dist/{components → src/components}/Radio/index.d.ts +0 -0
  198. package/dist/{components → src/components}/ScrollArea/index.d.ts +0 -0
  199. package/dist/{components → src/components}/Select/SkSelectSeparator.vue.d.ts +0 -0
  200. package/dist/{components → src/components}/Select/index.d.ts +0 -0
  201. package/dist/{components → src/components}/Sidebar/SkSidebarItem.vue.d.ts +0 -0
  202. package/dist/{components → src/components}/Sidebar/SkSidebarSection.vue.d.ts +0 -0
  203. package/dist/{components → src/components}/Skeleton/SkSkeleton.vue.d.ts +2 -2
  204. /package/dist/{components → src/components}/Skeleton/index.d.ts +0 -0
  205. /package/dist/{components → src/components}/Skeleton/types.d.ts +0 -0
  206. /package/dist/{components → src/components}/Slider/index.d.ts +0 -0
  207. /package/dist/{components → src/components}/Spinner/index.d.ts +0 -0
  208. /package/dist/{components → src/components}/Splitter/SkSplitter.vue.d.ts +0 -0
  209. /package/dist/{components → src/components}/Splitter/SkSplitterHandle.vue.d.ts +0 -0
  210. /package/dist/{components → src/components}/Splitter/SkSplitterPanel.vue.d.ts +0 -0
  211. /package/dist/{components → src/components}/Splitter/index.d.ts +0 -0
  212. /package/dist/{components → src/components}/Switch/index.d.ts +0 -0
  213. /package/dist/{components → src/components}/Table/index.d.ts +0 -0
  214. /package/dist/{components → src/components}/Tabs/SkTabList.vue.d.ts +0 -0
  215. /package/dist/{components → src/components}/Tabs/SkTabPanel.vue.d.ts +0 -0
  216. /package/dist/{components → src/components}/Tabs/SkTabPanels.vue.d.ts +0 -0
  217. /package/dist/{components → src/components}/Tabs/types.d.ts +0 -0
  218. /package/dist/{components → src/components}/Tag/types.d.ts +0 -0
  219. /package/dist/{components → src/components}/TagsInput/index.d.ts +0 -0
  220. /package/dist/{components → src/components}/Textarea/index.d.ts +0 -0
  221. /package/dist/{components → src/components}/Theme/SkTheme.vue.d.ts +0 -0
  222. /package/dist/{components → src/components}/Theme/types.d.ts +0 -0
  223. /package/dist/{components → src/components}/Theme/useTheme.d.ts +0 -0
  224. /package/dist/{components → src/components}/Toast/SkToast.vue.d.ts +0 -0
  225. /package/dist/{components → src/components}/Toast/SkToastProvider.vue.d.ts +0 -0
  226. /package/dist/{components → src/components}/Toast/index.d.ts +0 -0
  227. /package/dist/{components → src/components}/Toast/types.d.ts +0 -0
  228. /package/dist/{components → src/components}/Toast/useToast.d.ts +0 -0
  229. /package/dist/{components → src/components}/Toolbar/SkToolbar.vue.d.ts +0 -0
  230. /package/dist/{components → src/components}/Toolbar/SkToolbarButton.vue.d.ts +0 -0
  231. /package/dist/{components → src/components}/Toolbar/SkToolbarSeparator.vue.d.ts +0 -0
  232. /package/dist/{components → src/components}/Toolbar/SkToolbarToggleGroup.vue.d.ts +0 -0
  233. /package/dist/{components → src/components}/Toolbar/SkToolbarToggleItem.vue.d.ts +0 -0
  234. /package/dist/{components → src/components}/Toolbar/index.d.ts +0 -0
  235. /package/dist/{components → src/components}/Tooltip/SkTooltipProvider.vue.d.ts +0 -0
  236. /package/dist/{components → src/components}/Tooltip/index.d.ts +0 -0
  237. /package/dist/{components → src/components}/TreeView/SkTreeItem.vue.d.ts +0 -0
  238. /package/dist/{components → src/components}/TreeView/index.d.ts +0 -0
  239. /package/dist/{composables → src/composables}/useCustomColors.d.ts +0 -0
  240. /package/dist/{composables → src/composables}/useCustomColors.test.d.ts +0 -0
  241. /package/dist/{composables/usePortalContext.test.d.ts → src/composables/useFocusTrap.test.d.ts} +0 -0
  242. /package/dist/{composables → src/composables}/usePortalContext.d.ts +0 -0
  243. /package/dist/{types.d.ts → src/types.d.ts} +0 -0
@@ -0,0 +1,184 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Responsive Mixins
3
+ //
4
+ // Shared breakpoint scale and helpers for @media (viewport) and @container (component) queries.
5
+ // Keep these aligned with --sk-bp-* in tokens/_foundation-breakpoints.scss.
6
+ //----------------------------------------------------------------------------------------------------------------------
7
+
8
+ @use 'sass:map';
9
+ @use 'sass:math';
10
+ @use 'sass:meta';
11
+
12
+ $breakpoints: (
13
+ sm: 640px,
14
+ md: 1024px,
15
+ lg: 1280px,
16
+ xl: 1536px,
17
+ );
18
+
19
+ @function bp($size)
20
+ {
21
+ @if not map.has-key($breakpoints, $size)
22
+ {
23
+ @error "Unknown breakpoint '#{$size}'. Valid: #{map.keys($breakpoints)}.";
24
+ }
25
+ @return map.get($breakpoints, $size);
26
+ }
27
+
28
+ //----------------------------------------------------------------------------------------------------------------------
29
+ // Fluid Sizing
30
+ //
31
+ // `fluid-size($min, $max, $from: sm, $to: lg)` emits a `clamp()` expression that linearly
32
+ // interpolates `$min` to `$max` as the viewport grows from `$from` to `$to`.
33
+ //
34
+ // - `$min` / `$max` accept `px` or `rem` lengths (rem preferred for typography so user font
35
+ // scaling carries through).
36
+ // - `$from` / `$to` accept a breakpoint name (sm/md/lg/xl) or an explicit length.
37
+ // - Output pins to the floor/ceiling outside the fluid band; it never overshoots `$min` or
38
+ // `$max`.
39
+ //
40
+ // Why this exists rather than inline `clamp()`: consistency. Consumers anchor to the same
41
+ // breakpoint scale everywhere instead of eyeballing viewport widths, and the math for the
42
+ // slope + intercept is done once here instead of in every stylesheet.
43
+ //
44
+ // Example:
45
+ // h1 { font-size: fluid-size(1.5rem, 3rem); } // sm → lg (default)
46
+ // h2 { font-size: fluid-size(1.25rem, 2rem, md, xl); } // md → xl
47
+ // .hero { padding: fluid-size(1rem, 4rem); } // spacing works too
48
+ //----------------------------------------------------------------------------------------------------------------------
49
+
50
+ @function _fluid-resolve-vp($value)
51
+ {
52
+ @if meta.type-of($value) == 'string' { @return bp($value); }
53
+ @return $value;
54
+ }
55
+
56
+ @function _fluid-to-px($value)
57
+ {
58
+ $unit: math.unit($value);
59
+ @if $unit == 'px' { @return math.div($value, 1px); }
60
+ @if $unit == 'rem' { @return math.div($value, 1rem) * 16; }
61
+ @error "fluid-size expects px or rem lengths; got '#{$value}' (unit: '#{$unit}').";
62
+ }
63
+
64
+ @function fluid-size($min-size, $max-size, $from: sm, $to: lg)
65
+ {
66
+ $min-px: _fluid-to-px($min-size);
67
+ $max-px: _fluid-to-px($max-size);
68
+ $from-vp-px: _fluid-to-px(_fluid-resolve-vp($from));
69
+ $to-vp-px: _fluid-to-px(_fluid-resolve-vp($to));
70
+
71
+ @if $to-vp-px == $from-vp-px
72
+ {
73
+ @error "fluid-size: from-viewport and to-viewport must differ (got #{$from-vp-px}px for both).";
74
+ }
75
+
76
+ // size = slope * viewport + intercept (all in px). 1vw = viewport / 100, so
77
+ // `slope * viewport` in px == `slope * 100` in vw. Output the intercept in rem so it
78
+ // scales with the user's base font size.
79
+ $slope: math.div($max-px - $min-px, $to-vp-px - $from-vp-px);
80
+ $intercept-rem: math.div($min-px - $slope * $from-vp-px, 16);
81
+ $slope-vw: $slope * 100;
82
+
83
+ @return clamp(#{$min-size}, calc(#{$intercept-rem}rem + #{$slope-vw}vw), #{$max-size});
84
+ }
85
+
86
+ //----------------------------------------------------------------------------------------------------------------------
87
+ // Viewport Queries
88
+ //----------------------------------------------------------------------------------------------------------------------
89
+
90
+ @mixin media-up($size)
91
+ {
92
+ @media (min-width: #{bp($size)})
93
+ {
94
+ @content;
95
+ }
96
+ }
97
+
98
+ @mixin media-down($size)
99
+ {
100
+ @media (max-width: #{bp($size) - 0.02px})
101
+ {
102
+ @content;
103
+ }
104
+ }
105
+
106
+ //----------------------------------------------------------------------------------------------------------------------
107
+ // Container Queries
108
+ //
109
+ // Caller is responsible for establishing `container-type` / `container-name` on the ancestor.
110
+ //----------------------------------------------------------------------------------------------------------------------
111
+
112
+ @mixin container-up($size, $name: null)
113
+ {
114
+ @if $name
115
+ {
116
+ @container #{$name} (min-width: #{bp($size)})
117
+ {
118
+ @content;
119
+ }
120
+ }
121
+ @else
122
+ {
123
+ @container (min-width: #{bp($size)})
124
+ {
125
+ @content;
126
+ }
127
+ }
128
+ }
129
+
130
+ @mixin container-down($size, $name: null)
131
+ {
132
+ @if $name
133
+ {
134
+ @container #{$name} (max-width: #{bp($size) - 0.02px})
135
+ {
136
+ @content;
137
+ }
138
+ }
139
+ @else
140
+ {
141
+ @container (max-width: #{bp($size) - 0.02px})
142
+ {
143
+ @content;
144
+ }
145
+ }
146
+ }
147
+
148
+ //----------------------------------------------------------------------------------------------------------------------
149
+ // Input & Motion Preferences
150
+ //----------------------------------------------------------------------------------------------------------------------
151
+
152
+ @mixin touch
153
+ {
154
+ @media (pointer: coarse)
155
+ {
156
+ @content;
157
+ }
158
+ }
159
+
160
+ @mixin fine-pointer
161
+ {
162
+ @media (pointer: fine)
163
+ {
164
+ @content;
165
+ }
166
+ }
167
+
168
+ @mixin reduced-motion
169
+ {
170
+ @media (prefers-reduced-motion: reduce)
171
+ {
172
+ @content;
173
+ }
174
+ }
175
+
176
+ @mixin motion-safe
177
+ {
178
+ @media (prefers-reduced-motion: no-preference)
179
+ {
180
+ @content;
181
+ }
182
+ }
183
+
184
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,149 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Fluid Size Math Tests
3
+ //
4
+ // Compiles the `fluid-size` SCSS function against a handful of invocations and asserts the
5
+ // emitted clamp() hits the intended anchor points. Guards against unit-conversion drift
6
+ // (px/rem/vw) that silently flips the fluid curve.
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ import { describe, expect, it } from 'vitest';
10
+ import { compileString } from 'sass';
11
+ import { dirname } from 'node:path';
12
+ import { fileURLToPath, pathToFileURL } from 'node:url';
13
+
14
+ //----------------------------------------------------------------------------------------------------------------------
15
+
16
+ const here = dirname(fileURLToPath(import.meta.url));
17
+
18
+ function emit(call : string) : string
19
+ {
20
+ const source = `
21
+ @use 'responsive' as *;
22
+
23
+ .t { font-size: ${ call }; }
24
+ `;
25
+ const { css } = compileString(source, {
26
+ loadPaths: [ here ],
27
+ url: pathToFileURL(`${ here }/fluidSize.test.scss`),
28
+ });
29
+ const match = css.match(/font-size:\s*([^;]+);/);
30
+ if(!match) { throw new Error(`No font-size in compiled output:\n${ css }`); }
31
+ return match[1].trim();
32
+ }
33
+
34
+ /**
35
+ * Parse `clamp(min, calc(intercept-rem + slope-vw), max)` into numeric parts for assertions.
36
+ * Keeps unit suffixes as-is on min/max since callers usually pass them in a specific unit.
37
+ */
38
+ function parseClamp(expr : string) : { min : string; interceptRem : number; slopeVw : number; max : string }
39
+ {
40
+ // Sass may or may not preserve the `calc()` wrapper around the preferred value, so make it
41
+ // optional here.
42
+ const match = expr.match(
43
+ /^clamp\(\s*([^,]+),\s*(?:calc\(\s*)?(-?[\d.]+)rem\s*\+\s*(-?[\d.]+)vw\s*\)?,\s*([^)]+)\s*\)$/
44
+ );
45
+ if(!match) { throw new Error(`Could not parse clamp expression: ${ expr }`); }
46
+ return {
47
+ min: match[1].trim(),
48
+ interceptRem: parseFloat(match[2]),
49
+ slopeVw: parseFloat(match[3]),
50
+ max: match[4].trim(),
51
+ };
52
+ }
53
+
54
+ //----------------------------------------------------------------------------------------------------------------------
55
+
56
+ describe('fluid-size (SCSS)', () =>
57
+ {
58
+ describe('default breakpoints (sm → lg, 640px → 1280px)', () =>
59
+ {
60
+ it('1rem → 1.5rem: 0.5rem intercept + 1.25vw slope', () =>
61
+ {
62
+ const parsed = parseClamp(emit('fluid-size(1rem, 1.5rem)'));
63
+ expect(parsed.min).toBe('1rem');
64
+ expect(parsed.max).toBe('1.5rem');
65
+ expect(parsed.interceptRem).toBeCloseTo(0.5, 5);
66
+ expect(parsed.slopeVw).toBeCloseTo(1.25, 5);
67
+ });
68
+
69
+ it('hits min at the from-viewport anchor (vp=640px)', () =>
70
+ {
71
+ // clamp lower bound is 1rem; verify the calc also evaluates to 1rem at vp=640.
72
+ // At vp=640, 1vw = 6.4px = 0.4rem. intercept(0.5) + slope(1.25) * 0.4 = 1.0rem. ✓
73
+ const parsed = parseClamp(emit('fluid-size(1rem, 1.5rem)'));
74
+ const px = (parsed.interceptRem * 16) + ((parsed.slopeVw / 100) * 640);
75
+ expect(px).toBeCloseTo(16, 2); // 1rem = 16px
76
+ });
77
+
78
+ it('hits max at the to-viewport anchor (vp=1280px)', () =>
79
+ {
80
+ const parsed = parseClamp(emit('fluid-size(1rem, 1.5rem)'));
81
+ const px = (parsed.interceptRem * 16) + ((parsed.slopeVw / 100) * 1280);
82
+ expect(px).toBeCloseTo(24, 2); // 1.5rem = 24px
83
+ });
84
+ });
85
+
86
+ describe('custom breakpoint range (md → xl, 1024px → 1536px)', () =>
87
+ {
88
+ it('1.25rem → 2rem hits both anchors', () =>
89
+ {
90
+ const parsed = parseClamp(emit('fluid-size(1.25rem, 2rem, md, xl)'));
91
+ const atMd = (parsed.interceptRem * 16) + ((parsed.slopeVw / 100) * 1024);
92
+ const atXl = (parsed.interceptRem * 16) + ((parsed.slopeVw / 100) * 1536);
93
+ expect(atMd).toBeCloseTo(20, 2); // 1.25rem
94
+ expect(atXl).toBeCloseTo(32, 2); // 2rem
95
+ });
96
+ });
97
+
98
+ describe('px inputs', () =>
99
+ {
100
+ it('accepts px sizes and preserves them in the clamp bounds', () =>
101
+ {
102
+ const parsed = parseClamp(emit('fluid-size(16px, 64px, sm, lg)'));
103
+ expect(parsed.min).toBe('16px');
104
+ expect(parsed.max).toBe('64px');
105
+ const atSm = (parsed.interceptRem * 16) + ((parsed.slopeVw / 100) * 640);
106
+ const atLg = (parsed.interceptRem * 16) + ((parsed.slopeVw / 100) * 1280);
107
+ expect(atSm).toBeCloseTo(16, 2);
108
+ expect(atLg).toBeCloseTo(64, 2);
109
+ });
110
+ });
111
+
112
+ describe('explicit viewport lengths', () =>
113
+ {
114
+ it('accepts px viewports in place of breakpoint names', () =>
115
+ {
116
+ const named = parseClamp(emit('fluid-size(1rem, 1.5rem, sm, lg)'));
117
+ const explicit = parseClamp(emit('fluid-size(1rem, 1.5rem, 640px, 1280px)'));
118
+ expect(explicit.interceptRem).toBeCloseTo(named.interceptRem, 5);
119
+ expect(explicit.slopeVw).toBeCloseTo(named.slopeVw, 5);
120
+ });
121
+ });
122
+
123
+ describe('edge cases', () =>
124
+ {
125
+ it('equal min and max yields zero slope', () =>
126
+ {
127
+ const parsed = parseClamp(emit('fluid-size(1rem, 1rem)'));
128
+ expect(parsed.slopeVw).toBeCloseTo(0, 5);
129
+ expect(parsed.interceptRem).toBeCloseTo(1, 5);
130
+ });
131
+
132
+ it('throws when from-viewport equals to-viewport', () =>
133
+ {
134
+ expect(() => emit('fluid-size(1rem, 1.5rem, 640px, 640px)')).toThrow();
135
+ });
136
+
137
+ it('throws on unknown breakpoint name', () =>
138
+ {
139
+ expect(() => emit('fluid-size(1rem, 1.5rem, bogus, lg)')).toThrow();
140
+ });
141
+
142
+ it('throws on unsupported unit', () =>
143
+ {
144
+ expect(() => emit('fluid-size(1em, 2em)')).toThrow();
145
+ });
146
+ });
147
+ });
148
+
149
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Foundation Tokens - Breakpoints
3
+ *
4
+ * Single-source breakpoint scale shared between @media (viewport) and
5
+ * @container (component) queries. CSS custom properties are exposed for
6
+ * consumer visibility and JS access; SCSS-level values live in
7
+ * mixins/_responsive.scss and drive the media-up/container-up mixins.
8
+ *
9
+ * Scale rationale:
10
+ * sm ( 640px) - phones held landscape / narrow tablets
11
+ * md (1024px) - tablets / small laptop -- persistent sidebar threshold
12
+ * lg (1280px) - standard laptop / desktop
13
+ * xl (1536px) - large desktop / ultrawide
14
+ */
15
+
16
+ :root
17
+ {
18
+ /* ===================================================================
19
+ * Viewport Breakpoints
20
+ * =================================================================== */
21
+
22
+ --sk-bp-sm: 640px;
23
+ --sk-bp-md: 1024px;
24
+ --sk-bp-lg: 1280px;
25
+ --sk-bp-xl: 1536px;
26
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Foundation Tokens - Z-Index Stacking Scale
3
+ *
4
+ * One scale every SleekSpace component layers against so portaled content stacks in a
5
+ * predictable, documented order. Custom consumer layers can slot in between tokens by
6
+ * picking a number within the reserved gap.
7
+ *
8
+ * Reading order (bottom to top):
9
+ * sticky 100 - App-shell chrome that sits above the flow (sticky navbar / footer)
10
+ * drawer-scrim 900 - Dim + blur layer behind an open drawer
11
+ * drawer 901 - SkPage sidebar / aside drawer
12
+ * modal-scrim 1000 - Dim layer behind an open modal
13
+ * modal 1001 - SkModal content -- must be above drawer so modals launched from
14
+ * inside a drawer render on top
15
+ * popover 1100 - SkPopover (floating anchored surface)
16
+ * dropdown 1100 - SkDropdown + SkListbox menus (same layer as popover; a menu opened
17
+ * inside a modal renders above the modal)
18
+ * tooltip 1200 - SkTooltip -- higher than menus so a tooltip on a menu item stays
19
+ * visible
20
+ * toast 1300 - Ephemeral top-of-stack notifications
21
+ */
22
+
23
+ :root
24
+ {
25
+ /* ===================================================================
26
+ * Layering Scale
27
+ * =================================================================== */
28
+
29
+ --sk-z-sticky: 100;
30
+ --sk-z-drawer-scrim: 900;
31
+ --sk-z-drawer: 901;
32
+ --sk-z-modal-scrim: 1000;
33
+ --sk-z-modal: 1001;
34
+ --sk-z-popover: 1100;
35
+ --sk-z-dropdown: 1100;
36
+ --sk-z-tooltip: 1200;
37
+ --sk-z-toast: 1300;
38
+ }
@@ -25,6 +25,8 @@
25
25
  @use 'foundation-transitions';
26
26
  @use 'foundation-typography';
27
27
  @use 'foundation-scrollbar';
28
+ @use 'foundation-breakpoints';
29
+ @use 'foundation-z-index';
28
30
 
29
31
  /* ===================================================================
30
32
  * Semantic Tokens