@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,137 @@
1
+ <!--------------------------------------------------------------------------------------------------------------------
2
+ - Alert Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <div :class="classes" :style="customColorStyles" role="alert">
7
+ <div class="sk-alert-icon">
8
+ <slot name="icon">
9
+ <!-- Default icons for each kind -->
10
+ <svg
11
+ v-if="kind === 'info'"
12
+ viewBox="0 0 24 24"
13
+ fill="none"
14
+ stroke="currentColor"
15
+ stroke-width="2"
16
+ >
17
+ <circle cx="12" cy="12" r="10" />
18
+ <line x1="12" y1="16" x2="12" y2="12" />
19
+ <circle cx="12" cy="8" r="0.5" fill="currentColor" />
20
+ </svg>
21
+ <svg
22
+ v-else-if="kind === 'success'"
23
+ viewBox="0 0 24 24"
24
+ fill="none"
25
+ stroke="currentColor"
26
+ stroke-width="2"
27
+ >
28
+ <path d="M22 11.08V12a10 10 0 1 1-5.93-9.14" />
29
+ <polyline points="22 4 12 14.01 9 11.01" />
30
+ </svg>
31
+ <svg
32
+ v-else-if="kind === 'warning'"
33
+ viewBox="0 0 24 24"
34
+ fill="none"
35
+ stroke="currentColor"
36
+ stroke-width="2"
37
+ >
38
+ <path
39
+ d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"
40
+ />
41
+ <line x1="12" y1="9" x2="12" y2="13" />
42
+ <circle cx="12" cy="17" r="0.5" fill="currentColor" />
43
+ </svg>
44
+ <svg
45
+ v-else-if="kind === 'danger'"
46
+ viewBox="0 0 24 24"
47
+ fill="none"
48
+ stroke="currentColor"
49
+ stroke-width="2"
50
+ >
51
+ <circle cx="12" cy="12" r="10" />
52
+ <line x1="15" y1="9" x2="9" y2="15" />
53
+ <line x1="9" y1="9" x2="15" y2="15" />
54
+ </svg>
55
+ </slot>
56
+ </div>
57
+ <div class="sk-alert-content">
58
+ <slot />
59
+ </div>
60
+ </div>
61
+ </template>
62
+
63
+ <!--------------------------------------------------------------------------------------------------------------------->
64
+
65
+ <script setup lang="ts">
66
+ /**
67
+ * @component
68
+ * A flexible alert component for displaying informational messages.
69
+ * Supports multiple semantic kinds (info, success, warning, danger) with optional prominent styling.
70
+ */
71
+
72
+ import { computed, toRef } from 'vue';
73
+ import type { SkAlertKind } from './types';
74
+ import type { ComponentCustomColors } from '@/types';
75
+ import { useCustomColors } from '@/composables/useCustomColors';
76
+
77
+ //------------------------------------------------------------------------------------------------------------------
78
+
79
+ /**
80
+ * A flexible alert component for displaying informational messages.
81
+ * Supports multiple semantic kinds (info, success, warning, danger) with optional prominent styling.
82
+ *
83
+ * @example Basic alert
84
+ * ```vue
85
+ * <SkAlert kind="success">
86
+ * Your changes have been saved!
87
+ * </SkAlert>
88
+ * ```
89
+ *
90
+ * @example Custom colors
91
+ * ```vue
92
+ * <SkAlert
93
+ * base-color="oklch(0.65 0.25 280)"
94
+ * text-color="white"
95
+ * prominent
96
+ * >
97
+ * Custom purple alert with custom colors
98
+ * </SkAlert>
99
+ * ```
100
+ */
101
+ export interface SkAlertComponentProps extends ComponentCustomColors
102
+ {
103
+ /** Semantic kind determining the alert color and icon (info, success, warning, danger) */
104
+ kind ?: SkAlertKind;
105
+ /** Whether to use prominent styling with darker background and bolder appearance */
106
+ prominent ?: boolean;
107
+ }
108
+
109
+ //------------------------------------------------------------------------------------------------------------------
110
+
111
+ const props = withDefaults(defineProps<SkAlertComponentProps>(), {
112
+ kind: 'info',
113
+ prominent: false,
114
+ });
115
+
116
+ //------------------------------------------------------------------------------------------------------------------
117
+
118
+ const classes = computed(() =>
119
+ {
120
+ return {
121
+ 'sk-alert': true,
122
+ [`sk-${ props.kind }`]: true,
123
+ 'sk-prominent': props.prominent,
124
+ };
125
+ });
126
+
127
+ //------------------------------------------------------------------------------------------------------------------
128
+
129
+ // Custom color styles
130
+ const customColorStyles = useCustomColors(
131
+ 'alert',
132
+ toRef(() => props.baseColor),
133
+ toRef(() => props.textColor)
134
+ );
135
+ </script>
136
+
137
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,10 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Alert Component Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ /**
6
+ * Alert semantic kinds (feedback-focused subset)
7
+ */
8
+ export type SkAlertKind = 'info' | 'success' | 'warning' | 'danger';
9
+
10
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,141 @@
1
+ <template>
2
+ <div
3
+ :class="classes"
4
+ :style="customStyles"
5
+ >
6
+ <img
7
+ v-if="src && !imageError"
8
+ :src="src"
9
+ :alt="alt"
10
+ class="sk-avatar-image"
11
+ @error="handleImageError"
12
+ >
13
+ <span
14
+ v-else-if="initials"
15
+ class="sk-avatar-initials"
16
+ >
17
+ {{ displayInitials }}
18
+ </span>
19
+ <slot v-else name="icon">
20
+ <svg
21
+ class="sk-avatar-icon"
22
+ viewBox="0 0 24 24"
23
+ fill="currentColor"
24
+ >
25
+ <path d="M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" />
26
+ </svg>
27
+ </slot>
28
+ </div>
29
+ </template>
30
+
31
+ <!--------------------------------------------------------------------------------------------------------------------->
32
+
33
+ <style lang="scss" scoped>
34
+ // Component styles are implemented in /src/styles/components/_avatar.scss
35
+ </style>
36
+
37
+ <!--------------------------------------------------------------------------------------------------------------------->
38
+
39
+ <script setup lang="ts">
40
+ /**
41
+ * @component SkAvatar
42
+ * A user profile avatar component with image, initials, or icon fallback.
43
+ * Square shape with beveled top-left and bottom-right corners.
44
+ * Supports all 7 semantic kinds and custom colors.
45
+ */
46
+
47
+ import { computed, ref } from 'vue';
48
+
49
+ // Types
50
+ import type { ComponentKind } from '@/types';
51
+ import type { SkAvatarSize } from './types';
52
+
53
+ //------------------------------------------------------------------------------------------------------------------
54
+
55
+ export interface SkAvatarComponentProps
56
+ {
57
+ /** Image source URL */
58
+ src ?: string;
59
+ /** Alt text for image */
60
+ alt ?: string;
61
+ /** Fallback initials (1-2 characters) */
62
+ initials ?: string;
63
+ /** Semantic color kind */
64
+ kind ?: ComponentKind;
65
+ /** Avatar size */
66
+ size ?: SkAvatarSize;
67
+ /** Custom background color (overrides kind) */
68
+ baseColor ?: string;
69
+ /** Custom text color */
70
+ textColor ?: string;
71
+ }
72
+
73
+ //------------------------------------------------------------------------------------------------------------------
74
+
75
+ const props = withDefaults(defineProps<SkAvatarComponentProps>(), {
76
+ src: undefined,
77
+ alt: '',
78
+ initials: undefined,
79
+ kind: 'neutral',
80
+ size: 'md',
81
+ baseColor: undefined,
82
+ textColor: undefined,
83
+ });
84
+
85
+ //------------------------------------------------------------------------------------------------------------------
86
+ // State
87
+ //------------------------------------------------------------------------------------------------------------------
88
+
89
+ const imageError = ref(false);
90
+
91
+ //------------------------------------------------------------------------------------------------------------------
92
+ // Computed
93
+ //------------------------------------------------------------------------------------------------------------------
94
+
95
+ const displayInitials = computed(() =>
96
+ {
97
+ if(!props.initials)
98
+ {
99
+ return '';
100
+ }
101
+ return props.initials.slice(0, 2).toUpperCase();
102
+ });
103
+
104
+ const classes = computed(() => ({
105
+ 'sk-avatar': true,
106
+ [`sk-${ props.kind }`]: true,
107
+ [`sk-${ props.size }`]: true,
108
+ }));
109
+
110
+ //------------------------------------------------------------------------------------------------------------------
111
+ // Custom Colors
112
+ //------------------------------------------------------------------------------------------------------------------
113
+
114
+ const customStyles = computed(() =>
115
+ {
116
+ const styles : Record<string, string> = {};
117
+
118
+ if(props.baseColor)
119
+ {
120
+ styles['--sk-avatar-color-base'] = props.baseColor;
121
+ }
122
+
123
+ if(props.textColor)
124
+ {
125
+ styles['--sk-avatar-fg'] = props.textColor;
126
+ }
127
+
128
+ return styles;
129
+ });
130
+
131
+ //------------------------------------------------------------------------------------------------------------------
132
+ // Methods
133
+ //------------------------------------------------------------------------------------------------------------------
134
+
135
+ function handleImageError() : void
136
+ {
137
+ imageError.value = true;
138
+ }
139
+ </script>
140
+
141
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,8 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Avatar Component
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default } from './SkAvatar.vue';
6
+ export * from './types';
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,31 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Avatar Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ import type { ComponentKind, ComponentSize } from '@/types';
6
+
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ /** Avatar size */
10
+ export type SkAvatarSize = ComponentSize;
11
+
12
+ /** Avatar props interface */
13
+ export interface SkAvatarProps
14
+ {
15
+ /** Image source URL */
16
+ src ?: string;
17
+ /** Alt text for image */
18
+ alt ?: string;
19
+ /** Fallback initials (1-2 characters) */
20
+ initials ?: string;
21
+ /** Semantic color kind */
22
+ kind ?: ComponentKind;
23
+ /** Avatar size */
24
+ size ?: SkAvatarSize;
25
+ /** Custom background color (overrides kind) */
26
+ baseColor ?: string;
27
+ /** Custom text color */
28
+ textColor ?: string;
29
+ }
30
+
31
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,76 @@
1
+ <template>
2
+ <li class="sk-breadcrumb-item">
3
+ <component
4
+ :is="componentTag"
5
+ :class="linkClasses"
6
+ :to="to"
7
+ :href="href"
8
+ :aria-current="current ? 'page' : undefined"
9
+ :disabled="disabled"
10
+ >
11
+ <slot name="icon" />
12
+ <slot />
13
+ </component>
14
+ </li>
15
+ </template>
16
+
17
+ <!--------------------------------------------------------------------------------------------------------------------->
18
+
19
+ <style lang="scss" scoped>
20
+ // Styles implemented in /src/styles/components/_breadcrumbs.scss
21
+ </style>
22
+
23
+ <!--------------------------------------------------------------------------------------------------------------------->
24
+
25
+ <script setup lang="ts">
26
+ import { computed, inject } from 'vue';
27
+ import { RouterLink } from 'vue-router';
28
+
29
+ // Types
30
+ import type { SkBreadcrumbItemProps, SkBreadcrumbsKind } from './types';
31
+
32
+ //------------------------------------------------------------------------------------------------------------------
33
+
34
+ export type SkBreadcrumbItemComponentProps = SkBreadcrumbItemProps;
35
+
36
+ //------------------------------------------------------------------------------------------------------------------
37
+
38
+ const props = withDefaults(defineProps<SkBreadcrumbItemComponentProps>(), {
39
+ to: undefined,
40
+ href: undefined,
41
+ current: false,
42
+ disabled: false,
43
+ });
44
+
45
+ //------------------------------------------------------------------------------------------------------------------
46
+
47
+ const kind = inject<SkBreadcrumbsKind>('breadcrumbs-kind', 'neutral');
48
+
49
+ //------------------------------------------------------------------------------------------------------------------
50
+
51
+ const componentTag = computed<string | typeof RouterLink>(() =>
52
+ {
53
+ if(props.current || props.disabled)
54
+ {
55
+ return 'span';
56
+ }
57
+ if(props.to !== undefined)
58
+ {
59
+ return RouterLink;
60
+ }
61
+ if(props.href !== undefined)
62
+ {
63
+ return 'a';
64
+ }
65
+ return 'button';
66
+ });
67
+
68
+ const linkClasses = computed(() => ({
69
+ 'sk-breadcrumb-link': true,
70
+ [`sk-${ kind }`]: true,
71
+ }));
72
+
73
+ //------------------------------------------------------------------------------------------------------------------
74
+ </script>
75
+
76
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,38 @@
1
+ <template>
2
+ <span class="sk-breadcrumb-separator" aria-hidden="true">
3
+ {{ displaySeparator }}
4
+ </span>
5
+ </template>
6
+
7
+ <!--------------------------------------------------------------------------------------------------------------------->
8
+
9
+ <style lang="scss" scoped>
10
+ // Styles implemented in /src/styles/components/_breadcrumbs.scss
11
+ </style>
12
+
13
+ <!--------------------------------------------------------------------------------------------------------------------->
14
+
15
+ <script setup lang="ts">
16
+ import { computed, inject } from 'vue';
17
+
18
+ // Types
19
+ import type { SkBreadcrumbSeparatorProps } from './types';
20
+
21
+ //------------------------------------------------------------------------------------------------------------------
22
+
23
+ const props = withDefaults(defineProps<SkBreadcrumbSeparatorProps>(), {
24
+ separator: undefined,
25
+ });
26
+
27
+ //------------------------------------------------------------------------------------------------------------------
28
+
29
+ const parentSeparator = inject<string>('breadcrumbs-separator', '/');
30
+
31
+ //------------------------------------------------------------------------------------------------------------------
32
+
33
+ const displaySeparator = computed<string>(() => props.separator ?? parentSeparator);
34
+
35
+ //------------------------------------------------------------------------------------------------------------------
36
+ </script>
37
+
38
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,93 @@
1
+ <template>
2
+ <nav :class="classes" :style="customColorStyles" aria-label="Breadcrumb">
3
+ <ol class="sk-breadcrumbs-list">
4
+ <template v-for="(item, index) in processedItems" :key="index">
5
+ <component :is="item" />
6
+ <SkBreadcrumbSeparator v-if="index < processedItems.length - 1" />
7
+ </template>
8
+ </ol>
9
+ </nav>
10
+ </template>
11
+
12
+ <!--------------------------------------------------------------------------------------------------------------------->
13
+
14
+ <style lang="scss" scoped>
15
+ // Styles implemented in /src/styles/components/_breadcrumbs.scss
16
+ </style>
17
+
18
+ <!--------------------------------------------------------------------------------------------------------------------->
19
+
20
+ <script setup lang="ts">
21
+ import { type Slots, type VNode, computed, provide, toRef, useSlots } from 'vue';
22
+
23
+ // Types
24
+ import type { ComponentCustomColors } from '@/types';
25
+ import type { SkBreadcrumbsProps } from './types';
26
+
27
+ //------------------------------------------------------------------------------------------------------------------
28
+
29
+ export interface SkBreadcrumbsComponentProps extends SkBreadcrumbsProps, ComponentCustomColors
30
+ {
31
+ }
32
+
33
+ //------------------------------------------------------------------------------------------------------------------
34
+
35
+ // Components
36
+ import SkBreadcrumbSeparator from './SkBreadcrumbSeparator.vue';
37
+
38
+ // Composables
39
+ import { useCustomColors } from '@/composables/useCustomColors';
40
+
41
+ //------------------------------------------------------------------------------------------------------------------
42
+
43
+ const props = withDefaults(defineProps<SkBreadcrumbsComponentProps>(), {
44
+ kind: 'neutral',
45
+ separator: '/',
46
+ baseColor: undefined,
47
+ textColor: undefined,
48
+ });
49
+
50
+ //------------------------------------------------------------------------------------------------------------------
51
+
52
+ const slots : Slots = useSlots();
53
+
54
+ //------------------------------------------------------------------------------------------------------------------
55
+
56
+ provide('breadcrumbs-kind', toRef(() => props.kind));
57
+ provide('breadcrumbs-separator', toRef(() => props.separator));
58
+
59
+ //------------------------------------------------------------------------------------------------------------------
60
+
61
+ const customColorStyles = useCustomColors(
62
+ 'breadcrumbs',
63
+ toRef(() => props.baseColor),
64
+ toRef(() => props.textColor)
65
+ );
66
+
67
+ //------------------------------------------------------------------------------------------------------------------
68
+
69
+ const classes = computed(() => ({
70
+ 'sk-breadcrumbs': true,
71
+ [`sk-${ props.kind }`]: true,
72
+ }));
73
+
74
+ const processedItems = computed<VNode[]>(() =>
75
+ {
76
+ if(!slots.default)
77
+ {
78
+ return [];
79
+ }
80
+
81
+ const defaultSlot = slots.default();
82
+ if(!defaultSlot || defaultSlot.length === 0)
83
+ {
84
+ return [];
85
+ }
86
+
87
+ return defaultSlot;
88
+ });
89
+
90
+ //------------------------------------------------------------------------------------------------------------------
91
+ </script>
92
+
93
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,10 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Breadcrumbs Components
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default as SkBreadcrumbItem } from './SkBreadcrumbItem.vue';
6
+ export { default as SkBreadcrumbs } from './SkBreadcrumbs.vue';
7
+ export { default as SkBreadcrumbSeparator } from './SkBreadcrumbSeparator.vue';
8
+ export * from './types';
9
+
10
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,36 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Types for SkBreadcrumbs
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ // Types
6
+ import type { ComponentKind } from '@/types';
7
+ import type { RouteLocationRaw } from 'vue-router';
8
+
9
+ //----------------------------------------------------------------------------------------------------------------------
10
+
11
+ export type SkBreadcrumbsKind = ComponentKind;
12
+
13
+ //----------------------------------------------------------------------------------------------------------------------
14
+
15
+ export interface SkBreadcrumbsProps
16
+ {
17
+ kind ?: SkBreadcrumbsKind;
18
+ separator ?: string;
19
+ baseColor ?: string;
20
+ textColor ?: string;
21
+ }
22
+
23
+ export interface SkBreadcrumbItemProps
24
+ {
25
+ to ?: string | RouteLocationRaw;
26
+ href ?: string;
27
+ current ?: boolean;
28
+ disabled ?: boolean;
29
+ }
30
+
31
+ export interface SkBreadcrumbSeparatorProps
32
+ {
33
+ separator ?: string;
34
+ }
35
+
36
+ //----------------------------------------------------------------------------------------------------------------------