@skewedaspect/sleekspace-ui 0.2.0-beta.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 (266) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/dist/sleekspace-ui.css +12844 -0
  4. package/dist/sleekspace-ui.es.js +19021 -0
  5. package/dist/sleekspace-ui.umd.js +19040 -0
  6. package/docs/components/accordion.md +92 -0
  7. package/docs/components/alert.md +72 -0
  8. package/docs/components/avatar.md +69 -0
  9. package/docs/components/breadcrumbs.md +65 -0
  10. package/docs/components/button/_meta.yaml +12 -0
  11. package/docs/components/button/accessibility.md +16 -0
  12. package/docs/components/button/custom-colors.md +18 -0
  13. package/docs/components/button/icons.md +31 -0
  14. package/docs/components/button/intro.md +8 -0
  15. package/docs/components/button/kinds.md +25 -0
  16. package/docs/components/button/sizes.md +14 -0
  17. package/docs/components/button/states.md +12 -0
  18. package/docs/components/button/usage.md +23 -0
  19. package/docs/components/button/variants.md +14 -0
  20. package/docs/components/button.md +110 -0
  21. package/docs/components/card.md +87 -0
  22. package/docs/components/checkbox.md +77 -0
  23. package/docs/components/collapsible.md +71 -0
  24. package/docs/components/divider.md +62 -0
  25. package/docs/components/dropdown.md +88 -0
  26. package/docs/components/field.md +80 -0
  27. package/docs/components/group.md +41 -0
  28. package/docs/components/input.md +84 -0
  29. package/docs/components/listbox.md +82 -0
  30. package/docs/components/modal.md +101 -0
  31. package/docs/components/navbar.md +64 -0
  32. package/docs/components/number-input.md +78 -0
  33. package/docs/components/page.md +77 -0
  34. package/docs/components/pagination.md +88 -0
  35. package/docs/components/panel.md +74 -0
  36. package/docs/components/popover.md +93 -0
  37. package/docs/components/progress.md +76 -0
  38. package/docs/components/radio.md +86 -0
  39. package/docs/components/sidebar.md +74 -0
  40. package/docs/components/skeleton.md +76 -0
  41. package/docs/components/slider.md +94 -0
  42. package/docs/components/spinner.md +59 -0
  43. package/docs/components/switch.md +97 -0
  44. package/docs/components/table.md +91 -0
  45. package/docs/components/tabs.md +108 -0
  46. package/docs/components/tag.md +75 -0
  47. package/docs/components/tags-input.md +88 -0
  48. package/docs/components/textarea.md +80 -0
  49. package/docs/components/theme.md +65 -0
  50. package/docs/components/toast.md +95 -0
  51. package/docs/components/tooltip.md +90 -0
  52. package/docs/guides/custom-colors.md +84 -0
  53. package/docs/guides/design-tokens.md +105 -0
  54. package/docs/guides/getting-started.md +144 -0
  55. package/docs/guides/installation.md +62 -0
  56. package/docs/guides/theming.md +101 -0
  57. package/package.json +76 -0
  58. package/src/components/Accordion/SkAccordion.vue +133 -0
  59. package/src/components/Accordion/SkAccordionItem.vue +131 -0
  60. package/src/components/Accordion/index.ts +3 -0
  61. package/src/components/Accordion/types.ts +9 -0
  62. package/src/components/Alert/SkAlert.vue +137 -0
  63. package/src/components/Alert/types.ts +10 -0
  64. package/src/components/Avatar/SkAvatar.vue +141 -0
  65. package/src/components/Avatar/index.ts +8 -0
  66. package/src/components/Avatar/types.ts +31 -0
  67. package/src/components/Breadcrumbs/SkBreadcrumbItem.vue +76 -0
  68. package/src/components/Breadcrumbs/SkBreadcrumbSeparator.vue +38 -0
  69. package/src/components/Breadcrumbs/SkBreadcrumbs.vue +93 -0
  70. package/src/components/Breadcrumbs/index.ts +10 -0
  71. package/src/components/Breadcrumbs/types.ts +36 -0
  72. package/src/components/Button/SkButton.vue +148 -0
  73. package/src/components/Button/types.ts +21 -0
  74. package/src/components/Card/SkCard.vue +144 -0
  75. package/src/components/Card/types.ts +12 -0
  76. package/src/components/Checkbox/SkCheckbox.vue +136 -0
  77. package/src/components/Checkbox/index.ts +8 -0
  78. package/src/components/Checkbox/types.ts +10 -0
  79. package/src/components/Collapsible/SkCollapsible.vue +159 -0
  80. package/src/components/Collapsible/index.ts +2 -0
  81. package/src/components/Collapsible/types.ts +8 -0
  82. package/src/components/Divider/SkDivider.vue +63 -0
  83. package/src/components/Divider/types.ts +15 -0
  84. package/src/components/Dropdown/SkDropdown.vue +150 -0
  85. package/src/components/Dropdown/SkDropdownMenuItem.vue +58 -0
  86. package/src/components/Dropdown/SkDropdownMenuSeparator.vue +26 -0
  87. package/src/components/Dropdown/SkDropdownSubmenu.vue +107 -0
  88. package/src/components/Dropdown/index.ts +11 -0
  89. package/src/components/Dropdown/types.ts +11 -0
  90. package/src/components/Field/SkField.vue +152 -0
  91. package/src/components/Field/index.ts +8 -0
  92. package/src/components/Field/types.ts +7 -0
  93. package/src/components/Group/SkGroup.vue +52 -0
  94. package/src/components/Group/types.ts +10 -0
  95. package/src/components/Input/SkInput.vue +117 -0
  96. package/src/components/Input/index.ts +8 -0
  97. package/src/components/Input/types.ts +11 -0
  98. package/src/components/Listbox/SkListbox.vue +164 -0
  99. package/src/components/Listbox/SkListboxItem.vue +68 -0
  100. package/src/components/Listbox/SkListboxSeparator.vue +26 -0
  101. package/src/components/Listbox/index.ts +10 -0
  102. package/src/components/Listbox/types.ts +10 -0
  103. package/src/components/Modal/SkModal.vue +231 -0
  104. package/src/components/Modal/index.ts +8 -0
  105. package/src/components/Modal/types.ts +12 -0
  106. package/src/components/NavBar/SkNavBar.vue +83 -0
  107. package/src/components/NavBar/index.ts +8 -0
  108. package/src/components/NavBar/types.ts +15 -0
  109. package/src/components/NumberInput/SkNumberInput.vue +168 -0
  110. package/src/components/NumberInput/index.ts +8 -0
  111. package/src/components/NumberInput/types.ts +10 -0
  112. package/src/components/Page/SkPage.vue +94 -0
  113. package/src/components/Page/index.ts +8 -0
  114. package/src/components/Page/types.ts +21 -0
  115. package/src/components/Pagination/SkPagination.vue +185 -0
  116. package/src/components/Pagination/SkPaginationItem.vue +107 -0
  117. package/src/components/Pagination/index.ts +9 -0
  118. package/src/components/Pagination/types.ts +40 -0
  119. package/src/components/Panel/SkPanel.vue +96 -0
  120. package/src/components/Panel/types.ts +15 -0
  121. package/src/components/Popover/SkPopover.vue +185 -0
  122. package/src/components/Popover/index.ts +8 -0
  123. package/src/components/Popover/types.ts +11 -0
  124. package/src/components/Progress/SkProgress.vue +144 -0
  125. package/src/components/Progress/index.ts +8 -0
  126. package/src/components/Progress/types.ts +34 -0
  127. package/src/components/Radio/SkRadio.vue +110 -0
  128. package/src/components/Radio/SkRadioGroup.vue +92 -0
  129. package/src/components/Radio/index.ts +9 -0
  130. package/src/components/Radio/types.ts +11 -0
  131. package/src/components/Sidebar/README.md +405 -0
  132. package/src/components/Sidebar/SkSidebar.vue +88 -0
  133. package/src/components/Sidebar/SkSidebarItem.vue +58 -0
  134. package/src/components/Sidebar/SkSidebarSection.vue +40 -0
  135. package/src/components/Sidebar/types.ts +3 -0
  136. package/src/components/Skeleton/SkSkeleton.vue +171 -0
  137. package/src/components/Skeleton/index.ts +8 -0
  138. package/src/components/Skeleton/types.ts +31 -0
  139. package/src/components/Slider/SkSlider.vue +165 -0
  140. package/src/components/Slider/index.ts +8 -0
  141. package/src/components/Slider/types.ts +44 -0
  142. package/src/components/Spinner/SkSpinner.vue +105 -0
  143. package/src/components/Spinner/index.ts +8 -0
  144. package/src/components/Spinner/types.ts +28 -0
  145. package/src/components/Switch/SkSwitch.vue +215 -0
  146. package/src/components/Switch/index.ts +8 -0
  147. package/src/components/Switch/types.ts +12 -0
  148. package/src/components/Table/SkTable.vue +109 -0
  149. package/src/components/Table/index.ts +2 -0
  150. package/src/components/Table/types.ts +15 -0
  151. package/src/components/Tabs/README.md +331 -0
  152. package/src/components/Tabs/SkTab.vue +84 -0
  153. package/src/components/Tabs/SkTabList.vue +62 -0
  154. package/src/components/Tabs/SkTabPanel.vue +47 -0
  155. package/src/components/Tabs/SkTabPanels.vue +23 -0
  156. package/src/components/Tabs/SkTabs.vue +124 -0
  157. package/src/components/Tabs/types.ts +21 -0
  158. package/src/components/Tag/SkTag.vue +129 -0
  159. package/src/components/Tag/types.ts +15 -0
  160. package/src/components/TagsInput/SkTagsInput.vue +184 -0
  161. package/src/components/TagsInput/index.ts +8 -0
  162. package/src/components/TagsInput/types.ts +10 -0
  163. package/src/components/Textarea/SkTextarea.vue +117 -0
  164. package/src/components/Textarea/index.ts +8 -0
  165. package/src/components/Textarea/types.ts +10 -0
  166. package/src/components/Theme/SkTheme.vue +47 -0
  167. package/src/components/Theme/types.ts +17 -0
  168. package/src/components/Theme/useTheme.ts +131 -0
  169. package/src/components/Toast/SkToast.vue +156 -0
  170. package/src/components/Toast/SkToastProvider.vue +180 -0
  171. package/src/components/Toast/index.ts +15 -0
  172. package/src/components/Toast/types.ts +63 -0
  173. package/src/components/Toast/useToast.ts +78 -0
  174. package/src/components/Tooltip/SkTooltip.vue +162 -0
  175. package/src/components/Tooltip/SkTooltipProvider.vue +114 -0
  176. package/src/components/Tooltip/index.ts +9 -0
  177. package/src/components/Tooltip/types.ts +13 -0
  178. package/src/composables/useCustomColors.test.ts +505 -0
  179. package/src/composables/useCustomColors.ts +124 -0
  180. package/src/composables/usePortalContext.test.ts +402 -0
  181. package/src/composables/usePortalContext.ts +95 -0
  182. package/src/global.d.ts +76 -0
  183. package/src/index.ts +259 -0
  184. package/src/styles/_scrollbar.scss +100 -0
  185. package/src/styles/base/_fonts.scss +105 -0
  186. package/src/styles/base/_global.scss +47 -0
  187. package/src/styles/base/_index.scss +24 -0
  188. package/src/styles/base/_reset.scss +11 -0
  189. package/src/styles/base/_typography.scss +178 -0
  190. package/src/styles/components/_accordion.scss +250 -0
  191. package/src/styles/components/_alert.scss +239 -0
  192. package/src/styles/components/_avatar.scss +133 -0
  193. package/src/styles/components/_breadcrumbs.scss +137 -0
  194. package/src/styles/components/_button.scss +731 -0
  195. package/src/styles/components/_card.scss +141 -0
  196. package/src/styles/components/_checkbox.scss +232 -0
  197. package/src/styles/components/_collapsible.scss +158 -0
  198. package/src/styles/components/_divider.scss +121 -0
  199. package/src/styles/components/_field.scss +87 -0
  200. package/src/styles/components/_group.scss +138 -0
  201. package/src/styles/components/_index.scss +46 -0
  202. package/src/styles/components/_input.scss +205 -0
  203. package/src/styles/components/_listbox.scss +453 -0
  204. package/src/styles/components/_menu.scss +216 -0
  205. package/src/styles/components/_modal.scss +329 -0
  206. package/src/styles/components/_navbar.scss +258 -0
  207. package/src/styles/components/_number-input.scss +352 -0
  208. package/src/styles/components/_page.scss +98 -0
  209. package/src/styles/components/_pagination.scss +411 -0
  210. package/src/styles/components/_panel.scss +281 -0
  211. package/src/styles/components/_popover.scss +258 -0
  212. package/src/styles/components/_progress.scss +280 -0
  213. package/src/styles/components/_radio.scss +255 -0
  214. package/src/styles/components/_sidebar.scss +92 -0
  215. package/src/styles/components/_skeleton.scss +138 -0
  216. package/src/styles/components/_slider.scss +262 -0
  217. package/src/styles/components/_spinner.scss +331 -0
  218. package/src/styles/components/_switch.scss +370 -0
  219. package/src/styles/components/_table.scss +405 -0
  220. package/src/styles/components/_tabs.scss +486 -0
  221. package/src/styles/components/_tag.scss +425 -0
  222. package/src/styles/components/_tags-input.scss +279 -0
  223. package/src/styles/components/_textarea.scss +208 -0
  224. package/src/styles/components/_toast.scss +331 -0
  225. package/src/styles/components/_tooltip.scss +206 -0
  226. package/src/styles/fonts/Titillium_Web/OFL.txt +93 -0
  227. package/src/styles/fonts/Titillium_Web/TitilliumWeb-Black.ttf +0 -0
  228. package/src/styles/fonts/Titillium_Web/TitilliumWeb-Bold.ttf +0 -0
  229. package/src/styles/fonts/Titillium_Web/TitilliumWeb-BoldItalic.ttf +0 -0
  230. package/src/styles/fonts/Titillium_Web/TitilliumWeb-ExtraLight.ttf +0 -0
  231. package/src/styles/fonts/Titillium_Web/TitilliumWeb-ExtraLightItalic.ttf +0 -0
  232. package/src/styles/fonts/Titillium_Web/TitilliumWeb-Italic.ttf +0 -0
  233. package/src/styles/fonts/Titillium_Web/TitilliumWeb-Light.ttf +0 -0
  234. package/src/styles/fonts/Titillium_Web/TitilliumWeb-LightItalic.ttf +0 -0
  235. package/src/styles/fonts/Titillium_Web/TitilliumWeb-Regular.ttf +0 -0
  236. package/src/styles/fonts/Titillium_Web/TitilliumWeb-SemiBold.ttf +0 -0
  237. package/src/styles/fonts/Titillium_Web/TitilliumWeb-SemiBoldItalic.ttf +0 -0
  238. package/src/styles/index.scss +17 -0
  239. package/src/styles/mixins/_cut-border.scss +254 -0
  240. package/src/styles/mixins/_index.scss +7 -0
  241. package/src/styles/theme/_variables.scss +42 -0
  242. package/src/styles/themes/README.md +127 -0
  243. package/src/styles/themes/_colorful.scss +58 -0
  244. package/src/styles/themes/_greyscale.scss +58 -0
  245. package/src/styles/themes/index.scss +9 -0
  246. package/src/styles/tokens/README.md +268 -0
  247. package/src/styles/tokens/_foundation-borders.scss +26 -0
  248. package/src/styles/tokens/_foundation-colors.scss +169 -0
  249. package/src/styles/tokens/_foundation-glow.scss +36 -0
  250. package/src/styles/tokens/_foundation-radius.scss +53 -0
  251. package/src/styles/tokens/_foundation-scrollbar.scss +31 -0
  252. package/src/styles/tokens/_foundation-shadows.scss +37 -0
  253. package/src/styles/tokens/_foundation-space.scss +36 -0
  254. package/src/styles/tokens/_foundation-transitions.scss +37 -0
  255. package/src/styles/tokens/_foundation-typography.scss +58 -0
  256. package/src/styles/tokens/_semantic-color-kinds.scss +112 -0
  257. package/src/styles/tokens/_semantic-colors.scss +10 -0
  258. package/src/styles/tokens/_semantic-interactive.scss +29 -0
  259. package/src/styles/tokens/_semantic-scrollbar.scss +48 -0
  260. package/src/styles/tokens/_semantic-surfaces.scss +36 -0
  261. package/src/styles/tokens/index.scss +38 -0
  262. package/src/styles/tokens.scss +268 -0
  263. package/src/styles/utilities/_index.scss +9 -0
  264. package/src/styles/utilities/_typography.scss +121 -0
  265. package/src/types.ts +50 -0
  266. package/web-types.json +3524 -0
@@ -0,0 +1,731 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Button Component Styles
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ @use '../theme/variables' as *;
6
+ @use '../mixins' as *;
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
9
+ // Button Design Tokens
10
+ //----------------------------------------------------------------------------------------------------------------------
11
+
12
+ .sk-button
13
+ {
14
+ //------------------------------------------------------------------------------------------------------------------
15
+ // Size System Tokens
16
+ //------------------------------------------------------------------------------------------------------------------
17
+ // Button sizing is based on a scale system where md is the base (1.0) and other sizes scale proportionally.
18
+ // Heights scale uniformly, but font sizes and padding have custom scales for better optical balance.
19
+
20
+ /// Base button height (md size) - all other sizes derive from this (2.5rem = 40px)
21
+ --sk-button-height-base: 2.5rem;
22
+
23
+ /// Base font size for buttons (0.875rem = 14px)
24
+ --sk-button-font-size-base: 0.875rem;
25
+
26
+ /// Base horizontal padding for sm/md/lg sizes
27
+ --sk-button-padding-base: 1rem;
28
+
29
+ /// Size scale multipliers for height calculations
30
+ --sk-button-scale-xs: 0.6; // 60% = 24px height
31
+ --sk-button-scale-sm: 0.8; // 80% = 32px height
32
+ --sk-button-scale-md: 1; // 100% = 40px height (base)
33
+ --sk-button-scale-lg: 1.2; // 120% = 48px height
34
+ --sk-button-scale-xl: 1.4; // 140% = 56px height
35
+
36
+ /// Font size scale multipliers (different from height scale for optical balance)
37
+ --sk-button-font-scale-xs: 0.786; // 11px (0.6875rem)
38
+ --sk-button-font-scale-sm: 1; // 14px (matches base)
39
+ --sk-button-font-scale-md: 1; // 14px (matches base)
40
+ --sk-button-font-scale-lg: 1.143; // 16px (1rem)
41
+ --sk-button-font-scale-xl: 1.571; // 22px (1.375rem)
42
+
43
+ /// Padding overrides for sizes that need different values
44
+ --sk-button-padding-xs: 0.5rem; // Tighter padding for smallest size
45
+ --sk-button-padding-xl: 1.5rem; // More generous padding for largest size
46
+
47
+ /// Border radius calculation factor (height / factor = cut size)
48
+ /// References global token for consistency
49
+ --sk-button-radius-factor: var(--sk-border-radius-factor);
50
+
51
+ //------------------------------------------------------------------------------------------------------------------
52
+ // Typography Tokens
53
+ //------------------------------------------------------------------------------------------------------------------
54
+
55
+ /// Font weight for button text (semi-bold for emphasis)
56
+ --sk-button-font-weight: 600;
57
+
58
+ /// Line height for button text (1.5 for comfortable vertical spacing)
59
+ --sk-button-line-height: 1.5;
60
+
61
+ /// Gap between button content items (icon + text spacing)
62
+ --sk-button-gap: 0.5rem;
63
+
64
+ //------------------------------------------------------------------------------------------------------------------
65
+ // Border Tokens
66
+ //------------------------------------------------------------------------------------------------------------------
67
+
68
+ /// Border width (references global foundation token)
69
+ --sk-button-border-width: var(--sk-border-width-thin);
70
+
71
+ /// Dynamic border color (set by variants/states)
72
+ --sk-button-border-color: currentColor;
73
+
74
+ /// Dynamic glow shadow (set by hover states)
75
+ /// Use transparent shadow as default instead of 'none' to avoid breaking box-shadow syntax
76
+ --sk-button-glow-shadow: 0 0 0 transparent;
77
+
78
+ //------------------------------------------------------------------------------------------------------------------
79
+ // Transition Tokens
80
+ //------------------------------------------------------------------------------------------------------------------
81
+
82
+ /// Button transition duration (references global foundation token)
83
+ --sk-button-transition-duration: var(--sk-transition-normal);
84
+
85
+ /// Button transition easing (references global foundation token)
86
+ --sk-button-transition-easing: var(--sk-transition-easing);
87
+
88
+ //------------------------------------------------------------------------------------------------------------------
89
+ // State Tokens
90
+ //------------------------------------------------------------------------------------------------------------------
91
+
92
+ /// Disabled state opacity (references global foundation token)
93
+ --sk-button-disabled-opacity: var(--sk-opacity-disabled);
94
+
95
+ /// Loading state opacity (references global foundation token)
96
+ --sk-button-loading-opacity: var(--sk-opacity-loading);
97
+
98
+ //------------------------------------------------------------------------------------------------------------------
99
+ // Variant-Specific Tokens
100
+ //------------------------------------------------------------------------------------------------------------------
101
+
102
+ /// Outline variant background
103
+ --sk-button-outline-bg: rgba(5, 5, 5, 0.15);
104
+
105
+ /// Subtle variant background opacity (references global foundation token)
106
+ --sk-button-subtle-opacity: var(--sk-opacity-subtle);
107
+
108
+ /// Subtle variant hover background opacity (references global foundation token)
109
+ --sk-button-subtle-opacity-hover: var(--sk-opacity-subtle-hover);
110
+
111
+ /// Subtle variant border opacity (references global foundation token)
112
+ --sk-button-subtle-border-opacity: var(--sk-opacity-subtle-border);
113
+
114
+ /// Subtle variant border hover opacity (references global foundation token)
115
+ --sk-button-subtle-border-opacity-hover: var(--sk-opacity-subtle-border-hover);
116
+
117
+ /// Glow effect blur radius (intentionally smaller than panel glow for subtlety)
118
+ --sk-button-glow-size: 8px;
119
+
120
+ /// Glow effect opacity (intentionally different from panel for visual hierarchy)
121
+ --sk-button-glow-opacity: 0.4;
122
+
123
+ //------------------------------------------------------------------------------------------------------------------
124
+ // Generic Color Tokens
125
+ //------------------------------------------------------------------------------------------------------------------
126
+ // These base tokens are overridden by each kind (neutral, primary, accent, etc.).
127
+ // All color derivatives (hover, active, borders) are automatically calculated from these base tokens.
128
+ // This ensures consistent color behavior across all button kinds and variants.
129
+
130
+ /// Base color - the bright semantic color used for borders and as source for all backgrounds
131
+ /// Each kind (neutral, primary, accent, etc.) overrides this with their specific color
132
+ --sk-button-color-base: var(--sk-neutral-base);
133
+
134
+ /// Foreground/text color - calculated for optimal contrast against darkened backgrounds
135
+ /// Each kind overrides this with their pre-calculated foreground color
136
+ --sk-button-text: var(--sk-neutral-text);
137
+
138
+ /// Background color for solid buttons - darkened version of base color
139
+ /// Formula: mix(mix(base 75%, transparent 25%), black 46.25%)
140
+ /// This reduces lightness by approximately 60% for better contrast and depth
141
+ --sk-button-bg: color-mix(
142
+ in oklch,
143
+ color-mix(in oklch, var(--sk-button-color-base) 75%, transparent 25%),
144
+ #000 46.25%
145
+ );
146
+
147
+ /// Hover state background - slightly lighter than base background
148
+ --sk-button-bg-hover: color-mix(in oklch, var(--sk-button-bg) 85%, white 15%);
149
+
150
+ /// Active state background - slightly darker than base background for pressed effect
151
+ --sk-button-bg-active: color-mix(in oklch, var(--sk-button-bg) 85%, black 15%);
152
+
153
+ /// Base border color - uses the bright base color directly for vibrant edges
154
+ --sk-button-border-base: var(--sk-button-color-base);
155
+
156
+ /// Hover border color - slightly lighter than base for emphasis
157
+ --sk-button-border-hover: color-mix(in oklch, var(--sk-button-color-base), white 12.68%);
158
+ }
159
+
160
+ //----------------------------------------------------------------------------------------------------------------------
161
+ // Variant Mixins
162
+ //----------------------------------------------------------------------------------------------------------------------
163
+
164
+ // Mixin for solid variant
165
+ @mixin button-solid-kind($kind)
166
+ {
167
+ &.sk-#{ "" + $kind }
168
+ {
169
+ // Override base color tokens for this kind
170
+ --sk-button-color-base: var(--sk-#{ $kind }-base);
171
+ --sk-button-text: var(--sk-#{ $kind }-text);
172
+
173
+ // Set generic kind color for list markers and other cross-component features
174
+ --sk-kind-color: var(--sk-#{ $kind }-base);
175
+
176
+ // Set dynamic border color
177
+ --sk-button-border-color: var(--sk-button-border-base);
178
+
179
+ // Use calculated background and foreground
180
+ background-color: var(--sk-button-bg);
181
+ color: var(--sk-button-text);
182
+
183
+ &:hover:not(:disabled)
184
+ {
185
+ // Update border color and glow shadow
186
+ --sk-button-border-color: var(--sk-button-border-hover);
187
+ --sk-button-glow-shadow: 0 0 var(--sk-button-glow-size) oklch(from var(--sk-button-border-base) l c h / var(--sk-button-glow-opacity));
188
+
189
+ background-color: var(--sk-button-bg-hover);
190
+ }
191
+
192
+ &:active:not(:disabled)
193
+ {
194
+ --sk-button-border-color: var(--sk-button-border-hover);
195
+ --sk-button-glow-shadow: 0 0 0 transparent;
196
+
197
+ background-color: var(--sk-button-bg);
198
+ color: var(--sk-button-color-base);
199
+ }
200
+
201
+ &:focus-visible
202
+ {
203
+ outline-color: var(--sk-button-border-base);
204
+ }
205
+ }
206
+ }
207
+
208
+ // Mixin for outline variant
209
+ @mixin button-outline-kind($kind)
210
+ {
211
+ &.sk-#{ "" + $kind }
212
+ {
213
+ // Override base color tokens for this kind
214
+ --sk-button-color-base: var(--sk-#{ $kind }-base);
215
+ --sk-button-text: var(--sk-#{ $kind }-text);
216
+
217
+ // Set generic kind color for list markers and other cross-component features
218
+ --sk-kind-color: var(--sk-#{ $kind }-base);
219
+
220
+ --sk-button-border-color: var(--sk-button-border-base);
221
+
222
+ background-color: var(--sk-button-outline-bg);
223
+ color: var(--sk-button-color-base);
224
+
225
+ &:hover:not(:disabled)
226
+ {
227
+ --sk-button-border-color: var(--sk-button-border-hover);
228
+ --sk-button-glow-shadow: 0 0 var(--sk-button-glow-size) oklch(from var(--sk-button-border-base) l c h / var(--sk-button-glow-opacity));
229
+
230
+ background-color: var(--sk-button-bg);
231
+ }
232
+
233
+ &:active:not(:disabled)
234
+ {
235
+ --sk-button-border-color: var(--sk-button-border-hover);
236
+ --sk-button-glow-shadow: 0 0 0 transparent;
237
+
238
+ background-color: var(--sk-button-bg-hover);
239
+ color: var(--sk-button-text);
240
+ }
241
+ }
242
+ }
243
+
244
+ // Mixin for subtle variant (between ghost and solid)
245
+ @mixin button-subtle-kind($kind)
246
+ {
247
+ &.sk-#{ "" + $kind }
248
+ {
249
+ // Override base color tokens for this kind
250
+ --sk-button-color-base: var(--sk-#{ $kind }-base);
251
+ --sk-button-text: var(--sk-#{ $kind }-text);
252
+
253
+ // Set generic kind color for list markers and other cross-component features
254
+ --sk-kind-color: var(--sk-#{ $kind }-base);
255
+
256
+ --sk-button-border-color: oklch(from var(--sk-button-border-base) l c h / var(--sk-button-subtle-border-opacity));
257
+
258
+ background-color: oklch(from var(--sk-button-bg) l c h / var(--sk-button-subtle-opacity));
259
+ color: var(--sk-button-color-base);
260
+
261
+ &:hover:not(:disabled)
262
+ {
263
+ --sk-button-border-color: oklch(from var(--sk-button-border-base) l c h / var(--sk-button-subtle-border-opacity-hover));
264
+ --sk-button-glow-shadow: 0 0 var(--sk-button-glow-size) oklch(from var(--sk-button-border-base) l c h / var(--sk-button-glow-opacity));
265
+
266
+ background-color: oklch(from var(--sk-button-bg) l c h / var(--sk-button-subtle-opacity-hover));
267
+ }
268
+
269
+ &:active:not(:disabled)
270
+ {
271
+ --sk-button-border-color: var(--sk-button-border-base);
272
+ --sk-button-glow-shadow: 0 0 0 transparent;
273
+
274
+ background-color: var(--sk-button-bg);
275
+ color: var(--sk-button-text);
276
+ }
277
+ }
278
+ }
279
+
280
+ // Mixin for ghost variant
281
+ @mixin button-ghost-kind($kind)
282
+ {
283
+ &.sk-#{ "" + $kind }
284
+ {
285
+ // Override base color tokens for this kind
286
+ --sk-button-color-base: var(--sk-#{ $kind }-base);
287
+ --sk-button-text: var(--sk-#{ $kind }-text);
288
+
289
+ // Set generic kind color for list markers and other cross-component features
290
+ --sk-kind-color: var(--sk-#{ $kind }-base);
291
+
292
+ --sk-button-border-color: transparent;
293
+
294
+ background-color: transparent;
295
+ color: var(--sk-button-color-base);
296
+
297
+ &:hover:not(:disabled)
298
+ {
299
+ --sk-button-glow-shadow: 0 0 var(--sk-button-glow-size) oklch(from var(--sk-button-border-base) l c h / var(--sk-button-glow-opacity));
300
+
301
+ background-color: var(--sk-button-bg-hover);
302
+ }
303
+
304
+ &:active:not(:disabled)
305
+ {
306
+ --sk-button-border-color: var(--sk-button-border-hover);
307
+ --sk-button-glow-shadow: 0 0 0 transparent;
308
+
309
+ background-color: var(--sk-button-bg-hover);
310
+ color: var(--sk-button-text);
311
+ }
312
+ }
313
+ }
314
+
315
+ // Mixin for link variant
316
+ @mixin button-link-kind($kind)
317
+ {
318
+ &.sk-#{ "" + $kind }
319
+ {
320
+ // Override base color tokens for this kind
321
+ --sk-button-color-base: var(--sk-#{ $kind }-base);
322
+ --sk-button-text: var(--sk-#{ $kind }-text);
323
+
324
+ // Set generic kind color for list markers and other cross-component features
325
+ --sk-kind-color: var(--sk-#{ $kind }-base);
326
+
327
+ --sk-button-radius-factor: 10;
328
+ --sk-button-border-width: 0;
329
+ --sk-button-border-color: transparent;
330
+
331
+ background-color: transparent;
332
+ color: var(--sk-button-color-base);
333
+ text-decoration: none;
334
+ border: none;
335
+
336
+ &:hover:not(:disabled)
337
+ {
338
+ color: color-mix(in oklch, var(--sk-button-color-base) 92%, white 8%);
339
+ text-decoration-color: var(--sk-button-text);
340
+ text-decoration: underline;
341
+ }
342
+
343
+ &:active:not(:disabled)
344
+ {
345
+ color: var(--sk-button-text);
346
+ text-decoration-color: var(--sk-button-border-hover);
347
+ text-decoration: underline;
348
+ }
349
+ }
350
+ }
351
+
352
+ //----------------------------------------------------------------------------------------------------------------------
353
+
354
+ .sk-button
355
+ {
356
+ // Base styles
357
+ position: relative;
358
+ display: inline-flex;
359
+ align-items: center;
360
+ justify-content: center;
361
+ gap: var(--sk-button-gap);
362
+ font-weight: var(--sk-button-font-weight);
363
+ font-size: var(--sk-button-font-size-base);
364
+ line-height: var(--sk-button-line-height);
365
+ text-decoration: none; // Remove underline when rendered as anchor tag
366
+ border-width: var(--sk-button-border-width);
367
+ border-style: solid;
368
+ cursor: pointer;
369
+ user-select: none;
370
+ touch-action: manipulation;
371
+ flex-shrink: 0;
372
+
373
+ // Override list marker color to match component kind
374
+ // Uses generic --sk-kind-color set by kind mixins
375
+ ul li::marker
376
+ {
377
+ color: var(--sk-kind-color, var(--sk-button-color-base));
378
+ }
379
+
380
+ // Apply cut-border mixin for beveled corners with fallback
381
+ @include cut-border(
382
+ $cut: calc(var(--sk-button-height-base) / var(--sk-button-radius-factor)),
383
+ $border-width: var(--sk-button-border-width),
384
+ $border-color: var(--sk-button-border-color),
385
+ $corners: (top-left bottom-right)
386
+ );
387
+
388
+ // Apply glow shadow (only works in modern browsers with corner-shape support)
389
+ // Fallback browsers clip the shadow due to clip-path limitations
390
+ @supports (corner-shape: bevel)
391
+ {
392
+ box-shadow: var(--sk-button-glow-shadow);
393
+ }
394
+
395
+ // Transitions
396
+ transition:
397
+ color var(--sk-button-transition-duration) var(--sk-button-transition-easing),
398
+ background-color var(--sk-button-transition-duration) var(--sk-button-transition-easing),
399
+ border-color var(--sk-button-transition-duration) var(--sk-button-transition-easing),
400
+ box-shadow var(--sk-button-transition-duration) var(--sk-button-transition-easing);
401
+
402
+ // Remove default button styles
403
+ appearance: none;
404
+ font-family: inherit;
405
+
406
+ //------------------------------------------------------------------------------------------------------------------
407
+ // Size variants
408
+ //------------------------------------------------------------------------------------------------------------------
409
+
410
+ &.sk-xs
411
+ {
412
+ --sk-button-cut-size: calc(var(--sk-button-height-base) * var(--sk-button-scale-xs) / var(--sk-button-radius-factor));
413
+
414
+ height: calc(var(--sk-button-height-base) * var(--sk-button-scale-xs));
415
+ padding-left: var(--sk-button-padding-xs);
416
+ padding-right: var(--sk-button-padding-xs);
417
+ font-size: calc(var(--sk-button-font-size-base) * var(--sk-button-font-scale-xs));
418
+
419
+ @include cut-border(
420
+ $cut: var(--sk-button-cut-size),
421
+ $border-width: var(--sk-button-border-width),
422
+ $border-color: var(--sk-button-border-color),
423
+ $corners: (top-left bottom-right)
424
+ );
425
+ }
426
+
427
+ &.sk-sm
428
+ {
429
+ --sk-button-cut-size: calc(var(--sk-button-height-base) * var(--sk-button-scale-sm) / var(--sk-button-radius-factor));
430
+
431
+ height: calc(var(--sk-button-height-base) * var(--sk-button-scale-sm));
432
+ padding-left: var(--sk-button-padding-base);
433
+ padding-right: var(--sk-button-padding-base);
434
+ font-size: calc(var(--sk-button-font-size-base) * var(--sk-button-font-scale-sm));
435
+
436
+ @include cut-border(
437
+ $cut: var(--sk-button-cut-size),
438
+ $border-width: var(--sk-button-border-width),
439
+ $border-color: var(--sk-button-border-color),
440
+ $corners: (top-left bottom-right)
441
+ );
442
+ }
443
+
444
+ &.sk-md
445
+ {
446
+ --sk-button-cut-size: calc(var(--sk-button-height-base) * var(--sk-button-scale-md) / var(--sk-button-radius-factor));
447
+
448
+ height: calc(var(--sk-button-height-base) * var(--sk-button-scale-md));
449
+ padding-left: var(--sk-button-padding-base);
450
+ padding-right: var(--sk-button-padding-base);
451
+ font-size: calc(var(--sk-button-font-size-base) * var(--sk-button-font-scale-md));
452
+
453
+ @include cut-border(
454
+ $cut: var(--sk-button-cut-size),
455
+ $border-width: var(--sk-button-border-width),
456
+ $border-color: var(--sk-button-border-color),
457
+ $corners: (top-left bottom-right)
458
+ );
459
+ }
460
+
461
+ &.sk-lg
462
+ {
463
+ --sk-button-cut-size: calc(var(--sk-button-height-base) * var(--sk-button-scale-lg) / var(--sk-button-radius-factor));
464
+
465
+ height: calc(var(--sk-button-height-base) * var(--sk-button-scale-lg));
466
+ padding-left: var(--sk-button-padding-base);
467
+ padding-right: var(--sk-button-padding-base);
468
+ font-size: calc(var(--sk-button-font-size-base) * var(--sk-button-font-scale-lg));
469
+
470
+ @include cut-border(
471
+ $cut: var(--sk-button-cut-size),
472
+ $border-width: var(--sk-button-border-width),
473
+ $border-color: var(--sk-button-border-color),
474
+ $corners: (top-left bottom-right)
475
+ );
476
+ }
477
+
478
+ &.sk-xl
479
+ {
480
+ --sk-button-cut-size: calc(var(--sk-button-height-base) * var(--sk-button-scale-xl) / var(--sk-button-radius-factor));
481
+
482
+ height: calc(var(--sk-button-height-base) * var(--sk-button-scale-xl));
483
+ padding-left: var(--sk-button-padding-xl);
484
+ padding-right: var(--sk-button-padding-xl);
485
+ font-size: calc(var(--sk-button-font-size-base) * var(--sk-button-font-scale-xl));
486
+
487
+ @include cut-border(
488
+ $cut: var(--sk-button-cut-size),
489
+ $border-width: var(--sk-button-border-width),
490
+ $border-color: var(--sk-button-border-color),
491
+ $corners: (top-left bottom-right)
492
+ );
493
+ }
494
+
495
+ //------------------------------------------------------------------------------------------------------------------
496
+ // Variant: Outline
497
+ //------------------------------------------------------------------------------------------------------------------
498
+
499
+ &.sk-outline
500
+ {
501
+ @each $kind in $kinds
502
+ {
503
+ @include button-outline-kind($kind);
504
+ }
505
+
506
+ // Special case: neutral text and border are lighter for better differentiation
507
+ &.sk-neutral
508
+ {
509
+ --sk-button-border-color: color-mix(in oklch, var(--sk-button-border-base), white 25%);
510
+ color: color-mix(in oklch, var(--sk-button-color-base), white 50%);
511
+ }
512
+ }
513
+
514
+ //------------------------------------------------------------------------------------------------------------------
515
+ // Variant: Solid
516
+ //------------------------------------------------------------------------------------------------------------------
517
+
518
+ &.sk-solid
519
+ {
520
+ @each $kind in $kinds
521
+ {
522
+ @include button-solid-kind($kind);
523
+ }
524
+ }
525
+
526
+ //------------------------------------------------------------------------------------------------------------------
527
+ // Variant: Subtle
528
+ //------------------------------------------------------------------------------------------------------------------
529
+
530
+ &.sk-subtle
531
+ {
532
+ @each $kind in $kinds
533
+ {
534
+ @include button-subtle-kind($kind);
535
+ }
536
+
537
+ // Special case: neutral text and border are lighter (halfway to white) for better differentiation
538
+ &.sk-neutral
539
+ {
540
+ --sk-button-border-color: oklch(
541
+ from color-mix(in oklch, var(--sk-button-border-base), white 50%)
542
+ l c h / var(--sk-button-subtle-border-opacity)
543
+ );
544
+ color: color-mix(in oklch, var(--sk-button-color-base), white 50%);
545
+ }
546
+ }
547
+
548
+ //------------------------------------------------------------------------------------------------------------------
549
+ // Variant: Ghost
550
+ //------------------------------------------------------------------------------------------------------------------
551
+
552
+ &.sk-ghost
553
+ {
554
+ border-color: transparent;
555
+
556
+ @each $kind in $kinds
557
+ {
558
+ @include button-ghost-kind($kind);
559
+ }
560
+
561
+ // Special case: neutral text is lighter (halfway to white) for better differentiation
562
+ &.sk-neutral
563
+ {
564
+ color: color-mix(in oklch, var(--sk-button-color-base), white 50%);
565
+ }
566
+ }
567
+
568
+ //------------------------------------------------------------------------------------------------------------------
569
+ // Variant: Link
570
+ //------------------------------------------------------------------------------------------------------------------
571
+
572
+ &.sk-link
573
+ {
574
+ border-color: transparent;
575
+ padding-left: 0;
576
+ padding-right: 0;
577
+ text-decoration: underline;
578
+ text-underline-offset: 2px;
579
+
580
+ @each $kind in $kinds
581
+ {
582
+ @include button-link-kind($kind);
583
+ }
584
+
585
+ // Special case: neutral text is lighter (halfway to white) for better differentiation
586
+ &.sk-neutral
587
+ {
588
+ color: color-mix(in oklch, var(--sk-button-color-base), white 50%);
589
+
590
+ &:hover:not(:disabled)
591
+ {
592
+ color: color-mix(in oklch, var(--sk-button-color-base), white 60%);
593
+ }
594
+ }
595
+ }
596
+
597
+ //------------------------------------------------------------------------------------------------------------------
598
+ // State: Disabled
599
+ //------------------------------------------------------------------------------------------------------------------
600
+
601
+ &:disabled
602
+ {
603
+ opacity: var(--sk-button-disabled-opacity);
604
+ cursor: not-allowed;
605
+ }
606
+
607
+ //------------------------------------------------------------------------------------------------------------------
608
+ // State: Loading
609
+ //------------------------------------------------------------------------------------------------------------------
610
+
611
+ &.sk-loading
612
+ {
613
+ cursor: wait;
614
+
615
+ .sk-button-content
616
+ {
617
+ opacity: var(--sk-button-loading-opacity);
618
+ }
619
+ }
620
+
621
+ //------------------------------------------------------------------------------------------------------------------
622
+ // State: Pressed (Toggle Button State)
623
+ //------------------------------------------------------------------------------------------------------------------
624
+
625
+ &.sk-pressed
626
+ {
627
+ &.sk-outline,
628
+ &.sk-ghost
629
+ {
630
+ background-color: oklch(from var(--sk-button-bg) l c h / var(--sk-button-subtle-opacity));
631
+ }
632
+
633
+ &.sk-solid
634
+ {
635
+ background-color: var(--sk-button-bg-active);
636
+ }
637
+
638
+ &.sk-subtle
639
+ {
640
+ background-color: var(--sk-button-bg);
641
+ }
642
+ }
643
+
644
+ //------------------------------------------------------------------------------------------------------------------
645
+ // Loading spinner
646
+ //------------------------------------------------------------------------------------------------------------------
647
+
648
+ .sk-button-loader
649
+ {
650
+ position: absolute;
651
+ width: 1em;
652
+ height: 1em;
653
+ border: 2px solid currentColor;
654
+ border-right-color: transparent;
655
+ border-radius: 50%;
656
+ animation: sk-button-spin 0.6s linear infinite;
657
+ }
658
+
659
+ //------------------------------------------------------------------------------------------------------------------
660
+ // Icon support
661
+ //------------------------------------------------------------------------------------------------------------------
662
+
663
+ // Icon-only buttons have square aspect ratio and larger icons
664
+ &.sk-icon-only
665
+ {
666
+ padding-left: 0;
667
+ padding-right: 0;
668
+ aspect-ratio: 1;
669
+
670
+ .sk-button-icon
671
+ {
672
+ font-size: 1.25em;
673
+ }
674
+ }
675
+
676
+ // Icon wrappers
677
+ .sk-button-icon
678
+ {
679
+ display: inline-flex;
680
+ align-items: center;
681
+ justify-content: center;
682
+ flex-shrink: 0;
683
+ line-height: 1;
684
+
685
+ svg
686
+ {
687
+ width: 1em;
688
+ height: 1em;
689
+ display: block;
690
+ }
691
+ }
692
+
693
+ // Button content wrapper
694
+ .sk-button-content
695
+ {
696
+ display: inline-flex;
697
+ align-items: center;
698
+ gap: var(--sk-button-gap);
699
+
700
+ &.loading
701
+ {
702
+ visibility: hidden;
703
+ }
704
+ }
705
+
706
+ // Button text wrapper
707
+ .sk-button-text
708
+ {
709
+ display: inline-flex;
710
+ align-items: center;
711
+ }
712
+ }
713
+
714
+ //----------------------------------------------------------------------------------------------------------------------
715
+ // Animations
716
+ //----------------------------------------------------------------------------------------------------------------------
717
+
718
+ @keyframes sk-button-spin
719
+ {
720
+ from
721
+ {
722
+ transform: rotate(0deg);
723
+ }
724
+
725
+ to
726
+ {
727
+ transform: rotate(360deg);
728
+ }
729
+ }
730
+
731
+ //----------------------------------------------------------------------------------------------------------------------