@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,148 @@
1
+ <!----------------------------------------------------------------------------------------------------------------------
2
+ - Button Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <component
7
+ :is="componentTag"
8
+ :type="componentTag === 'button' ? type : undefined"
9
+ :href="componentTag === 'a' ? href : undefined"
10
+ :to="componentTag === 'router-link' ? to : undefined"
11
+ :disabled="disabled || loading"
12
+ :class="classes"
13
+ :style="customColorStyles"
14
+ :aria-pressed="pressed ? 'true' : undefined"
15
+ :aria-busy="loading ? 'true' : undefined"
16
+ role="button"
17
+ >
18
+ <span v-if="loading" class="sk-button-loader" aria-hidden="true" />
19
+ <span :class="{ 'sk-button-content': true, 'loading': loading }">
20
+ <span v-if="$slots.leading" class="sk-button-icon sk-button-icon-leading">
21
+ <slot name="leading" />
22
+ </span>
23
+ <span v-if="$slots.icon" class="sk-button-icon sk-button-icon-only">
24
+ <slot name="icon" />
25
+ </span>
26
+ <span v-if="$slots.default" class="sk-button-text">
27
+ <slot />
28
+ </span>
29
+ <span v-if="$slots.trailing" class="sk-button-icon sk-button-icon-trailing">
30
+ <slot name="trailing" />
31
+ </span>
32
+ </span>
33
+ </component>
34
+ </template>
35
+
36
+ <!--------------------------------------------------------------------------------------------------------------------->
37
+
38
+ <style lang="scss" scoped>
39
+ // Component styles are implemented in /src/styles/components/_button.scss
40
+ </style>
41
+
42
+ <!--------------------------------------------------------------------------------------------------------------------->
43
+
44
+ <script setup lang="ts">
45
+ /**
46
+ * @component
47
+ * A versatile button component with multiple variants, sizes, and states.
48
+ * Supports rendering as button, link (a), or router-link.
49
+ */
50
+
51
+ import { type Slots, computed, toRef, useSlots } from 'vue';
52
+ import type { SkButtonKind, SkButtonSize, SkButtonType, SkButtonVariant } from './types';
53
+ import type { ComponentCustomColors } from '@/types';
54
+ import { useCustomColors } from '@/composables/useCustomColors';
55
+
56
+ //------------------------------------------------------------------------------------------------------------------
57
+
58
+ /**
59
+ * A versatile button component with multiple variants, sizes, and states.
60
+ * Supports rendering as button, link (a), or router-link.
61
+ */
62
+ export interface SkButtonComponentProps extends ComponentCustomColors
63
+ {
64
+ /** HTML button type attribute */
65
+ type ?: SkButtonType;
66
+ /** Semantic color kind */
67
+ kind ?: SkButtonKind;
68
+ /** Visual variant style */
69
+ variant ?: SkButtonVariant;
70
+ /** Button size */
71
+ size ?: SkButtonSize;
72
+ /** Disabled state */
73
+ disabled ?: boolean;
74
+ /** Loading state with spinner */
75
+ loading ?: boolean;
76
+ /** Toggle pressed state */
77
+ pressed ?: boolean;
78
+ /** Href for anchor tag rendering */
79
+ href ?: string;
80
+ /** Route for router-link rendering */
81
+ to ?: string | Record<string, any>;
82
+ }
83
+
84
+ //------------------------------------------------------------------------------------------------------------------
85
+
86
+ const props = withDefaults(defineProps<SkButtonComponentProps>(), {
87
+ type: 'button',
88
+ kind: 'neutral',
89
+ variant: 'solid',
90
+ size: 'md',
91
+ disabled: false,
92
+ loading: false,
93
+ pressed: false,
94
+ href: undefined,
95
+ to: undefined,
96
+ });
97
+
98
+ //------------------------------------------------------------------------------------------------------------------
99
+
100
+ const slots : Slots = useSlots();
101
+
102
+ //------------------------------------------------------------------------------------------------------------------
103
+
104
+ // Determine which component to render
105
+ const componentTag = computed<string>(() =>
106
+ {
107
+ if(props.to !== undefined)
108
+ {
109
+ return 'router-link';
110
+ }
111
+ else if(props.href !== undefined)
112
+ {
113
+ return 'a';
114
+ }
115
+ else
116
+ {
117
+ return 'button';
118
+ }
119
+ });
120
+
121
+ //------------------------------------------------------------------------------------------------------------------
122
+
123
+ const classes = computed<Record<string, boolean>>(() =>
124
+ {
125
+ const isIconOnly = !!(slots.icon && !slots.default);
126
+
127
+ return {
128
+ 'sk-button': true,
129
+ [`sk-${ props.kind }`]: true,
130
+ [`sk-${ props.variant }`]: true,
131
+ [`sk-${ props.size }`]: true,
132
+ 'sk-loading': props.loading,
133
+ 'sk-pressed': props.pressed,
134
+ 'sk-icon-only': isIconOnly,
135
+ };
136
+ });
137
+
138
+ //------------------------------------------------------------------------------------------------------------------
139
+
140
+ // Custom color styles
141
+ const customColorStyles = useCustomColors(
142
+ 'button',
143
+ toRef(() => props.baseColor),
144
+ toRef(() => props.textColor)
145
+ );
146
+ </script>
147
+
148
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,21 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Button Component Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ import type { ComponentKind, ComponentSize, ComponentVariant } from '@/types';
6
+
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ // HTML button type attribute
10
+ export type SkButtonType = 'button' | 'submit' | 'reset';
11
+
12
+ // Button semantic kinds (uses common types)
13
+ export type SkButtonKind = ComponentKind;
14
+
15
+ // Button visual variants (uses common types)
16
+ export type SkButtonVariant = ComponentVariant;
17
+
18
+ // Button sizes (uses common types)
19
+ export type SkButtonSize = ComponentSize;
20
+
21
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,144 @@
1
+ <!----------------------------------------------------------------------------------------------------------------------
2
+ - Card Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <SkPanel
7
+ :kind="kind"
8
+ :size="size"
9
+ :show-decoration="effectiveShowDecoration"
10
+ :no-border="noBorder"
11
+ :base-color="baseColor"
12
+ :text-color="textColor"
13
+ :class="classes"
14
+ >
15
+ <div v-if="title || $slots.header" class="sk-card-header" :style="headerStyles">
16
+ <h3 v-if="title" class="sk-card-title">
17
+ {{ title }}
18
+ </h3>
19
+ <slot name="header" />
20
+ </div>
21
+ <div v-if="$slots.media" class="sk-card-media">
22
+ <slot name="media" />
23
+ </div>
24
+ <div v-if="$slots.default" :class="contentClasses">
25
+ <slot />
26
+ </div>
27
+ <div v-if="$slots.footer" class="sk-card-footer">
28
+ <slot name="footer" />
29
+ </div>
30
+ </SkPanel>
31
+ </template>
32
+
33
+ <!--------------------------------------------------------------------------------------------------------------------->
34
+
35
+ <script setup lang="ts">
36
+ /**
37
+ * @component
38
+ * A structured card component with optional header, media, content, and footer sections.
39
+ * Built on top of SkPanel with additional styling and layout features.
40
+ */
41
+
42
+ import { computed } from 'vue';
43
+ import SkPanel from '../Panel/SkPanel.vue';
44
+ import type { SkCardKind } from './types';
45
+ import type { SkPanelSize } from '../Panel/types';
46
+ import type { ComponentCustomColors } from '@/types';
47
+
48
+ //------------------------------------------------------------------------------------------------------------------
49
+
50
+ /**
51
+ * A structured card component with optional header, media, content, and footer sections.
52
+ * Built on top of SkPanel with additional styling and layout features.
53
+ */
54
+ export interface SkCardComponentProps extends ComponentCustomColors
55
+ {
56
+ /** Semantic color kind for the card */
57
+ kind ?: SkCardKind;
58
+ /** Size of the card affecting padding and spacing */
59
+ size ?: SkPanelSize;
60
+ /** Whether to show the decorative accent border (when not explicitly disabled by noDecoration) */
61
+ showDecoration ?: boolean;
62
+ /** Explicitly disable the decorative accent border */
63
+ noDecoration ?: boolean;
64
+ /** Whether to hide the card border entirely */
65
+ noBorder ?: boolean;
66
+ /** Optional title text displayed in the header section */
67
+ title ?: string;
68
+ /** Custom background color for the card header */
69
+ headerColor ?: string;
70
+ /** Makes the content area scrollable (card needs a constrained height) */
71
+ scrollable ?: boolean;
72
+ }
73
+
74
+ //------------------------------------------------------------------------------------------------------------------
75
+
76
+ const props = withDefaults(defineProps<SkCardComponentProps>(), {
77
+ kind: 'neutral',
78
+ size: 'md',
79
+ showDecoration: undefined,
80
+ noDecoration: false,
81
+ noBorder: false,
82
+ title: undefined,
83
+ headerColor: undefined,
84
+ scrollable: false,
85
+ });
86
+
87
+ //------------------------------------------------------------------------------------------------------------------
88
+
89
+ const classes = computed(() =>
90
+ {
91
+ return {
92
+ 'sk-card': true,
93
+ };
94
+ });
95
+
96
+ const contentClasses = computed(() =>
97
+ {
98
+ return {
99
+ 'sk-card-content': true,
100
+ 'sk-panel-scroll-content': props.scrollable,
101
+ };
102
+ });
103
+
104
+ //------------------------------------------------------------------------------------------------------------------
105
+
106
+ // Handle decoration prop logic
107
+ const effectiveShowDecoration = computed(() =>
108
+ {
109
+ // noBorder automatically disables decoration
110
+ if(props.noBorder)
111
+ {
112
+ return false;
113
+ }
114
+ // noDecoration takes precedence
115
+ if(props.noDecoration)
116
+ {
117
+ return false;
118
+ }
119
+ // If showDecoration is explicitly set, use it
120
+ if(props.showDecoration !== undefined)
121
+ {
122
+ return props.showDecoration;
123
+ }
124
+ // Default to true
125
+ return true;
126
+ });
127
+
128
+ //------------------------------------------------------------------------------------------------------------------
129
+
130
+ // Header styles - set background color directly
131
+ const headerStyles = computed(() =>
132
+ {
133
+ const styles : Record<string, string> = {};
134
+
135
+ if(props.headerColor)
136
+ {
137
+ styles['background-color'] = props.headerColor;
138
+ }
139
+
140
+ return styles;
141
+ });
142
+ </script>
143
+
144
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,12 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Card Component Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ import type { ComponentKind } from '@/types';
6
+
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ // Card semantic kinds (uses common types)
10
+ export type SkCardKind = ComponentKind;
11
+
12
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,136 @@
1
+ <!----------------------------------------------------------------------------------------------------------------------
2
+ - Checkbox Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <label :class="labelClasses">
7
+ <CheckboxRoot
8
+ v-model="checked"
9
+ :class="classes"
10
+ :style="customColorStyles"
11
+ :disabled="disabled"
12
+ :required="required"
13
+ :name="name"
14
+ >
15
+ <CheckboxIndicator class="sk-checkbox-indicator">
16
+ <!-- Checkmark for checked state -->
17
+ <svg
18
+ v-if="checked === true"
19
+ xmlns="http://www.w3.org/2000/svg"
20
+ viewBox="0 0 24 24"
21
+ fill="none"
22
+ stroke="currentColor"
23
+ stroke-width="3"
24
+ stroke-linecap="square"
25
+ stroke-linejoin="miter"
26
+ class="sk-checkbox-icon"
27
+ >
28
+ <polyline points="20 6 9 17 4 12" />
29
+ </svg>
30
+ <!-- Horizontal line for indeterminate state -->
31
+ <svg
32
+ v-else-if="checked === 'indeterminate'"
33
+ xmlns="http://www.w3.org/2000/svg"
34
+ viewBox="0 0 24 24"
35
+ fill="none"
36
+ stroke="currentColor"
37
+ stroke-width="3"
38
+ stroke-linecap="square"
39
+ class="sk-checkbox-icon"
40
+ >
41
+ <line x1="6" y1="12" x2="18" y2="12" />
42
+ </svg>
43
+ </CheckboxIndicator>
44
+ </CheckboxRoot>
45
+ <span v-if="label || $slots.default" class="sk-checkbox-label">
46
+ <slot>{{ label }}</slot>
47
+ </span>
48
+ </label>
49
+ </template>
50
+
51
+ <!--------------------------------------------------------------------------------------------------------------------->
52
+
53
+ <style lang="scss" scoped>
54
+ // Component styles are implemented in /src/styles/components/_checkbox.scss
55
+ </style>
56
+
57
+ <!--------------------------------------------------------------------------------------------------------------------->
58
+
59
+ <script setup lang="ts">
60
+ /**
61
+ * @component
62
+ * A checkbox component for boolean or indeterminate states powered by RekaUI.
63
+ * Supports semantic color kinds and flexible sizing.
64
+ */
65
+
66
+ import { computed, toRef } from 'vue';
67
+ import { CheckboxIndicator, CheckboxRoot } from 'reka-ui';
68
+
69
+ // Types
70
+ import type { ComponentCustomColors } from '@/types';
71
+ import type { SkCheckboxKind, SkCheckboxSize } from './types';
72
+
73
+ // Composables
74
+ import { useCustomColors } from '@/composables/useCustomColors';
75
+
76
+ //------------------------------------------------------------------------------------------------------------------
77
+
78
+ /**
79
+ * A checkbox component for boolean or indeterminate states powered by RekaUI.
80
+ */
81
+ export interface SkCheckboxComponentProps extends ComponentCustomColors
82
+ {
83
+ /** Semantic color kind */
84
+ kind ?: SkCheckboxKind;
85
+ /** Checkbox size */
86
+ size ?: SkCheckboxSize;
87
+ /** Disabled state */
88
+ disabled ?: boolean;
89
+ /** Required for form validation */
90
+ required ?: boolean;
91
+ /** Form field name */
92
+ name ?: string;
93
+ /** Label text (can be overridden by default slot) */
94
+ label ?: string;
95
+ }
96
+
97
+ //------------------------------------------------------------------------------------------------------------------
98
+
99
+ const props = withDefaults(defineProps<SkCheckboxComponentProps>(), {
100
+ kind: 'neutral',
101
+ size: 'md',
102
+ disabled: false,
103
+ required: false,
104
+ name: undefined,
105
+ label: undefined,
106
+ });
107
+
108
+ //------------------------------------------------------------------------------------------------------------------
109
+
110
+ const checked = defineModel<boolean | 'indeterminate'>({ default: false });
111
+
112
+ //------------------------------------------------------------------------------------------------------------------
113
+
114
+ const classes = computed(() => ({
115
+ 'sk-checkbox': true,
116
+ [`sk-${ props.kind }`]: true,
117
+ [`sk-${ props.size }`]: true,
118
+ }));
119
+
120
+ //------------------------------------------------------------------------------------------------------------------
121
+
122
+ const labelClasses = computed(() => ({
123
+ 'sk-checkbox-wrapper': true,
124
+ 'sk-disabled': props.disabled,
125
+ }));
126
+
127
+ //------------------------------------------------------------------------------------------------------------------
128
+
129
+ const customColorStyles = useCustomColors(
130
+ 'checkbox',
131
+ toRef(() => props.baseColor),
132
+ toRef(() => props.textColor)
133
+ );
134
+ </script>
135
+
136
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,8 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Checkbox Component Exports
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default as SkCheckbox } from './SkCheckbox.vue';
6
+ export type { SkCheckboxKind, SkCheckboxSize } from './types';
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,10 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Checkbox Component Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ import type { ComponentKind, ComponentSize } from '@/types';
6
+
7
+ export type SkCheckboxKind = ComponentKind;
8
+ export type SkCheckboxSize = ComponentSize;
9
+
10
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,159 @@
1
+ <!----------------------------------------------------------------------------------------------------------------------
2
+ - Collapsible Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <CollapsibleRoot
7
+ v-model:open="isOpen"
8
+ :disabled="disabled"
9
+ :class="classes"
10
+ :style="customColorStyles"
11
+ >
12
+ <CollapsibleTrigger as-child>
13
+ <slot name="trigger" :open="isOpen">
14
+ <SkButton
15
+ :kind="baseColor ? undefined : kind"
16
+ :base-color="baseColor"
17
+ :text-color="textColor"
18
+ variant="ghost"
19
+ >
20
+ {{ triggerText }}
21
+ <template #trailing>
22
+ <svg
23
+ xmlns="http://www.w3.org/2000/svg"
24
+ viewBox="0 0 24 24"
25
+ fill="none"
26
+ stroke="currentColor"
27
+ stroke-width="2"
28
+ stroke-linecap="square"
29
+ stroke-linejoin="miter"
30
+ :class="chevronClasses"
31
+ style="width: 1rem; height: 1rem;"
32
+ >
33
+ <polyline points="6 9 12 15 18 9" />
34
+ </svg>
35
+ </template>
36
+ </SkButton>
37
+ </slot>
38
+ </CollapsibleTrigger>
39
+ <CollapsibleContent class="sk-collapsible-content">
40
+ <div class="sk-collapsible-content-inner">
41
+ <slot />
42
+ </div>
43
+ </CollapsibleContent>
44
+ </CollapsibleRoot>
45
+ </template>
46
+
47
+ <!--------------------------------------------------------------------------------------------------------------------->
48
+
49
+ <style lang="scss" scoped>
50
+ // Collapsible styles are implemented in /src/styles/components/_collapsible.scss
51
+ </style>
52
+
53
+ <!--------------------------------------------------------------------------------------------------------------------->
54
+
55
+ <script setup lang="ts">
56
+ /**
57
+ * @component
58
+ * Collapsible component for showing/hiding content with smooth animations.
59
+ */
60
+
61
+ import { computed, toRef } from 'vue';
62
+ import {
63
+ CollapsibleContent,
64
+ CollapsibleRoot,
65
+ CollapsibleTrigger,
66
+ } from 'reka-ui';
67
+
68
+ // Types
69
+ import type { ComponentCustomColors } from '@/types';
70
+ import type { SkCollapsibleKind } from './types';
71
+
72
+ // Components
73
+ import SkButton from '../Button/SkButton.vue';
74
+
75
+ // Composables
76
+ import { useCustomColors } from '@/composables/useCustomColors';
77
+
78
+ //------------------------------------------------------------------------------------------------------------------
79
+
80
+ /**
81
+ * Collapsible component for showing/hiding content with smooth animations.
82
+ *
83
+ * @example Basic usage
84
+ * ```vue
85
+ * <SkCollapsible v-model:open="isOpen" trigger-text="Show more">
86
+ * <p>Hidden content here</p>
87
+ * </SkCollapsible>
88
+ * ```
89
+ *
90
+ * @example Custom trigger
91
+ * ```vue
92
+ * <SkCollapsible v-model:open="isOpen">
93
+ * <template #trigger="{ open }">
94
+ * <SkButton>{{ open ? 'Hide' : 'Show' }} Details</SkButton>
95
+ * </template>
96
+ * <p>Collapsible content here</p>
97
+ * </SkCollapsible>
98
+ * ```
99
+ */
100
+ export interface SkCollapsibleComponentProps extends ComponentCustomColors
101
+ {
102
+ /** Controlled state (v-model:open) */
103
+ open ?: boolean;
104
+ /** Initial uncontrolled state */
105
+ defaultOpen ?: boolean;
106
+ /** Disable interaction */
107
+ disabled ?: boolean;
108
+ /** Semantic color kind */
109
+ kind ?: SkCollapsibleKind;
110
+ /** Text for default trigger */
111
+ triggerText ?: string;
112
+ }
113
+
114
+ //------------------------------------------------------------------------------------------------------------------
115
+
116
+ const props = withDefaults(defineProps<SkCollapsibleComponentProps>(), {
117
+ open: undefined,
118
+ defaultOpen: false,
119
+ disabled: false,
120
+ kind: 'neutral',
121
+ triggerText: 'Toggle',
122
+ });
123
+
124
+ const emit = defineEmits<{
125
+ 'update:open' : [ value : boolean ];
126
+ }>();
127
+
128
+ //------------------------------------------------------------------------------------------------------------------
129
+
130
+ // Two-way binding for open state
131
+ const isOpen = computed({
132
+ get: () => props.open,
133
+ set: (value) => emit('update:open', value ?? false),
134
+ });
135
+
136
+ //------------------------------------------------------------------------------------------------------------------
137
+
138
+ const classes = computed(() => ({
139
+ 'sk-collapsible': true,
140
+ // Only apply kind class if custom colors are NOT provided
141
+ [`sk-${ props.kind }`]: !props.baseColor,
142
+ 'sk-open': isOpen.value,
143
+ }));
144
+
145
+ const chevronClasses = computed(() => ({
146
+ 'sk-collapsible-chevron': true,
147
+ 'sk-open': isOpen.value,
148
+ }));
149
+
150
+ //------------------------------------------------------------------------------------------------------------------
151
+
152
+ const customColorStyles = useCustomColors(
153
+ 'collapsible',
154
+ toRef(() => props.baseColor),
155
+ toRef(() => props.textColor)
156
+ );
157
+ </script>
158
+
159
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,2 @@
1
+ export { default as SkCollapsible } from './SkCollapsible.vue';
2
+ export * from './types';
@@ -0,0 +1,8 @@
1
+ // Types
2
+ import type { ComponentKind } from '@/types';
3
+
4
+ //----------------------------------------------------------------------------------------------------------------------
5
+
6
+ export type SkCollapsibleKind = ComponentKind;
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------