- Highlighted Text Highlighted Text Highlighted Text Highlighted Text Highlighted Text
+
+ Title active not animated
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam nec purus nec
+ ligula luctus aliquam. Nulla facilisi. Nulla facilisi. Nulla facilisi. Nulla
+ facilisi. Nulla facilisi. Nulla facilisi. Nulla facilisi. Nulla facilisi.
+
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam nec purus nec
ligula luctus aliquam. Nulla facilisi. Nulla facilisi. Nulla facilisi. Nulla
diff --git a/src/components/YHighlightedText/YHighlightedText.vue b/src/components/YHighlightedText/YHighlightedText.vue
index afe7a7f9..5afc8924 100644
--- a/src/components/YHighlightedText/YHighlightedText.vue
+++ b/src/components/YHighlightedText/YHighlightedText.vue
@@ -10,13 +10,14 @@
diff --git a/src/components/YHighlightedText/types.ts b/src/components/YHighlightedText/types.ts
index 7e4acf12..b466397c 100644
--- a/src/components/YHighlightedText/types.ts
+++ b/src/components/YHighlightedText/types.ts
@@ -1,4 +1,6 @@
-export interface YHighlightedTextProps {
+import { ColorProps } from '@/composables/theming/color'
+
+export interface YHighlightedTextProps extends ColorProps {
as?: 'p' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'span' | 'div'
animate?: boolean
active?: boolean
diff --git a/src/components/YInput/YInput.vue b/src/components/YInput/YInput.vue
index 27c61dd0..e469d54f 100644
--- a/src/components/YInput/YInput.vue
+++ b/src/components/YInput/YInput.vue
@@ -2,15 +2,19 @@
{{ label }}
@@ -21,7 +25,7 @@ import { useAttrs, useTemplateRef } from 'vue'
import { YLabel } from '@/components/YLabel'
import { useColor, useRaw, useSize, useState, useVariant } from '@/composables'
import { useComponentProps } from '@/composables/component'
-import { inputEventsKey, inputEventsKeyInterface } from '@/composables/input'
+import { inputEventsKey } from '@/composables/input'
import { computed, inject } from 'vue'
import './YInput.css'
import { YInputProps } from './types'
@@ -78,7 +82,17 @@ const { sizeClass } = useSize(props)
const { rawClasses } = useRaw(props)
const attrs = useAttrs()
-const { handleEvent, modelValue } = inject(inputEventsKey) as inputEventsKeyInterface
+// const { handleEvent, modelValue } = inject(inputEventsKey) as inputEventsKeyInterface
+
+const injected = inject(inputEventsKey, null)
+
+const handleEvent =
+ injected?.handleEvent ??
+ ((e: Event) => {
+ if (isDisabled.value) e.preventDefault()
+ })
+
+const modelValue = injected?.modelValue ?? computed(() => props.modelValue ?? '')
// Apply classes and styles to the input element
const componentProps = useComponentProps({
diff --git a/src/components/YInputText/YInputText.vue b/src/components/YInputText/YInputText.vue
index 5092b31c..645252c5 100644
--- a/src/components/YInputText/YInputText.vue
+++ b/src/components/YInputText/YInputText.vue
@@ -4,8 +4,8 @@
v-bind="props"
input-class="y-input-text"
type="text"
- :value="modelValue"
- @input="handleInput"
+ :model-value="modelValue"
+ @change="updateModelValue"
/>
@@ -22,5 +22,5 @@ const props = withDefaults(defineProps(), {
const emit: EmitFn = defineEmits(['update:modelValue', 'input', 'change', 'blur'])
const attrs = useAttrs()
-const { modelValue, handleInput } = useInput({ props, attrs, emit })
+const { modelValue, updateModelValue } = useInput({ props, attrs, emit })
diff --git a/src/components/YMenu/YMenu.css b/src/components/YMenu/YMenu.css
index a89deddf..79f00a37 100644
--- a/src/components/YMenu/YMenu.css
+++ b/src/components/YMenu/YMenu.css
@@ -8,5 +8,6 @@
background-color: inherit;
padding-left: 1rem;
padding-right: 1rem;
+
--component-box-shadow: var(--component-box-shadow);
}
diff --git a/src/components/YMenu/YMenu.scss b/src/components/YMenu/YMenu.scss
index 7d166d43..685a713a 100644
--- a/src/components/YMenu/YMenu.scss
+++ b/src/components/YMenu/YMenu.scss
@@ -3,6 +3,7 @@
@use '@/assets/scss/global.scss' as *;
@use '@/assets/scss/theme/state' as state;
@use '@/assets/scss/theme/color' as color;
+
// TODO: change to kebab-case
.y-menu {
// @include theme-component;
@@ -18,5 +19,6 @@
background-color: inherit; /* rt-bg-white */
padding-left: 1rem; /* rt-px-4 -> 16px */
padding-right: 1rem; /* rt-px-4 -> 16px */
+
@include utils.component(box-shadow, utils.component(box-shadow));
}
diff --git a/src/components/YModal/YModal.css b/src/components/YModal/YModal.css
index 1857b9c1..99558843 100644
--- a/src/components/YModal/YModal.css
+++ b/src/components/YModal/YModal.css
@@ -75,7 +75,7 @@
}
}
-@media (min-width: 768px) {
+@media (width >= 768px) {
.y-modal {
width: var(--modal-size, var(--modal-size-default));
}
@@ -115,5 +115,6 @@
.y-modal-footer .y-button {
--component-margin-bottom: var(--component-box-shadow-y);
+
border: var(--component-border);
}
diff --git a/src/components/YRow/YRow.stories.ts b/src/components/YRow/YRow.stories.ts
new file mode 100644
index 00000000..b08ede05
--- /dev/null
+++ b/src/components/YRow/YRow.stories.ts
@@ -0,0 +1,50 @@
+import type { Meta, StoryObj } from '@storybook/vue3-vite'
+import { boxArgTypes } from '../YBox/YBox.stories'
+import YRow from './YRow.vue'
+// import { useThemeComponentStory } from '@/composables'
+
+// const { commonArgTypes, commonArgs, generateCommonStories } = useThemeComponentStory(YRow)
+
+const meta: Meta = {
+ // TODO: TO CHANGE PATH
+ title: 'Components/YRow',
+ component: YRow,
+ tags: ['autodocs'],
+ argTypes: {
+ type: { control: 'select', options: ['default', 'cluster', 'switcher'] },
+ ...boxArgTypes,
+ },
+ args: {
+ type: 'default',
+ // ...commonArgs,
+ },
+}
+
+export default meta
+type Story = StoryObj
+
+const renderGenericStory: Story = {
+ render: (args, { argTypes }) => ({
+ components: { YRow },
+ props: Object.keys(argTypes),
+ template: `
+
+ Column 1
+ Column 2
+ Column 3
+ Column 4
+ Column 5
+
+ `,
+ setup() {
+ return { args }
+ },
+ }),
+}
+
+export { renderGenericStory as Default }
+
+// TODO: if you use useThemeComponentStory
+// const { Default, Outlined, Disabled, Raw, Small, Large } = generateCommonStories(renderGenericStory)
+
+// export { Default, Outlined, Disabled, Raw, Small, Large }
diff --git a/src/components/YRow/YRow.test.ts b/src/components/YRow/YRow.test.ts
new file mode 100644
index 00000000..1003ad2a
--- /dev/null
+++ b/src/components/YRow/YRow.test.ts
@@ -0,0 +1,17 @@
+import { render } from '@testing-library/vue'
+import { describe, expect, it } from 'vitest'
+
+import YRow from './YRow.vue'
+
+describe('YRow', () => {
+ it('renders', () => {
+ const yrow = render(YRow, {
+ // slots: {
+ // default: 'Default content for YRow component',
+ // },
+ })
+
+ // expect(yrow.html()).toContain('Default content for YRow component')
+ expect(yrow.html()).toMatchSnapshot()
+ })
+})
diff --git a/src/components/YRow/YRow.vue b/src/components/YRow/YRow.vue
new file mode 100644
index 00000000..5de47ffb
--- /dev/null
+++ b/src/components/YRow/YRow.vue
@@ -0,0 +1,32 @@
+
+
+
+ Default content for YRow component
+
+
+
+
+
diff --git a/src/components/YRow/__snapshots__/YRow.test.ts.snap b/src/components/YRow/__snapshots__/YRow.test.ts.snap
new file mode 100644
index 00000000..bc705c79
--- /dev/null
+++ b/src/components/YRow/__snapshots__/YRow.test.ts.snap
@@ -0,0 +1,7 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`YRow > renders 1`] = `
+"
+
Default content for YRow component
+
"
+`;
diff --git a/src/components/YRow/index.ts b/src/components/YRow/index.ts
new file mode 100644
index 00000000..6dfae687
--- /dev/null
+++ b/src/components/YRow/index.ts
@@ -0,0 +1 @@
+export { default as YRow } from './YRow.vue'
\ No newline at end of file
diff --git a/src/components/YSection/YSection.css b/src/components/YSection/YSection.css
index 604b49ca..4051015a 100644
--- a/src/components/YSection/YSection.css
+++ b/src/components/YSection/YSection.css
@@ -1,18 +1,21 @@
.y-section {
- width: 100%;
- display: flex;
- flex-wrap: wrap;
- padding: 15px 22px 10px;
+ /* width: 100%; */
+ --padding-xs: var(--media-xs) 15px 22px 10px;
+ --padding-sm: var(--media-sm) 40px 20px 10px 0;
+ --padding-md: var(--media-md) 50px 37px 0 0;
+
+ padding: var(--padding-md, var(--padding-sm, var(--padding-xs)));
&:last-child {
padding-bottom: 22px;
}
}
-@media (min-width: 768px) {
+@media (width >= 768px) {
.y-section {
flex-wrap: nowrap;
- padding: 40px 20px 10px 0;
+
+ /* padding: 40px 20px 10px 0; */
.y-vertical-title {
--space-unit: 1rem;
@@ -21,12 +24,12 @@
}
}
-@media (min-width: 1024px) {
+@media (width >= 1024px) {
.y-section {
- padding: 50px 37px 0 0;
+ /* padding: 50px 37px 0 0; */
&:last-child {
- padding-bottom: 50px;
+ /* padding-bottom: 50px; */
}
}
}
diff --git a/src/components/YSection/YSection.vue b/src/components/YSection/YSection.vue
index 348f9a63..6d7a6356 100644
--- a/src/components/YSection/YSection.vue
+++ b/src/components/YSection/YSection.vue
@@ -1,17 +1,17 @@
-
+
{{ title }}
-
+
-
-
+
+
diff --git a/src/components/YStack/__snapshots__/YStack.test.ts.snap b/src/components/YStack/__snapshots__/YStack.test.ts.snap
new file mode 100644
index 00000000..0214230b
--- /dev/null
+++ b/src/components/YStack/__snapshots__/YStack.test.ts.snap
@@ -0,0 +1,7 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`YStack > renders 1`] = `
+"
+
Default content for YStack component
+
"
+`;
diff --git a/src/components/YStack/index.ts b/src/components/YStack/index.ts
new file mode 100644
index 00000000..b9d5ac72
--- /dev/null
+++ b/src/components/YStack/index.ts
@@ -0,0 +1 @@
+export { default as YStack } from './YStack.vue'
\ No newline at end of file
diff --git a/src/components/YTable/YTable.scss b/src/components/YTable/YTable.scss
index e19993a5..3888f599 100644
--- a/src/components/YTable/YTable.scss
+++ b/src/components/YTable/YTable.scss
@@ -20,8 +20,8 @@
&:hover {
.y-table-data-cell {
opacity: 0.6;
-
background-color: var(--color-primary-20);
+
&:hover {
opacity: 1;
background-color: var(--color-primary-30);
@@ -35,6 +35,7 @@
background-color: var(--color-background);
}
}
+
.y-table-row {
// border-bottom: utils.space(xxs) solid utils.color(primary);
diff --git a/src/components/YTag/YTag.css b/src/components/YTag/YTag.css
index 16ed3b92..42f1bfdd 100644
--- a/src/components/YTag/YTag.css
+++ b/src/components/YTag/YTag.css
@@ -1,5 +1,6 @@
.y-tag {
display: inline-flex;
+
--component-margin-bottom: none;
--component-padding-y: 0.15rem;
diff --git a/src/components/YTag/YTag.scss b/src/components/YTag/YTag.scss
index 8691c556..f7e007dd 100644
--- a/src/components/YTag/YTag.scss
+++ b/src/components/YTag/YTag.scss
@@ -7,7 +7,9 @@
@include theme-component;
display: inline-flex;
+
@include utils.component(margin-bottom, none);
+
// text-transform: uppercase;
@include utils.component(padding-y, 0.15rem);
diff --git a/src/components/YThemePicker/YThemePicker.vue b/src/components/YThemePicker/YThemePicker.vue
index 345b0aa9..33ff3ac2 100644
--- a/src/components/YThemePicker/YThemePicker.vue
+++ b/src/components/YThemePicker/YThemePicker.vue
@@ -1,24 +1,36 @@
-
-
-
-
-
-
- Randomize
-
+
+
+
+
+
+
+
+ Randomize
+
+
{{ getToken('border-radius-base') }}
-
+
+
diff --git a/src/components/YVerticalTitle/YVerticalTitle.css b/src/components/YVerticalTitle/YVerticalTitle.css
index 29a76ad0..ce217d48 100644
--- a/src/components/YVerticalTitle/YVerticalTitle.css
+++ b/src/components/YVerticalTitle/YVerticalTitle.css
@@ -13,13 +13,12 @@
color: var(--theme-color);
position: relative;
z-index: 1;
-
min-height: var(--heading-height);
text-align: center;
flex: 1 0 100%;
}
-@media (min-width: 768px) {
+@media (width >= 768px) {
.y-vertical-title {
font-size: var(--y-vertical-title-font-size-md);
display: flex;
@@ -34,13 +33,13 @@
}
}
-@media (min-width: 1024px) {
+@media (width >= 1024px) {
.y-vertical-title {
padding: 0 46px 0 37px;
}
}
-@media (min-width: 1280px) {
+@media (width >= 1280px) {
.y-vertical-title {
font-size: var(--y-vertical-title-font-size-xs-and-xl);
}
diff --git a/src/components/YVerticalTitle/YVerticalTitle.scss b/src/components/YVerticalTitle/YVerticalTitle.scss
index 584b606b..914877d8 100644
--- a/src/components/YVerticalTitle/YVerticalTitle.scss
+++ b/src/components/YVerticalTitle/YVerticalTitle.scss
@@ -19,7 +19,6 @@
color: var(--theme-color);
position: relative;
z-index: 1;
-
min-height: var(--heading-height);
text-align: center;
flex: 1 0 100%;
diff --git a/src/components/utils.ts b/src/components/utils.ts
new file mode 100644
index 00000000..3ca1cc48
--- /dev/null
+++ b/src/components/utils.ts
@@ -0,0 +1,260 @@
+import { PropType } from 'vue'
+import type { DesignTokens } from '../assets/css/themes/tokens/types/theme'
+
+// TODO: Review as done by Claude 80%
+export {
+ getSpacingOptions,
+ isDefined,
+ parseBackgroundColorProps,
+ parseBorderProps,
+ parseHeightProps,
+ parseMarginProps,
+ parsePaddingProps,
+ parseRadiusProps,
+ parseWidthProps,
+}
+
+function isDefined(value: unknown): boolean {
+ return value !== undefined && value !== null
+}
+
+// Derive types from DesignTokens interface (type-only import, no runtime dependency)
+export type SpacingKey = keyof DesignTokens['spacing']
+export type RadiusKey = keyof DesignTokens['radius']
+export type WidthKey = keyof DesignTokens['cube']['utility']['width']
+export type HeightKey = keyof DesignTokens['cube']['utility']['height']
+export type MarginKey = SpacingKey | 'auto' | '0'
+export type BorderKey =
+ | keyof DesignTokens['cube']['utility']['border']
+ | keyof DesignTokens['cube']['utility']['border']['theme']
+ | keyof DesignTokens['cube']['utility']['border']['width']
+export type BackgroundColorKey = keyof DesignTokens['cube']['utility']['bg']
+
+const spacingOptions: SpacingKey[] = ['xxs', 'xs', 'sm', 'md', 'lg', 'xl', 'xxl']
+
+function getSpacingOptions(): SpacingKey[] {
+ return spacingOptions
+}
+
+/**
+ * Take a input to represent padding in a Vue component props and generate corresponding utility classes
+ *
+ * e.g.
+ * padding="md sm xs lg" => will generate ['padding-top-md', 'padding-right-sm', 'padding-bottom-xs', 'padding-left-lg']
+ *
+ * @param {(SpacingKey | SpacingKey[])} paddingProps
+ * @returns {(string | string[])}
+ */
+function parsePaddingProps(paddingProps?: SpacingKey | SpacingKey[]): string | string[] {
+ if (!isDefined(paddingProps)) {
+ return []
+ }
+
+ const values = paddingProps
+ ?.toString()
+ .split(' ')
+ .map((v) => v.trim())
+
+ if (values && values.length === 1) {
+ const value = values[0]
+
+ return [`padding-${value}`]
+ }
+
+ if (values && values.length === 2) {
+ const [vertical, horizontal] = values
+ return [`padding-x-${horizontal}`, `padding-y-${vertical}`]
+ }
+
+ if (values && values.length === 3) {
+ const [top, horizontal, bottom] = values
+ return [`padding-top-${top}`, `padding-x-${horizontal}`, `padding-bottom-${bottom}`]
+ }
+
+ if (values && values.length === 4) {
+ const [top, right, bottom, left] = values
+ return [
+ `padding-top-${top}`,
+ `padding-right-${right}`,
+ `padding-bottom-${bottom}`,
+ `padding-left-${left}`,
+ ]
+ }
+
+ return []
+}
+
+export function definePropsFromType() {
+ return {} as {
+ [K in keyof T]: {
+ type: PropType
+ }
+ }
+}
+
+function parseRadiusProps(radiusProps?: RadiusKey | RadiusKey[]): string | string[] {
+ if (!isDefined(radiusProps)) {
+ return []
+ }
+
+ const values = radiusProps
+ ?.toString()
+ .split(' ')
+ .map((v) => v.trim())
+
+ if (values && values.length === 1) {
+ const value = values[0]
+
+ return [`radius-${value}`]
+ }
+
+ if (values && values.length === 2) {
+ const [top, bottom] = values
+ return [`radius-y-top-${top}`, `radius-y-bottom-${bottom}`]
+ }
+
+ if (values && values.length === 3) {
+ const [topLeft, topRight, bottom] = values
+ return [`radius-top-left-${topLeft}`, `radius-top-right-${topRight}`, `radius-bottom-${bottom}`]
+ }
+
+ if (values && values.length === 4) {
+ const [topLeft, topRight, bottomRight, bottomLeft] = values
+ return [
+ `radius-top-left-${topLeft}`,
+ `radius-top-right-${topRight}`,
+ `radius-bottom-right-${bottomRight}`,
+ `radius-bottom-left-${bottomLeft}`,
+ ]
+ }
+
+ return []
+}
+
+/**
+ * Parse width prop and generate corresponding utility class
+ *
+ * e.g.
+ * width="full" => ['width-full']
+ *
+ * @param {WidthKey} widthProps
+ * @returns {string[]}
+ */
+function parseWidthProps(widthProps?: WidthKey): string[] {
+ if (!isDefined(widthProps)) {
+ return []
+ }
+ return [`width-${widthProps}`]
+}
+
+/**
+ * Parse height prop and generate corresponding utility class
+ *
+ * e.g.
+ * height="screen" => ['height-screen']
+ *
+ * @param {HeightKey} heightProps
+ * @returns {string[]}
+ */
+function parseHeightProps(heightProps?: HeightKey): string[] {
+ if (!isDefined(heightProps)) {
+ return []
+ }
+ return [`height-${heightProps}`]
+}
+
+/**
+ * Parse margin prop and generate corresponding utility classes
+ * Follows the same CSS shorthand pattern as padding
+ *
+ * e.g.
+ * margin="md" => ['margin-md']
+ * margin="md lg" => ['margin-y-md', 'margin-x-lg']
+ * margin="md lg sm" => ['margin-top-md', 'margin-x-lg', 'margin-bottom-sm']
+ * margin="md lg sm xl" => ['margin-top-md', 'margin-right-lg', 'margin-bottom-sm', 'margin-left-xl']
+ *
+ * @param {(MarginKey | MarginKey[])} marginProps
+ * @returns {string[]}
+ */
+function parseMarginProps(marginProps?: MarginKey | MarginKey[]): string[] {
+ if (!isDefined(marginProps)) {
+ return []
+ }
+
+ const values = marginProps
+ ?.toString()
+ .split(' ')
+ .map((v) => v.trim())
+
+ if (values && values.length === 1) {
+ const value = values[0]
+ return [`margin-${value}`]
+ }
+
+ if (values && values.length === 2) {
+ const [vertical, horizontal] = values
+ return [`margin-y-${vertical}`, `margin-x-${horizontal}`]
+ }
+
+ if (values && values.length === 3) {
+ const [top, horizontal, bottom] = values
+ return [`margin-top-${top}`, `margin-x-${horizontal}`, `margin-bottom-${bottom}`]
+ }
+
+ if (values && values.length === 4) {
+ const [top, right, bottom, left] = values
+ return [
+ `margin-top-${top}`,
+ `margin-right-${right}`,
+ `margin-bottom-${bottom}`,
+ `margin-left-${left}`,
+ ]
+ }
+
+ return []
+}
+
+/**
+ * Parse border prop and generate corresponding utility classes
+ *
+ * e.g.
+ * border="all" => ['border-all']
+ * border="top bottom" => ['border-top', 'border-bottom']
+ *
+ * @param {(BorderKey | BorderKey[])} borderProps
+ * @returns {string[]}
+ */
+function parseBorderProps(borderProps?: BorderKey | BorderKey[]): string[] {
+ if (!isDefined(borderProps)) {
+ return []
+ }
+
+ if (Array.isArray(borderProps)) {
+ return borderProps.map((v) => `border-${v}`)
+ }
+ const values = borderProps
+ ?.toString()
+ .split(' ')
+ .map((v) => v.trim())
+ if (!values || values.length === 0) {
+ return []
+ }
+
+ return values.map((v) => `border-${v}`)
+}
+
+/**
+ * Parse backgroundColor prop and generate corresponding utility class
+ *
+ * e.g.
+ * backgroundColor="primary" => ['bg-primary']
+ *
+ * @param {BackgroundColorKey} backgroundColorProps
+ * @returns {string[]}
+ */
+function parseBackgroundColorProps(backgroundColorProps?: BackgroundColorKey): string[] {
+ if (!isDefined(backgroundColorProps)) {
+ return []
+ }
+ return [`bg-${backgroundColorProps}`]
+}
diff --git a/src/composables/animation.ts b/src/composables/animation.ts
index 928f6bf1..8a5a8a48 100644
--- a/src/composables/animation.ts
+++ b/src/composables/animation.ts
@@ -64,7 +64,7 @@ export function useHoverEvent(target: MaybeRefOrGetter) {
console.warn('📟 - element is undefined or null', element)
return
}
- element.style.setProperty('--is-not-hovered-yet', 'none')
+ element.style.setProperty('--is-not-hovered-yet', ' ;')
})
watch(
@@ -76,7 +76,7 @@ export function useHoverEvent(target: MaybeRefOrGetter) {
return
}
if (newVal && element instanceof HTMLElement) {
- element.style.removeProperty('--has-changed-once')
+ element.style.setProperty('--is-not-hovered-yet', 'initial')
}
},
)
diff --git a/src/composables/event.ts b/src/composables/event.ts
index 45ca1d23..2731ab9d 100644
--- a/src/composables/event.ts
+++ b/src/composables/event.ts
@@ -71,7 +71,7 @@ export function useInputEvent(props: YInputProps, attrs: Record
emit('change', value)
break
case 'focus':
- el.focus()
+ emit('focus', value)
break
case 'blur':
emit('blur', value)
diff --git a/src/composables/use-theme-tokens.ts b/src/composables/use-theme-tokens.ts
index 3e0b0599..3ac24e96 100644
--- a/src/composables/use-theme-tokens.ts
+++ b/src/composables/use-theme-tokens.ts
@@ -1,16 +1,19 @@
-import { YThemeToken } from '@/assets/css/tokens/types/theme'
+// use-theme-tokens.ts
import { isClientSide } from '@/utils/is-client-side'
+import type { YThemeToken } from 'unholy-tokens/types/tokens'
-// TODO: rewrite (GPT)
-export type YThemeTokenName = keyof YThemeToken // e.g. "border-radius-base" | ...
-export type YCssVarName = `--${YThemeTokenName}` // e.g. "--border-radius-base" | ...
+// ✅ only string keys
+export type YThemeTokenName = Extract
+
+// ✅ css var union
+export type YCssVarName = `--${YThemeTokenName}`
export function useThemeTokens(target: HTMLElement = document.documentElement) {
- type Token = keyof YThemeToken
+ type Token = YThemeTokenName
const setToken = (token: Token, value: string | null) => {
if (!isClientSide()) return
- const cssVar = `--${token}` as const
+ const cssVar = `--${token}` as YCssVarName
if (value === null) target.style.removeProperty(cssVar)
else target.style.setProperty(cssVar, value)
}
diff --git a/src/index.ts b/src/index.ts
index d3e96da7..b32d72d7 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,10 +1,5 @@
-// import { Wrapper } from './components'
-
-// export { Wrapper }
-// import './assets/scss/main.scss'
-
-// import { Wrapper, YButton, YInput, Container, Flex, Card, Highlighted } from './components'
-
+// Supports weights 100-900
+import '@fontsource-variable/roboto'
// Composables
export * from './components'
export * from './composables'
diff --git a/stylelint.config.mjs b/stylelint.config.mjs
index b8d5af94..68a47925 100644
--- a/stylelint.config.mjs
+++ b/stylelint.config.mjs
@@ -1,5 +1,10 @@
export default {
- ignoreFiles: ['storybook-static/**', 'dist/**', 'node_modules/**'],
+ ignoreFiles: [
+ 'storybook-static/**',
+ 'dist/**',
+ 'node_modules/**',
+ 'src/assets/css/themes/tokens/**',
+ ],
extends: [
'stylelint-config-standard',
'stylelint-config-standard-scss',
diff --git a/tsconfig.json b/tsconfig.json
index d463c786..e3399953 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -23,7 +23,12 @@
"baseUrl": ".",
"paths": {
- "@/*": ["src/*"]
+ "@/*": ["src/*"],
+ "@/components/*": ["src/components/*"],
+ "@/composables/*": ["src/composables/*"],
+ "@/utils/*": ["src/utils/*"],
+ "@/assets/*": ["src/assets/*"],
+ "unholy-tokens/*": ["src/assets/css/themes/tokens/*"]
}
},
"include": [
diff --git a/vite.config.ts b/vite.config.ts
index 0324eaa2..876624de 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -5,6 +5,7 @@ import { fileURLToPath, URL } from 'url'
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import vueDevTools from 'vite-plugin-vue-devtools'
+import tsconfigPaths from 'vite-tsconfig-paths'
// const pathSrc = resolve(__dirname, './src')
@@ -16,6 +17,8 @@ export default defineConfig(({ mode }) => {
return {
plugins: [
vue(),
+ // Give vite the ability to resolve imports using TypeScript's path mapping.
+ tsconfigPaths(),
dts({
entryRoot: './src',
tsconfigPath: fileURLToPath(new URL('./tsconfig.json', import.meta.url)),
@@ -33,6 +36,7 @@ export default defineConfig(({ mode }) => {
alias: [
{ find: '@', replacement: fileURLToPath(new URL('./src/', import.meta.url)) },
{ find: '../../../', replacement: fileURLToPath(new URL('./src/assets', import.meta.url)) },
+ { find: 'unholy-tokens/*', replacement: 'src/assets/css/themes/tokens/*' },
],
},
// publicDir: 'public',