@300codes/design-system 1.2.1 → 1.2.3
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/package.json
CHANGED
|
@@ -14,6 +14,8 @@ const meta: Meta<TabsListProps> = {
|
|
|
14
14
|
options: ['md', 'lg'],
|
|
15
15
|
},
|
|
16
16
|
items: { control: 'object' },
|
|
17
|
+
iconPath: { control: 'text' },
|
|
18
|
+
vertical: { control: 'boolean' },
|
|
17
19
|
},
|
|
18
20
|
};
|
|
19
21
|
|
|
@@ -62,6 +64,50 @@ export const Sizes: Story = {
|
|
|
62
64
|
}),
|
|
63
65
|
};
|
|
64
66
|
|
|
67
|
+
export const WithIcons: Story = {
|
|
68
|
+
args: {
|
|
69
|
+
size: 'md',
|
|
70
|
+
items: [
|
|
71
|
+
{ label: 'Overview', value: 'overview', icon: 'house' },
|
|
72
|
+
{ label: 'Analytics', value: 'analytics', icon: 'chart-bar' },
|
|
73
|
+
{ label: 'Reports', value: 'reports', icon: 'file-text' },
|
|
74
|
+
{ label: 'Settings', value: 'settings', icon: 'gear' },
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
render: (args: TabsListProps) => ({
|
|
78
|
+
components: { TabsList },
|
|
79
|
+
setup() {
|
|
80
|
+
const active = ref('overview');
|
|
81
|
+
return { args, active };
|
|
82
|
+
},
|
|
83
|
+
template: '<TabsList v-bind="args" v-model="active" />',
|
|
84
|
+
}),
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
export const Vertical: Story = {
|
|
88
|
+
parameters: {
|
|
89
|
+
controls: { disable: true },
|
|
90
|
+
},
|
|
91
|
+
args: {
|
|
92
|
+
size: 'md',
|
|
93
|
+
items: [
|
|
94
|
+
{ label: 'Overview', value: 'overview', icon: 'house' },
|
|
95
|
+
{ label: 'Analytics', value: 'analytics', icon: 'chart-bar' },
|
|
96
|
+
{ label: 'Reports', value: 'reports', icon: 'file-text' },
|
|
97
|
+
{ label: 'Settings', value: 'settings', icon: 'gear' },
|
|
98
|
+
],
|
|
99
|
+
},
|
|
100
|
+
render: (args: TabsListProps) => ({
|
|
101
|
+
components: { TabsList },
|
|
102
|
+
setup() {
|
|
103
|
+
const active = ref('overview');
|
|
104
|
+
return { args, active };
|
|
105
|
+
},
|
|
106
|
+
template:
|
|
107
|
+
'<div style="width: 200px"><TabsList v-bind="args" v-model="active" :vertical="true" /></div>',
|
|
108
|
+
}),
|
|
109
|
+
};
|
|
110
|
+
|
|
65
111
|
export const WithDisabled: Story = {
|
|
66
112
|
args: {
|
|
67
113
|
size: 'md',
|
|
@@ -1,19 +1,25 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { ref, computed, watch } from 'vue';
|
|
3
|
+
import BaseIcon from '../BaseIcon/BaseIcon.vue';
|
|
3
4
|
|
|
4
5
|
export interface TabsListItem {
|
|
5
6
|
label: string;
|
|
6
7
|
value: string;
|
|
7
8
|
disabled?: boolean;
|
|
9
|
+
icon?: string;
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
export interface TabsListProps {
|
|
11
13
|
items: TabsListItem[];
|
|
12
14
|
size?: 'md' | 'lg';
|
|
15
|
+
iconPath?: string;
|
|
16
|
+
vertical?: boolean;
|
|
13
17
|
}
|
|
14
18
|
|
|
15
19
|
const props = withDefaults(defineProps<TabsListProps>(), {
|
|
16
20
|
size: 'md',
|
|
21
|
+
iconPath: '/icons',
|
|
22
|
+
vertical: false,
|
|
17
23
|
});
|
|
18
24
|
|
|
19
25
|
const model = defineModel<string>({ default: '' });
|
|
@@ -71,6 +77,7 @@ watch(model, () => {
|
|
|
71
77
|
:class="[
|
|
72
78
|
'tabsList',
|
|
73
79
|
`tabsList--${size}`,
|
|
80
|
+
{ 'tabsList--vertical': vertical },
|
|
74
81
|
'flex flex-nowrap items-center overflow-x-auto list-none m-0 p-0',
|
|
75
82
|
]"
|
|
76
83
|
@focusout="handleFocusOut"
|
|
@@ -98,6 +105,13 @@ watch(model, () => {
|
|
|
98
105
|
@keydown="handleKeydown($event, index)"
|
|
99
106
|
>
|
|
100
107
|
{{ item.label }}
|
|
108
|
+
|
|
109
|
+
<BaseIcon
|
|
110
|
+
v-if="item.icon"
|
|
111
|
+
:name="item.icon"
|
|
112
|
+
:icon-path="iconPath"
|
|
113
|
+
size="md"
|
|
114
|
+
/>
|
|
101
115
|
</button>
|
|
102
116
|
</li>
|
|
103
117
|
</ul>
|
|
@@ -122,6 +136,7 @@ watch(model, () => {
|
|
|
122
136
|
font-weight: var(--tabsList-font-weight, 600);
|
|
123
137
|
outline: var(--tabsList-outline-width, 4px) solid transparent;
|
|
124
138
|
outline-offset: var(--tabsList-outline-offset, -4px);
|
|
139
|
+
gap: var(--tabsList-icon-gap, 0);
|
|
125
140
|
}
|
|
126
141
|
|
|
127
142
|
.tabsList__tab:hover:not(.tabsList__tab--active):not(.tabsList__tab--disabled) {
|
|
@@ -142,6 +157,20 @@ watch(model, () => {
|
|
|
142
157
|
@apply cursor-not-allowed pointer-events-none opacity-50;
|
|
143
158
|
}
|
|
144
159
|
|
|
160
|
+
/* ── vertical (md breakpoint and up) ── */
|
|
161
|
+
|
|
162
|
+
.tabsList--vertical {
|
|
163
|
+
@apply md:flex-col;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.tabsList--vertical > li {
|
|
167
|
+
@apply md:w-full;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.tabsList--vertical .tabsList__tab {
|
|
171
|
+
@apply md:w-full md:justify-between;
|
|
172
|
+
}
|
|
173
|
+
|
|
145
174
|
/* ── lg ── */
|
|
146
175
|
|
|
147
176
|
.tabsList--lg {
|
|
@@ -152,5 +181,6 @@ watch(model, () => {
|
|
|
152
181
|
padding: 0 var(--tabsList-lg-px, 2.25rem);
|
|
153
182
|
height: var(--tabsList-lg-h, 3.5rem);
|
|
154
183
|
font-size: var(--tabsList-lg-font-size, 1rem);
|
|
184
|
+
gap: var(--tabsList-lg-icon-gap, 0);
|
|
155
185
|
}
|
|
156
186
|
</style>
|
package/src/css/tokens.css
CHANGED
|
@@ -434,10 +434,12 @@
|
|
|
434
434
|
--tabsList-px: theme(--spacing-7); /* 28px */
|
|
435
435
|
--tabsList-h: theme(--spacing-10); /* 40px */
|
|
436
436
|
--tabsList-font-size: theme(--text-sm);
|
|
437
|
+
--tabsList-icon-gap: theme(--spacing-0); /* 0px */
|
|
437
438
|
|
|
438
439
|
/* lg */
|
|
439
440
|
--tabsList-lg-gap: theme(--spacing-4); /* 16px */
|
|
440
441
|
--tabsList-lg-px: theme(--spacing-9); /* 36px */
|
|
441
442
|
--tabsList-lg-h: theme(--spacing-14); /* 56px */
|
|
442
443
|
--tabsList-lg-font-size: theme(--text-base);
|
|
444
|
+
--tabsList-lg-icon-gap: theme(--spacing-0); /* 0px */
|
|
443
445
|
}
|