vanilla-vue-ui 0.0.0 → 0.0.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.
Files changed (33) hide show
  1. package/basic/app-bar/WAppBar.stories.ts +41 -0
  2. package/basic/app-bar/WAppBar.vue +48 -0
  3. package/basic/banner/BannerStore.ts +54 -0
  4. package/basic/banner/WBanner.stories.ts +28 -0
  5. package/basic/banner/WBanner.vue +41 -0
  6. package/basic/breadcrumb/WBreadcrumb.stories.ts +25 -0
  7. package/basic/breadcrumb/WBreadcrumb.vue +97 -0
  8. package/basic/button/ButtonSize.ts +2 -0
  9. package/basic/button/WButton.spec.ts +17 -0
  10. package/basic/button/WButton.stories.ts +68 -0
  11. package/basic/button/WButton.vue +81 -0
  12. package/basic/icon/WIcon.vue +5 -0
  13. package/basic/range/WRange.vue +113 -17
  14. package/basic/text-field/TextFieldSize.ts +2 -0
  15. package/basic/text-field/WTextField.stories.ts +88 -0
  16. package/basic/text-field/WTextField.vue +188 -0
  17. package/basic/tooltip/WTooltip.stories.ts +87 -0
  18. package/basic/tooltip/WTooltip.vue +63 -0
  19. package/package.json +44 -30
  20. package/template/footer-simple/WFooterSimple.stories.ts +23 -0
  21. package/template/footer-simple/WFooterSimple.vue +20 -0
  22. package/template/navigation-drawer/NavigationDrawer.stories.ts +59 -0
  23. package/template/navigation-drawer/NavigationDrawer.vue +121 -0
  24. package/template/navigation-drawer/NavigationDrawerContent.ts +11 -0
  25. package/template/primary-button/WPrimaryButton.spec.ts +17 -0
  26. package/template/primary-button/WPrimaryButton.stories.ts +30 -0
  27. package/template/primary-button/WPrimaryButton.vue +9 -0
  28. package/template/secondary-button/WSecondaryButton.spec.ts +17 -0
  29. package/template/secondary-button/WSecondaryButton.stories.ts +30 -0
  30. package/template/secondary-button/WSecondaryButton.vue +9 -0
  31. package/template/tree-menu/TreeMenuContent.ts +11 -0
  32. package/template/tree-menu/WTreeMenu.stories.ts +55 -0
  33. package/template/tree-menu/WTreeMenu.vue +152 -0
@@ -0,0 +1,88 @@
1
+ // Replace vue3 with vue if you are using Storybook for Vue 2
2
+ import type { Meta, StoryObj } from '@storybook/vue3';
3
+ import TextField from './WTextField.vue';
4
+
5
+ type TextFieldProps = InstanceType<typeof TextField>['$props']
6
+
7
+ const meta: Meta<typeof TextField> = {
8
+ component: TextField,
9
+ };
10
+
11
+ export default meta;
12
+ type Story = StoryObj<typeof TextField>;
13
+
14
+ /*
15
+ *👇 Render functions are a framework specific feature to allow you control on how the component renders.
16
+ * See https://storybook.js.org/docs/api/csf
17
+ * to learn how to use render functions.
18
+ */
19
+ export const Primary: Story = {
20
+ render: (args: TextFieldProps) => ({
21
+ setup() {
22
+ return {
23
+ ...args
24
+ }
25
+ },
26
+ components: { TextField },
27
+ template: `
28
+ <div class="p-4">
29
+ <div class="mb-2"><TextField size="xs" value="John" :classes="classes"></TextField></div>
30
+ <div class="mb-2"><TextField size="sm" value="John" :classes="classes"></TextField></div>
31
+ <div class="mb-2"><TextField size="base" value="John" :classes="classes"></TextField></div>
32
+ <div class="mb-2"><TextField size="lg" value="John" :classes="classes"></TextField></div>
33
+ <div class="mb-2"><TextField size="2xl" value="John" :classes="classes"></TextField></div>
34
+ <div class="mb-2"><TextField size="3xl" value="John" :classes="classes"></TextField></div>
35
+ <div class="mb-2"><TextField size="6xl" value="John" :classes="classes"></TextField></div>
36
+ </div>
37
+ `,
38
+ }),
39
+ args: {
40
+ classes: {
41
+ content: {
42
+ input: {
43
+ color: 'text-onSurface dark:text-onSurface-dark',
44
+ backgroundColor: 'bg-white dark:bg-surface-dark'
45
+ }
46
+ }
47
+ }
48
+ }
49
+ };
50
+
51
+ export const WithLabel: Story = {
52
+ render: () => ({
53
+ components: { TextField },
54
+ template: `
55
+ <div class="mb-2"><TextField size="xs" label="Name"></TextField></div>
56
+ <div class="mb-2"><TextField size="sm" label="Name"></TextField></div>
57
+ <div class="mb-2"><TextField size="base" label="Name"></TextField></div>
58
+ <div class="mb-2"><TextField size="lg" label="Name"></TextField></div>
59
+ <div class="mb-2"><TextField size="2xl" label="Name"></TextField></div>
60
+ <div class="mb-2"><TextField size="3xl" label="Name"></TextField></div>
61
+ <div class="mb-2"><TextField size="6xl" label="Name"></TextField></div>
62
+ `,
63
+ }),
64
+ };
65
+
66
+ export const WithPlaceholder: Story = {
67
+ render: () => ({
68
+ components: { TextField },
69
+ template: '<TextField placeholder="ć…„ćŠ›ă—ăŠăă ă•ă„"></TextField>',
70
+ }),
71
+ };
72
+
73
+ export const WithError: Story = {
74
+ render: (args: TextFieldProps) => ({
75
+ setup() {
76
+ return {
77
+ ...args,
78
+ };
79
+ },
80
+ components: { TextField },
81
+ template: '<TextField value="John Smith" :rules="rules"></TextField>',
82
+ }),
83
+ args: {
84
+ rules: [
85
+ (value: string) => value.length <= 5 || 'Max 5 characters',
86
+ ],
87
+ },
88
+ };
@@ -0,0 +1,188 @@
1
+ <template>
2
+ <div
3
+ :class="[
4
+ mergedClasses.outline?.base,
5
+ mergedClasses.outline?.backgroundColor,
6
+ ]"
7
+ >
8
+ <label :for="name" :class="mergedClasses.label?.base">{{ label }}</label>
9
+ <div class="relative flex">
10
+ <div class="flex-1">
11
+ <input
12
+ :id="id"
13
+ :name="name"
14
+ :value="value"
15
+ :placeholder="placeholder"
16
+ :required="required"
17
+ :autocomplete="autocomplete"
18
+ :class="[
19
+ textSize,
20
+ mergedClasses.content?.input?.base,
21
+ mergedClasses.content?.input?.backgroundColor,
22
+ mergedClasses.content?.input?.color,
23
+ ]"
24
+ :type="type"
25
+ @change="changeValue($event)"
26
+ @input="inputValue($event)"
27
+ >
28
+ </div>
29
+
30
+ <div class="flex-shrink-0">
31
+ <slot name="trailing" />
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <p v-if="errorMassage.length > 0" :class="mergedClasses.errorMessage?.base">{{ errorMassage }}</p>
36
+ </template>
37
+
38
+ <script setup lang="ts">
39
+ import { ref, defineProps, type PropType, defineExpose } from 'vue'
40
+ import type { ClassObject } from '../../types/ClassObject';
41
+ import { deepMergeClassObject } from '../../util';
42
+ // @ts-ignore
43
+ import type { TextFieldSize } from './TextFieldSize'
44
+
45
+ const props = defineProps({
46
+ value: {
47
+ type: String as PropType<string>
48
+ },
49
+ label: {
50
+ type: String as PropType<string>
51
+ },
52
+ placeholder: {
53
+ type: String as PropType<string>
54
+ },
55
+ type: {
56
+ type: String as PropType<string>
57
+ },
58
+ autocomplete: {
59
+ type: String as PropType<string>
60
+ },
61
+ required: {
62
+ type: Boolean as PropType<boolean>
63
+ },
64
+ rules: {
65
+ type: Array as PropType<ValidationRule[]>
66
+ },
67
+ size: {
68
+ type: String as PropType<TextFieldSize>,
69
+ default: 'base',
70
+ },
71
+ name: {
72
+ type: String as PropType<string>
73
+ },
74
+ id: {
75
+ type: String as PropType<string>
76
+ },
77
+ classes: {
78
+ type: Object as PropType<ClassObject>,
79
+ }
80
+ });
81
+
82
+
83
+ const defaultClasses: ClassObject = {
84
+ content: {
85
+ input: {
86
+ base: "block w-full border-0 p-0 placeholder:text-gray-400 sm:leading-6 focus:outline-none focus:ring-0",
87
+ backgroundColor: 'bg-surface dark:bg-surface-dark',
88
+ color: 'text-onSurface dark:text-onSurface-dark'
89
+ },
90
+ },
91
+ outline: {
92
+ base: "rounded-md px-3 pb-1.5 pt-2.5 shadow-sm ring-1 ring-inset ring-gray-300 focus-within:ring-2 focus-within:ring-primary dark:focus-within:ring-primary-dark",
93
+ backgroundColor: 'bg-surface dark:bg-surface-dark',
94
+ },
95
+ label: {
96
+ base: "block text-xs font-medium text-onSurface dark:text-onSurface-dark"
97
+ },
98
+ errorMessage: {
99
+ base: "mt-1 ml-1 text-sm text-red-600"
100
+ }
101
+ }
102
+
103
+ // props.classesăŒæžĄă•ă‚ŒăŠă„ăȘい栮搈、defaultClassesă‚’äœżç”šă™ă‚‹
104
+ const mergedClasses = props.classes ? deepMergeClassObject(defaultClasses, props.classes) : defaultClasses;
105
+
106
+
107
+ const textSize = ref('text-' + props.size)
108
+
109
+ // emit ă‚’ćźšçŸ©
110
+ const emit = defineEmits<{
111
+ input: [value: Event],
112
+ change: [value: Event]
113
+ }>()
114
+
115
+ const errorMassage = ref("")
116
+
117
+ type ValidationRule = (value: string) => boolean | string
118
+
119
+ //
120
+ // Sample
121
+ //
122
+ // let rules: ValidationRule[] = [
123
+ // value => !!value || 'Required.', // required
124
+ // value => value.length <= 20 || 'Max 20 characters', // max
125
+ // value => {
126
+ // const pattern = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
127
+ // return pattern.test(value) || 'Invalid e-mail.'
128
+ // }, // email
129
+ // ]
130
+
131
+ // 戝曞バăƒȘăƒ‡ăƒŒă‚·ăƒ§ăƒł
132
+ // undefined じゃăȘかったら
133
+ if (typeof props.value === "string") {
134
+ const setupErrorMessage = validate(props.value)
135
+ if (setupErrorMessage) {
136
+ errorMassage.value = setupErrorMessage as string
137
+ }
138
+ }
139
+
140
+ // input ăźć€‰æ›Žă‚’ć—ă‘ć–ă‚‹
141
+ function changeValue(event: Event) {
142
+ const target = event.target as HTMLInputElement | null
143
+ if (target) {
144
+ const validationResult = validate(target.value)
145
+ if (validationResult === true) {
146
+ // バăƒȘăƒ‡ăƒŒă‚·ăƒ§ăƒłă«é€šăŁăŸă‚‰
147
+ emit('change', event)
148
+ errorMassage.value = ""; // ă‚šăƒ©ăƒŒăƒĄăƒƒă‚»ăƒŒă‚žă‚’ă‚ŻăƒȘケ
149
+ } else {
150
+ errorMassage.value = validationResult as string; // ă‚šăƒ©ăƒŒăƒĄăƒƒă‚»ăƒŒă‚žă‚’èš­ćźš
151
+ }
152
+ }
153
+ }
154
+
155
+ function inputValue(event: Event) {
156
+ const target = event.target as HTMLInputElement | null
157
+ if (target) {
158
+ const validationResult = validate(target.value)
159
+ if (validationResult === true) {
160
+ // バăƒȘăƒ‡ăƒŒă‚·ăƒ§ăƒłă«é€šăŁăŸă‚‰
161
+ errorMassage.value = ""; // ă‚šăƒ©ăƒŒăƒĄăƒƒă‚»ăƒŒă‚žă‚’ă‚ŻăƒȘケ
162
+ } else {
163
+ errorMassage.value = validationResult as string; // ă‚šăƒ©ăƒŒăƒĄăƒƒă‚»ăƒŒă‚žă‚’èš­ćźš
164
+ }
165
+ }
166
+
167
+ emit('input', event)
168
+ }
169
+
170
+ // バăƒȘăƒ‡ăƒŒă‚·ăƒ§ăƒł
171
+ function validate(value: string): boolean | string {
172
+ if (props.rules) {
173
+ for (const rule of props.rules) {
174
+ const result = rule(value);
175
+ if (result !== true) {
176
+ // ăƒ«ăƒŒăƒ«ăŒæ–‡ć­—ćˆ—ïŒˆă‚šăƒ©ăƒŒăƒĄăƒƒă‚»ăƒŒă‚žïŒ‰ă‚’èż”ă—ăŸć Žćˆă€ăƒăƒȘăƒ‡ăƒŒă‚·ăƒ§ăƒłć€±æ•—
177
+ return result;
178
+ }
179
+ }
180
+ }
181
+ return true; // ăƒ«ăƒŒăƒ«ăŒèš­ćźšă•ă‚ŒăŠăȘい or すăčăŠăźăƒ«ăƒŒăƒ«ăŒæˆćŠŸ
182
+ }
183
+
184
+ // ć€–éƒšă‹ă‚‰ă‚‚ć‘Œăłć‡șă›ă‚‹ă‚ˆă†ă«ă™ă‚‹
185
+ defineExpose({
186
+ validate
187
+ });
188
+ </script>
@@ -0,0 +1,87 @@
1
+ // Replace vue3 with vue if you are using Storybook for Vue 2
2
+ import type { Meta, StoryObj } from '@storybook/vue3';
3
+ import WTooltip from './WTooltip.vue';
4
+ import Button from '../button/WButton.vue'
5
+ import { ref, watch } from 'vue';
6
+
7
+ type WTooltipProps = InstanceType<typeof WTooltip>['$props']
8
+
9
+ const meta: Meta<typeof WTooltip> = {
10
+ component: WTooltip,
11
+ };
12
+
13
+ export default meta;
14
+ type Story = StoryObj<typeof WTooltip>;
15
+
16
+ /*
17
+ *👇 Render functions are a framework specific feature to allow you control on how the component renders.
18
+ * See https://storybook.js.org/docs/api/csf
19
+ * to learn how to use render functions.
20
+ */
21
+
22
+ export const Primary: Story = {
23
+ render: (args: WTooltipProps) => ({
24
+ setup() {
25
+ return {
26
+ ...args,
27
+ };
28
+ },
29
+ components: { WTooltip, Button },
30
+ template: `
31
+ <w-tooltip hoverText="ăƒ›ăƒăƒŒ" reactiveText="text" :isReact="isReact">
32
+ <Button>Text</Button>
33
+ </w-tooltip>
34
+ `,
35
+ }),
36
+ args: {
37
+ isReact: false
38
+ },
39
+ };
40
+
41
+ export const isReact: Story = {
42
+ render: (args) => ({
43
+ setup() {
44
+ // isReact を ref 挖
45
+ const isReact = ref(args.isReact);
46
+
47
+ watch(() => args.isReact, (val) => {
48
+ isReact.value = val;
49
+ });
50
+
51
+ return {
52
+ isReact,
53
+ };
54
+ },
55
+ components: { WTooltip, Button },
56
+ template: `
57
+ <w-tooltip
58
+ reactiveText="Clicked."
59
+ :isReact="isReact"
60
+ >
61
+ <Button @click="isReact = true">Text</Button>
62
+ </w-tooltip>
63
+ `,
64
+ }),
65
+ args: {
66
+ isReact: false,
67
+ },
68
+ };
69
+
70
+ export const init: Story = {
71
+ render: (args: WTooltipProps) => ({
72
+ setup() {
73
+ return {
74
+ ...args,
75
+ };
76
+ },
77
+ components: { WTooltip, Button },
78
+ template: `
79
+ <w-tooltip hoverText="ăƒ›ăƒăƒŒ" :showHoverOnMount="true">
80
+ <Button>Text</Button>
81
+ </w-tooltip>
82
+ `,
83
+ }),
84
+ args: {
85
+ isReact: false
86
+ },
87
+ };
@@ -0,0 +1,63 @@
1
+ <template>
2
+ <span class="relative group">
3
+ <div @mouseenter="showTooltip" @mouseleave="hideTooltip">
4
+ <slot />
5
+ </div>
6
+ <span v-show="isReact" class="absolute z-50 whitespace-nowrap -bottom-12 left-1/2 -translate-x-1/2 bg-gray-600 py-1 px-2 text-white rounded">{{ reactiveText }}</span>
7
+ <span v-show="!isReact && isShowTooltip" class="absolute z-50 whitespace-nowrap -bottom-12 left-1/2 -translate-x-1/2 bg-gray-600 py-1 px-2 text-white rounded">{{ hoverText }}</span>
8
+ </span>
9
+ </template>
10
+
11
+ <script setup lang="ts">
12
+ import { ref, defineProps, defineEmits, watch, type PropType, onMounted } from 'vue';
13
+
14
+ const isShowTooltip = ref(false)
15
+
16
+ const props = defineProps({
17
+ reactiveText: {
18
+ type: String,
19
+ default: ''
20
+ },
21
+ hoverText: {
22
+ type: String,
23
+ required: false,
24
+ default: ''
25
+ },
26
+ isReact: {
27
+ type: Boolean,
28
+ default: false
29
+ },
30
+ showHoverOnMount: {
31
+ type: Boolean as PropType<boolean>,
32
+ default: false,
33
+ }
34
+ })
35
+
36
+ const emit = defineEmits(['update:isReact'])
37
+
38
+ // currentStep ăźć€‰æ›Žă‚’ç›ŁèŠ–
39
+ watch(
40
+ () => props.isReact, (newValue) => {
41
+ if (newValue === true) {
42
+ setTimeout(() => { emit('update:isReact', false) }, 1000)
43
+ }
44
+ }
45
+ )
46
+
47
+ onMounted(() => {
48
+ if (props.showHoverOnMount) {
49
+ showTooltip()
50
+ setTimeout(() => { hideTooltip() }, 3000)
51
+ }
52
+ })
53
+
54
+ function showTooltip() {
55
+ if (props.hoverText.length) {
56
+ isShowTooltip.value = true
57
+ }
58
+ }
59
+
60
+ function hideTooltip() {
61
+ isShowTooltip.value = false
62
+ }
63
+ </script>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vanilla-vue-ui",
3
- "version": "0.0.0",
3
+ "version": "0.0.2",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "files": [
@@ -31,39 +31,53 @@
31
31
  "copy": "npm run copy-template && npm run copy-basic && npm run copy-custom && npm run copy-icon && npm run copy-types && npm run copy-util"
32
32
  },
33
33
  "dependencies": {
34
- "vue": "^3.5.13"
34
+ "@headlessui/vue": "^1.7.17",
35
+ "@heroicons/vue": "^2.1.1",
36
+ "dayjs": "^1.11.11",
37
+ "japanjs": "^0.1.6",
38
+ "konva": "^9.3.15",
39
+ "pinia": "^2.1.7",
40
+ "vue": "^3.3.11",
41
+ "vue-konva": "^3.1.0",
42
+ "vue-router": "^4.3.2"
35
43
  },
36
44
  "devDependencies": {
37
- "@chromatic-com/storybook": "^3.2.4",
38
- "@storybook/addon-essentials": "^8.5.5",
39
- "@storybook/addon-interactions": "^8.5.5",
40
- "@storybook/addon-onboarding": "^8.5.5",
41
- "@storybook/blocks": "^8.5.5",
42
- "@storybook/test": "^8.5.5",
43
- "@storybook/vue3": "^8.5.5",
44
- "@storybook/vue3-vite": "^8.5.5",
45
+ "@rushstack/eslint-patch": "^1.3.3",
46
+ "@storybook/addon-essentials": "^7.6.10",
47
+ "@storybook/addon-interactions": "^7.6.10",
48
+ "@storybook/addon-links": "^7.6.10",
49
+ "@storybook/addon-themes": "^7.6.20",
50
+ "@storybook/blocks": "^7.6.10",
51
+ "@storybook/test": "^7.6.10",
52
+ "@storybook/vue3": "^7.6.10",
53
+ "@storybook/vue3-vite": "^7.6.10",
54
+ "@tsconfig/node18": "^18.2.2",
45
55
  "@tsconfig/node22": "^22.0.0",
46
- "@types/jsdom": "^21.1.7",
47
- "@types/node": "^22.9.3",
48
- "@vitejs/plugin-vue": "^5.2.1",
49
- "@vitest/eslint-plugin": "1.1.10",
50
- "@vue/eslint-config-prettier": "^10.1.0",
51
- "@vue/eslint-config-typescript": "^14.1.3",
52
- "@vue/test-utils": "^2.4.6",
53
- "@vue/tsconfig": "^0.7.0",
56
+ "@types/jsdom": "^21.1.6",
57
+ "@types/node": "^18.19.3",
58
+ "@vitejs/plugin-vue": "^4.5.2",
59
+ "@vue/eslint-config-prettier": "^8.0.0",
60
+ "@vue/eslint-config-typescript": "^12.0.0",
61
+ "@vue/test-utils": "^2.4.3",
62
+ "@vue/tsconfig": "^0.5.0",
63
+ "autoprefixer": "^10.4.17",
54
64
  "copyfiles": "^2.4.1",
55
- "eslint": "^9.14.0",
56
- "eslint-plugin-storybook": "^0.11.2",
57
- "eslint-plugin-vue": "^9.30.0",
58
- "jsdom": "^25.0.1",
59
- "npm-run-all2": "^7.0.1",
60
- "prettier": "^3.3.3",
61
- "storybook": "^8.5.5",
62
- "typescript": "~5.6.3",
63
- "vite": "^6.0.1",
64
- "vite-plugin-vue-devtools": "^7.6.5",
65
- "vitest": "^2.1.5",
66
- "vue-tsc": "^2.1.10"
65
+ "eslint": "^8.57.0",
66
+ "eslint-plugin-storybook": "^0.6.15",
67
+ "eslint-plugin-vue": "^9.27.0",
68
+ "jsdom": "^23.0.1",
69
+ "npm-run-all2": "^6.1.1",
70
+ "postcss": "^8.4.33",
71
+ "prettier": "^3.0.3",
72
+ "react": "^18.2.0",
73
+ "react-dom": "^18.2.0",
74
+ "storybook": "^7.6.10",
75
+ "tailwindcss": "^3.4.1",
76
+ "typescript": "~5.3.0",
77
+ "vite": "^5.0.10",
78
+ "vite-plugin-vue-devtools": "^7.7.2",
79
+ "vitest": "^1.0.4",
80
+ "vue-tsc": "^1.8.25"
67
81
  },
68
82
  "eslintConfig": {
69
83
  "extends": [
@@ -0,0 +1,23 @@
1
+ // Replace vue3 with vue if you are using Storybook for Vue 2
2
+ import type { Meta, StoryObj } from '@storybook/vue3';
3
+
4
+ import FooterSimple from './WFooterSimple.vue';
5
+
6
+ const meta: Meta<typeof FooterSimple> = {
7
+ component: FooterSimple,
8
+ };
9
+
10
+ export default meta;
11
+ type Story = StoryObj<typeof FooterSimple>;
12
+
13
+ /*
14
+ *👇 Render functions are a framework specific feature to allow you control on how the component renders.
15
+ * See https://storybook.js.org/docs/api/csf
16
+ * to learn how to use render functions.
17
+ */
18
+ export const Primary: Story = {
19
+ render: () => ({
20
+ components: { FooterSimple },
21
+ template: '<FooterSimple></FooterSimple>',
22
+ }),
23
+ };
@@ -0,0 +1,20 @@
1
+ <template>
2
+ <footer class="fixed bottom-0">
3
+ <div class="mb-4 ml-4">
4
+ <p class="text-center text-xs leading-5 text-gray-500">{{ props.text }}</p>
5
+ </div>
6
+ </footer>
7
+ </template>
8
+
9
+ <script setup lang="ts">
10
+ import { defineProps, type PropType } from 'vue'
11
+
12
+ const props = defineProps({
13
+ text: {
14
+ type: String as PropType<string>,
15
+ required: false,
16
+ default: `© 2020 Your Company, Inc. All rights reserved.`
17
+ }
18
+ })
19
+
20
+ </script>
@@ -0,0 +1,59 @@
1
+ // Replace vue3 with vue if you are using Storybook for Vue 2
2
+ import type { Meta, StoryObj } from '@storybook/vue3';
3
+ import NavigationDrawer from './NavigationDrawer.vue';
4
+ import {
5
+ HomeIcon,
6
+ BellAlertIcon,
7
+ ChatBubbleBottomCenterTextIcon,
8
+ Cog6ToothIcon,
9
+ CurrencyYenIcon,
10
+ CubeIcon,
11
+ BookOpenIcon,
12
+ MinusIcon
13
+ } from '@heroicons/vue/24/outline'
14
+
15
+ type NavigationDrawerProps = InstanceType<typeof NavigationDrawer>['$props']
16
+
17
+ const meta: Meta<typeof NavigationDrawer> = {
18
+ component: NavigationDrawer,
19
+ };
20
+
21
+ export default meta;
22
+ type Story = StoryObj<typeof NavigationDrawer>;
23
+
24
+ /*
25
+ *👇 Render functions are a framework specific feature to allow you control on how the component renders.
26
+ * See https://storybook.js.org/docs/api/csf
27
+ * to learn how to use render functions.
28
+ */
29
+ export const Primary: Story = {
30
+ render: (args: NavigationDrawerProps) => ({
31
+ setup() {
32
+ return {
33
+ ...args
34
+ }
35
+ },
36
+ components: { NavigationDrawer },
37
+ template: '<NavigationDrawer :title="title" :navigationTop="navigationTop" :navigationBottom="navigationBottom"></NavigationDrawer>',
38
+ }),
39
+ args: {
40
+ title: 'ăƒ€ăƒƒă‚·ăƒ„ăƒœăƒŒăƒ‰',
41
+ navigationTop: [
42
+ { name: 'ăƒĄăƒ‹ăƒ„ăƒŒ', href: '/menu', onClick: undefined, icon: HomeIcon, current: false },
43
+ { name: 'ăƒȘクスă‚čト', href: '/request', icon: CubeIcon, current: false },
44
+ { name: 'ć±„æ­Ž', href: '/history', icon: BookOpenIcon, current: false },
45
+ { name: 'æ”Żæ‰•ă„', href: '/payment', icon: CurrencyYenIcon, current: false, isOpen: true,
46
+ subItems: [
47
+ { name: '珟金', href: '/payment', icon: MinusIcon, current: false },
48
+ { name: 'クレゾット', href: '/payment', icon: MinusIcon, current: false }
49
+ ]
50
+ },
51
+ { name: 'ăƒĄăƒƒă‚»ăƒŒă‚ž', href: '/message', icon: BellAlertIcon, current: false },
52
+ { name: '敏い搈わせ', href: '/contact', icon: ChatBubbleBottomCenterTextIcon, current: false },
53
+ { name: 'èš­ćźš', href: '/setting', icon: Cog6ToothIcon, current: false },
54
+ ],
55
+ navigationBottom: [
56
+ { name: 'ログケォト', href: undefined, onClick: () => console.log('click.'), icon: undefined, current: undefined },
57
+ ]
58
+ }
59
+ };