design-system-dashboard-devmunity 0.3.0 → 1.0.1
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/README.md +33 -31
- package/app/app.config.ts +2 -1
- package/app/app.vue +21 -3
- package/app/assets/css/settings/base.css +33 -33
- package/app/assets/css/themes/components/badge.js +7 -0
- package/app/assets/css/themes/components/input.js +5 -0
- package/app/assets/css/themes/index.js +2 -1
- package/app/components/BaseButton.vue +3 -0
- package/app/components/Colors.mdx +42 -0
- package/app/components/Indroduction.mdx +100 -0
- package/app/components/a/button/a-button-avatar-dropdown.stories.ts +83 -0
- package/app/components/a/button/a-button-avatar-dropdown.vue +41 -17
- package/app/components/a/button/a-button-navigation.stories.ts +66 -0
- package/app/components/a/button/a-button-navigation.vue +57 -0
- package/app/components/a/card/a-card-inner.stories.ts +89 -0
- package/app/components/a/card/a-card-inner.vue +38 -0
- package/app/components/a/dropdown/a-dropdown-avatar.stories.ts +160 -0
- package/app/components/a/dropdown/a-dropdown-avatar.vue +75 -33
- package/app/components/a/pill/a-pill.stories.ts +91 -0
- package/app/components/a/pill/a-pill.vue +63 -42
- package/app/components/b/badge/b-badge.stories.ts +77 -0
- package/app/components/b/badge/b-badge.vue +55 -0
- package/app/components/b/card/b-card.stories.ts +120 -0
- package/app/components/b/card/b-card.vue +49 -32
- package/app/components/b/modal/b-modal.stories.ts +210 -0
- package/app/components/b/modal/b-modal.vue +125 -81
- package/app/components/c/badge/c-badge-status.stories.ts +72 -0
- package/app/components/c/badge/c-badge-status.vue +60 -0
- package/app/components/c/modal/c-modal-danger.stories.ts +112 -0
- package/app/components/c/modal/c-modal-danger.vue +60 -41
- package/app/components/d/action-buttons/d-action-buttons.stories.ts +90 -0
- package/app/components/d/action-buttons/d-action-buttons.vue +121 -0
- package/app/components/d/card/d-card-header.stories.ts +123 -0
- package/app/components/{b/card/b-card-header.vue → d/card/d-card-header.vue} +62 -44
- package/app/components/d/upload/d-upload-avatar.stories.ts +66 -0
- package/app/components/d/upload/d-upload-avatar.vue +95 -0
- package/app/pages/test.vue +27 -16
- package/app/types/index.ts +1 -0
- package/app/types/semantic-colors.type.ts +3 -0
- package/app/utils/util-get-colors-from-css.ts +53 -0
- package/nuxt.config.ts +11 -16
- package/package.json +84 -68
- package/.editorconfig +0 -13
- package/.github/workflows/release.yml +0 -36
- package/.husky/commit-msg +0 -1
- package/.husky/pre-commit +0 -0
- package/.prettierrc +0 -24
- package/.storybook/main.js +0 -25
- package/.storybook/preview.js +0 -13
- package/.vscode/settings.json +0 -28
- package/CHANGELOG.md +0 -46
- package/app/Introduction.mdx +0 -44
- package/app/components/a/button/a-button-back.vue +0 -33
- package/app/components/b/card/b-card-inner.vue +0 -25
- package/app/components/d/d-action-buttons.vue +0 -99
- package/commitlint.config.js +0 -8
- package/tsconfig.json +0 -8
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import BBadge, { type BadgeColor, type BadgeVariant } from './b-badge.vue'
|
|
3
|
+
|
|
4
|
+
const meta = {
|
|
5
|
+
title: 'Bases/Badge/BBadge',
|
|
6
|
+
component: BBadge,
|
|
7
|
+
parameters: {
|
|
8
|
+
docs: {
|
|
9
|
+
description: {
|
|
10
|
+
component:
|
|
11
|
+
'A small, rounded label used to display brief information. Typically used to show the status of an item.',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
argTypes: {
|
|
16
|
+
value: {
|
|
17
|
+
control: 'select',
|
|
18
|
+
options: ['active', 'inactive', 'error', ''] satisfies string[],
|
|
19
|
+
},
|
|
20
|
+
// @ts-ignore
|
|
21
|
+
name: {
|
|
22
|
+
name: '[slot name]',
|
|
23
|
+
description: 'Any dynamic slot for the badge',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
} satisfies Meta<typeof BBadge>
|
|
27
|
+
|
|
28
|
+
export default meta
|
|
29
|
+
|
|
30
|
+
type Story = StoryObj<typeof meta>
|
|
31
|
+
|
|
32
|
+
const styles = {
|
|
33
|
+
active: {
|
|
34
|
+
color: 'primary' as BadgeColor,
|
|
35
|
+
variant: 'solid' as BadgeVariant,
|
|
36
|
+
icon: 'heroicons:check-20-solid',
|
|
37
|
+
},
|
|
38
|
+
inactive: { color: 'neutral' as BadgeColor, variant: 'subtle' as BadgeVariant },
|
|
39
|
+
error: {
|
|
40
|
+
color: 'error' as BadgeColor,
|
|
41
|
+
variant: 'soft' as BadgeVariant,
|
|
42
|
+
icon: 'heroicons:x-circle-20-solid',
|
|
43
|
+
},
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export const Default: Story = {
|
|
47
|
+
args: {
|
|
48
|
+
label: 'Default Style',
|
|
49
|
+
value: 'unknown',
|
|
50
|
+
styles,
|
|
51
|
+
defaultStyle: { color: 'neutral' as BadgeColor, variant: 'outline' as BadgeVariant },
|
|
52
|
+
},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export const Active: Story = {
|
|
56
|
+
args: {
|
|
57
|
+
...Default.args,
|
|
58
|
+
label: 'Active Item',
|
|
59
|
+
value: 'active',
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export const Inactive: Story = {
|
|
64
|
+
args: {
|
|
65
|
+
...Default.args,
|
|
66
|
+
label: 'Inactive Item',
|
|
67
|
+
value: 'inactive',
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export const ErrorState: Story = {
|
|
72
|
+
args: {
|
|
73
|
+
...Default.args,
|
|
74
|
+
label: 'Error Occurred',
|
|
75
|
+
value: 'error',
|
|
76
|
+
},
|
|
77
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import type { UBadge } from '#components'
|
|
3
|
+
import { badge } from '~/assets/css/themes'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Badge style configuration object
|
|
7
|
+
*/
|
|
8
|
+
export type BadgeSize = InstanceType<typeof UBadge>['$props']['size']
|
|
9
|
+
export type BadgeColor = InstanceType<typeof UBadge>['$props']['color']
|
|
10
|
+
export type BadgeVariant = InstanceType<typeof UBadge>['$props']['variant']
|
|
11
|
+
|
|
12
|
+
interface BadgeStyles {
|
|
13
|
+
[key: string]: Partial<InstanceType<typeof UBadge>['$props']> & { [key: string]: any }
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
/**
|
|
18
|
+
* The label text to display on the badge
|
|
19
|
+
*/
|
|
20
|
+
label: string
|
|
21
|
+
/**
|
|
22
|
+
* The active style variant key of the `styles` object
|
|
23
|
+
*/
|
|
24
|
+
value?: string
|
|
25
|
+
/**
|
|
26
|
+
* Custom style settings for different badge variants. The options are derived from the props expected by `UBadge`
|
|
27
|
+
*/
|
|
28
|
+
styles?: BadgeStyles
|
|
29
|
+
/**
|
|
30
|
+
* Default style configuration for the badge
|
|
31
|
+
*/
|
|
32
|
+
defaultStyle?: BadgeStyles[string]
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
36
|
+
value: '',
|
|
37
|
+
styles: () => ({}),
|
|
38
|
+
defaultStyle: () => badge,
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
defineSlots<{
|
|
42
|
+
/**
|
|
43
|
+
* Any dynamic slots for the badge content
|
|
44
|
+
*/
|
|
45
|
+
[name: string]: any
|
|
46
|
+
}>()
|
|
47
|
+
</script>
|
|
48
|
+
|
|
49
|
+
<template>
|
|
50
|
+
<UBadge :label="label" v-bind="styles[value] ?? props.defaultStyle">
|
|
51
|
+
<template v-for="(_, name) in $slots" v-slot:[name]="slotData">
|
|
52
|
+
<slot :name="name" v-bind="slotData" />
|
|
53
|
+
</template>
|
|
54
|
+
</UBadge>
|
|
55
|
+
</template>
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
2
|
+
import BCard, { type CardVariant } from './b-card.vue'
|
|
3
|
+
import ACardInner from '@/components/a/card/a-card-inner.vue'
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Bases/Card/BCard',
|
|
7
|
+
component: BCard,
|
|
8
|
+
parameters: {
|
|
9
|
+
docs: {
|
|
10
|
+
description: {
|
|
11
|
+
component:
|
|
12
|
+
'A base card component that serves as a fundamental design element for grouping and organizing content. Its style is based on a border with rounded corners and is structured into distinct header, body, and footer sections.',
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
argTypes: {
|
|
17
|
+
as: {
|
|
18
|
+
control: 'text',
|
|
19
|
+
},
|
|
20
|
+
variant: {
|
|
21
|
+
control: 'select',
|
|
22
|
+
options: ['outline', 'solid', 'soft', 'ghost'] satisfies CardVariant[],
|
|
23
|
+
},
|
|
24
|
+
hasBodyExpanded: {
|
|
25
|
+
control: 'boolean',
|
|
26
|
+
},
|
|
27
|
+
hasFooterDivider: {
|
|
28
|
+
control: 'boolean',
|
|
29
|
+
},
|
|
30
|
+
},
|
|
31
|
+
} satisfies Meta<typeof BCard>
|
|
32
|
+
|
|
33
|
+
export default meta
|
|
34
|
+
|
|
35
|
+
type Story = StoryObj<typeof meta>
|
|
36
|
+
|
|
37
|
+
const template = `
|
|
38
|
+
<BCard v-bind="args">
|
|
39
|
+
<template #header>
|
|
40
|
+
<ACardInner class="font-bold">Header</ACardInner>
|
|
41
|
+
</template>
|
|
42
|
+
<ACardInner>Body content goes here. It can be long.</ACardInner>
|
|
43
|
+
<template #footer>
|
|
44
|
+
<ACardInner class="text-sm text-gray-500">Footer content</ACardInner>
|
|
45
|
+
</template>
|
|
46
|
+
</BCard>
|
|
47
|
+
`
|
|
48
|
+
|
|
49
|
+
export const Default: Story = {
|
|
50
|
+
args: {
|
|
51
|
+
variant: 'outline',
|
|
52
|
+
hasBodyExpanded: false,
|
|
53
|
+
hasFooterDivider: true,
|
|
54
|
+
},
|
|
55
|
+
render: (args) => ({
|
|
56
|
+
components: { BCard, ACardInner },
|
|
57
|
+
setup() {
|
|
58
|
+
return { args }
|
|
59
|
+
},
|
|
60
|
+
template,
|
|
61
|
+
}),
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const Solid: Story = {
|
|
65
|
+
args: {
|
|
66
|
+
...Default.args,
|
|
67
|
+
variant: 'solid',
|
|
68
|
+
},
|
|
69
|
+
render: (args) => ({
|
|
70
|
+
components: { BCard, ACardInner },
|
|
71
|
+
setup() {
|
|
72
|
+
return { args }
|
|
73
|
+
},
|
|
74
|
+
template,
|
|
75
|
+
}),
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export const WithExpandedBody: Story = {
|
|
79
|
+
args: {
|
|
80
|
+
...Default.args,
|
|
81
|
+
hasBodyExpanded: true,
|
|
82
|
+
},
|
|
83
|
+
render: (args) => ({
|
|
84
|
+
components: { BCard, ACardInner },
|
|
85
|
+
setup() {
|
|
86
|
+
return { args }
|
|
87
|
+
},
|
|
88
|
+
template,
|
|
89
|
+
}),
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export const WithoutFooterDivider: Story = {
|
|
93
|
+
args: {
|
|
94
|
+
variant: 'outline',
|
|
95
|
+
hasBodyExpanded: true,
|
|
96
|
+
hasFooterDivider: true,
|
|
97
|
+
class: 'h-64', // Force height to show expansion
|
|
98
|
+
},
|
|
99
|
+
render: (args) => ({
|
|
100
|
+
components: { BCard, ACardInner },
|
|
101
|
+
setup() {
|
|
102
|
+
return { args }
|
|
103
|
+
},
|
|
104
|
+
template: `
|
|
105
|
+
<div class="h-64">
|
|
106
|
+
<BCard v-bind="args">
|
|
107
|
+
<template #header>
|
|
108
|
+
<ACardInner>Fixed Header</ACardInner>
|
|
109
|
+
</template>
|
|
110
|
+
<ACardInner>
|
|
111
|
+
<p v-for="i in 10" :key="i">Scrollable content line {{ i }}</p>
|
|
112
|
+
</ACardInner>
|
|
113
|
+
<template #footer>
|
|
114
|
+
<ACardInner>Fixed Footer</ACardInner>
|
|
115
|
+
</template>
|
|
116
|
+
</BCard>
|
|
117
|
+
</div>
|
|
118
|
+
`,
|
|
119
|
+
}),
|
|
120
|
+
}
|
|
@@ -1,39 +1,61 @@
|
|
|
1
|
-
<script lang="
|
|
1
|
+
<script lang="ts" setup>
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import { twMerge } from 'tailwind-merge'
|
|
4
|
+
import type { UCard } from '#components'
|
|
4
5
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
6
|
+
// Types
|
|
7
|
+
export type CardVariant = InstanceType<typeof UCard>['$props']['variant']
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
/**
|
|
11
|
+
* The HTML tag to render the card as
|
|
12
|
+
* @default 'div'
|
|
13
|
+
*/
|
|
14
|
+
as?: string
|
|
15
|
+
/**
|
|
16
|
+
* The visual variant of the card
|
|
17
|
+
* @default 'outline'
|
|
18
|
+
*/
|
|
19
|
+
variant?: CardVariant
|
|
20
|
+
/**
|
|
21
|
+
* Whether the card body should expand to fill available space
|
|
22
|
+
* @default false
|
|
23
|
+
*/
|
|
24
|
+
hasBodyExpanded?: boolean
|
|
25
|
+
/**
|
|
26
|
+
* Whether to show a divider above the footer
|
|
27
|
+
* @default true
|
|
28
|
+
*/
|
|
29
|
+
hasFooterDivider?: boolean
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
33
|
+
as: 'article',
|
|
34
|
+
variant: 'outline',
|
|
35
|
+
hasBodyExpanded: false,
|
|
36
|
+
hasFooterDivider: true,
|
|
31
37
|
})
|
|
32
38
|
|
|
39
|
+
defineSlots<{
|
|
40
|
+
/**
|
|
41
|
+
* The default slot in which all the content
|
|
42
|
+
*/
|
|
43
|
+
default(): any
|
|
44
|
+
/**
|
|
45
|
+
* The header slot
|
|
46
|
+
*/
|
|
47
|
+
header(): any
|
|
48
|
+
/**
|
|
49
|
+
* The footer slot
|
|
50
|
+
*/
|
|
51
|
+
footer(): any
|
|
52
|
+
}>()
|
|
53
|
+
|
|
33
54
|
// Computed
|
|
34
55
|
|
|
35
56
|
const uiStyles = computed(() => {
|
|
36
57
|
const baseStyles = {
|
|
58
|
+
root: '',
|
|
37
59
|
header: 'p-0 sm:p-0',
|
|
38
60
|
body: 'p-0 sm:p-0',
|
|
39
61
|
footer: 'p-0 sm:p-0 sm:px-0',
|
|
@@ -51,11 +73,6 @@ const uiStyles = computed(() => {
|
|
|
51
73
|
baseStyles.body = twMerge(baseStyles.body, 'border-none')
|
|
52
74
|
}
|
|
53
75
|
|
|
54
|
-
// Apply custom ui prop (overrides previous styles)
|
|
55
|
-
if (props.ui) {
|
|
56
|
-
Object.assign(baseStyles, props.ui)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
76
|
return baseStyles
|
|
60
77
|
})
|
|
61
78
|
</script>
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { reactive } from 'vue'
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/vue3'
|
|
3
|
+
import type { SemanticColors } from '@/types'
|
|
4
|
+
import { fn } from '@storybook/test'
|
|
5
|
+
import { semanticColors } from '@/utils/util-get-colors-from-css'
|
|
6
|
+
import UButton from '@nuxt/ui/components/Button.vue'
|
|
7
|
+
import UForm from '@nuxt/ui/components/Form.vue'
|
|
8
|
+
import UFormField from '@nuxt/ui/components/FormField.vue'
|
|
9
|
+
import UInput from '@nuxt/ui/components/Input.vue'
|
|
10
|
+
import BModal from './b-modal.vue'
|
|
11
|
+
|
|
12
|
+
const meta = {
|
|
13
|
+
title: 'Bases/Modal/BModal',
|
|
14
|
+
component: BModal,
|
|
15
|
+
parameters: {
|
|
16
|
+
docs: {
|
|
17
|
+
description: {
|
|
18
|
+
component:
|
|
19
|
+
'Base modal component. Its structure consists of a blank body, and a header and footer with a predefined design. It can contain text, any other element in the body, or a form, for which the schema and state can be defined.',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
argTypes: {
|
|
24
|
+
primaryButtonColor: {
|
|
25
|
+
control: 'select',
|
|
26
|
+
options: Object.keys(semanticColors) as SemanticColors[],
|
|
27
|
+
},
|
|
28
|
+
'onOn-click-primary-button': {
|
|
29
|
+
table: { disable: true },
|
|
30
|
+
},
|
|
31
|
+
'onOn-click-secondary-button': {
|
|
32
|
+
table: { disable: true },
|
|
33
|
+
},
|
|
34
|
+
'onOn-submit': {
|
|
35
|
+
table: { disable: true },
|
|
36
|
+
},
|
|
37
|
+
modelValue: {
|
|
38
|
+
control: 'boolean',
|
|
39
|
+
name: 'isOpen',
|
|
40
|
+
description: 'Whether the modal is open',
|
|
41
|
+
table: {
|
|
42
|
+
category: 'v-model',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
args: {
|
|
47
|
+
'onOn-click-primary-button': fn(),
|
|
48
|
+
'onOn-click-secondary-button': fn(),
|
|
49
|
+
'onOn-submit': fn(),
|
|
50
|
+
},
|
|
51
|
+
render: (args) =>
|
|
52
|
+
({
|
|
53
|
+
components: { BModal, UButton },
|
|
54
|
+
setup() {
|
|
55
|
+
return { args }
|
|
56
|
+
},
|
|
57
|
+
template: `
|
|
58
|
+
<div>
|
|
59
|
+
<UButton label="Open Modal" @click="args.modelValue = true" />
|
|
60
|
+
<BModal v-bind="args" v-model="args.modelValue" />
|
|
61
|
+
</div>
|
|
62
|
+
`,
|
|
63
|
+
}) as any,
|
|
64
|
+
} satisfies Meta<typeof BModal>
|
|
65
|
+
|
|
66
|
+
export default meta
|
|
67
|
+
|
|
68
|
+
type Story = StoryObj<typeof meta>
|
|
69
|
+
|
|
70
|
+
export const Default: Story = {
|
|
71
|
+
args: {
|
|
72
|
+
title: 'Modal Title',
|
|
73
|
+
description: 'This is a description of the modal.',
|
|
74
|
+
modelValue: false,
|
|
75
|
+
primaryButtonText: 'Save',
|
|
76
|
+
secondaryButtonText: 'Cancel',
|
|
77
|
+
primaryButtonColor: 'primary',
|
|
78
|
+
},
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export const WithTextContent: Story = {
|
|
82
|
+
args: {
|
|
83
|
+
...Default.args,
|
|
84
|
+
title: 'Text Content',
|
|
85
|
+
description: 'Modal with simple text content',
|
|
86
|
+
text: 'This is the body text content passed via the "text" prop.',
|
|
87
|
+
modelValue: false,
|
|
88
|
+
},
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export const WithSlot: Story = {
|
|
92
|
+
args: {
|
|
93
|
+
...Default.args,
|
|
94
|
+
title: 'With Slot',
|
|
95
|
+
description: 'Modal with custom content',
|
|
96
|
+
modelValue: false,
|
|
97
|
+
},
|
|
98
|
+
render: (args) =>
|
|
99
|
+
({
|
|
100
|
+
components: { BModal, UButton },
|
|
101
|
+
setup() {
|
|
102
|
+
return { args }
|
|
103
|
+
},
|
|
104
|
+
template: `
|
|
105
|
+
<div>
|
|
106
|
+
<UButton label="Open Modal" @click="args.modelValue = true" />
|
|
107
|
+
<BModal v-bind="args" v-model="args.modelValue">
|
|
108
|
+
<div class="space-y-4">
|
|
109
|
+
<p class="text-sm text-gray-600">
|
|
110
|
+
This is a custom content area where you can place any elements,
|
|
111
|
+
such as forms, images, or additional text.
|
|
112
|
+
</p>
|
|
113
|
+
<div class="p-4 bg-blue-50 border border-blue-200 rounded-lg">
|
|
114
|
+
<span class="text-blue-700 font-medium">Note:</span>
|
|
115
|
+
Custom slots allow for maximum flexibility in modal design.
|
|
116
|
+
</div>
|
|
117
|
+
</div>
|
|
118
|
+
</BModal>
|
|
119
|
+
</div>
|
|
120
|
+
`,
|
|
121
|
+
}) as any,
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export const WithForm: Story = {
|
|
125
|
+
args: {
|
|
126
|
+
...Default.args,
|
|
127
|
+
title: 'With Form',
|
|
128
|
+
description: 'Modal with form',
|
|
129
|
+
modelValue: false,
|
|
130
|
+
class: 'w-74',
|
|
131
|
+
},
|
|
132
|
+
render: (args) =>
|
|
133
|
+
({
|
|
134
|
+
components: {
|
|
135
|
+
BModal,
|
|
136
|
+
UButton: UButton as any,
|
|
137
|
+
UForm: UForm as any,
|
|
138
|
+
UFormField: UFormField as any,
|
|
139
|
+
UInput: UInput as any,
|
|
140
|
+
},
|
|
141
|
+
setup() {
|
|
142
|
+
const schema = {
|
|
143
|
+
email: {
|
|
144
|
+
type: 'string',
|
|
145
|
+
required: true,
|
|
146
|
+
format: 'email',
|
|
147
|
+
},
|
|
148
|
+
password: {
|
|
149
|
+
type: 'string',
|
|
150
|
+
required: true,
|
|
151
|
+
format: 'password',
|
|
152
|
+
},
|
|
153
|
+
}
|
|
154
|
+
const state = reactive({
|
|
155
|
+
email: '',
|
|
156
|
+
password: '',
|
|
157
|
+
})
|
|
158
|
+
return { args, schema, state }
|
|
159
|
+
},
|
|
160
|
+
template: `
|
|
161
|
+
<div>
|
|
162
|
+
<UButton label="Open Modal" @click="args.modelValue = true" />
|
|
163
|
+
<BModal v-bind="args" v-model="args.modelValue">
|
|
164
|
+
<UForm :schema="schema" :state="state" class="space-y-4 w-full">
|
|
165
|
+
<UFormField label="Email" name="email" class="w-full">
|
|
166
|
+
<UInput v-model="state.email" type="email" />
|
|
167
|
+
</UFormField>
|
|
168
|
+
|
|
169
|
+
<UFormField label="Password" name="password" class="w-full">
|
|
170
|
+
<UInput v-model="state.password" type="password" />
|
|
171
|
+
</UFormField>
|
|
172
|
+
</UForm>
|
|
173
|
+
</BModal>
|
|
174
|
+
</div>
|
|
175
|
+
`,
|
|
176
|
+
}) as any,
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export const ButtonsBlock: Story = {
|
|
180
|
+
args: {
|
|
181
|
+
...Default.args,
|
|
182
|
+
title: 'Block Buttons',
|
|
183
|
+
description: 'Buttons are full width',
|
|
184
|
+
hasButtonsBlock: true,
|
|
185
|
+
modelValue: false,
|
|
186
|
+
text: 'Check the buttons below.',
|
|
187
|
+
},
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export const NoFooter: Story = {
|
|
191
|
+
args: {
|
|
192
|
+
...Default.args,
|
|
193
|
+
title: 'No Footer',
|
|
194
|
+
description: 'This modal has no footer',
|
|
195
|
+
hasFooter: false,
|
|
196
|
+
modelValue: false,
|
|
197
|
+
text: 'Footer is hidden.',
|
|
198
|
+
},
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export const DisabledPrimary: Story = {
|
|
202
|
+
args: {
|
|
203
|
+
...Default.args,
|
|
204
|
+
title: 'Disabled Action',
|
|
205
|
+
description: 'Primary button is disabled',
|
|
206
|
+
isPrimaryButtonDisabled: true,
|
|
207
|
+
modelValue: false,
|
|
208
|
+
text: 'You cannot save right now.',
|
|
209
|
+
},
|
|
210
|
+
}
|