@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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@300codes/design-system",
3
- "version": "1.2.1",
3
+ "version": "1.2.3",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src/components",
@@ -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>
@@ -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
  }