@300codes/design-system 1.0.0 → 1.1.0

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.0.0",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src/components",
@@ -21,7 +21,8 @@
21
21
  "./radio-input": "./src/components/RadioInput/index.ts",
22
22
  "./tabs-list": "./src/components/TabsList/index.ts",
23
23
  "./search-input": "./src/components/SearchInput/index.ts",
24
- "./base-tooltip": "./src/components/BaseTooltip/index.ts"
24
+ "./base-tooltip": "./src/components/BaseTooltip/index.ts",
25
+ "./flat-icon-button": "./src/components/FlatIconButton/index.ts"
25
26
  },
26
27
  "scripts": {
27
28
  "build": "vue-tsc --noEmit",
@@ -0,0 +1,81 @@
1
+ import type { Meta, StoryObj } from '@storybook/vue3-vite';
2
+ import type { ConcreteComponent } from 'vue';
3
+ import type { FlatIconButtonProps } from './FlatIconButton.vue';
4
+ import FlatIconButton from './FlatIconButton.vue';
5
+
6
+ const meta: Meta<FlatIconButtonProps> = {
7
+ title: 'Components/FlatIconButton',
8
+ component: FlatIconButton as unknown as ConcreteComponent<FlatIconButtonProps>,
9
+ tags: ['autodocs'],
10
+ argTypes: {
11
+ iconName: { control: 'text' },
12
+ iconPath: { control: 'text' },
13
+ iconSize: {
14
+ control: 'select',
15
+ options: ['xs', 'sm', 'md', 'lg', 'xl'],
16
+ },
17
+ ariaLabel: { control: 'text' },
18
+ },
19
+ };
20
+
21
+ export default meta;
22
+ type Story = StoryObj<FlatIconButtonProps>;
23
+
24
+ export const Default: Story = {
25
+ args: {
26
+ iconName: 'close',
27
+ iconSize: 'sm',
28
+ ariaLabel: 'Close',
29
+ },
30
+ render: (args: FlatIconButtonProps) => ({
31
+ components: { FlatIconButton },
32
+ setup() {
33
+ return { args };
34
+ },
35
+ template: '<FlatIconButton v-bind="args" />',
36
+ }),
37
+ };
38
+
39
+ export const Search: Story = {
40
+ args: {
41
+ iconName: 'search',
42
+ iconSize: 'sm',
43
+ ariaLabel: 'Search',
44
+ },
45
+ render: (args: FlatIconButtonProps) => ({
46
+ components: { FlatIconButton },
47
+ setup() {
48
+ return { args };
49
+ },
50
+ template: '<FlatIconButton v-bind="args" />',
51
+ }),
52
+ };
53
+
54
+ export const MediumSize: Story = {
55
+ args: {
56
+ iconName: 'close',
57
+ iconSize: 'md',
58
+ ariaLabel: 'Close',
59
+ },
60
+ render: (args: FlatIconButtonProps) => ({
61
+ components: { FlatIconButton },
62
+ setup() {
63
+ return { args };
64
+ },
65
+ template: '<FlatIconButton v-bind="args" />',
66
+ }),
67
+ };
68
+
69
+ export const Sizes: Story = {
70
+ render: () => ({
71
+ components: { FlatIconButton },
72
+ template: `
73
+ <div class="flex items-center gap-4">
74
+ <FlatIconButton icon-name="close" icon-size="xs" aria-label="Close xs" />
75
+ <FlatIconButton icon-name="close" icon-size="sm" aria-label="Close sm" />
76
+ <FlatIconButton icon-name="close" icon-size="md" aria-label="Close md" />
77
+ <FlatIconButton icon-name="close" icon-size="lg" aria-label="Close lg" />
78
+ </div>
79
+ `,
80
+ }),
81
+ };
@@ -0,0 +1,54 @@
1
+ <script setup lang="ts">
2
+ import type { IconSize } from '../../types/icon';
3
+ import BaseIcon from '../BaseIcon/BaseIcon.vue';
4
+
5
+ export interface FlatIconButtonProps {
6
+ iconName: string;
7
+ iconPath?: string;
8
+ iconSize?: IconSize;
9
+ ariaLabel?: string;
10
+ }
11
+
12
+ withDefaults(defineProps<FlatIconButtonProps>(), {
13
+ iconPath: '/icons',
14
+ iconSize: 'sm',
15
+ ariaLabel: undefined,
16
+ });
17
+
18
+ const emit = defineEmits<{
19
+ click: [];
20
+ }>();
21
+ </script>
22
+
23
+ <template>
24
+ <button
25
+ type="button"
26
+ class="flatIconButton inline-flex items-center justify-center cursor-pointer"
27
+ :aria-label="ariaLabel"
28
+ @click="emit('click')"
29
+ >
30
+ <BaseIcon
31
+ :name="iconName"
32
+ :icon-path="iconPath"
33
+ :size="iconSize"
34
+ />
35
+ </button>
36
+ </template>
37
+
38
+ <style scoped>
39
+ .flatIconButton {
40
+ color: var(--flatIconButton-fg, #0e161b);
41
+ background: var(--flatIconButton-bg, transparent);
42
+ padding: var(--flatIconButton-p, 0.25rem);
43
+ border-radius: var(--flatIconButton-radius, 9999px);
44
+ }
45
+
46
+ .flatIconButton:hover {
47
+ background-color: var(--flatIconButton-bg-hover, #f3f4f6);
48
+ }
49
+
50
+ .flatIconButton:focus-visible {
51
+ outline: 2px solid var(--flatIconButton-outline, #0066cc);
52
+ outline-offset: 1px;
53
+ }
54
+ </style>
@@ -0,0 +1,2 @@
1
+ export { default as FlatIconButton } from './FlatIconButton.vue';
2
+ export type { FlatIconButtonProps } from './FlatIconButton.vue';
@@ -2,7 +2,7 @@
2
2
  import { ref, computed, nextTick, watch } from 'vue';
3
3
  import { useMediaQuery, onClickOutside } from '@vueuse/core';
4
4
  import BaseIcon from '../BaseIcon/BaseIcon.vue';
5
- import InputIconButton from '../TextInput/components/InputIconButton.vue';
5
+ import FlatIconButton from '../FlatIconButton/FlatIconButton.vue';
6
6
 
7
7
  export type SelectOption = string | { value: string; label: string };
8
8
 
@@ -259,7 +259,7 @@ watch(isMobile, () => {
259
259
  >
260
260
  {{ mobileTitle || placeholder }}
261
261
 
262
- <InputIconButton
262
+ <FlatIconButton
263
263
  icon-name="close"
264
264
  aria-label="Close"
265
265
  class="ml-auto"
@@ -1,7 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import { computed, ref, type Ref } from 'vue';
3
3
  import type { IconSize } from '../../types/icon';
4
- import InputIconButton from './components/InputIconButton.vue';
4
+ import FlatIconButton from '../FlatIconButton/FlatIconButton.vue';
5
5
 
6
6
  export type InputType = 'text' | 'password' | 'email' | 'tel' | 'search';
7
7
  export type FilterType = 'number' | 'number-dash' | 'alpha' | 'alpha-space';
@@ -124,7 +124,7 @@ defineExpose<{ el: Ref<HTMLInputElement | undefined> }>({ el });
124
124
  @keyup.enter="emit('enter')"
125
125
  >
126
126
 
127
- <InputIconButton
127
+ <FlatIconButton
128
128
  v-if="iconLeft"
129
129
  :icon-name="iconLeft.name"
130
130
  :icon-path="iconLeft.iconPath"
@@ -134,7 +134,7 @@ defineExpose<{ el: Ref<HTMLInputElement | undefined> }>({ el });
134
134
  @click="emit('clickIcon', 'left')"
135
135
  />
136
136
 
137
- <InputIconButton
137
+ <FlatIconButton
138
138
  v-if="iconRight"
139
139
  :icon-name="iconRight.name"
140
140
  :icon-path="iconRight.iconPath"
@@ -12,4 +12,5 @@ export * from './RadioInput/index';
12
12
  export * from './TabsList/index';
13
13
  export * from './SearchInput/index';
14
14
  export * from './BaseTooltip/index';
15
+ export * from './FlatIconButton/index';
15
16
  export type { IconSize } from '../types/icon';
@@ -182,15 +182,6 @@
182
182
  --input-border-color-disabled: theme(--color-input-border-disabled);
183
183
  --input-placeholder-fg-disabled: theme(--color-input-placeholder-disabled);
184
184
 
185
- /* icon button */
186
- --input-icon-bg: transparent;
187
- --input-icon-fg: theme(--color-input-icon);
188
- --input-icon-fg-hover: theme(--color-input-icon-hover);
189
- --input-icon-bg-hover: theme(--color-input-icon-bg-hover);
190
- --input-icon-outline: theme(--color-outline);
191
- --input-icon-p: theme(--spacing-1);
192
- --input-icon-radius: theme(--radius-full);
193
-
194
185
  /* ────────────────────────────────────────────────
195
186
  * TextInput — sizing
196
187
  * ──────────────────────────────────────────────── */
@@ -382,6 +373,18 @@
382
373
  --baseTooltip-lg-arrow-half-w: theme(--spacing-3); /* lg half-width 12px */
383
374
  --baseTooltip-lg-arrow-h: theme(--spacing-4); /* lg arrow height 16px */
384
375
 
376
+ /* ────────────────────────────────────────────────
377
+ * FlatIconButton
378
+ * ──────────────────────────────────────────────── */
379
+
380
+ --flatIconButton-bg: transparent;
381
+ --flatIconButton-fg: theme(--color-input-icon);
382
+ --flatIconButton-fg-hover: theme(--color-input-icon-hover);
383
+ --flatIconButton-bg-hover: theme(--color-input-icon-bg-hover);
384
+ --flatIconButton-outline: theme(--color-outline);
385
+ --flatIconButton-p: theme(--spacing-1);
386
+ --flatIconButton-radius: theme(--radius-full);
387
+
385
388
  /* ────────────────────────────────────────────────
386
389
  * TabsList
387
390
  * ──────────────────────────────────────────────── */
@@ -1,54 +0,0 @@
1
- <script setup lang="ts">
2
- import type { IconSize } from '../../../types/icon';
3
- import BaseIcon from '../../BaseIcon/BaseIcon.vue';
4
-
5
- export interface InputIconButtonProps {
6
- iconName: string;
7
- iconPath?: string;
8
- iconSize?: IconSize;
9
- ariaLabel?: string;
10
- }
11
-
12
- withDefaults(defineProps<InputIconButtonProps>(), {
13
- iconPath: '/icons',
14
- iconSize: 'sm',
15
- ariaLabel: undefined,
16
- });
17
-
18
- const emit = defineEmits<{
19
- click: [];
20
- }>();
21
- </script>
22
-
23
- <template>
24
- <button
25
- type="button"
26
- class="inputIconButton inline-flex items-center justify-center cursor-pointer"
27
- :aria-label="ariaLabel"
28
- @click="emit('click')"
29
- >
30
- <BaseIcon
31
- :name="iconName"
32
- :icon-path="iconPath"
33
- :size="iconSize"
34
- />
35
- </button>
36
- </template>
37
-
38
- <style scoped>
39
- .inputIconButton {
40
- color: var(--input-icon-fg, #0e161b);
41
- background: var(--input-icon-bg, transparent);
42
- padding: var(--input-icon-p, 0.25rem);
43
- border-radius: var(--input-icon-radius, 9999px);
44
- }
45
-
46
- .inputIconButton:hover {
47
- background-color: var(--input-icon-bg-hover, #f3f4f6);
48
- }
49
-
50
- .inputIconButton:focus-visible {
51
- outline: 2px solid var(--input-icon-outline, #0066cc);
52
- outline-offset: 1px;
53
- }
54
- </style>