@skewedaspect/sleekspace-ui 0.3.0 → 0.5.0
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/dist/components/Alert/SkAlert.vue.d.ts +18 -8
- package/dist/components/Alert/types.d.ts +3 -2
- package/dist/components/Page/SkPage.vue.d.ts +9 -0
- package/dist/components/Page/types.d.ts +3 -0
- package/dist/sleekspace-ui.css +47 -24
- package/dist/sleekspace-ui.es.js +67 -41
- package/dist/sleekspace-ui.umd.js +67 -41
- package/dist/tokens.css +23 -0
- package/docs/guides/design-tokens/foundation-other.md +16 -3
- package/docs/guides/design-tokens/semantic-states.md +26 -11
- package/docs/guides/design-tokens/themes.md +13 -2
- package/docs/guides/getting-started.md +31 -30
- package/docs/guides/theming.md +262 -8
- package/package.json +4 -4
- package/src/components/Alert/SkAlert.vue +50 -17
- package/src/components/Alert/types.ts +7 -2
- package/src/components/Page/SkPage.vue +36 -2
- package/src/components/Page/types.ts +6 -0
- package/src/styles/_scrollbar.scss +2 -2
- package/src/styles/base/_global.scss +3 -3
- package/src/styles/components/_alert.scss +5 -5
- package/src/styles/components/_page.scss +2 -2
- package/src/styles/tokens/_foundation-colors.scss +4 -0
- package/src/styles/tokens/_foundation-transitions.scss +8 -0
- package/src/styles/tokens/_semantic-surfaces.scss +15 -0
- package/web-types.json +24 -4
|
@@ -15224,7 +15224,10 @@ Defaulting to \`null\`.`);
|
|
|
15224
15224
|
}
|
|
15225
15225
|
});
|
|
15226
15226
|
const SkAccordionItem = /* @__PURE__ */ _export_sfc(_sfc_main$Q, [["__scopeId", "data-v-5e73d91f"]]);
|
|
15227
|
-
const _hoisted_1$w = {
|
|
15227
|
+
const _hoisted_1$w = {
|
|
15228
|
+
key: 0,
|
|
15229
|
+
class: "sk-alert-icon"
|
|
15230
|
+
};
|
|
15228
15231
|
const _hoisted_2$h = {
|
|
15229
15232
|
key: 0,
|
|
15230
15233
|
viewBox: "0 0 24 24",
|
|
@@ -15253,24 +15256,35 @@ Defaulting to \`null\`.`);
|
|
|
15253
15256
|
stroke: "currentColor",
|
|
15254
15257
|
"stroke-width": "2"
|
|
15255
15258
|
};
|
|
15256
|
-
const _hoisted_6$
|
|
15259
|
+
const _hoisted_6$4 = { class: "sk-alert-content" };
|
|
15257
15260
|
const _sfc_main$P = /* @__PURE__ */ vue.defineComponent({
|
|
15258
15261
|
__name: "SkAlert",
|
|
15259
15262
|
props: {
|
|
15260
15263
|
kind: { default: "info" },
|
|
15261
|
-
|
|
15264
|
+
subtle: { type: Boolean, default: false },
|
|
15265
|
+
showIcon: { type: Boolean, default: void 0 },
|
|
15262
15266
|
baseColor: {},
|
|
15263
15267
|
textColor: {}
|
|
15264
15268
|
},
|
|
15265
15269
|
setup(__props) {
|
|
15270
|
+
const FEEDBACK_KINDS = ["info", "success", "warning", "danger"];
|
|
15266
15271
|
const props = __props;
|
|
15272
|
+
const slots = vue.useSlots();
|
|
15267
15273
|
const classes = vue.computed(() => {
|
|
15268
15274
|
return {
|
|
15269
15275
|
"sk-alert": true,
|
|
15270
15276
|
[`sk-${props.kind}`]: true,
|
|
15271
|
-
"sk-
|
|
15277
|
+
"sk-subtle": props.subtle
|
|
15272
15278
|
};
|
|
15273
15279
|
});
|
|
15280
|
+
const shouldShowIcon = vue.computed(() => {
|
|
15281
|
+
if (props.showIcon !== void 0) {
|
|
15282
|
+
return props.showIcon;
|
|
15283
|
+
}
|
|
15284
|
+
const hasDefaultIcon = FEEDBACK_KINDS.includes(props.kind);
|
|
15285
|
+
const hasSlotContent = !!slots.icon;
|
|
15286
|
+
return hasDefaultIcon || hasSlotContent;
|
|
15287
|
+
});
|
|
15274
15288
|
const customColorStyles = useCustomColors(
|
|
15275
15289
|
"alert",
|
|
15276
15290
|
vue.toRef(() => props.baseColor),
|
|
@@ -15282,7 +15296,7 @@ Defaulting to \`null\`.`);
|
|
|
15282
15296
|
style: vue.normalizeStyle(vue.unref(customColorStyles)),
|
|
15283
15297
|
role: "alert"
|
|
15284
15298
|
}, [
|
|
15285
|
-
vue.
|
|
15299
|
+
shouldShowIcon.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$w, [
|
|
15286
15300
|
vue.renderSlot(_ctx.$slots, "icon", {}, () => [
|
|
15287
15301
|
__props.kind === "info" ? (vue.openBlock(), vue.createElementBlock("svg", _hoisted_2$h, [..._cache[0] || (_cache[0] = [
|
|
15288
15302
|
vue.createElementVNode("circle", {
|
|
@@ -15339,8 +15353,8 @@ Defaulting to \`null\`.`);
|
|
|
15339
15353
|
}, null, -1)
|
|
15340
15354
|
])])) : vue.createCommentVNode("", true)
|
|
15341
15355
|
])
|
|
15342
|
-
]),
|
|
15343
|
-
vue.createElementVNode("div", _hoisted_6$
|
|
15356
|
+
])) : vue.createCommentVNode("", true),
|
|
15357
|
+
vue.createElementVNode("div", _hoisted_6$4, [
|
|
15344
15358
|
vue.renderSlot(_ctx.$slots, "default")
|
|
15345
15359
|
])
|
|
15346
15360
|
], 6);
|
|
@@ -17013,17 +17027,38 @@ Defaulting to \`null\`.`);
|
|
|
17013
17027
|
}
|
|
17014
17028
|
});
|
|
17015
17029
|
const SkNumberInput = /* @__PURE__ */ _export_sfc(_sfc_main$s, [["__scopeId", "data-v-b589687f"]]);
|
|
17016
|
-
const
|
|
17030
|
+
const ThemeSymbol = Symbol("SkTheme");
|
|
17031
|
+
function provideTheme(initialTheme = "greyscale") {
|
|
17032
|
+
const currentTheme = vue.ref(initialTheme);
|
|
17033
|
+
const setTheme = (theme) => {
|
|
17034
|
+
currentTheme.value = theme;
|
|
17035
|
+
};
|
|
17036
|
+
const context2 = {
|
|
17037
|
+
currentTheme,
|
|
17038
|
+
setTheme
|
|
17039
|
+
};
|
|
17040
|
+
vue.provide(ThemeSymbol, context2);
|
|
17041
|
+
return context2;
|
|
17042
|
+
}
|
|
17043
|
+
function useTheme() {
|
|
17044
|
+
const context2 = vue.inject(ThemeSymbol);
|
|
17045
|
+
if (!context2) {
|
|
17046
|
+
throw new Error("useTheme must be called within an SkTheme component");
|
|
17047
|
+
}
|
|
17048
|
+
return context2;
|
|
17049
|
+
}
|
|
17050
|
+
const _hoisted_1$e = ["data-scheme"];
|
|
17051
|
+
const _hoisted_2$8 = {
|
|
17017
17052
|
key: 0,
|
|
17018
17053
|
class: "sk-page-header"
|
|
17019
17054
|
};
|
|
17020
|
-
const
|
|
17021
|
-
const
|
|
17055
|
+
const _hoisted_3$6 = { class: "sk-page-main" };
|
|
17056
|
+
const _hoisted_4$5 = {
|
|
17022
17057
|
key: 0,
|
|
17023
17058
|
class: "sk-page-sidebar"
|
|
17024
17059
|
};
|
|
17025
|
-
const
|
|
17026
|
-
const
|
|
17060
|
+
const _hoisted_5$3 = { class: "sk-page-content" };
|
|
17061
|
+
const _hoisted_6$3 = {
|
|
17027
17062
|
key: 1,
|
|
17028
17063
|
class: "sk-page-footer"
|
|
17029
17064
|
};
|
|
@@ -17033,7 +17068,8 @@ Defaulting to \`null\`.`);
|
|
|
17033
17068
|
sidebarPosition: { default: "left" },
|
|
17034
17069
|
fixedHeader: { type: Boolean, default: false },
|
|
17035
17070
|
fixedFooter: { type: Boolean, default: false },
|
|
17036
|
-
sidebarWidth: { default: void 0 }
|
|
17071
|
+
sidebarWidth: { default: void 0 },
|
|
17072
|
+
theme: { default: void 0 }
|
|
17037
17073
|
},
|
|
17038
17074
|
setup(__props) {
|
|
17039
17075
|
const props = __props;
|
|
@@ -17051,30 +17087,40 @@ Defaulting to \`null\`.`);
|
|
|
17051
17087
|
"--sk-page-sidebar-width": props.sidebarWidth
|
|
17052
17088
|
};
|
|
17053
17089
|
});
|
|
17090
|
+
if (props.theme) {
|
|
17091
|
+
const { currentTheme, setTheme } = provideTheme(props.theme);
|
|
17092
|
+
vue.provide("sk-theme", currentTheme);
|
|
17093
|
+
vue.watch(() => props.theme, (newTheme) => {
|
|
17094
|
+
if (newTheme) {
|
|
17095
|
+
setTheme(newTheme);
|
|
17096
|
+
}
|
|
17097
|
+
});
|
|
17098
|
+
}
|
|
17054
17099
|
return (_ctx, _cache) => {
|
|
17055
17100
|
return vue.openBlock(), vue.createElementBlock("div", {
|
|
17056
17101
|
class: vue.normalizeClass(classes.value),
|
|
17057
|
-
style: vue.normalizeStyle(customStyles.value)
|
|
17102
|
+
style: vue.normalizeStyle(customStyles.value),
|
|
17103
|
+
"data-scheme": __props.theme
|
|
17058
17104
|
}, [
|
|
17059
|
-
_ctx.$slots.header ? (vue.openBlock(), vue.createElementBlock("header",
|
|
17105
|
+
_ctx.$slots.header ? (vue.openBlock(), vue.createElementBlock("header", _hoisted_2$8, [
|
|
17060
17106
|
vue.renderSlot(_ctx.$slots, "header", {}, void 0, true)
|
|
17061
17107
|
])) : vue.createCommentVNode("", true),
|
|
17062
|
-
vue.createElementVNode("div",
|
|
17063
|
-
_ctx.$slots.sidebar ? (vue.openBlock(), vue.createElementBlock("aside",
|
|
17108
|
+
vue.createElementVNode("div", _hoisted_3$6, [
|
|
17109
|
+
_ctx.$slots.sidebar ? (vue.openBlock(), vue.createElementBlock("aside", _hoisted_4$5, [
|
|
17064
17110
|
vue.renderSlot(_ctx.$slots, "sidebar", {}, void 0, true)
|
|
17065
17111
|
])) : vue.createCommentVNode("", true),
|
|
17066
|
-
vue.createElementVNode("main",
|
|
17112
|
+
vue.createElementVNode("main", _hoisted_5$3, [
|
|
17067
17113
|
vue.renderSlot(_ctx.$slots, "default", {}, void 0, true)
|
|
17068
17114
|
])
|
|
17069
17115
|
]),
|
|
17070
|
-
_ctx.$slots.footer ? (vue.openBlock(), vue.createElementBlock("footer",
|
|
17116
|
+
_ctx.$slots.footer ? (vue.openBlock(), vue.createElementBlock("footer", _hoisted_6$3, [
|
|
17071
17117
|
vue.renderSlot(_ctx.$slots, "footer", {}, void 0, true)
|
|
17072
17118
|
])) : vue.createCommentVNode("", true)
|
|
17073
|
-
],
|
|
17119
|
+
], 14, _hoisted_1$e);
|
|
17074
17120
|
};
|
|
17075
17121
|
}
|
|
17076
17122
|
});
|
|
17077
|
-
const SkPage = /* @__PURE__ */ _export_sfc(_sfc_main$r, [["__scopeId", "data-v-
|
|
17123
|
+
const SkPage = /* @__PURE__ */ _export_sfc(_sfc_main$r, [["__scopeId", "data-v-ad672949"]]);
|
|
17078
17124
|
const _hoisted_1$d = ["disabled", "aria-label", "aria-current"];
|
|
17079
17125
|
const _hoisted_2$7 = { key: 0 };
|
|
17080
17126
|
const _hoisted_3$5 = { key: 1 };
|
|
@@ -18882,26 +18928,6 @@ Defaulting to \`null\`.`);
|
|
|
18882
18928
|
};
|
|
18883
18929
|
}
|
|
18884
18930
|
});
|
|
18885
|
-
const ThemeSymbol = Symbol("SkTheme");
|
|
18886
|
-
function provideTheme(initialTheme = "greyscale") {
|
|
18887
|
-
const currentTheme = vue.ref(initialTheme);
|
|
18888
|
-
const setTheme = (theme) => {
|
|
18889
|
-
currentTheme.value = theme;
|
|
18890
|
-
};
|
|
18891
|
-
const context2 = {
|
|
18892
|
-
currentTheme,
|
|
18893
|
-
setTheme
|
|
18894
|
-
};
|
|
18895
|
-
vue.provide(ThemeSymbol, context2);
|
|
18896
|
-
return context2;
|
|
18897
|
-
}
|
|
18898
|
-
function useTheme() {
|
|
18899
|
-
const context2 = vue.inject(ThemeSymbol);
|
|
18900
|
-
if (!context2) {
|
|
18901
|
-
throw new Error("useTheme must be called within an SkTheme component");
|
|
18902
|
-
}
|
|
18903
|
-
return context2;
|
|
18904
|
-
}
|
|
18905
18931
|
const _hoisted_1 = ["data-scheme"];
|
|
18906
18932
|
const _sfc_main = /* @__PURE__ */ vue.defineComponent({
|
|
18907
18933
|
__name: "SkTheme",
|
package/dist/tokens.css
CHANGED
|
@@ -158,6 +158,9 @@
|
|
|
158
158
|
--sk-opacity-medium: 0.40;
|
|
159
159
|
--sk-opacity-strong: 0.60;
|
|
160
160
|
--sk-opacity-opaque: 1;
|
|
161
|
+
/* Semantic opacity aliases */
|
|
162
|
+
--sk-opacity-disabled: 0.5;
|
|
163
|
+
--sk-opacity-loading: 0.6;
|
|
161
164
|
/* ===================================================================
|
|
162
165
|
* Color Mixing Percentages
|
|
163
166
|
* Tokenized mixing amounts for color-mix() function
|
|
@@ -351,6 +354,12 @@
|
|
|
351
354
|
--sk-transition-easing-ease-in: ease-in;
|
|
352
355
|
--sk-transition-easing-ease-out: ease-out;
|
|
353
356
|
--sk-transition-easing-ease-in-out: ease-in-out;
|
|
357
|
+
/* ===================================================================
|
|
358
|
+
* Default Aliases
|
|
359
|
+
* Generic names that resolve to the most common values
|
|
360
|
+
* =================================================================== */
|
|
361
|
+
--sk-transition-duration-base: var(--sk-transition-duration-normal);
|
|
362
|
+
--sk-transition-easing: var(--sk-transition-easing-ease-out);
|
|
354
363
|
/* ===================================================================
|
|
355
364
|
* Common Transition Combinations
|
|
356
365
|
* Convenience tokens for frequently used transitions
|
|
@@ -652,6 +661,10 @@
|
|
|
652
661
|
*
|
|
653
662
|
* Background and text colors for surfaces and general use.
|
|
654
663
|
* These provide a consistent color system independent of component kinds.
|
|
664
|
+
*
|
|
665
|
+
* Defaults are defined on :root as fallbacks. Themes can override any of these
|
|
666
|
+
* via [data-scheme] selectors. The [data-scheme] rule also applies background
|
|
667
|
+
* and text color so that any themed element gets the correct surface treatment.
|
|
655
668
|
*/
|
|
656
669
|
:root {
|
|
657
670
|
/* ===================================================================
|
|
@@ -677,6 +690,16 @@
|
|
|
677
690
|
--sk-border-subtle: var(--sk-color-gray-80); /* Subtle borders/dividers */
|
|
678
691
|
}
|
|
679
692
|
|
|
693
|
+
/**
|
|
694
|
+
* Apply text color to any themed element so descendants inherit the correct
|
|
695
|
+
* color without needing to set it themselves. Background is intentionally NOT
|
|
696
|
+
* set here — page-level containers like SkPage handle their own background
|
|
697
|
+
* via the surface tokens.
|
|
698
|
+
*/
|
|
699
|
+
[data-scheme] {
|
|
700
|
+
color: var(--sk-text-primary);
|
|
701
|
+
}
|
|
702
|
+
|
|
680
703
|
/**
|
|
681
704
|
* Semantic Tokens - Interactive
|
|
682
705
|
*
|
|
@@ -33,9 +33,22 @@ Beyond colors, foundation tokens cover spacing, borders, typography, transitions
|
|
|
33
33
|
--sk-font-size-lg: 1.125rem
|
|
34
34
|
--sk-font-size-xl: 1.25rem
|
|
35
35
|
|
|
36
|
-
/*
|
|
36
|
+
/* Transition Durations */
|
|
37
37
|
--sk-transition-duration-instant: 0ms
|
|
38
38
|
--sk-transition-duration-fast: 150ms
|
|
39
|
-
--sk-transition-duration-normal:
|
|
40
|
-
--sk-transition-duration-slow:
|
|
39
|
+
--sk-transition-duration-normal: 250ms
|
|
40
|
+
--sk-transition-duration-slow: 350ms
|
|
41
|
+
--sk-transition-duration-slower: 500ms
|
|
42
|
+
|
|
43
|
+
/* Transition Easing */
|
|
44
|
+
--sk-transition-easing-linear: linear
|
|
45
|
+
--sk-transition-easing-ease: ease
|
|
46
|
+
--sk-transition-easing-ease-in: ease-in
|
|
47
|
+
--sk-transition-easing-ease-out: ease-out
|
|
48
|
+
--sk-transition-easing-ease-in-out: ease-in-out
|
|
49
|
+
|
|
50
|
+
/* Common Transition Combinations */
|
|
51
|
+
--sk-transition-fast: all 150ms ease-out
|
|
52
|
+
--sk-transition-normal: all 250ms ease-out
|
|
53
|
+
--sk-transition-slow: all 350ms ease-out
|
|
41
54
|
```
|
|
@@ -24,19 +24,32 @@ Hover and active states are automatically calculated using CSS `color-mix()`:
|
|
|
24
24
|
|
|
25
25
|
### Surface & Text Semantics
|
|
26
26
|
|
|
27
|
-
Background and text colors for layouts and content, separate from interactive component colors.
|
|
27
|
+
Background and text colors for layouts and content, separate from interactive component colors. Any element with a `data-scheme` attribute (set by `SkTheme` or `SkPage`'s `theme` prop) automatically inherits `color: var(--sk-text-primary)`. Page-level containers like `SkPage` set their own `background: var(--sk-surface-base)`.
|
|
28
28
|
|
|
29
29
|
```css
|
|
30
30
|
/* Surface Colors */
|
|
31
|
-
--sk-surface-base:
|
|
32
|
-
--sk-surface-raised:
|
|
33
|
-
--sk-surface-overlay: var(--sk-color-gray-
|
|
31
|
+
--sk-surface-base: var(--sk-color-gray-90) /* Main background */
|
|
32
|
+
--sk-surface-raised: var(--sk-color-gray-95) /* Elevated surfaces (cards, panels) */
|
|
33
|
+
--sk-surface-overlay: var(--sk-color-gray-80) /* Overlays (modals, dropdowns) */
|
|
34
34
|
|
|
35
35
|
/* Text Colors */
|
|
36
|
-
--sk-text-primary:
|
|
37
|
-
--sk-text-secondary: var(--sk-color-gray-
|
|
38
|
-
--sk-text-tertiary:
|
|
39
|
-
--sk-text-disabled:
|
|
36
|
+
--sk-text-primary: oklch(1 0 0) /* Primary body text (white) */
|
|
37
|
+
--sk-text-secondary: var(--sk-color-gray-30) /* Secondary/muted text */
|
|
38
|
+
--sk-text-tertiary: var(--sk-color-gray-50) /* Tertiary/placeholder text */
|
|
39
|
+
--sk-text-disabled: var(--sk-color-gray-60) /* Disabled text */
|
|
40
|
+
|
|
41
|
+
/* Border Colors */
|
|
42
|
+
--sk-border-normal: var(--sk-color-gray-70) /* Standard borders */
|
|
43
|
+
--sk-border-subtle: var(--sk-color-gray-80) /* Subtle borders/dividers */
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Custom themes can override any of these surface tokens to change the overall look:
|
|
47
|
+
|
|
48
|
+
```css
|
|
49
|
+
[data-scheme='my-theme'] {
|
|
50
|
+
--sk-surface-base: var(--sk-color-purple-90);
|
|
51
|
+
--sk-text-primary: oklch(0.95 0.02 300);
|
|
52
|
+
}
|
|
40
53
|
```
|
|
41
54
|
|
|
42
55
|
### Interactive State Semantics
|
|
@@ -45,11 +58,13 @@ Unified focus and selection states across all interactive components.
|
|
|
45
58
|
|
|
46
59
|
```css
|
|
47
60
|
/* Focus Ring */
|
|
48
|
-
--sk-focus-ring-color:
|
|
49
|
-
--sk-focus-ring-width:
|
|
61
|
+
--sk-focus-ring-color: var(--sk-primary-base)
|
|
62
|
+
--sk-focus-ring-width: var(--sk-border-width-normal)
|
|
50
63
|
--sk-focus-ring-offset: 2px
|
|
64
|
+
--sk-focus-ring-style: var(--sk-border-style-solid)
|
|
65
|
+
--sk-focus-ring: var(--sk-focus-ring-width) var(--sk-focus-ring-style) var(--sk-focus-ring-color)
|
|
51
66
|
|
|
52
67
|
/* Selection */
|
|
53
68
|
--sk-selection-background: var(--sk-primary-base)
|
|
54
|
-
--sk-selection-text:
|
|
69
|
+
--sk-selection-text: var(--sk-primary-text)
|
|
55
70
|
```
|
|
@@ -4,7 +4,7 @@ section: themes
|
|
|
4
4
|
|
|
5
5
|
## Themes
|
|
6
6
|
|
|
7
|
-
Themes map foundation colors to semantic kinds. Each theme is defined as a CSS attribute selector that overrides semantic tokens.
|
|
7
|
+
Themes map foundation colors to semantic kinds. Each theme is defined as a CSS attribute selector that overrides semantic tokens. `SkPage` automatically applies the theme's surface background; all themed elements inherit the correct text color.
|
|
8
8
|
|
|
9
9
|
### Available Themes
|
|
10
10
|
|
|
@@ -24,15 +24,26 @@ Themes are defined in `src/styles/themes/`. Each theme file exports a `[data-sch
|
|
|
24
24
|
--sk-primary-base: var(--sk-color-mint-50);
|
|
25
25
|
--sk-accent-base: var(--sk-color-orange-50);
|
|
26
26
|
/* ... define all 7 semantic kinds */
|
|
27
|
+
|
|
28
|
+
/* Optional: override surface tokens */
|
|
29
|
+
--sk-surface-base: var(--sk-color-purple-90);
|
|
27
30
|
}
|
|
28
31
|
```
|
|
29
32
|
|
|
30
33
|
### Using Themes
|
|
31
34
|
|
|
32
|
-
|
|
35
|
+
Use `SkPage` with a `theme` prop (recommended) or wrap content in `SkTheme`:
|
|
33
36
|
|
|
34
37
|
```vue
|
|
38
|
+
<!-- Recommended: SkPage acts as theme provider -->
|
|
39
|
+
<SkPage theme="colorful">
|
|
40
|
+
<YourApp />
|
|
41
|
+
</SkPage>
|
|
42
|
+
|
|
43
|
+
<!-- Alternative: standalone theme wrapper -->
|
|
35
44
|
<SkTheme theme="greyscale">
|
|
36
45
|
<YourApp />
|
|
37
46
|
</SkTheme>
|
|
38
47
|
```
|
|
48
|
+
|
|
49
|
+
See the [Theming Guide](/docs/guides/theming) for creating custom themes.
|
|
@@ -10,7 +10,7 @@ SleekSpace UI is a Vue 3 component library with a cyberpunk aesthetic. It provid
|
|
|
10
10
|
|
|
11
11
|
### Minimal Example
|
|
12
12
|
|
|
13
|
-
The only requirement is
|
|
13
|
+
The only requirement is establishing a theme context. The simplest way is with `SkTheme`:
|
|
14
14
|
|
|
15
15
|
```vue
|
|
16
16
|
<template>
|
|
@@ -26,49 +26,50 @@ The only requirement is wrapping your app in `SkTheme`. Here is the simplest set
|
|
|
26
26
|
</template>
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
That's it. You can start using any SleekSpace component inside `SkTheme
|
|
29
|
+
That's it. You can start using any SleekSpace component inside the theme context. If you're using `SkPage`, you can skip `SkTheme` entirely — see the next section.
|
|
30
30
|
|
|
31
31
|
### Recommended Setup with SkPage
|
|
32
32
|
|
|
33
|
-
For most applications, you will want a proper page layout with a header, sidebar, and content area. `SkPage` provides this structure:
|
|
33
|
+
For most applications, you will want a proper page layout with a header, sidebar, and content area. `SkPage` provides this structure and can act as a theme provider directly via its `theme` prop — no `SkTheme` wrapper needed:
|
|
34
34
|
|
|
35
35
|
```vue
|
|
36
36
|
<template>
|
|
37
|
-
<
|
|
38
|
-
<
|
|
39
|
-
<
|
|
40
|
-
<
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<
|
|
46
|
-
<
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
</SkPage>
|
|
63
|
-
</SkTheme>
|
|
37
|
+
<SkPage theme="colorful" fixed-header>
|
|
38
|
+
<template #header>
|
|
39
|
+
<SkNavBar kind="primary">
|
|
40
|
+
<template #brand>My App</template>
|
|
41
|
+
</SkNavBar>
|
|
42
|
+
</template>
|
|
43
|
+
|
|
44
|
+
<template #sidebar>
|
|
45
|
+
<SkSidebar>
|
|
46
|
+
<SkSidebarItem href="/">Home</SkSidebarItem>
|
|
47
|
+
<SkSidebarItem href="/settings">Settings</SkSidebarItem>
|
|
48
|
+
</SkSidebar>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
51
|
+
<SkPanel kind="neutral">
|
|
52
|
+
<h2>Welcome to SleekSpace UI</h2>
|
|
53
|
+
<SkButton kind="accent" variant="solid">
|
|
54
|
+
Get Started
|
|
55
|
+
</SkButton>
|
|
56
|
+
</SkPanel>
|
|
57
|
+
|
|
58
|
+
<template #footer>
|
|
59
|
+
<p>Footer content goes here</p>
|
|
60
|
+
</template>
|
|
61
|
+
</SkPage>
|
|
64
62
|
</template>
|
|
65
63
|
```
|
|
66
64
|
|
|
65
|
+
> **Note:** When `theme` is provided, `SkPage` sets `data-scheme` on its root element and provides theme context to all descendants — including portal components like dropdowns and modals. If you omit the `theme` prop, `SkPage` behaves as a pure layout component and you'll need an `SkTheme` wrapper instead.
|
|
66
|
+
|
|
67
67
|
### Why Use SkPage?
|
|
68
68
|
|
|
69
69
|
`SkPage` is optional, but most applications will benefit from it:
|
|
70
70
|
|
|
71
71
|
- **Full page layout structure** -- Provides header, sidebar, content, and footer regions in a single component.
|
|
72
|
+
- **Built-in theme provider** -- Pass a `theme` prop to eliminate the `SkTheme` wrapper entirely.
|
|
72
73
|
- **Semantic HTML** -- Uses `<main>`, `<header>`, `<footer>`, and `<aside>` elements for better accessibility and SEO.
|
|
73
74
|
- **Fixed headers and footers** -- Keep navigation visible while the content area scrolls independently.
|
|
74
75
|
- **Flexible slots** -- All slots are optional. Use just a header, just a sidebar, or any combination. The layout adapts automatically.
|