@a-vision-software/vue-input-components 1.3.26 → 1.4.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/README.md +5 -1
- package/dist/src/components/Modal.vue.d.ts +75 -0
- package/dist/src/index.d.ts +2 -1
- package/dist/src/types/index.d.ts +1 -0
- package/dist/src/types/modal.d.ts +21 -0
- package/dist/vue-input-components.cjs.js +1 -1
- package/dist/vue-input-components.css +1 -1
- package/dist/vue-input-components.es.js +1286 -1186
- package/dist/vue-input-components.umd.js +1 -1
- package/package.json +2 -2
- package/src/assets/colors.css +3 -1
- package/src/components/Modal.vue +186 -0
- package/src/index.ts +2 -1
- package/src/router/index.ts +7 -0
- package/src/types/index.ts +1 -0
- package/src/types/modal.ts +23 -0
- package/src/views/DashboardView.vue +7 -0
- package/src/views/ModalTestView.vue +201 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@a-vision-software/vue-input-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "A collection of reusable Vue 3 input components with TypeScript support",
|
|
5
5
|
"author": "A-Vision Software",
|
|
6
6
|
"license": "MIT",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "git",
|
|
9
9
|
"url": "https://github.com/a-vision/vue-input-components.git"
|
|
10
10
|
},
|
|
11
|
-
"homepage": "https://
|
|
11
|
+
"homepage": "https://a-vision.github.io/vue-input-components/",
|
|
12
12
|
"keywords": [
|
|
13
13
|
"vue",
|
|
14
14
|
"vue3",
|
package/src/assets/colors.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
:root {
|
|
2
2
|
/* Base colors */
|
|
3
3
|
--primary-color: #3498db;
|
|
4
|
-
--primary-color-light: rgb(from var(--primary-color) r g b /
|
|
4
|
+
--primary-color-light: rgb(from var(--primary-color) r g b / 60%);
|
|
5
5
|
--secondary-color: #2ecc71;
|
|
6
6
|
|
|
7
7
|
/* Text colors */
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
/* UI colors */
|
|
12
12
|
--border-color: #555555;
|
|
13
|
+
--modal-border-color: #e0e0e0;
|
|
14
|
+
--modal-backdrop-color: rgba(0, 0, 0, 0.5);
|
|
13
15
|
--icon-color: rgb(from var(--border-color) r g b / 80%);
|
|
14
16
|
|
|
15
17
|
/* State colors */
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<Teleport to="body">
|
|
3
|
+
<transition name="modal-fade">
|
|
4
|
+
<div v-if="modelValue" class="modal-backdrop">
|
|
5
|
+
<div class="modal" :style="modalStyle" role="dialog" aria-labelledby="modalTitle"
|
|
6
|
+
aria-describedby="modalContent">
|
|
7
|
+
<div v-if="props.isLargeIcon && props.icon" class="modal-large-icon">
|
|
8
|
+
<font-awesome-icon :icon="props.icon" :style="{ color: props.iconColor }" />
|
|
9
|
+
</div>
|
|
10
|
+
<div class="modal-header" id="modalTitle">
|
|
11
|
+
<slot name="header">
|
|
12
|
+
<div class="header-content">
|
|
13
|
+
<font-awesome-icon v-if="props.icon && !props.isLargeIcon" :icon="props.icon"
|
|
14
|
+
:style="{ color: props.iconColor }" />
|
|
15
|
+
<h3 v-if="title" :style="{ color: props.titleBarColor }">{{ title }}</h3>
|
|
16
|
+
</div>
|
|
17
|
+
</slot>
|
|
18
|
+
<button type="button" class="modal-close" @click="close" aria-label="Close modal">
|
|
19
|
+
<font-awesome-icon icon="rectangle-xmark" />
|
|
20
|
+
</button>
|
|
21
|
+
</div>
|
|
22
|
+
|
|
23
|
+
<div class="modal-body" id="modalContent">
|
|
24
|
+
<slot></slot>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
<div class="modal-footer">
|
|
28
|
+
<slot name="footer"></slot>
|
|
29
|
+
</div>
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
</transition>
|
|
33
|
+
</Teleport>
|
|
34
|
+
</template>
|
|
35
|
+
|
|
36
|
+
<script setup lang="ts">
|
|
37
|
+
import { computed } from 'vue'
|
|
38
|
+
import { ModalProps, ModalEmits } from '../types/modal'
|
|
39
|
+
|
|
40
|
+
const props = withDefaults(defineProps<ModalProps>(), {
|
|
41
|
+
modelValue: false,
|
|
42
|
+
title: '',
|
|
43
|
+
minWidth: '300px',
|
|
44
|
+
maxWidth: '800px',
|
|
45
|
+
minHeight: 'auto',
|
|
46
|
+
maxHeight: '80vh',
|
|
47
|
+
titleBarColor: 'var(--primary-color, #3498db)',
|
|
48
|
+
backgroundColor: 'var(--background-color, #f8f9fa)',
|
|
49
|
+
icon: undefined,
|
|
50
|
+
isLargeIcon: false,
|
|
51
|
+
iconColor: 'var(--primary-color, #3498db)'
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
const emit = defineEmits<ModalEmits>()
|
|
55
|
+
|
|
56
|
+
const close = () => {
|
|
57
|
+
emit('update:modelValue', false)
|
|
58
|
+
emit('close')
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const open = () => {
|
|
62
|
+
emit('update:modelValue', true)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const modalStyle = computed(() => ({
|
|
66
|
+
minWidth: props.minWidth,
|
|
67
|
+
maxWidth: props.maxWidth,
|
|
68
|
+
minHeight: props.minHeight,
|
|
69
|
+
maxHeight: props.maxHeight,
|
|
70
|
+
backgroundColor: props.backgroundColor
|
|
71
|
+
}))
|
|
72
|
+
|
|
73
|
+
defineExpose({
|
|
74
|
+
open,
|
|
75
|
+
close
|
|
76
|
+
})
|
|
77
|
+
</script>
|
|
78
|
+
|
|
79
|
+
<style scoped>
|
|
80
|
+
.modal-backdrop {
|
|
81
|
+
position: fixed;
|
|
82
|
+
top: 0;
|
|
83
|
+
left: 0;
|
|
84
|
+
width: 100%;
|
|
85
|
+
height: 100%;
|
|
86
|
+
background-color: var(--modal-backdrop-color);
|
|
87
|
+
display: flex;
|
|
88
|
+
justify-content: center;
|
|
89
|
+
align-items: center;
|
|
90
|
+
z-index: 1000;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.modal {
|
|
94
|
+
border-radius: 0.5rem;
|
|
95
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.33);
|
|
96
|
+
display: flex;
|
|
97
|
+
flex-direction: column;
|
|
98
|
+
margin: 1rem;
|
|
99
|
+
width: 100%;
|
|
100
|
+
overflow: visible;
|
|
101
|
+
position: relative;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.modal-large-icon {
|
|
105
|
+
position: absolute;
|
|
106
|
+
left: 50%;
|
|
107
|
+
transform: translate(-50%, -75%);
|
|
108
|
+
background-color: var(--background-color, #ffffff);
|
|
109
|
+
border-radius: 50%;
|
|
110
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
111
|
+
z-index: 1;
|
|
112
|
+
|
|
113
|
+
svg {
|
|
114
|
+
width: 4rem;
|
|
115
|
+
height: 4rem;
|
|
116
|
+
margin: 1rem;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.header-content {
|
|
121
|
+
display: flex;
|
|
122
|
+
align-items: center;
|
|
123
|
+
gap: 0.5rem;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
.header-content .font-awesome-icon {
|
|
127
|
+
font-size: 1.25rem;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.modal-header {
|
|
131
|
+
display: flex;
|
|
132
|
+
justify-content: space-between;
|
|
133
|
+
align-items: center;
|
|
134
|
+
padding: 1rem;
|
|
135
|
+
border-bottom: 1px solid var(--modal-border-color, #e0e0e0);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.modal-header h3 {
|
|
139
|
+
margin: 0;
|
|
140
|
+
font-size: 1.25rem;
|
|
141
|
+
font-weight: 500;
|
|
142
|
+
color: var(--primary-color, #3498db);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.modal-close {
|
|
146
|
+
background: transparent;
|
|
147
|
+
border: none;
|
|
148
|
+
color: var(--text-muted, #00000088);
|
|
149
|
+
cursor: pointer;
|
|
150
|
+
font-size: 1.25rem;
|
|
151
|
+
padding: 0.25rem;
|
|
152
|
+
display: flex;
|
|
153
|
+
align-items: center;
|
|
154
|
+
justify-content: center;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.modal-close:hover {
|
|
158
|
+
opacity: 0.8;
|
|
159
|
+
color: var(--danger-color, #aa0400);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.modal-body {
|
|
163
|
+
padding: 1rem;
|
|
164
|
+
overflow-y: auto;
|
|
165
|
+
min-height: 50px;
|
|
166
|
+
flex: 1;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
.modal-footer {
|
|
170
|
+
padding: 1rem;
|
|
171
|
+
border-top: 1px solid var(--modal-border-color, #e0e0e0);
|
|
172
|
+
display: flex;
|
|
173
|
+
justify-content: flex-end;
|
|
174
|
+
gap: 0.5rem;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
.modal-fade-enter-active,
|
|
178
|
+
.modal-fade-leave-active {
|
|
179
|
+
transition: opacity 0.3s;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.modal-fade-enter-from,
|
|
183
|
+
.modal-fade-leave-to {
|
|
184
|
+
opacity: 0;
|
|
185
|
+
}
|
|
186
|
+
</style>
|
package/src/index.ts
CHANGED
|
@@ -5,7 +5,8 @@ import Action from './components/Action.vue'
|
|
|
5
5
|
import Dropdown from './components/Dropdown.vue'
|
|
6
6
|
import Checkbox from './components/Checkbox.vue'
|
|
7
7
|
import List from './components/List.vue'
|
|
8
|
+
import Modal from './components/Modal.vue'
|
|
8
9
|
|
|
9
|
-
export { TextInput, FileUpload, Navigation, Action, Dropdown, Checkbox, List }
|
|
10
|
+
export { TextInput, FileUpload, Navigation, Action, Dropdown, Checkbox, List, Modal }
|
|
10
11
|
|
|
11
12
|
export * from './types'
|
package/src/router/index.ts
CHANGED
|
@@ -7,6 +7,7 @@ import NavigationTestView from '../views/NavigationTestView.vue'
|
|
|
7
7
|
import DropdownTestView from '../views/DropdownTestView.vue'
|
|
8
8
|
import CheckboxTestView from '../views/CheckboxTestView.vue'
|
|
9
9
|
import ListTestView from '../views/ListTestView.vue'
|
|
10
|
+
import ModalTestView from '../views/ModalTestView.vue'
|
|
10
11
|
|
|
11
12
|
const router = createRouter({
|
|
12
13
|
history: createWebHistory(import.meta.env.BASE_URL),
|
|
@@ -59,6 +60,12 @@ const router = createRouter({
|
|
|
59
60
|
component: ListTestView,
|
|
60
61
|
meta: { title: 'List Test' },
|
|
61
62
|
},
|
|
63
|
+
{
|
|
64
|
+
path: '/modal',
|
|
65
|
+
name: 'modal',
|
|
66
|
+
component: ModalTestView,
|
|
67
|
+
meta: { title: 'Modal Test' },
|
|
68
|
+
},
|
|
62
69
|
],
|
|
63
70
|
})
|
|
64
71
|
|
package/src/types/index.ts
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface ModalProps {
|
|
2
|
+
modelValue: boolean
|
|
3
|
+
title?: string
|
|
4
|
+
minWidth?: string
|
|
5
|
+
maxWidth?: string
|
|
6
|
+
minHeight?: string
|
|
7
|
+
maxHeight?: string
|
|
8
|
+
titleBarColor?: string
|
|
9
|
+
backgroundColor?: string
|
|
10
|
+
icon?: string
|
|
11
|
+
isLargeIcon?: boolean
|
|
12
|
+
iconColor?: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface ModalEmits {
|
|
16
|
+
(e: 'update:modelValue', value: boolean): void
|
|
17
|
+
(e: 'close'): void
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ModalComponent {
|
|
21
|
+
open: () => void
|
|
22
|
+
close: () => void
|
|
23
|
+
}
|
|
@@ -52,6 +52,13 @@
|
|
|
52
52
|
<span class="dashboard__label">Action</span>
|
|
53
53
|
<span class="dashboard__description">Interactive buttons and links with various styles</span>
|
|
54
54
|
</router-link>
|
|
55
|
+
<router-link to="/modal" class="dashboard__item">
|
|
56
|
+
<div class="dashboard__icon-wrapper">
|
|
57
|
+
<font-awesome-icon icon="rectangle-xmark" class="dashboard__icon" />
|
|
58
|
+
</div>
|
|
59
|
+
<span class="dashboard__label">Modal</span>
|
|
60
|
+
<span class="dashboard__description">Popup dialog windows for displaying content and forms</span>
|
|
61
|
+
</router-link>
|
|
55
62
|
</div>
|
|
56
63
|
</div>
|
|
57
64
|
</template>
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="modal-test">
|
|
3
|
+
<h1>Modal Test</h1>
|
|
4
|
+
<p class="subtitle">A reusable modal component for displaying content in a popup dialog.</p>
|
|
5
|
+
|
|
6
|
+
<div class="section">
|
|
7
|
+
<h2>Basic Modal</h2>
|
|
8
|
+
<p>A simple modal with a title and content.</p>
|
|
9
|
+
|
|
10
|
+
<Action label="Open Basic Modal" @click="showBasicModal = true" />
|
|
11
|
+
|
|
12
|
+
<Modal v-model="showBasicModal" title="Basic Modal Example" icon="info-circle">
|
|
13
|
+
<p>This is a basic modal example with default styling.</p>
|
|
14
|
+
<p>The modal can be closed by clicking the X button in the top right corner.</p>
|
|
15
|
+
</Modal>
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
<div class="section">
|
|
19
|
+
<h2>Custom Styled Modal</h2>
|
|
20
|
+
<p>A modal with custom styling options and custom header/footer content.</p>
|
|
21
|
+
|
|
22
|
+
<Action label="Open Custom Modal" @click="showCustomModal = true" />
|
|
23
|
+
|
|
24
|
+
<Modal v-model="showCustomModal" min-width="400px" max-width="600px" title-bar-color="var(--primary-color)"
|
|
25
|
+
background-color="#f9f9f9" icon="user" is-large-icon iconColor="var(--primary-color-light)">
|
|
26
|
+
<template #header>
|
|
27
|
+
<div class="custom-header">
|
|
28
|
+
<h3>Custom Modal Header</h3>
|
|
29
|
+
</div>
|
|
30
|
+
</template>
|
|
31
|
+
|
|
32
|
+
<template #footer>
|
|
33
|
+
<div class="custom-footer">
|
|
34
|
+
<Action label="Cancel" variant="transparent" @click="showCustomModal = false" />
|
|
35
|
+
<Action label="Save" @click="saveAndClose" />
|
|
36
|
+
</div>
|
|
37
|
+
</template>
|
|
38
|
+
|
|
39
|
+
<div class="custom-content">
|
|
40
|
+
<p>This modal has custom styling and a custom header.</p>
|
|
41
|
+
<p>You can use slots to customize the header, body, and footer.</p>
|
|
42
|
+
|
|
43
|
+
<div class="form-group">
|
|
44
|
+
<TextInput v-model="inputValue" label="Name" placeholder="Enter your name..." />
|
|
45
|
+
</div>
|
|
46
|
+
|
|
47
|
+
<div class="form-group">
|
|
48
|
+
<Dropdown v-model="selectedOption" :options="dropdownOptions" label="Select an option"
|
|
49
|
+
placeholder="Choose an option..." />
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</Modal>
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
<div class="section">
|
|
56
|
+
<h2>Form Modal Example</h2>
|
|
57
|
+
<p>A modal containing a form that can be submitted.</p>
|
|
58
|
+
|
|
59
|
+
<Action label="Open Form Modal" @click="showFormModal = true" />
|
|
60
|
+
|
|
61
|
+
<Modal v-model="showFormModal" title="Form Submission">
|
|
62
|
+
<form @submit.prevent="submitForm">
|
|
63
|
+
<div class="form-group">
|
|
64
|
+
<TextInput v-model="formData.name" label="Name" placeholder="Enter your name" required />
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<div class="form-group">
|
|
68
|
+
<TextInput v-model="formData.email" label="Email" type="email" placeholder="Enter your email" required />
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<div class="form-group">
|
|
72
|
+
<TextInput v-model="formData.message" label="Message" type="textarea" placeholder="Enter your message" />
|
|
73
|
+
</div>
|
|
74
|
+
|
|
75
|
+
<div class="form-actions">
|
|
76
|
+
<Action label="Cancel" variant="transparent" @click="showFormModal = false" />
|
|
77
|
+
<Action label="Submit" type="submit" />
|
|
78
|
+
</div>
|
|
79
|
+
</form>
|
|
80
|
+
</Modal>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</template>
|
|
84
|
+
|
|
85
|
+
<script setup lang="ts">
|
|
86
|
+
import { ref } from 'vue'
|
|
87
|
+
import Modal from '../components/Modal.vue'
|
|
88
|
+
import Action from '../components/Action.vue'
|
|
89
|
+
import TextInput from '../components/TextInput.vue'
|
|
90
|
+
import Dropdown from '../components/Dropdown.vue'
|
|
91
|
+
|
|
92
|
+
// Basic Modal
|
|
93
|
+
const showBasicModal = ref(false)
|
|
94
|
+
|
|
95
|
+
// Custom Modal
|
|
96
|
+
const showCustomModal = ref(false)
|
|
97
|
+
const inputValue = ref('')
|
|
98
|
+
const selectedOption = ref('')
|
|
99
|
+
const dropdownOptions = [
|
|
100
|
+
{ id: 'option1', value: 'option1', label: 'Option 1' },
|
|
101
|
+
{ id: 'option2', value: 'option2', label: 'Option 2' },
|
|
102
|
+
{ id: 'option3', value: 'option3', label: 'Option 3' }
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
// Form Modal
|
|
106
|
+
const showFormModal = ref(false)
|
|
107
|
+
const formData = ref({
|
|
108
|
+
name: '',
|
|
109
|
+
email: '',
|
|
110
|
+
message: ''
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
// Methods
|
|
114
|
+
const saveAndClose = () => {
|
|
115
|
+
alert(`Name: ${inputValue.value}\nSelected Option: ${selectedOption.value}`)
|
|
116
|
+
showCustomModal.value = false
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const submitForm = () => {
|
|
120
|
+
alert(`Form submitted!\nName: ${formData.value.name}\nEmail: ${formData.value.email}\nMessage: ${formData.value.message}`)
|
|
121
|
+
showFormModal.value = false
|
|
122
|
+
|
|
123
|
+
// Reset form
|
|
124
|
+
formData.value = {
|
|
125
|
+
name: '',
|
|
126
|
+
email: '',
|
|
127
|
+
message: ''
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
</script>
|
|
131
|
+
|
|
132
|
+
<style scoped>
|
|
133
|
+
.modal-test {
|
|
134
|
+
max-width: 1200px;
|
|
135
|
+
margin: 0 auto;
|
|
136
|
+
padding: 2rem 1.5rem;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
h1 {
|
|
140
|
+
margin-bottom: 0.5rem;
|
|
141
|
+
color: var(--text-color);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.subtitle {
|
|
145
|
+
color: var(--text-muted);
|
|
146
|
+
margin-bottom: 2rem;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.section {
|
|
150
|
+
margin-bottom: 2rem;
|
|
151
|
+
padding: 1.5rem;
|
|
152
|
+
background-color: var(--background-color, #ffffff);
|
|
153
|
+
border-radius: 0.5rem;
|
|
154
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.section h2 {
|
|
158
|
+
margin-top: 0;
|
|
159
|
+
margin-bottom: 0.5rem;
|
|
160
|
+
font-size: 1.25rem;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.section p {
|
|
164
|
+
margin-bottom: 1rem;
|
|
165
|
+
color: var(--text-muted);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.custom-header {
|
|
169
|
+
display: flex;
|
|
170
|
+
align-items: center;
|
|
171
|
+
gap: 0.5rem;
|
|
172
|
+
color: var(--primary-color, #4AAE9B);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.custom-header h3 {
|
|
176
|
+
margin: 0;
|
|
177
|
+
color: var(--primary-color, #4AAE9B);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.custom-content {
|
|
181
|
+
padding: 1rem 0;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
.custom-footer {
|
|
185
|
+
display: flex;
|
|
186
|
+
justify-content: flex-end;
|
|
187
|
+
gap: 0.5rem;
|
|
188
|
+
width: 100%;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
.form-group {
|
|
192
|
+
margin-bottom: 1rem;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.form-actions {
|
|
196
|
+
display: flex;
|
|
197
|
+
justify-content: flex-end;
|
|
198
|
+
gap: 0.5rem;
|
|
199
|
+
margin-top: 1.5rem;
|
|
200
|
+
}
|
|
201
|
+
</style>
|