@300codes/design-system 1.2.1 → 1.2.2

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.2",
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,40 @@ 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
+ render: () => ({
92
+ components: { TabsList },
93
+ setup() {
94
+ const active = ref('overview');
95
+ return { active, defaultItems };
96
+ },
97
+ template: '<div style="width: 200px"><TabsList :items="defaultItems" v-model="active" :vertical="true" /></div>',
98
+ }),
99
+ };
100
+
65
101
  export const WithDisabled: Story = {
66
102
  args: {
67
103
  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,16 @@ 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
+ .tabsList--vertical > li,
166
+ .tabsList--vertical .tabsList__tab {
167
+ @apply md:w-full;
168
+ }
169
+
145
170
  /* ── lg ── */
146
171
 
147
172
  .tabsList--lg {
@@ -152,5 +177,6 @@ watch(model, () => {
152
177
  padding: 0 var(--tabsList-lg-px, 2.25rem);
153
178
  height: var(--tabsList-lg-h, 3.5rem);
154
179
  font-size: var(--tabsList-lg-font-size, 1rem);
180
+ gap: var(--tabsList-lg-icon-gap, 0);
155
181
  }
156
182
  </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
  }