cja-phoenix 0.3.7 → 0.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/dist/cja-phoenix.es.js +2112 -2050
- package/dist/style.css +1 -1
- package/dist/types/components/composite/CjaMenuBar.vue.d.ts +10 -5
- package/dist/types/components/forms/NumberInput.vue.d.ts +1 -1
- package/dist/types/components/forms/TextInput.vue.d.ts +4 -0
- package/dist/types/components/structural/CjaButton.vue.d.ts +2 -0
- package/dist/types/components/structural/Modal.vue.d.ts +40 -5
- package/dist/types/stories/CjaButton.story.vue.d.ts +2 -0
- package/dist/types/stories/ContentTabs.story.vue.d.ts +2 -0
- package/dist/types/stories/Modal.story.vue.d.ts +2 -0
- package/package.json +1 -1
- package/src/assets/breakpoints.scss +12 -0
- package/src/assets/forms.scss +3 -3
- package/src/assets/main.scss +1 -0
- package/src/components/composite/CheckoutCrossSell.vue +2 -0
- package/src/components/composite/CheckoutMilestones.vue +4 -2
- package/src/components/composite/CjaMenuBar.vue +130 -64
- package/src/components/composite/FunnelLayout.vue +7 -5
- package/src/components/composite/FunnelTitle.vue +3 -1
- package/src/components/forms/TextInput.vue +16 -0
- package/src/components/forms/structure/InputError.vue +3 -1
- package/src/components/forms/structure/InputTitle.vue +2 -1
- package/src/components/structural/CjaButton.vue +37 -15
- package/src/components/structural/GridContainer.vue +2 -1
- package/src/components/structural/GridItem.vue +3 -1
- package/src/components/structural/InfoMessage.vue +5 -3
- package/src/components/structural/Modal.vue +76 -63
- package/src/stories/CjaButton.story.vue +192 -0
- package/src/stories/ContentTabs.story.vue +59 -0
- package/src/stories/Modal.story.vue +127 -0
- package/src/utils/useViewportDetector.ts +2 -2
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<Teleport to="body">
|
|
3
3
|
<Transition name="fade">
|
|
4
|
-
<div v-show="active" class="modal-backdrop">
|
|
4
|
+
<div v-show="active" class="modal-backdrop" :style="{ ...cssVars }">
|
|
5
5
|
<div class="modal-overlay" @click.self="closeModal">
|
|
6
6
|
<div class="modal-container" ref="modalContainer">
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
7
|
+
<div class="modal-header" :class="{ 'has-title': $slots.header }">
|
|
8
|
+
<div class="modal-header-wrapper">
|
|
9
|
+
<slot name="header"></slot>
|
|
10
|
+
</div>
|
|
11
|
+
<button
|
|
12
|
+
type="button"
|
|
13
|
+
class="btn-close m-cgg-icon--cross"
|
|
14
|
+
aria-label="Close"
|
|
15
|
+
@click="closeModal"
|
|
16
|
+
></button>
|
|
17
17
|
</div>
|
|
18
18
|
<div class="modal-body">
|
|
19
19
|
<slot name="body"></slot>
|
|
@@ -29,27 +29,42 @@
|
|
|
29
29
|
</template>
|
|
30
30
|
|
|
31
31
|
<script lang="ts" setup>
|
|
32
|
-
import { ref, watch } from "vue";
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
import { ref, watch, computed } from "vue";
|
|
33
|
+
|
|
34
|
+
const props = withDefaults(
|
|
35
|
+
defineProps<{
|
|
36
|
+
maxWidth?: {
|
|
37
|
+
md?: string;
|
|
38
|
+
lg?: string;
|
|
39
|
+
xl?: string;
|
|
40
|
+
};
|
|
41
|
+
}>(),
|
|
42
|
+
{
|
|
43
|
+
maxWidth: () => ({
|
|
44
|
+
md: "min(calc(100% - 48px), 768px)",
|
|
45
|
+
lg: "min(calc(100% - 48px), 1024px)",
|
|
46
|
+
xl: "1024px",
|
|
47
|
+
}),
|
|
48
|
+
}
|
|
49
|
+
);
|
|
37
50
|
|
|
38
51
|
const active = ref(false);
|
|
39
52
|
const modalContainer = ref();
|
|
40
53
|
|
|
54
|
+
const cssVars = computed(() => ({
|
|
55
|
+
"--md-max-width": props.maxWidth.md,
|
|
56
|
+
"--lg-max-width": props.maxWidth.lg,
|
|
57
|
+
"--xl-max-width": props.maxWidth.xl,
|
|
58
|
+
}));
|
|
59
|
+
|
|
41
60
|
const emit = defineEmits(["close"]);
|
|
42
61
|
|
|
43
62
|
watch(
|
|
44
63
|
() => active.value,
|
|
45
64
|
(active) => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
} else {
|
|
50
|
-
document.body.style.overflow = "";
|
|
51
|
-
document.documentElement.style.overflow = "";
|
|
52
|
-
}
|
|
65
|
+
document.querySelectorAll("html, body").forEach((el) => {
|
|
66
|
+
(el as HTMLElement).style.overflow = active ? "hidden" : "";
|
|
67
|
+
});
|
|
53
68
|
}
|
|
54
69
|
);
|
|
55
70
|
|
|
@@ -74,6 +89,8 @@ defineExpose({ active, openModal, closeModal, toggleModal });
|
|
|
74
89
|
</script>
|
|
75
90
|
|
|
76
91
|
<style lang="scss" scoped>
|
|
92
|
+
@import "../../assets/breakpoints.scss";
|
|
93
|
+
|
|
77
94
|
.modal-backdrop {
|
|
78
95
|
position: fixed;
|
|
79
96
|
top: 0;
|
|
@@ -105,87 +122,83 @@ defineExpose({ active, openModal, closeModal, toggleModal });
|
|
|
105
122
|
box-sizing: border-box;
|
|
106
123
|
display: flex;
|
|
107
124
|
flex-direction: column;
|
|
125
|
+
gap: 16px;
|
|
108
126
|
|
|
109
|
-
@media screen and (min-width:
|
|
127
|
+
@media screen and (min-width: $break-md-min) {
|
|
110
128
|
top: 50%;
|
|
111
129
|
left: 50%;
|
|
112
130
|
transform: translateY(-50%) translateX(-50%);
|
|
113
|
-
max-width:
|
|
114
|
-
max-height: calc(100% -
|
|
131
|
+
max-width: var(--md-max-width);
|
|
132
|
+
max-height: calc(100% - 48px);
|
|
115
133
|
border-radius: 8px;
|
|
116
134
|
padding: 20px 40px;
|
|
117
135
|
height: auto;
|
|
118
136
|
}
|
|
119
137
|
|
|
120
|
-
@media screen and (min-width:
|
|
121
|
-
max-width:
|
|
138
|
+
@media screen and (min-width: $break-lg-min) {
|
|
139
|
+
max-width: var(--lg-max-width);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@media screen and (min-width: $break-xl-min) {
|
|
143
|
+
max-width: var(--xl-max-width);
|
|
122
144
|
}
|
|
123
145
|
|
|
124
146
|
.modal-header {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
padding: 0 20px 15px 0;
|
|
129
|
-
border-bottom: 1px solid #dedede;
|
|
130
|
-
|
|
131
|
-
@media screen and (min-width: 601px) {
|
|
132
|
-
font-size: 24px;
|
|
133
|
-
line-height: 27px;
|
|
134
|
-
}
|
|
147
|
+
display: grid;
|
|
148
|
+
grid-template-columns: 1fr 20px;
|
|
149
|
+
padding: 0;
|
|
135
150
|
|
|
136
151
|
&:before,
|
|
137
152
|
&:after {
|
|
138
153
|
content: none;
|
|
139
154
|
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
.btn-close {
|
|
143
|
-
position: absolute;
|
|
144
|
-
top: 20px;
|
|
145
|
-
right: 20px;
|
|
146
|
-
background: none;
|
|
147
|
-
border: none;
|
|
148
|
-
padding: 0;
|
|
149
|
-
outline: 0;
|
|
150
|
-
height: 20px;
|
|
151
|
-
cursor: pointer;
|
|
152
|
-
z-index: 2;
|
|
153
155
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
+
&.has-title {
|
|
157
|
+
padding: 0 0 8px 0;
|
|
158
|
+
border-bottom: 1px solid #dedede;
|
|
156
159
|
}
|
|
157
160
|
|
|
158
|
-
|
|
159
|
-
display: block;
|
|
161
|
+
.modal-header-wrapper {
|
|
160
162
|
font-size: 16px;
|
|
161
163
|
line-height: 20px;
|
|
164
|
+
font-weight: 700;
|
|
162
165
|
}
|
|
163
166
|
|
|
164
|
-
|
|
167
|
+
.btn-close {
|
|
168
|
+
background: none;
|
|
169
|
+
border: none;
|
|
170
|
+
padding: 0;
|
|
165
171
|
outline: 0;
|
|
172
|
+
height: 20px;
|
|
173
|
+
width: 20px;
|
|
174
|
+
cursor: pointer;
|
|
175
|
+
z-index: 2;
|
|
176
|
+
font-size: 16px;
|
|
177
|
+
line-height: 20px;
|
|
178
|
+
|
|
179
|
+
&:focus {
|
|
180
|
+
outline: 0;
|
|
181
|
+
}
|
|
166
182
|
}
|
|
167
183
|
}
|
|
168
184
|
|
|
169
185
|
.modal-body {
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
line-height: 17px;
|
|
186
|
+
font-size: 14px;
|
|
187
|
+
line-height: 18px;
|
|
173
188
|
overflow-y: auto;
|
|
174
189
|
flex-grow: 1;
|
|
175
190
|
height: auto;
|
|
176
|
-
padding: 15px;
|
|
177
191
|
}
|
|
178
192
|
|
|
179
193
|
.modal-footer {
|
|
180
194
|
border-top: 1px solid #dedede;
|
|
181
|
-
padding:
|
|
182
|
-
margin-top: 15px;
|
|
195
|
+
padding: 8px 0 0;
|
|
183
196
|
|
|
184
197
|
:deep(.button-container) {
|
|
185
198
|
display: flex;
|
|
186
199
|
flex-direction: row;
|
|
187
200
|
justify-content: flex-end;
|
|
188
|
-
gap:
|
|
201
|
+
gap: 8px;
|
|
189
202
|
}
|
|
190
203
|
}
|
|
191
204
|
}
|
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import CjaButton from "../components/structural/CjaButton.vue";
|
|
3
|
+
import TextInput from "../components/forms/TextInput.vue";
|
|
4
|
+
|
|
5
|
+
const initState = () => ({
|
|
6
|
+
content: "Button Text",
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const initStateAllConfigs = () => ({
|
|
10
|
+
content: "Button Text",
|
|
11
|
+
type: "primary" as "primary" | "secondary" | "tertiary",
|
|
12
|
+
color: "blue" as "blue" | "orange" | "white",
|
|
13
|
+
size: "md" as "sm" | "md" | "lg",
|
|
14
|
+
icon: "" as string,
|
|
15
|
+
iconAny: "" as string,
|
|
16
|
+
iconPosition: "right" as "left" | "right",
|
|
17
|
+
loading: false as boolean,
|
|
18
|
+
disabled: false as boolean,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const initStateIcon = () => ({
|
|
22
|
+
type: "primary" as "primary" | "secondary" | "tertiary",
|
|
23
|
+
color: "blue" as "blue" | "orange" | "white",
|
|
24
|
+
size: "md" as "sm" | "md" | "lg",
|
|
25
|
+
icon: "m-cgg-icon--gears" as string,
|
|
26
|
+
iconAny: "" as string,
|
|
27
|
+
iconPosition: "right" as "left" | "right",
|
|
28
|
+
loading: false as boolean,
|
|
29
|
+
disabled: false as boolean,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
const options = {
|
|
33
|
+
type: ["primary", "secondary", "tertiary"],
|
|
34
|
+
color: ["blue", "orange", "white"],
|
|
35
|
+
size: ["sm", "md", "lg"],
|
|
36
|
+
icon: [
|
|
37
|
+
{ label: "None", value: "" },
|
|
38
|
+
{ label: "Chevron Right", value: "m-cgg-icon--chevron-right" },
|
|
39
|
+
{ label: "Chevron Down", value: "m-cgg-icon--chevron-down" },
|
|
40
|
+
{ label: "Gears", value: "m-cgg-icon--gears" },
|
|
41
|
+
],
|
|
42
|
+
iconPosition: ["right", "left"],
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const inputValue = "";
|
|
46
|
+
</script>
|
|
47
|
+
|
|
48
|
+
<template>
|
|
49
|
+
<Story title="Button">
|
|
50
|
+
<Variant title="Default" :init-state="initState">
|
|
51
|
+
<template #default="{ state }">
|
|
52
|
+
<CjaButton>{{ state.content }}</CjaButton>
|
|
53
|
+
</template>
|
|
54
|
+
|
|
55
|
+
<template #controls="{ state }">
|
|
56
|
+
<HstText type="text" v-model="state.content" title="Content" />
|
|
57
|
+
</template>
|
|
58
|
+
</Variant>
|
|
59
|
+
<Variant title="All Configs" :init-state="initStateAllConfigs">
|
|
60
|
+
<template #default="{ state }">
|
|
61
|
+
<div class="form-container">
|
|
62
|
+
<TextInput v-model="inputValue" :size="state.size" />
|
|
63
|
+
<CjaButton
|
|
64
|
+
:type="state.type"
|
|
65
|
+
:color="state.color"
|
|
66
|
+
:size="state.size"
|
|
67
|
+
:icon="state.iconAny || state.icon"
|
|
68
|
+
:iconPosition="state.iconPosition"
|
|
69
|
+
:loading="state.loading"
|
|
70
|
+
:disabled="state.disabled"
|
|
71
|
+
>{{ state.content }}</CjaButton
|
|
72
|
+
>
|
|
73
|
+
</div>
|
|
74
|
+
</template>
|
|
75
|
+
|
|
76
|
+
<template #controls="{ state }">
|
|
77
|
+
<HstText type="text" v-model="state.content" title="Content" />
|
|
78
|
+
<HstSelect v-model="state.type" :options="options.type" title="Type" />
|
|
79
|
+
<HstSelect
|
|
80
|
+
v-model="state.color"
|
|
81
|
+
:options="options.color"
|
|
82
|
+
title="Color"
|
|
83
|
+
/>
|
|
84
|
+
<HstSelect v-model="state.size" :options="options.size" title="Size" />
|
|
85
|
+
<HstText type="text" v-model="state.iconAny" title="Icon Any" />
|
|
86
|
+
<HstSelect v-model="state.icon" :options="options.icon" title="Icon" />
|
|
87
|
+
<HstSelect
|
|
88
|
+
v-model="state.iconPosition"
|
|
89
|
+
:options="options.iconPosition"
|
|
90
|
+
title="Icon Position"
|
|
91
|
+
/>
|
|
92
|
+
<HstCheckbox v-model="state.loading" title="Loading" />
|
|
93
|
+
<HstCheckbox v-model="state.disabled" title="Disabled" />
|
|
94
|
+
</template>
|
|
95
|
+
</Variant>
|
|
96
|
+
<Variant title="Icon Button" :init-state="initStateIcon">
|
|
97
|
+
<template #default="{ state }">
|
|
98
|
+
<div class="form-container">
|
|
99
|
+
<TextInput v-model="inputValue" :size="state.size" />
|
|
100
|
+
<CjaButton
|
|
101
|
+
:type="state.type"
|
|
102
|
+
:color="state.color"
|
|
103
|
+
:size="state.size"
|
|
104
|
+
:icon="state.iconAny || state.icon"
|
|
105
|
+
:iconPosition="state.iconPosition"
|
|
106
|
+
:loading="state.loading"
|
|
107
|
+
:disabled="state.disabled"
|
|
108
|
+
/>
|
|
109
|
+
</div>
|
|
110
|
+
</template>
|
|
111
|
+
|
|
112
|
+
<template #controls="{ state }">
|
|
113
|
+
<HstSelect v-model="state.type" :options="options.type" title="Type" />
|
|
114
|
+
<HstSelect
|
|
115
|
+
v-model="state.color"
|
|
116
|
+
:options="options.color"
|
|
117
|
+
title="Color"
|
|
118
|
+
/>
|
|
119
|
+
<HstSelect v-model="state.size" :options="options.size" title="Size" />
|
|
120
|
+
<HstText type="text" v-model="state.iconAny" title="Icon Any" />
|
|
121
|
+
<HstSelect v-model="state.icon" :options="options.icon" title="Icon" />
|
|
122
|
+
<HstSelect
|
|
123
|
+
v-model="state.iconPosition"
|
|
124
|
+
:options="options.iconPosition"
|
|
125
|
+
title="Icon Position"
|
|
126
|
+
/>
|
|
127
|
+
<HstCheckbox v-model="state.loading" title="Loading" />
|
|
128
|
+
<HstCheckbox v-model="state.disabled" title="Disabled" />
|
|
129
|
+
</template>
|
|
130
|
+
</Variant>
|
|
131
|
+
</Story>
|
|
132
|
+
</template>
|
|
133
|
+
|
|
134
|
+
<style lang="scss" scoped>
|
|
135
|
+
.form-container {
|
|
136
|
+
display: grid;
|
|
137
|
+
grid-template-columns: 200px max-content;
|
|
138
|
+
gap: 24px;
|
|
139
|
+
}
|
|
140
|
+
</style>
|
|
141
|
+
|
|
142
|
+
<docs lang="md">
|
|
143
|
+
## Props
|
|
144
|
+
|
|
145
|
+
#### type
|
|
146
|
+
|
|
147
|
+
Defines fill and border type
|
|
148
|
+
|
|
149
|
+
- **primary** has background fill
|
|
150
|
+
- **secondary** is bordered without fill
|
|
151
|
+
- **tertiary** does not have background or border
|
|
152
|
+
|
|
153
|
+
#### color
|
|
154
|
+
|
|
155
|
+
Defines button color profile
|
|
156
|
+
|
|
157
|
+
- <b style="color: #076b9c">blue</b>
|
|
158
|
+
- <b style="color: #f58423">orange</b>
|
|
159
|
+
- <b style="color: #fff">white</b>
|
|
160
|
+
|
|
161
|
+
#### size
|
|
162
|
+
|
|
163
|
+
Defines button size, changing padding and font-size
|
|
164
|
+
|
|
165
|
+
- **sm**
|
|
166
|
+
- **md**
|
|
167
|
+
- **lg**
|
|
168
|
+
|
|
169
|
+
#### icon
|
|
170
|
+
|
|
171
|
+
An iconia class icon, inserted as a class into a span
|
|
172
|
+
|
|
173
|
+
#### iconPosition
|
|
174
|
+
|
|
175
|
+
Defines icon position relative to button text
|
|
176
|
+
|
|
177
|
+
- **left**
|
|
178
|
+
- **right**
|
|
179
|
+
|
|
180
|
+
#### loading
|
|
181
|
+
|
|
182
|
+
Displays a spinner when boolean is true, prevents display of button text and icon
|
|
183
|
+
|
|
184
|
+
## Defaults
|
|
185
|
+
|
|
186
|
+
When implementing a **CjaButton** component with no props, the following props are pre-defined as default:
|
|
187
|
+
|
|
188
|
+
- **type**: primary
|
|
189
|
+
- **color**: <b style="color: #076b9c">blue</b>
|
|
190
|
+
- **size**: md
|
|
191
|
+
- **iconPosition**: right
|
|
192
|
+
</docs>
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import ContentTabs from "../components/structural/ContentTabs.vue";
|
|
3
|
+
|
|
4
|
+
const initState = () => ({
|
|
5
|
+
tabs: ["Tab 1", "Tab 2"],
|
|
6
|
+
});
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<Story title="Content Tabs">
|
|
11
|
+
<Variant title="Default" :init-state="initState">
|
|
12
|
+
<template #default="{ state }">
|
|
13
|
+
<ContentTabs :defaultTab="0" :tabs="state.tabs">
|
|
14
|
+
<template #[i] v-for="(tab, i) in state.tabs">
|
|
15
|
+
Each tab must match a numbered slot equivalent to the position on
|
|
16
|
+
the array, this is the slot for: {{ tab }}
|
|
17
|
+
</template>
|
|
18
|
+
</ContentTabs>
|
|
19
|
+
</template>
|
|
20
|
+
|
|
21
|
+
<template #controls="{ state }">
|
|
22
|
+
<HstJson v-model="state.tabs" title="Tabs"></HstJson>
|
|
23
|
+
</template>
|
|
24
|
+
|
|
25
|
+
<template #source>
|
|
26
|
+
<textarea v-pre>
|
|
27
|
+
<ContentTabs :defaultTab="0" :tabs="['Tab 1', 'Tab 2']">
|
|
28
|
+
<template #0> Slot content </template>
|
|
29
|
+
<template #1> Slot content </template>
|
|
30
|
+
</ContentTabs>
|
|
31
|
+
</textarea>
|
|
32
|
+
</template>
|
|
33
|
+
</Variant>
|
|
34
|
+
</Story>
|
|
35
|
+
</template>
|
|
36
|
+
|
|
37
|
+
<docs lang="md">
|
|
38
|
+
### Props
|
|
39
|
+
|
|
40
|
+
#### defaultTab
|
|
41
|
+
|
|
42
|
+
The initial active tab when the component is first rendered.
|
|
43
|
+
|
|
44
|
+
#### tabs
|
|
45
|
+
|
|
46
|
+
An array of strings displayed on the tab controls, each one must match a numbered slot in order to display content properly.
|
|
47
|
+
|
|
48
|
+
### Emits
|
|
49
|
+
|
|
50
|
+
#### tab:changed
|
|
51
|
+
|
|
52
|
+
Triggered when the tab controls are clicked, sends the new tab number.
|
|
53
|
+
|
|
54
|
+
### Exposed
|
|
55
|
+
|
|
56
|
+
#### activeTab
|
|
57
|
+
|
|
58
|
+
Exposes the **activeTab** variable, used to display the current selected tab.
|
|
59
|
+
</docs>
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import Modal from "../components/structural/Modal.vue";
|
|
4
|
+
import CjaButton from "../components/structural/CjaButton.vue";
|
|
5
|
+
|
|
6
|
+
const modal = ref();
|
|
7
|
+
|
|
8
|
+
const initState = () => ({
|
|
9
|
+
mdMaxWidth: "min(calc(100% - 48px), 768px)",
|
|
10
|
+
lgMaxWidth: "min(calc(100% - 48px), 1024px)",
|
|
11
|
+
xlMaxWidth: "1024px",
|
|
12
|
+
modalHeader: true,
|
|
13
|
+
modalBody: true,
|
|
14
|
+
modalFooter: false,
|
|
15
|
+
});
|
|
16
|
+
</script>
|
|
17
|
+
|
|
18
|
+
<template>
|
|
19
|
+
<Story title="Modal">
|
|
20
|
+
<Variant title="Default" :init-state="initState">
|
|
21
|
+
<template #default="{ state }">
|
|
22
|
+
<Modal
|
|
23
|
+
ref="modal"
|
|
24
|
+
:maxWidth="{
|
|
25
|
+
md: state.mdMaxWidth,
|
|
26
|
+
lg: state.lgMaxWidth,
|
|
27
|
+
xl: state.xlMaxWidth,
|
|
28
|
+
}"
|
|
29
|
+
>
|
|
30
|
+
<template #header v-if="state.modalHeader">
|
|
31
|
+
Modal Header Slot
|
|
32
|
+
</template>
|
|
33
|
+
<template #body v-if="state.modalBody">
|
|
34
|
+
<div class="modal-body">
|
|
35
|
+
<h2>Modal Body Slot</h2>
|
|
36
|
+
<p>
|
|
37
|
+
The modal body slot can host whatever component you need to use
|
|
38
|
+
inside
|
|
39
|
+
</p>
|
|
40
|
+
</div>
|
|
41
|
+
</template>
|
|
42
|
+
<template #footer v-if="state.modalFooter">
|
|
43
|
+
<div class="modal-footer">Modal Footer Slot</div>
|
|
44
|
+
</template>
|
|
45
|
+
</Modal>
|
|
46
|
+
|
|
47
|
+
<CjaButton @click="modal.openModal()">Open modal</CjaButton>
|
|
48
|
+
</template>
|
|
49
|
+
|
|
50
|
+
<template #controls="{ state }">
|
|
51
|
+
<HstText v-model="state.mdMaxWidth" title="Max Width md" />
|
|
52
|
+
<HstText v-model="state.lgMaxWidth" title="Max Width lg" />
|
|
53
|
+
<HstText v-model="state.xlMaxWidth" title="Max Width xl" />
|
|
54
|
+
<HstCheckbox v-model="state.modalHeader" title="Modal Header" />
|
|
55
|
+
<HstCheckbox v-model="state.modalBody" title="Modal Body" />
|
|
56
|
+
<HstCheckbox v-model="state.modalFooter" title="Modal Footer" />
|
|
57
|
+
</template>
|
|
58
|
+
</Variant>
|
|
59
|
+
</Story>
|
|
60
|
+
</template>
|
|
61
|
+
|
|
62
|
+
<style lang="scss" scoped>
|
|
63
|
+
h2 {
|
|
64
|
+
margin-top: 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
p {
|
|
68
|
+
margin: 0;
|
|
69
|
+
}
|
|
70
|
+
</style>
|
|
71
|
+
|
|
72
|
+
<docs lang="md">
|
|
73
|
+
### Props
|
|
74
|
+
|
|
75
|
+
#### maxWidth
|
|
76
|
+
|
|
77
|
+
Defines a maxWidth CSS string for the **md**, **lg** and **xl** viewports.
|
|
78
|
+
|
|
79
|
+
### Slots
|
|
80
|
+
|
|
81
|
+
#### #header
|
|
82
|
+
|
|
83
|
+
Displays content inside the header slot space and adds a horizontal rule below it to the modal.
|
|
84
|
+
|
|
85
|
+
#### #body
|
|
86
|
+
|
|
87
|
+
Displays content inside the modal, becoming scrollable after a threshold. If you need to stylize slotted content, wrap the html within a div, it will be scoped to the vue scope you are currently working with.
|
|
88
|
+
|
|
89
|
+
#### #footer
|
|
90
|
+
|
|
91
|
+
Displays content below the modal body, separated by a horizontal ruler. Exempt from the scrollable container.
|
|
92
|
+
|
|
93
|
+
### Emits
|
|
94
|
+
|
|
95
|
+
#### @close
|
|
96
|
+
|
|
97
|
+
Triggered when the modal is closed, through the close button or clicking outside the modal window.
|
|
98
|
+
|
|
99
|
+
### Exposed
|
|
100
|
+
|
|
101
|
+
#### active
|
|
102
|
+
|
|
103
|
+
Exposes the modal's current **active** status, allows you to detect if the modal is opened or closed.
|
|
104
|
+
|
|
105
|
+
#### openModal()
|
|
106
|
+
|
|
107
|
+
Exposes the **openModal** method, used to display the modal, typically wrapped in a local function to perform additional changes before opening the modal.
|
|
108
|
+
|
|
109
|
+
#### closeModal()
|
|
110
|
+
|
|
111
|
+
Exposes the **closeModal** method, used to hide the modal, emits a **@close** event.
|
|
112
|
+
|
|
113
|
+
#### toggleModal()
|
|
114
|
+
|
|
115
|
+
Exposes the **toggleModal** method, used to hide or show the modal depending on the current **active** value. Emits a **@close** event if the modal was closed.
|
|
116
|
+
|
|
117
|
+
## Defaults
|
|
118
|
+
|
|
119
|
+
- **maxWidth**:
|
|
120
|
+
```
|
|
121
|
+
{
|
|
122
|
+
md: "min(calc(100% - 48px), 768px)",
|
|
123
|
+
lg: "min(calc(100% - 48px), 1024px)",
|
|
124
|
+
xl: "1024px"
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
</docs>
|