@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.
- package/LICENSE +21 -0
- package/README.md +111 -0
- package/dist/sleekspace-ui.css +12844 -0
- package/dist/sleekspace-ui.es.js +19021 -0
- package/dist/sleekspace-ui.umd.js +19040 -0
- package/docs/components/accordion.md +92 -0
- package/docs/components/alert.md +72 -0
- package/docs/components/avatar.md +69 -0
- package/docs/components/breadcrumbs.md +65 -0
- package/docs/components/button/_meta.yaml +12 -0
- package/docs/components/button/accessibility.md +16 -0
- package/docs/components/button/custom-colors.md +18 -0
- package/docs/components/button/icons.md +31 -0
- package/docs/components/button/intro.md +8 -0
- package/docs/components/button/kinds.md +25 -0
- package/docs/components/button/sizes.md +14 -0
- package/docs/components/button/states.md +12 -0
- package/docs/components/button/usage.md +23 -0
- package/docs/components/button/variants.md +14 -0
- package/docs/components/button.md +110 -0
- package/docs/components/card.md +87 -0
- package/docs/components/checkbox.md +77 -0
- package/docs/components/collapsible.md +71 -0
- package/docs/components/divider.md +62 -0
- package/docs/components/dropdown.md +88 -0
- package/docs/components/field.md +80 -0
- package/docs/components/group.md +41 -0
- package/docs/components/input.md +84 -0
- package/docs/components/listbox.md +82 -0
- package/docs/components/modal.md +101 -0
- package/docs/components/navbar.md +64 -0
- package/docs/components/number-input.md +78 -0
- package/docs/components/page.md +77 -0
- package/docs/components/pagination.md +88 -0
- package/docs/components/panel.md +74 -0
- package/docs/components/popover.md +93 -0
- package/docs/components/progress.md +76 -0
- package/docs/components/radio.md +86 -0
- package/docs/components/sidebar.md +74 -0
- package/docs/components/skeleton.md +76 -0
- package/docs/components/slider.md +94 -0
- package/docs/components/spinner.md +59 -0
- package/docs/components/switch.md +97 -0
- package/docs/components/table.md +91 -0
- package/docs/components/tabs.md +108 -0
- package/docs/components/tag.md +75 -0
- package/docs/components/tags-input.md +88 -0
- package/docs/components/textarea.md +80 -0
- package/docs/components/theme.md +65 -0
- package/docs/components/toast.md +95 -0
- package/docs/components/tooltip.md +90 -0
- package/docs/guides/custom-colors.md +84 -0
- package/docs/guides/design-tokens.md +105 -0
- package/docs/guides/getting-started.md +144 -0
- package/docs/guides/installation.md +62 -0
- package/docs/guides/theming.md +101 -0
- package/package.json +76 -0
- package/src/components/Accordion/SkAccordion.vue +133 -0
- package/src/components/Accordion/SkAccordionItem.vue +131 -0
- package/src/components/Accordion/index.ts +3 -0
- package/src/components/Accordion/types.ts +9 -0
- package/src/components/Alert/SkAlert.vue +137 -0
- package/src/components/Alert/types.ts +10 -0
- package/src/components/Avatar/SkAvatar.vue +141 -0
- package/src/components/Avatar/index.ts +8 -0
- package/src/components/Avatar/types.ts +31 -0
- package/src/components/Breadcrumbs/SkBreadcrumbItem.vue +76 -0
- package/src/components/Breadcrumbs/SkBreadcrumbSeparator.vue +38 -0
- package/src/components/Breadcrumbs/SkBreadcrumbs.vue +93 -0
- package/src/components/Breadcrumbs/index.ts +10 -0
- package/src/components/Breadcrumbs/types.ts +36 -0
- package/src/components/Button/SkButton.vue +148 -0
- package/src/components/Button/types.ts +21 -0
- package/src/components/Card/SkCard.vue +144 -0
- package/src/components/Card/types.ts +12 -0
- package/src/components/Checkbox/SkCheckbox.vue +136 -0
- package/src/components/Checkbox/index.ts +8 -0
- package/src/components/Checkbox/types.ts +10 -0
- package/src/components/Collapsible/SkCollapsible.vue +159 -0
- package/src/components/Collapsible/index.ts +2 -0
- package/src/components/Collapsible/types.ts +8 -0
- package/src/components/Divider/SkDivider.vue +63 -0
- package/src/components/Divider/types.ts +15 -0
- package/src/components/Dropdown/SkDropdown.vue +150 -0
- package/src/components/Dropdown/SkDropdownMenuItem.vue +58 -0
- package/src/components/Dropdown/SkDropdownMenuSeparator.vue +26 -0
- package/src/components/Dropdown/SkDropdownSubmenu.vue +107 -0
- package/src/components/Dropdown/index.ts +11 -0
- package/src/components/Dropdown/types.ts +11 -0
- package/src/components/Field/SkField.vue +152 -0
- package/src/components/Field/index.ts +8 -0
- package/src/components/Field/types.ts +7 -0
- package/src/components/Group/SkGroup.vue +52 -0
- package/src/components/Group/types.ts +10 -0
- package/src/components/Input/SkInput.vue +117 -0
- package/src/components/Input/index.ts +8 -0
- package/src/components/Input/types.ts +11 -0
- package/src/components/Listbox/SkListbox.vue +164 -0
- package/src/components/Listbox/SkListboxItem.vue +68 -0
- package/src/components/Listbox/SkListboxSeparator.vue +26 -0
- package/src/components/Listbox/index.ts +10 -0
- package/src/components/Listbox/types.ts +10 -0
- package/src/components/Modal/SkModal.vue +231 -0
- package/src/components/Modal/index.ts +8 -0
- package/src/components/Modal/types.ts +12 -0
- package/src/components/NavBar/SkNavBar.vue +83 -0
- package/src/components/NavBar/index.ts +8 -0
- package/src/components/NavBar/types.ts +15 -0
- package/src/components/NumberInput/SkNumberInput.vue +168 -0
- package/src/components/NumberInput/index.ts +8 -0
- package/src/components/NumberInput/types.ts +10 -0
- package/src/components/Page/SkPage.vue +94 -0
- package/src/components/Page/index.ts +8 -0
- package/src/components/Page/types.ts +21 -0
- package/src/components/Pagination/SkPagination.vue +185 -0
- package/src/components/Pagination/SkPaginationItem.vue +107 -0
- package/src/components/Pagination/index.ts +9 -0
- package/src/components/Pagination/types.ts +40 -0
- package/src/components/Panel/SkPanel.vue +96 -0
- package/src/components/Panel/types.ts +15 -0
- package/src/components/Popover/SkPopover.vue +185 -0
- package/src/components/Popover/index.ts +8 -0
- package/src/components/Popover/types.ts +11 -0
- package/src/components/Progress/SkProgress.vue +144 -0
- package/src/components/Progress/index.ts +8 -0
- package/src/components/Progress/types.ts +34 -0
- package/src/components/Radio/SkRadio.vue +110 -0
- package/src/components/Radio/SkRadioGroup.vue +92 -0
- package/src/components/Radio/index.ts +9 -0
- package/src/components/Radio/types.ts +11 -0
- package/src/components/Sidebar/README.md +405 -0
- package/src/components/Sidebar/SkSidebar.vue +88 -0
- package/src/components/Sidebar/SkSidebarItem.vue +58 -0
- package/src/components/Sidebar/SkSidebarSection.vue +40 -0
- package/src/components/Sidebar/types.ts +3 -0
- package/src/components/Skeleton/SkSkeleton.vue +171 -0
- package/src/components/Skeleton/index.ts +8 -0
- package/src/components/Skeleton/types.ts +31 -0
- package/src/components/Slider/SkSlider.vue +165 -0
- package/src/components/Slider/index.ts +8 -0
- package/src/components/Slider/types.ts +44 -0
- package/src/components/Spinner/SkSpinner.vue +105 -0
- package/src/components/Spinner/index.ts +8 -0
- package/src/components/Spinner/types.ts +28 -0
- package/src/components/Switch/SkSwitch.vue +215 -0
- package/src/components/Switch/index.ts +8 -0
- package/src/components/Switch/types.ts +12 -0
- package/src/components/Table/SkTable.vue +109 -0
- package/src/components/Table/index.ts +2 -0
- package/src/components/Table/types.ts +15 -0
- package/src/components/Tabs/README.md +331 -0
- package/src/components/Tabs/SkTab.vue +84 -0
- package/src/components/Tabs/SkTabList.vue +62 -0
- package/src/components/Tabs/SkTabPanel.vue +47 -0
- package/src/components/Tabs/SkTabPanels.vue +23 -0
- package/src/components/Tabs/SkTabs.vue +124 -0
- package/src/components/Tabs/types.ts +21 -0
- package/src/components/Tag/SkTag.vue +129 -0
- package/src/components/Tag/types.ts +15 -0
- package/src/components/TagsInput/SkTagsInput.vue +184 -0
- package/src/components/TagsInput/index.ts +8 -0
- package/src/components/TagsInput/types.ts +10 -0
- package/src/components/Textarea/SkTextarea.vue +117 -0
- package/src/components/Textarea/index.ts +8 -0
- package/src/components/Textarea/types.ts +10 -0
- package/src/components/Theme/SkTheme.vue +47 -0
- package/src/components/Theme/types.ts +17 -0
- package/src/components/Theme/useTheme.ts +131 -0
- package/src/components/Toast/SkToast.vue +156 -0
- package/src/components/Toast/SkToastProvider.vue +180 -0
- package/src/components/Toast/index.ts +15 -0
- package/src/components/Toast/types.ts +63 -0
- package/src/components/Toast/useToast.ts +78 -0
- package/src/components/Tooltip/SkTooltip.vue +162 -0
- package/src/components/Tooltip/SkTooltipProvider.vue +114 -0
- package/src/components/Tooltip/index.ts +9 -0
- package/src/components/Tooltip/types.ts +13 -0
- package/src/composables/useCustomColors.test.ts +505 -0
- package/src/composables/useCustomColors.ts +124 -0
- package/src/composables/usePortalContext.test.ts +402 -0
- package/src/composables/usePortalContext.ts +95 -0
- package/src/global.d.ts +76 -0
- package/src/index.ts +259 -0
- package/src/styles/_scrollbar.scss +100 -0
- package/src/styles/base/_fonts.scss +105 -0
- package/src/styles/base/_global.scss +47 -0
- package/src/styles/base/_index.scss +24 -0
- package/src/styles/base/_reset.scss +11 -0
- package/src/styles/base/_typography.scss +178 -0
- package/src/styles/components/_accordion.scss +250 -0
- package/src/styles/components/_alert.scss +239 -0
- package/src/styles/components/_avatar.scss +133 -0
- package/src/styles/components/_breadcrumbs.scss +137 -0
- package/src/styles/components/_button.scss +731 -0
- package/src/styles/components/_card.scss +141 -0
- package/src/styles/components/_checkbox.scss +232 -0
- package/src/styles/components/_collapsible.scss +158 -0
- package/src/styles/components/_divider.scss +121 -0
- package/src/styles/components/_field.scss +87 -0
- package/src/styles/components/_group.scss +138 -0
- package/src/styles/components/_index.scss +46 -0
- package/src/styles/components/_input.scss +205 -0
- package/src/styles/components/_listbox.scss +453 -0
- package/src/styles/components/_menu.scss +216 -0
- package/src/styles/components/_modal.scss +329 -0
- package/src/styles/components/_navbar.scss +258 -0
- package/src/styles/components/_number-input.scss +352 -0
- package/src/styles/components/_page.scss +98 -0
- package/src/styles/components/_pagination.scss +411 -0
- package/src/styles/components/_panel.scss +281 -0
- package/src/styles/components/_popover.scss +258 -0
- package/src/styles/components/_progress.scss +280 -0
- package/src/styles/components/_radio.scss +255 -0
- package/src/styles/components/_sidebar.scss +92 -0
- package/src/styles/components/_skeleton.scss +138 -0
- package/src/styles/components/_slider.scss +262 -0
- package/src/styles/components/_spinner.scss +331 -0
- package/src/styles/components/_switch.scss +370 -0
- package/src/styles/components/_table.scss +405 -0
- package/src/styles/components/_tabs.scss +486 -0
- package/src/styles/components/_tag.scss +425 -0
- package/src/styles/components/_tags-input.scss +279 -0
- package/src/styles/components/_textarea.scss +208 -0
- package/src/styles/components/_toast.scss +331 -0
- package/src/styles/components/_tooltip.scss +206 -0
- package/src/styles/fonts/Titillium_Web/OFL.txt +93 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-Black.ttf +0 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-Bold.ttf +0 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-BoldItalic.ttf +0 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-ExtraLight.ttf +0 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-ExtraLightItalic.ttf +0 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-Italic.ttf +0 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-Light.ttf +0 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-LightItalic.ttf +0 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-Regular.ttf +0 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-SemiBold.ttf +0 -0
- package/src/styles/fonts/Titillium_Web/TitilliumWeb-SemiBoldItalic.ttf +0 -0
- package/src/styles/index.scss +17 -0
- package/src/styles/mixins/_cut-border.scss +254 -0
- package/src/styles/mixins/_index.scss +7 -0
- package/src/styles/theme/_variables.scss +42 -0
- package/src/styles/themes/README.md +127 -0
- package/src/styles/themes/_colorful.scss +58 -0
- package/src/styles/themes/_greyscale.scss +58 -0
- package/src/styles/themes/index.scss +9 -0
- package/src/styles/tokens/README.md +268 -0
- package/src/styles/tokens/_foundation-borders.scss +26 -0
- package/src/styles/tokens/_foundation-colors.scss +169 -0
- package/src/styles/tokens/_foundation-glow.scss +36 -0
- package/src/styles/tokens/_foundation-radius.scss +53 -0
- package/src/styles/tokens/_foundation-scrollbar.scss +31 -0
- package/src/styles/tokens/_foundation-shadows.scss +37 -0
- package/src/styles/tokens/_foundation-space.scss +36 -0
- package/src/styles/tokens/_foundation-transitions.scss +37 -0
- package/src/styles/tokens/_foundation-typography.scss +58 -0
- package/src/styles/tokens/_semantic-color-kinds.scss +112 -0
- package/src/styles/tokens/_semantic-colors.scss +10 -0
- package/src/styles/tokens/_semantic-interactive.scss +29 -0
- package/src/styles/tokens/_semantic-scrollbar.scss +48 -0
- package/src/styles/tokens/_semantic-surfaces.scss +36 -0
- package/src/styles/tokens/index.scss +38 -0
- package/src/styles/tokens.scss +268 -0
- package/src/styles/utilities/_index.scss +9 -0
- package/src/styles/utilities/_typography.scss +121 -0
- package/src/types.ts +50 -0
- package/web-types.json +3524 -0
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<!----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
- Radio Component
|
|
3
|
+
--------------------------------------------------------------------------------------------------------------------->
|
|
4
|
+
|
|
5
|
+
<template>
|
|
6
|
+
<label :class="labelClasses">
|
|
7
|
+
<RadioGroupItem
|
|
8
|
+
:class="classes"
|
|
9
|
+
:style="customColorStyles"
|
|
10
|
+
:value="value"
|
|
11
|
+
:disabled="disabled"
|
|
12
|
+
>
|
|
13
|
+
<RadioGroupIndicator class="sk-radio-indicator" />
|
|
14
|
+
</RadioGroupItem>
|
|
15
|
+
<span v-if="label || $slots.default" class="sk-radio-label">
|
|
16
|
+
<slot>{{ label }}</slot>
|
|
17
|
+
</span>
|
|
18
|
+
</label>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<!--------------------------------------------------------------------------------------------------------------------->
|
|
22
|
+
|
|
23
|
+
<style lang="scss" scoped>
|
|
24
|
+
// Component styles are implemented in /src/styles/components/_radio.scss
|
|
25
|
+
</style>
|
|
26
|
+
|
|
27
|
+
<!--------------------------------------------------------------------------------------------------------------------->
|
|
28
|
+
|
|
29
|
+
<script setup lang="ts">
|
|
30
|
+
/**
|
|
31
|
+
* @component
|
|
32
|
+
* An individual radio button component powered by RekaUI.
|
|
33
|
+
* Must be used within SkRadioGroup.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import { type ComputedRef, computed, inject, toRef } from 'vue';
|
|
37
|
+
import { RadioGroupIndicator, RadioGroupItem } from 'reka-ui';
|
|
38
|
+
|
|
39
|
+
// Types
|
|
40
|
+
import type { ComponentCustomColors } from '@/types';
|
|
41
|
+
import type { SkRadioKind, SkRadioSize } from './types';
|
|
42
|
+
|
|
43
|
+
// Composables
|
|
44
|
+
import { useCustomColors } from '@/composables/useCustomColors';
|
|
45
|
+
|
|
46
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* An individual radio button component powered by RekaUI.
|
|
50
|
+
* Must be used within SkRadioGroup.
|
|
51
|
+
*/
|
|
52
|
+
export interface SkRadioComponentProps extends ComponentCustomColors
|
|
53
|
+
{
|
|
54
|
+
/** Value for this radio option */
|
|
55
|
+
value : string | number;
|
|
56
|
+
/** Label text (can be overridden by default slot) */
|
|
57
|
+
label ?: string;
|
|
58
|
+
/** Disabled state */
|
|
59
|
+
disabled ?: boolean;
|
|
60
|
+
/** Semantic color kind (inherits from parent if not set) */
|
|
61
|
+
kind ?: SkRadioKind;
|
|
62
|
+
/** Size (inherits from parent if not set) */
|
|
63
|
+
size ?: SkRadioSize;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
67
|
+
|
|
68
|
+
const props = withDefaults(defineProps<SkRadioComponentProps>(), {
|
|
69
|
+
label: undefined,
|
|
70
|
+
disabled: false,
|
|
71
|
+
kind: undefined,
|
|
72
|
+
size: undefined,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
// Inject parent kind and size
|
|
78
|
+
const parentKind = inject<ComputedRef<SkRadioKind | undefined>>('radio-kind', computed(() => undefined));
|
|
79
|
+
const parentSize = inject<ComputedRef<SkRadioSize | undefined>>('radio-size', computed(() => undefined));
|
|
80
|
+
|
|
81
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
82
|
+
|
|
83
|
+
const effectiveKind = computed(() => props.kind ?? parentKind.value ?? 'neutral');
|
|
84
|
+
const effectiveSize = computed(() => props.size ?? parentSize.value ?? 'md');
|
|
85
|
+
|
|
86
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
const classes = computed(() => ({
|
|
89
|
+
'sk-radio': true,
|
|
90
|
+
[`sk-${ effectiveKind.value }`]: true,
|
|
91
|
+
[`sk-${ effectiveSize.value }`]: true,
|
|
92
|
+
}));
|
|
93
|
+
|
|
94
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
95
|
+
|
|
96
|
+
const labelClasses = computed(() => ({
|
|
97
|
+
'sk-radio-wrapper': true,
|
|
98
|
+
'sk-disabled': props.disabled,
|
|
99
|
+
}));
|
|
100
|
+
|
|
101
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
102
|
+
|
|
103
|
+
const customColorStyles = useCustomColors(
|
|
104
|
+
'radio',
|
|
105
|
+
toRef(() => props.baseColor),
|
|
106
|
+
toRef(() => props.textColor)
|
|
107
|
+
);
|
|
108
|
+
</script>
|
|
109
|
+
|
|
110
|
+
<!--------------------------------------------------------------------------------------------------------------------->
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<!----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
- RadioGroup Component
|
|
3
|
+
--------------------------------------------------------------------------------------------------------------------->
|
|
4
|
+
|
|
5
|
+
<template>
|
|
6
|
+
<RadioGroupRoot
|
|
7
|
+
v-model="modelValue"
|
|
8
|
+
:class="classes"
|
|
9
|
+
:orientation="orientation"
|
|
10
|
+
:disabled="disabled"
|
|
11
|
+
:required="required"
|
|
12
|
+
:name="name"
|
|
13
|
+
>
|
|
14
|
+
<slot />
|
|
15
|
+
</RadioGroupRoot>
|
|
16
|
+
</template>
|
|
17
|
+
|
|
18
|
+
<!--------------------------------------------------------------------------------------------------------------------->
|
|
19
|
+
|
|
20
|
+
<style lang="scss" scoped>
|
|
21
|
+
// Component styles are implemented in /src/styles/components/_radio.scss
|
|
22
|
+
</style>
|
|
23
|
+
|
|
24
|
+
<!--------------------------------------------------------------------------------------------------------------------->
|
|
25
|
+
|
|
26
|
+
<script setup lang="ts">
|
|
27
|
+
/**
|
|
28
|
+
* @component
|
|
29
|
+
* A radio group container for exclusive selection powered by RekaUI.
|
|
30
|
+
* Manages state and keyboard navigation for child SkRadio components.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { computed, provide } from 'vue';
|
|
34
|
+
import { RadioGroupRoot } from 'reka-ui';
|
|
35
|
+
|
|
36
|
+
// Types
|
|
37
|
+
import type { SkRadioGroupOrientation, SkRadioKind, SkRadioSize } from './types';
|
|
38
|
+
|
|
39
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A radio group container for exclusive selection powered by RekaUI.
|
|
43
|
+
*/
|
|
44
|
+
export interface SkRadioGroupComponentProps
|
|
45
|
+
{
|
|
46
|
+
/** Orientation for layout */
|
|
47
|
+
orientation ?: SkRadioGroupOrientation;
|
|
48
|
+
/** Semantic color kind for all radios */
|
|
49
|
+
kind ?: SkRadioKind;
|
|
50
|
+
/** Size for all radios */
|
|
51
|
+
size ?: SkRadioSize;
|
|
52
|
+
/** Disabled state for entire group */
|
|
53
|
+
disabled ?: boolean;
|
|
54
|
+
/** Required for form validation */
|
|
55
|
+
required ?: boolean;
|
|
56
|
+
/** Form field name */
|
|
57
|
+
name ?: string;
|
|
58
|
+
/** Enable circular keyboard navigation */
|
|
59
|
+
loop ?: boolean;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
const props = withDefaults(defineProps<SkRadioGroupComponentProps>(), {
|
|
65
|
+
orientation: 'vertical',
|
|
66
|
+
kind: 'neutral',
|
|
67
|
+
size: 'md',
|
|
68
|
+
disabled: false,
|
|
69
|
+
required: false,
|
|
70
|
+
name: undefined,
|
|
71
|
+
loop: true,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
const modelValue = defineModel<string | number>();
|
|
77
|
+
|
|
78
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
79
|
+
|
|
80
|
+
// Provide kind and size to child radios
|
|
81
|
+
provide('radio-kind', computed(() => props.kind));
|
|
82
|
+
provide('radio-size', computed(() => props.size));
|
|
83
|
+
|
|
84
|
+
//------------------------------------------------------------------------------------------------------------------
|
|
85
|
+
|
|
86
|
+
const classes = computed(() => ({
|
|
87
|
+
'sk-radio-group': true,
|
|
88
|
+
[`sk-${ props.orientation }`]: true,
|
|
89
|
+
}));
|
|
90
|
+
</script>
|
|
91
|
+
|
|
92
|
+
<!--------------------------------------------------------------------------------------------------------------------->
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Radio Component Exports
|
|
3
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
export { default as SkRadio } from './SkRadio.vue';
|
|
6
|
+
export { default as SkRadioGroup } from './SkRadioGroup.vue';
|
|
7
|
+
export type { SkRadioKind, SkRadioGroupOrientation, SkRadioSize } from './types';
|
|
8
|
+
|
|
9
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
2
|
+
// Radio Component Types
|
|
3
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
4
|
+
|
|
5
|
+
import type { ComponentKind, ComponentSize } from '@/types';
|
|
6
|
+
|
|
7
|
+
export type SkRadioKind = ComponentKind;
|
|
8
|
+
export type SkRadioSize = ComponentSize;
|
|
9
|
+
export type SkRadioGroupOrientation = 'horizontal' | 'vertical';
|
|
10
|
+
|
|
11
|
+
//----------------------------------------------------------------------------------------------------------------------
|
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
# Sidebar Component
|
|
2
|
+
|
|
3
|
+
A flexible navigation sidebar container with semantic color theming, styled sections, and angled clip-path hover effects. Built on the Panel component with active link highlighting and router integration support.
|
|
4
|
+
|
|
5
|
+
## Architecture
|
|
6
|
+
|
|
7
|
+
The Sidebar component consists of three sub-components:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
SkSidebar (root container)
|
|
11
|
+
└── SkSidebarSection (optional grouping)
|
|
12
|
+
└── SkSidebarItem (navigation link)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### Component Roles
|
|
16
|
+
|
|
17
|
+
- **SkSidebar**: Root container that wraps a Panel for consistent styling
|
|
18
|
+
- **SkSidebarSection**: Optional grouping component with a title for organizing nav items
|
|
19
|
+
- **SkSidebarItem**: Individual navigation link (supports any element type)
|
|
20
|
+
|
|
21
|
+
## Basic Usage
|
|
22
|
+
|
|
23
|
+
```vue
|
|
24
|
+
<template>
|
|
25
|
+
<div class="layout">
|
|
26
|
+
<SkSidebar>
|
|
27
|
+
<SkSidebarSection title="Navigation">
|
|
28
|
+
<SkSidebarItem href="/">Home</SkSidebarItem>
|
|
29
|
+
<SkSidebarItem href="/products">Products</SkSidebarItem>
|
|
30
|
+
<SkSidebarItem href="/about">About</SkSidebarItem>
|
|
31
|
+
<SkSidebarItem href="/contact">Contact</SkSidebarItem>
|
|
32
|
+
</SkSidebarSection>
|
|
33
|
+
</SkSidebar>
|
|
34
|
+
|
|
35
|
+
<main class="content">
|
|
36
|
+
<!-- Your page content -->
|
|
37
|
+
</main>
|
|
38
|
+
</div>
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<style>
|
|
42
|
+
.layout {
|
|
43
|
+
display: flex;
|
|
44
|
+
gap: 1rem;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.content {
|
|
48
|
+
flex: 1;
|
|
49
|
+
}
|
|
50
|
+
</style>
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Multiple Sections
|
|
54
|
+
|
|
55
|
+
Organize navigation into logical groups using multiple sections:
|
|
56
|
+
|
|
57
|
+
```vue
|
|
58
|
+
<SkSidebar>
|
|
59
|
+
<SkSidebarSection title="Application">
|
|
60
|
+
<SkSidebarItem href="/dashboard">Dashboard</SkSidebarItem>
|
|
61
|
+
<SkSidebarItem href="/analytics">Analytics</SkSidebarItem>
|
|
62
|
+
</SkSidebarSection>
|
|
63
|
+
|
|
64
|
+
<SkDivider />
|
|
65
|
+
|
|
66
|
+
<SkSidebarSection title="Management">
|
|
67
|
+
<SkSidebarItem href="/users">Users</SkSidebarItem>
|
|
68
|
+
<SkSidebarItem href="/teams">Teams</SkSidebarItem>
|
|
69
|
+
</SkSidebarSection>
|
|
70
|
+
|
|
71
|
+
<SkDivider />
|
|
72
|
+
|
|
73
|
+
<SkSidebarSection title="Account">
|
|
74
|
+
<SkSidebarItem href="/settings">Settings</SkSidebarItem>
|
|
75
|
+
<SkSidebarItem href="/billing">Billing</SkSidebarItem>
|
|
76
|
+
</SkSidebarSection>
|
|
77
|
+
</SkSidebar>
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Semantic Colors
|
|
81
|
+
|
|
82
|
+
Apply semantic color themes to the entire sidebar:
|
|
83
|
+
|
|
84
|
+
```vue
|
|
85
|
+
<SkSidebar kind="primary">
|
|
86
|
+
<SkSidebarSection title="Navigation">
|
|
87
|
+
<SkSidebarItem href="/">Home</SkSidebarItem>
|
|
88
|
+
</SkSidebarSection>
|
|
89
|
+
</SkSidebar>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Available kinds: `neutral` (default), `primary`, `accent`, `info`, `success`, `warning`, `danger`
|
|
93
|
+
|
|
94
|
+
## Custom Colors
|
|
95
|
+
|
|
96
|
+
Use custom colors for complete theming control:
|
|
97
|
+
|
|
98
|
+
```vue
|
|
99
|
+
<SkSidebar
|
|
100
|
+
base-color="oklch(0.3 0.15 260)"
|
|
101
|
+
text-color="oklch(0.85 0.05 260)"
|
|
102
|
+
>
|
|
103
|
+
<SkSidebarSection title="Navigation">
|
|
104
|
+
<SkSidebarItem href="/dashboard">Dashboard</SkSidebarItem>
|
|
105
|
+
<SkSidebarItem href="/analytics">Analytics</SkSidebarItem>
|
|
106
|
+
</SkSidebarSection>
|
|
107
|
+
</SkSidebar>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## Width Control
|
|
111
|
+
|
|
112
|
+
Customize the sidebar width:
|
|
113
|
+
|
|
114
|
+
```vue
|
|
115
|
+
<SkSidebar width="250px">
|
|
116
|
+
<!-- Navigation items -->
|
|
117
|
+
</SkSidebar>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## Router Integration
|
|
121
|
+
|
|
122
|
+
### Vue Router
|
|
123
|
+
|
|
124
|
+
Use with Vue Router's `<RouterLink>`:
|
|
125
|
+
|
|
126
|
+
```vue
|
|
127
|
+
<SkSidebarItem as="RouterLink" to="/">
|
|
128
|
+
Home
|
|
129
|
+
</SkSidebarItem>
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
The `router-link-active` class is automatically applied to active routes.
|
|
133
|
+
|
|
134
|
+
### Manual Active State
|
|
135
|
+
|
|
136
|
+
Control active state manually:
|
|
137
|
+
|
|
138
|
+
```vue
|
|
139
|
+
<script setup>
|
|
140
|
+
const currentPage = ref('home');
|
|
141
|
+
</script>
|
|
142
|
+
|
|
143
|
+
<template>
|
|
144
|
+
<SkSidebarItem
|
|
145
|
+
href="/"
|
|
146
|
+
:active="currentPage === 'home'"
|
|
147
|
+
>
|
|
148
|
+
Home
|
|
149
|
+
</SkSidebarItem>
|
|
150
|
+
</template>
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Icons
|
|
154
|
+
|
|
155
|
+
Add icons to sidebar items:
|
|
156
|
+
|
|
157
|
+
```vue
|
|
158
|
+
<SkSidebarItem href="/dashboard">
|
|
159
|
+
<FontAwesomeIcon :icon="['fas', 'chart-line']" class="mr-2" />
|
|
160
|
+
Dashboard
|
|
161
|
+
</SkSidebarItem>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Without Sections
|
|
165
|
+
|
|
166
|
+
Sections are optional - items can be direct children of the sidebar:
|
|
167
|
+
|
|
168
|
+
```vue
|
|
169
|
+
<SkSidebar>
|
|
170
|
+
<SkSidebarItem href="/">Home</SkSidebarItem>
|
|
171
|
+
<SkSidebarItem href="/about">About</SkSidebarItem>
|
|
172
|
+
<SkSidebarItem href="/contact">Contact</SkSidebarItem>
|
|
173
|
+
</SkSidebar>
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Button Items
|
|
177
|
+
|
|
178
|
+
Render items as buttons for non-navigation actions:
|
|
179
|
+
|
|
180
|
+
```vue
|
|
181
|
+
<SkSidebarSection title="Actions">
|
|
182
|
+
<SkSidebarItem
|
|
183
|
+
as="button"
|
|
184
|
+
@click="handleLogout"
|
|
185
|
+
>
|
|
186
|
+
Logout
|
|
187
|
+
</SkSidebarItem>
|
|
188
|
+
</SkSidebarSection>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Positioning
|
|
192
|
+
|
|
193
|
+
The Sidebar component does NOT include positioning styles - you control the layout:
|
|
194
|
+
|
|
195
|
+
### Fixed Positioning
|
|
196
|
+
|
|
197
|
+
```vue
|
|
198
|
+
<template>
|
|
199
|
+
<div class="app-layout">
|
|
200
|
+
<div class="sidebar-wrapper">
|
|
201
|
+
<SkSidebar>
|
|
202
|
+
<!-- nav items -->
|
|
203
|
+
</SkSidebar>
|
|
204
|
+
</div>
|
|
205
|
+
<main class="main-content">
|
|
206
|
+
<!-- content -->
|
|
207
|
+
</main>
|
|
208
|
+
</div>
|
|
209
|
+
</template>
|
|
210
|
+
|
|
211
|
+
<style>
|
|
212
|
+
.app-layout {
|
|
213
|
+
display: flex;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.sidebar-wrapper {
|
|
217
|
+
position: fixed;
|
|
218
|
+
top: 0;
|
|
219
|
+
left: 0;
|
|
220
|
+
height: 100vh;
|
|
221
|
+
z-index: 10;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.main-content {
|
|
225
|
+
margin-left: 180px; /* match sidebar width */
|
|
226
|
+
flex: 1;
|
|
227
|
+
}
|
|
228
|
+
</style>
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
### Sticky Positioning
|
|
232
|
+
|
|
233
|
+
```vue
|
|
234
|
+
<style>
|
|
235
|
+
.sidebar-wrapper {
|
|
236
|
+
position: sticky;
|
|
237
|
+
top: 0;
|
|
238
|
+
height: 100vh;
|
|
239
|
+
}
|
|
240
|
+
</style>
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Flex Layout
|
|
244
|
+
|
|
245
|
+
```vue
|
|
246
|
+
<template>
|
|
247
|
+
<div class="flex-layout">
|
|
248
|
+
<SkSidebar />
|
|
249
|
+
<main class="flex-1">
|
|
250
|
+
<!-- content -->
|
|
251
|
+
</main>
|
|
252
|
+
</div>
|
|
253
|
+
</template>
|
|
254
|
+
|
|
255
|
+
<style>
|
|
256
|
+
.flex-layout {
|
|
257
|
+
display: flex;
|
|
258
|
+
gap: 1rem;
|
|
259
|
+
}
|
|
260
|
+
</style>
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## API Reference
|
|
264
|
+
|
|
265
|
+
### SkSidebar Props
|
|
266
|
+
|
|
267
|
+
| Prop | Type | Default | Description |
|
|
268
|
+
|------|------|---------|-------------|
|
|
269
|
+
| `kind` | `ComponentKind` | `'neutral'` | Semantic color kind for the sidebar |
|
|
270
|
+
| `width` | `string` | `'180px'` | CSS width value for the sidebar |
|
|
271
|
+
| `baseColor` | `string` | `undefined` | Custom base color (CSS color value) |
|
|
272
|
+
| `textColor` | `string` | `undefined` | Custom text color (CSS color value) |
|
|
273
|
+
|
|
274
|
+
### SkSidebarSection Props
|
|
275
|
+
|
|
276
|
+
| Prop | Type | Default | Description |
|
|
277
|
+
|------|------|---------|-------------|
|
|
278
|
+
| `title` | `string` | `undefined` | Optional section heading |
|
|
279
|
+
|
|
280
|
+
### SkSidebarItem Props
|
|
281
|
+
|
|
282
|
+
| Prop | Type | Default | Description |
|
|
283
|
+
|------|------|---------|-------------|
|
|
284
|
+
| `as` | `string` | `'a'` | HTML tag or component name to render as |
|
|
285
|
+
| `active` | `boolean` | `false` | Whether this item is currently active |
|
|
286
|
+
|
|
287
|
+
**Note**: All HTML attributes and component props are passed through via `v-bind="$attrs"`, so you can use `href`, `to`, `@click`, etc. directly on `SkSidebarItem`.
|
|
288
|
+
|
|
289
|
+
## Styling
|
|
290
|
+
|
|
291
|
+
Sidebar uses CSS custom properties inherited from Panel:
|
|
292
|
+
|
|
293
|
+
```css
|
|
294
|
+
.sk-sidebar {
|
|
295
|
+
--sk-sidebar-width: /* sidebar width */
|
|
296
|
+
--sk-panel-color-base: /* background color from Panel */
|
|
297
|
+
--sk-panel-fg: /* text color from Panel */
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
.sk-sidebar-item {
|
|
301
|
+
/* Angled clip-path on hover/active */
|
|
302
|
+
clip-path: polygon(
|
|
303
|
+
10px 0%,
|
|
304
|
+
100% 0%,
|
|
305
|
+
100% calc(100% - 10px),
|
|
306
|
+
calc(100% - 10px) 100%,
|
|
307
|
+
0% 100%,
|
|
308
|
+
0% 10px
|
|
309
|
+
);
|
|
310
|
+
}
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
## Common Patterns
|
|
314
|
+
|
|
315
|
+
### Collapsible Sidebar
|
|
316
|
+
|
|
317
|
+
```vue
|
|
318
|
+
<script setup>
|
|
319
|
+
const collapsed = ref(false);
|
|
320
|
+
</script>
|
|
321
|
+
|
|
322
|
+
<template>
|
|
323
|
+
<SkSidebar :width="collapsed ? '60px' : '180px'">
|
|
324
|
+
<button @click="collapsed = !collapsed" class="collapse-btn">
|
|
325
|
+
{{ collapsed ? '→' : '←' }}
|
|
326
|
+
</button>
|
|
327
|
+
<SkSidebarSection v-if="!collapsed" title="Navigation">
|
|
328
|
+
<SkSidebarItem href="/">Home</SkSidebarItem>
|
|
329
|
+
</SkSidebarSection>
|
|
330
|
+
</SkSidebar>
|
|
331
|
+
</template>
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
### Sidebar with User Profile
|
|
335
|
+
|
|
336
|
+
```vue
|
|
337
|
+
<SkSidebar>
|
|
338
|
+
<SkSidebarSection title="Navigation">
|
|
339
|
+
<SkSidebarItem href="/dashboard">Dashboard</SkSidebarItem>
|
|
340
|
+
<SkSidebarItem href="/projects">Projects</SkSidebarItem>
|
|
341
|
+
</SkSidebarSection>
|
|
342
|
+
|
|
343
|
+
<SkDivider />
|
|
344
|
+
|
|
345
|
+
<SkSidebarSection title="Account">
|
|
346
|
+
<div class="user-profile">
|
|
347
|
+
<img :src="user.avatar" class="avatar" />
|
|
348
|
+
<span>{{ user.name }}</span>
|
|
349
|
+
</div>
|
|
350
|
+
<SkSidebarItem href="/settings">Settings</SkSidebarItem>
|
|
351
|
+
<SkSidebarItem as="button" @click="logout">Logout</SkSidebarItem>
|
|
352
|
+
</SkSidebarSection>
|
|
353
|
+
</SkSidebar>
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
### Conditional Navigation
|
|
357
|
+
|
|
358
|
+
```vue
|
|
359
|
+
<SkSidebar>
|
|
360
|
+
<SkSidebarSection title="Main">
|
|
361
|
+
<SkSidebarItem href="/">Home</SkSidebarItem>
|
|
362
|
+
<SkSidebarItem href="/dashboard">Dashboard</SkSidebarItem>
|
|
363
|
+
</SkSidebarSection>
|
|
364
|
+
|
|
365
|
+
<SkSidebarSection v-if="isAdmin" title="Admin">
|
|
366
|
+
<SkSidebarItem href="/admin/users">Manage Users</SkSidebarItem>
|
|
367
|
+
<SkSidebarItem href="/admin/settings">System Settings</SkSidebarItem>
|
|
368
|
+
</SkSidebarSection>
|
|
369
|
+
</SkSidebar>
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## Best Practices
|
|
373
|
+
|
|
374
|
+
1. **Semantic Sections**: Group related navigation items into logical sections
|
|
375
|
+
2. **Clear Labels**: Use concise, descriptive labels for navigation items
|
|
376
|
+
3. **Active States**: Always indicate the current page/section
|
|
377
|
+
4. **Consistent Width**: Maintain consistent sidebar width across your application
|
|
378
|
+
5. **Icons**: Use icons consistently - either all items have icons or none do
|
|
379
|
+
6. **Keyboard Navigation**: Ensure items are keyboard-accessible (native with links/buttons)
|
|
380
|
+
7. **Mobile Considerations**: Consider a drawer/overlay pattern for mobile viewports
|
|
381
|
+
8. **Logical Order**: Place most important/frequently used items at the top
|
|
382
|
+
|
|
383
|
+
## Accessibility
|
|
384
|
+
|
|
385
|
+
- **Semantic HTML**: Uses `<aside>` and `<nav>` elements for proper landmark roles
|
|
386
|
+
- **Link Accessibility**: Links and buttons receive proper focus states
|
|
387
|
+
- **Active Indication**: Active items visually and programmatically indicated
|
|
388
|
+
- **Keyboard Navigation**: All items accessible via Tab key
|
|
389
|
+
- **Screen Readers**: Section titles provide context for navigation groups
|
|
390
|
+
|
|
391
|
+
## Layout Considerations
|
|
392
|
+
|
|
393
|
+
The Sidebar component is a **presentational component** - it does not include positioning or layout styles. This gives you complete control over how it fits into your application's layout.
|
|
394
|
+
|
|
395
|
+
**Why no built-in positioning?**
|
|
396
|
+
- Different apps have different layout needs (fixed, sticky, flex, grid)
|
|
397
|
+
- Avoids conflicts with parent layout systems
|
|
398
|
+
- Keeps the component flexible and reusable
|
|
399
|
+
- Prevents z-index and stacking context issues
|
|
400
|
+
|
|
401
|
+
**You are responsible for:**
|
|
402
|
+
- Positioning the sidebar in your layout
|
|
403
|
+
- Managing responsive behavior (mobile drawers, etc.)
|
|
404
|
+
- Coordinating with other fixed/sticky elements (headers, footers)
|
|
405
|
+
- Handling overflow and scrolling behavior
|