@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,107 @@
1
+ <template>
2
+ <button
3
+ :class="classes"
4
+ :disabled="disabled || type === 'ellipsis'"
5
+ :aria-label="ariaLabel"
6
+ :aria-current="active ? 'page' : undefined"
7
+ @click="handleClick"
8
+ >
9
+ <span v-if="type === 'prev'">‹</span>
10
+ <span v-else-if="type === 'next'">›</span>
11
+ <span v-else-if="type === 'first'">‹‹</span>
12
+ <span v-else-if="type === 'last'">››</span>
13
+ <span v-else-if="type === 'ellipsis'">...</span>
14
+ <span v-else>{{ page }}</span>
15
+ </button>
16
+ </template>
17
+
18
+ <!--------------------------------------------------------------------------------------------------------------------->
19
+
20
+ <style lang="scss" scoped>
21
+ // Styles implemented in /src/styles/components/_pagination.scss
22
+ </style>
23
+
24
+ <!--------------------------------------------------------------------------------------------------------------------->
25
+
26
+ <script setup lang="ts">
27
+ import { type Ref, computed, inject } from 'vue';
28
+
29
+ // Types
30
+ import type { SkPaginationItemProps, SkPaginationKind, SkPaginationSize, SkPaginationVariant } from './types';
31
+
32
+ //------------------------------------------------------------------------------------------------------------------
33
+
34
+ export type SkPaginationItemComponentProps = SkPaginationItemProps;
35
+
36
+ //------------------------------------------------------------------------------------------------------------------
37
+
38
+ const props = withDefaults(defineProps<SkPaginationItemComponentProps>(), {
39
+ page: undefined,
40
+ active: false,
41
+ disabled: false,
42
+ type: 'page',
43
+ });
44
+
45
+ const emit = defineEmits<{
46
+ click : [ page : number ];
47
+ }>();
48
+
49
+ //------------------------------------------------------------------------------------------------------------------
50
+
51
+ const kindRef = inject<Ref<SkPaginationKind>>('pagination-kind');
52
+ const sizeRef = inject<Ref<SkPaginationSize>>('pagination-size');
53
+ const variantRef = inject<Ref<SkPaginationVariant>>('pagination-variant');
54
+
55
+ const kind = computed(() => kindRef?.value ?? 'neutral');
56
+ const size = computed(() => sizeRef?.value ?? 'md');
57
+ const variant = computed(() => variantRef?.value ?? 'solid');
58
+
59
+ //------------------------------------------------------------------------------------------------------------------
60
+
61
+ const classes = computed(() => ({
62
+ 'sk-pagination-item': true,
63
+ [`sk-${ kind.value }`]: true,
64
+ [`sk-${ size.value }`]: true,
65
+ [`sk-${ variant.value }`]: true,
66
+ 'sk-active': props.active,
67
+ 'sk-ellipsis': props.type === 'ellipsis',
68
+ }));
69
+
70
+ const ariaLabel = computed(() =>
71
+ {
72
+ switch (props.type)
73
+ {
74
+ case 'prev':
75
+ return 'Previous page';
76
+ case 'next':
77
+ return 'Next page';
78
+ case 'first':
79
+ return 'First page';
80
+ case 'last':
81
+ return 'Last page';
82
+ case 'page':
83
+ return `Page ${ props.page }`;
84
+ default:
85
+ return undefined;
86
+ }
87
+ });
88
+
89
+ //------------------------------------------------------------------------------------------------------------------
90
+
91
+ function handleClick() : void
92
+ {
93
+ if(props.type === 'ellipsis' || props.disabled)
94
+ {
95
+ return;
96
+ }
97
+
98
+ if(props.page !== undefined)
99
+ {
100
+ emit('click', props.page);
101
+ }
102
+ }
103
+
104
+ //------------------------------------------------------------------------------------------------------------------
105
+ </script>
106
+
107
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,9 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Pagination Components
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default as SkPagination } from './SkPagination.vue';
6
+ export { default as SkPaginationItem } from './SkPaginationItem.vue';
7
+ export * from './types';
8
+
9
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,40 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Types for SkPagination
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ // Types
6
+ import type { ComponentKind, ComponentSize } from '@/types';
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
9
+
10
+ export type SkPaginationKind = ComponentKind;
11
+ export type SkPaginationSize = ComponentSize;
12
+ export type SkPaginationVariant = 'solid' | 'outline' | 'subtle' | 'ghost';
13
+ export type SkPaginationItemType = 'page' | 'prev' | 'next' | 'ellipsis' | 'first' | 'last';
14
+
15
+ //----------------------------------------------------------------------------------------------------------------------
16
+
17
+ export interface SkPaginationProps
18
+ {
19
+ modelValue ?: number;
20
+ total : number;
21
+ siblingCount ?: number;
22
+ showFirstLast ?: boolean;
23
+ showPrevNext ?: boolean;
24
+ kind ?: SkPaginationKind;
25
+ size ?: SkPaginationSize;
26
+ variant ?: SkPaginationVariant;
27
+ disabled ?: boolean;
28
+ baseColor ?: string;
29
+ textColor ?: string;
30
+ }
31
+
32
+ export interface SkPaginationItemProps
33
+ {
34
+ page ?: number;
35
+ active ?: boolean;
36
+ disabled ?: boolean;
37
+ type : SkPaginationItemType;
38
+ }
39
+
40
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,96 @@
1
+ <!----------------------------------------------------------------------------------------------------------------------
2
+ - Panel Component
3
+ --------------------------------------------------------------------------------------------------------------------->
4
+
5
+ <template>
6
+ <div :class="classes" :style="customColorStyles">
7
+ <slot />
8
+ </div>
9
+ </template>
10
+
11
+ <!--------------------------------------------------------------------------------------------------------------------->
12
+
13
+ <style lang="scss" scoped>
14
+ // Control decoration visibility via v-bind
15
+ .sk-panel::after {
16
+ display: v-bind('decorationDisplay');
17
+ }
18
+ </style>
19
+
20
+ <!--------------------------------------------------------------------------------------------------------------------->
21
+
22
+ <script setup lang="ts">
23
+ /**
24
+ * @component
25
+ * A foundational container component with borders, background colors, and optional decorative accents.
26
+ * Serves as the base for other components like SkCard and SkSidebar.
27
+ */
28
+
29
+ import { computed, toRef } from 'vue';
30
+ import type { SkPanelKind, SkPanelSize } from './types';
31
+ import type { ComponentCustomColors } from '@/types';
32
+ import { useCustomColors } from '@/composables/useCustomColors';
33
+
34
+ //------------------------------------------------------------------------------------------------------------------
35
+
36
+ /**
37
+ * A foundational container component with borders, background colors, and optional decorative accents.
38
+ * Serves as the base for other components like SkCard and SkSidebar.
39
+ */
40
+ export interface SkPanelComponentProps extends ComponentCustomColors
41
+ {
42
+ /** Semantic color kind for the panel */
43
+ kind ?: SkPanelKind;
44
+ /** Size affecting padding and spacing inside the panel */
45
+ size ?: SkPanelSize;
46
+ /** Whether to display the decorative accent border */
47
+ showDecoration ?: boolean;
48
+ /** Whether to remove the border entirely */
49
+ noBorder ?: boolean;
50
+ }
51
+
52
+ //------------------------------------------------------------------------------------------------------------------
53
+
54
+ const props = withDefaults(defineProps<SkPanelComponentProps>(), {
55
+ kind: 'neutral',
56
+ size: 'md',
57
+ showDecoration: true,
58
+ noBorder: false,
59
+ });
60
+
61
+ //------------------------------------------------------------------------------------------------------------------
62
+
63
+ const classes = computed(() =>
64
+ {
65
+ return {
66
+ 'sk-panel': true,
67
+ [`sk-${ props.kind }`]: true,
68
+ [`sk-${ props.size }`]: true,
69
+ 'sk-no-border': props.noBorder,
70
+ };
71
+ });
72
+
73
+ //------------------------------------------------------------------------------------------------------------------
74
+
75
+ // Custom color styles
76
+ const customColorStyles = useCustomColors(
77
+ 'panel',
78
+ toRef(() => props.baseColor),
79
+ toRef(() => props.textColor)
80
+ );
81
+
82
+ //------------------------------------------------------------------------------------------------------------------
83
+
84
+ // Control decoration visibility
85
+ // Note: noBorder automatically disables decoration
86
+ const decorationDisplay = computed(() =>
87
+ {
88
+ if(props.noBorder)
89
+ {
90
+ return 'none';
91
+ }
92
+ return props.showDecoration ? 'block' : 'none';
93
+ });
94
+ </script>
95
+
96
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,15 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Panel Component Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ import type { ComponentKind } from '@/types';
6
+
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ // Panel semantic kinds (uses common types)
10
+ export type SkPanelKind = ComponentKind;
11
+
12
+ // Panel sizes (only affects cut size, not padding or dimensions)
13
+ export type SkPanelSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
14
+
15
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,185 @@
1
+ <template>
2
+ <PopoverRoot v-model:open="isOpen">
3
+ <PopoverTrigger as-child>
4
+ <slot name="trigger" />
5
+ </PopoverTrigger>
6
+ <PopoverPortal>
7
+ <PopoverContent
8
+ :class="contentClasses"
9
+ :style="customColorStyles"
10
+ :data-scheme="theme"
11
+ :side="side"
12
+ :align="align"
13
+ :side-offset="sideOffset"
14
+ :collision-padding="8"
15
+ >
16
+ <!-- Header -->
17
+ <div v-if="title || $slots.header" class="sk-popover-header">
18
+ <h3 v-if="title" class="sk-popover-title">
19
+ {{ title }}
20
+ </h3>
21
+ <slot name="header" />
22
+ <PopoverClose
23
+ v-if="closable"
24
+ class="sk-popover-close"
25
+ aria-label="Close"
26
+ >
27
+ <svg
28
+ xmlns="http://www.w3.org/2000/svg"
29
+ width="16"
30
+ height="16"
31
+ viewBox="0 0 24 24"
32
+ fill="none"
33
+ stroke="currentColor"
34
+ stroke-width="2"
35
+ stroke-linecap="round"
36
+ stroke-linejoin="round"
37
+ >
38
+ <line x1="18" y1="6" x2="6" y2="18" />
39
+ <line x1="6" y1="6" x2="18" y2="18" />
40
+ </svg>
41
+ </PopoverClose>
42
+ </div>
43
+
44
+ <!-- Content -->
45
+ <div v-if="$slots.default" class="sk-popover-body">
46
+ <slot />
47
+ </div>
48
+
49
+ <!-- Footer -->
50
+ <div v-if="$slots.footer" class="sk-popover-footer">
51
+ <slot name="footer" />
52
+ </div>
53
+
54
+ <!-- Arrow -->
55
+ <PopoverArrow v-if="showArrow" class="sk-popover-arrow" />
56
+ </PopoverContent>
57
+ </PopoverPortal>
58
+ </PopoverRoot>
59
+ </template>
60
+
61
+ <!--------------------------------------------------------------------------------------------------------------------->
62
+
63
+ <style lang="scss" scoped>
64
+ // Popover styles are implemented in /src/styles/components/_popover.scss
65
+ </style>
66
+
67
+ <!--------------------------------------------------------------------------------------------------------------------->
68
+
69
+ <script setup lang="ts">
70
+ /**
71
+ * @component
72
+ * Popover component for floating panels positioned relative to a trigger.
73
+ * Combines tooltip-like positioning with card-like structure.
74
+ */
75
+
76
+ import { computed, toRef } from 'vue';
77
+ import {
78
+ PopoverArrow,
79
+ PopoverClose,
80
+ PopoverContent,
81
+ PopoverPortal,
82
+ PopoverRoot,
83
+ PopoverTrigger,
84
+ } from 'reka-ui';
85
+
86
+ // Types
87
+ import type { ComponentCustomColors, ComponentKind } from '@/types';
88
+ import type { SkPopoverAlign, SkPopoverSide } from './types';
89
+
90
+ // Composables
91
+ import { useCustomColors } from '@/composables/useCustomColors';
92
+ import { usePortalContext } from '@/composables/usePortalContext';
93
+
94
+ //------------------------------------------------------------------------------------------------------------------
95
+
96
+ /**
97
+ * Popover component for floating panels positioned relative to a trigger.
98
+ *
99
+ * Combines tooltip-like positioning with card-like structure for rich content.
100
+ *
101
+ * @example Basic usage with title
102
+ * ```vue
103
+ * <SkPopover title="Settings">
104
+ * <template #trigger><SkButton>Open</SkButton></template>
105
+ * <p>Popover content here</p>
106
+ * </SkPopover>
107
+ * ```
108
+ *
109
+ * @example With footer actions
110
+ * ```vue
111
+ * <SkPopover title="Confirm Action" kind="danger">
112
+ * <template #trigger><SkButton kind="danger">Delete</SkButton></template>
113
+ * <p>Are you sure you want to delete this item?</p>
114
+ * <template #footer>
115
+ * <SkButton variant="ghost" size="sm">Cancel</SkButton>
116
+ * <SkButton kind="danger" size="sm">Delete</SkButton>
117
+ * </template>
118
+ * </SkPopover>
119
+ * ```
120
+ */
121
+ export interface SkPopoverComponentProps extends ComponentCustomColors
122
+ {
123
+ /** Semantic color kind */
124
+ kind ?: ComponentKind;
125
+ /** Which side of the trigger to show the popover */
126
+ side ?: SkPopoverSide;
127
+ /** Alignment along the side */
128
+ align ?: SkPopoverAlign;
129
+ /** Offset from the trigger in pixels */
130
+ sideOffset ?: number;
131
+ /** Whether to show the arrow pointing to the trigger */
132
+ showArrow ?: boolean;
133
+ /** Optional title displayed in the header */
134
+ title ?: string;
135
+ /** Whether to show a close button in the header */
136
+ closable ?: boolean;
137
+ /** Control the open state (v-model) */
138
+ open ?: boolean;
139
+ }
140
+
141
+ //------------------------------------------------------------------------------------------------------------------
142
+
143
+ const props = withDefaults(defineProps<SkPopoverComponentProps>(), {
144
+ kind: 'neutral',
145
+ side: 'bottom',
146
+ align: 'center',
147
+ sideOffset: 8,
148
+ showArrow: true,
149
+ title: undefined,
150
+ closable: true,
151
+ open: undefined,
152
+ });
153
+
154
+ const emit = defineEmits<{
155
+ 'update:open' : [ value : boolean ];
156
+ }>();
157
+
158
+ //------------------------------------------------------------------------------------------------------------------
159
+
160
+ // Two-way binding for open state
161
+ const isOpen = computed({
162
+ get: () => props.open,
163
+ set: (value) => emit('update:open', value ?? false),
164
+ });
165
+
166
+ // Handle portal context (theme injection/re-provision for nested portal components)
167
+ const { theme } = usePortalContext();
168
+
169
+ //------------------------------------------------------------------------------------------------------------------
170
+
171
+ const contentClasses = computed(() => ({
172
+ 'sk-popover-content': true,
173
+ [`sk-${ props.kind }`]: true,
174
+ }));
175
+
176
+ //------------------------------------------------------------------------------------------------------------------
177
+
178
+ const customColorStyles = useCustomColors(
179
+ 'popover',
180
+ toRef(() => props.baseColor),
181
+ toRef(() => props.textColor)
182
+ );
183
+ </script>
184
+
185
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,8 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Popover Component Exports
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default as SkPopover } from './SkPopover.vue';
6
+ export type { SkPopoverAlign, SkPopoverSide } from './types';
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,11 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Popover Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ /** Popover positioning side */
6
+ export type SkPopoverSide = 'top' | 'right' | 'bottom' | 'left';
7
+
8
+ /** Popover alignment */
9
+ export type SkPopoverAlign = 'start' | 'center' | 'end';
10
+
11
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,144 @@
1
+ <template>
2
+ <ProgressRoot
3
+ v-model="internalValue"
4
+ :max="max"
5
+ :class="rootClasses"
6
+ :style="customStyles"
7
+ >
8
+ <ProgressIndicator
9
+ class="sk-progress-indicator"
10
+ :style="indicatorStyle"
11
+ />
12
+ <span
13
+ v-if="showValue && !isIndeterminate"
14
+ :class="['sk-progress-value', `sk-value-${ props.valuePosition }`]"
15
+ >
16
+ {{ Math.round(percentage) }}%
17
+ </span>
18
+ </ProgressRoot>
19
+ </template>
20
+
21
+ <!--------------------------------------------------------------------------------------------------------------------->
22
+
23
+ <style lang="scss" scoped>
24
+ // Component styles are implemented in /src/styles/components/_progress.scss
25
+ </style>
26
+
27
+ <!--------------------------------------------------------------------------------------------------------------------->
28
+
29
+ <script setup lang="ts">
30
+ /**
31
+ * @component SkProgress
32
+ * A progress bar component with determinate and indeterminate modes.
33
+ * Supports all 7 semantic kinds and custom colors.
34
+ */
35
+
36
+ import { computed } from 'vue';
37
+ import { ProgressIndicator, ProgressRoot } from 'reka-ui';
38
+
39
+ // Types
40
+ import type { ComponentKind } from '@/types';
41
+ import type { SkProgressSize, SkProgressValuePosition } from './types';
42
+
43
+ //------------------------------------------------------------------------------------------------------------------
44
+
45
+ export interface SkProgressComponentProps
46
+ {
47
+ /** Progress value (0 to max). Use null or undefined for indeterminate state */
48
+ value ?: number | null;
49
+ /** Maximum value */
50
+ max ?: number;
51
+ /** Semantic color kind */
52
+ kind ?: ComponentKind;
53
+ /** Bar height size */
54
+ size ?: SkProgressSize;
55
+ /** Show percentage label */
56
+ showValue ?: boolean;
57
+ /** Position of the value label */
58
+ valuePosition ?: SkProgressValuePosition;
59
+ /** Custom bar color (overrides kind) */
60
+ baseColor ?: string;
61
+ /** Custom track/background color */
62
+ trackColor ?: string;
63
+ }
64
+
65
+ //------------------------------------------------------------------------------------------------------------------
66
+
67
+ const props = withDefaults(defineProps<SkProgressComponentProps>(), {
68
+ value: null,
69
+ max: 100,
70
+ kind: 'primary',
71
+ size: 'md',
72
+ showValue: false,
73
+ valuePosition: 'center',
74
+ baseColor: undefined,
75
+ trackColor: undefined,
76
+ });
77
+
78
+ //------------------------------------------------------------------------------------------------------------------
79
+
80
+ // Reka UI expects undefined for indeterminate, not null
81
+ const internalValue = computed(() =>
82
+ {
83
+ return props.value === null ? undefined : props.value;
84
+ });
85
+
86
+ const isIndeterminate = computed(() => props.value === null || props.value === undefined);
87
+
88
+ const percentage = computed(() =>
89
+ {
90
+ if(isIndeterminate.value)
91
+ {
92
+ return 0;
93
+ }
94
+ return ((props.value ?? 0) / props.max) * 100;
95
+ });
96
+
97
+ //------------------------------------------------------------------------------------------------------------------
98
+ // Classes
99
+ //------------------------------------------------------------------------------------------------------------------
100
+
101
+ const rootClasses = computed(() => ({
102
+ 'sk-progress': true,
103
+ [`sk-${ props.kind }`]: true,
104
+ [`sk-${ props.size }`]: true,
105
+ 'sk-indeterminate': isIndeterminate.value,
106
+ 'sk-empty': !isIndeterminate.value && percentage.value === 0,
107
+ 'sk-complete': !isIndeterminate.value && percentage.value >= 100,
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-progress-color-base'] = props.baseColor;
121
+ }
122
+
123
+ if(props.trackColor)
124
+ {
125
+ styles['--sk-progress-track-bg'] = props.trackColor;
126
+ }
127
+
128
+ return styles;
129
+ });
130
+
131
+ const indicatorStyle = computed(() =>
132
+ {
133
+ if(isIndeterminate.value)
134
+ {
135
+ return {};
136
+ }
137
+
138
+ return {
139
+ width: `${ percentage.value }%`,
140
+ };
141
+ });
142
+ </script>
143
+
144
+ <!--------------------------------------------------------------------------------------------------------------------->
@@ -0,0 +1,8 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Progress Component Exports
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ export { default as SkProgress } from './SkProgress.vue';
6
+ export * from './types';
7
+
8
+ //----------------------------------------------------------------------------------------------------------------------
@@ -0,0 +1,34 @@
1
+ //----------------------------------------------------------------------------------------------------------------------
2
+ // Progress Types
3
+ //----------------------------------------------------------------------------------------------------------------------
4
+
5
+ import type { ComponentKind, ComponentSize } from '@/types';
6
+
7
+ //----------------------------------------------------------------------------------------------------------------------
8
+
9
+ /** Progress bar size */
10
+ export type SkProgressSize = ComponentSize;
11
+
12
+ /** Progress value label position */
13
+ export type SkProgressValuePosition = 'left' | 'center' | 'right';
14
+
15
+ /** Progress bar props interface */
16
+ export interface SkProgressProps
17
+ {
18
+ /** Progress value (0 to max). Use null or undefined for indeterminate state */
19
+ modelValue ?: number | null;
20
+ /** Maximum value */
21
+ max ?: number;
22
+ /** Semantic color kind */
23
+ kind ?: ComponentKind;
24
+ /** Bar height size */
25
+ size ?: SkProgressSize;
26
+ /** Show percentage label */
27
+ showValue ?: boolean;
28
+ /** Custom bar color (overrides kind) */
29
+ baseColor ?: string;
30
+ /** Custom track/background color */
31
+ trackColor ?: string;
32
+ }
33
+
34
+ //----------------------------------------------------------------------------------------------------------------------