@300codes/design-system 1.2.0 → 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.0",
3
+ "version": "1.2.2",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src/components",
@@ -56,13 +56,13 @@ const nativeAttrs = computed((): Record<string, unknown> => {
56
56
  v-bind="nativeAttrs"
57
57
  :class="[
58
58
  'baseLabel',
59
- 'no-underline inline-flex items-center justify-center',
60
59
  `baseLabel--${props.variant}`,
61
60
  `baseLabel--${props.size}`,
62
61
  {
63
62
  'baseLabel--interactive': isInteractive,
64
63
  'baseLabel--disabled': props.disabled,
65
64
  },
65
+ 'no-underline inline-flex items-center justify-center',
66
66
  ]"
67
67
  >
68
68
  <slot />
@@ -79,10 +79,9 @@ const nativeAttrs = computed((): Record<string, unknown> => {
79
79
  border: var(--baseLabel-border-width, 1px) solid var(--baseLabel-border, transparent);
80
80
  border-radius: var(--baseLabel-radius, 3.5rem);
81
81
  padding: var(--baseLabel-py, 0.125rem) var(--baseLabel-px, 0.5rem);
82
- min-height: var(--baseLabel-min-h, 1.5rem);
82
+ height: var(--baseLabel-min-h, 1.5rem);
83
83
  font-size: var(--baseLabel-font-size, 0.75rem);
84
84
  font-weight: var(--baseLabel-font-weight, 600);
85
- line-height: 1.2;
86
85
  }
87
86
 
88
87
  .baseLabel--interactive {
@@ -106,7 +105,8 @@ const nativeAttrs = computed((): Record<string, unknown> => {
106
105
  /* ── sm ── */
107
106
 
108
107
  .baseLabel--sm {
109
- min-height: var(--baseLabel-sm-min-h, 1.25rem);
108
+ height: var(--baseLabel-sm-min-h, 1.25rem);
109
+ font-size: var(--baseLabel-sm-font-size, 0.625rem);
110
110
  }
111
111
 
112
112
  /* ── secondary ── */
@@ -41,7 +41,7 @@ const emit = defineEmits<{
41
41
  .flatIconButton {
42
42
  color: var(--flatIconButton-fg, #0e161b);
43
43
  background: var(--flatIconButton-bg, transparent);
44
- padding: var(--flatIconButton-p, 0.25rem);
44
+ padding: var(--flatIconButton-p, 0);
45
45
  border-radius: var(--flatIconButton-radius, 9999px);
46
46
  }
47
47
 
@@ -132,6 +132,7 @@ watch(model, (val) => {
132
132
 
133
133
  .quantitySelector__input {
134
134
  width: var(--_input-w);
135
+ min-width: var(--_input-w);
135
136
  font-size: var(--_fs);
136
137
  color: var(--quantitySelector-fg, #0e161b);
137
138
  }
@@ -93,7 +93,6 @@ const nativeAttrs = computed((): Record<string, unknown> => {
93
93
  min-height: var(--simpleButton-min-h, 3.5rem);
94
94
  font-size: var(--simpleButton-font-size, 1rem);
95
95
  font-weight: var(--simpleButton-font-weight, 600);
96
- line-height: 1.2;
97
96
  gap: var(--simpleButton-gap, 1rem);
98
97
  }
99
98
 
@@ -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>
@@ -126,6 +126,7 @@
126
126
 
127
127
  /* sm */
128
128
  --baseLabel-sm-min-h: theme(--spacing-5);
129
+ --baseLabel-sm-font-size: theme(--text-2xs);
129
130
 
130
131
  /* ────────────────────────────────────────────────
131
132
  * LabelInput
@@ -382,7 +383,7 @@
382
383
  --flatIconButton-fg-hover: theme(--color-input-icon-hover);
383
384
  --flatIconButton-bg-hover: theme(--color-input-icon-bg-hover);
384
385
  --flatIconButton-outline: theme(--color-outline);
385
- --flatIconButton-p: theme(--spacing-1);
386
+ --flatIconButton-p: theme(--spacing-0);
386
387
  --flatIconButton-radius: theme(--radius-full);
387
388
 
388
389
  /* ────────────────────────────────────────────────
@@ -433,10 +434,12 @@
433
434
  --tabsList-px: theme(--spacing-7); /* 28px */
434
435
  --tabsList-h: theme(--spacing-10); /* 40px */
435
436
  --tabsList-font-size: theme(--text-sm);
437
+ --tabsList-icon-gap: theme(--spacing-0); /* 0px */
436
438
 
437
439
  /* lg */
438
440
  --tabsList-lg-gap: theme(--spacing-4); /* 16px */
439
441
  --tabsList-lg-px: theme(--spacing-9); /* 36px */
440
442
  --tabsList-lg-h: theme(--spacing-14); /* 56px */
441
443
  --tabsList-lg-font-size: theme(--text-base);
444
+ --tabsList-lg-icon-gap: theme(--spacing-0); /* 0px */
442
445
  }