Skip to content

Commit 8156971

Browse files
feat(Modal/Slideover): add actions slot (#4358)
Co-authored-by: Benjamin Canac <[email protected]>
1 parent 1a8feb7 commit 8156971

File tree

8 files changed

+108
-0
lines changed

8 files changed

+108
-0
lines changed

src/runtime/components/Modal.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export interface ModalSlots {
6565
header(props: { close: () => void }): any
6666
title(props?: {}): any
6767
description(props?: {}): any
68+
actions(props?: {}): any
6869
close(props: { close: () => void, ui: { [K in keyof Required<Modal['slots']>]: (props?: Record<string, any>) => string } }): any
6970
body(props: { close: () => void }): any
7071
footer(props: { close: () => void }): any
@@ -166,6 +167,8 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.modal || {})
166167
</DialogDescription>
167168
</div>
168169

170+
<slot name="actions" />
171+
169172
<DialogClose v-if="props.close || !!slots.close" as-child>
170173
<slot name="close" :close="close" :ui="ui">
171174
<UButton

src/runtime/components/Slideover.vue

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ export interface SlideoverSlots {
6565
header(props: { close: () => void }): any
6666
title(props?: {}): any
6767
description(props?: {}): any
68+
actions(props?: {}): any
6869
close(props: { close: () => void, ui: { [K in keyof Required<Slideover['slots']>]: (props?: Record<string, any>) => string } }): any
6970
body(props: { close: () => void }): any
7071
footer(props: { close: () => void }): any
@@ -174,6 +175,8 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.slideover ||
174175
</DialogDescription>
175176
</div>
176177

178+
<slot name="actions" />
179+
177180
<DialogClose v-if="props.close || !!slots.close" as-child>
178181
<slot name="close" :close="close" :ui="ui">
179182
<UButton

test/components/Modal.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ describe('Modal', () => {
2323
['with header slot', { props, slots: { header: () => 'Header slot' } }],
2424
['with title slot', { props, slots: { title: () => 'Title slot' } }],
2525
['with description slot', { props, slots: { description: () => 'Description slot' } }],
26+
['with actions slot', { props, slots: { actions: () => 'Actions slot' } }],
2627
['with close slot', { props, slots: { close: () => 'Close slot' } }],
2728
['with body slot', { props, slots: { body: () => 'Body slot' } }],
2829
['with footer slot', { props, slots: { footer: () => 'Footer slot' } }]

test/components/Slideover.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ describe('Slideover', () => {
2525
['with header slot', { props, slots: { header: () => 'Header slot' } }],
2626
['with title slot', { props, slots: { title: () => 'Title slot' } }],
2727
['with description slot', { props, slots: { description: () => 'Description slot' } }],
28+
['with actions slot', { props, slots: { actions: () => 'Actions slot' } }],
2829
['with close slot', { props, slots: { close: () => 'Close slot' } }],
2930
['with body slot', { props, slots: { body: () => 'Body slot' } }],
3031
['with footer slot', { props, slots: { footer: () => 'Footer slot' } }]

test/components/__snapshots__/Modal-vue.spec.ts.snap

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`Modal > renders with actions slot correctly 1`] = `
4+
"<!--v-if-->
5+
<!--teleport start-->
6+
7+
8+
<div data-state="open" style="pointer-events: auto;" class="fixed inset-0 bg-elevated/75 data-[state=open]:animate-[fade-in_200ms_ease-out] data-[state=closed]:animate-[fade-out_200ms_ease-in]"></div>
9+
<div data-dismissable-layer="" style="pointer-events: auto;" tabindex="-1" class="fixed bg-default divide-y divide-default flex flex-col focus:outline-none data-[state=open]:animate-[scale-in_200ms_ease-out] data-[state=closed]:animate-[scale-out_200ms_ease-in] top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[calc(100vw-2rem)] max-w-lg max-h-[calc(100dvh-2rem)] sm:max-h-[calc(100dvh-4rem)] rounded-lg shadow-lg ring ring-default overflow-hidden" id="" role="dialog" aria-describedby="reka-dialog-description-v-1" aria-labelledby="reka-dialog-title-v-0" data-state="open">
10+
<!--v-if-->
11+
<div class="flex items-center gap-1.5 p-4 sm:px-6 min-h-16">
12+
<div class="">
13+
<!--v-if-->
14+
<!--v-if-->
15+
</div>Actions slot<button type="button" aria-label="Close" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors text-sm gap-1.5 text-default hover:bg-elevated focus:outline-none focus-visible:bg-elevated hover:disabled:bg-transparent dark:hover:disabled:bg-transparent hover:aria-disabled:bg-transparent dark:hover:aria-disabled:bg-transparent p-1.5 absolute top-4 end-4"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" viewBox="0 0 16 16" class="shrink-0 size-5"></svg>
16+
<!--v-if-->
17+
<!--v-if-->
18+
</button>
19+
</div>
20+
<!--v-if-->
21+
<!--v-if-->
22+
</div>
23+
24+
25+
<!--teleport end-->"
26+
`;
27+
328
exports[`Modal > renders with body slot correctly 1`] = `
429
"<!--v-if-->
530
<!--teleport start-->

test/components/__snapshots__/Modal.spec.ts.snap

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`Modal > renders with actions slot correctly 1`] = `
4+
"<!--v-if-->
5+
<!--teleport start-->
6+
7+
8+
<div data-state="open" style="pointer-events: auto;" class="fixed inset-0 bg-elevated/75 data-[state=open]:animate-[fade-in_200ms_ease-out] data-[state=closed]:animate-[fade-out_200ms_ease-in]"></div>
9+
<div data-dismissable-layer="" style="pointer-events: auto;" tabindex="-1" class="fixed bg-default divide-y divide-default flex flex-col focus:outline-none data-[state=open]:animate-[scale-in_200ms_ease-out] data-[state=closed]:animate-[scale-out_200ms_ease-in] top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[calc(100vw-2rem)] max-w-lg max-h-[calc(100dvh-2rem)] sm:max-h-[calc(100dvh-4rem)] rounded-lg shadow-lg ring ring-default overflow-hidden" id="" role="dialog" aria-describedby="reka-dialog-description-v-0-0-1" aria-labelledby="reka-dialog-title-v-0-0-0" data-state="open">
10+
<!--v-if-->
11+
<div class="flex items-center gap-1.5 p-4 sm:px-6 min-h-16">
12+
<div class="">
13+
<!--v-if-->
14+
<!--v-if-->
15+
</div>Actions slot<button type="button" aria-label="Close" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors text-sm gap-1.5 text-default hover:bg-elevated focus:outline-none focus-visible:bg-elevated hover:disabled:bg-transparent dark:hover:disabled:bg-transparent hover:aria-disabled:bg-transparent dark:hover:aria-disabled:bg-transparent p-1.5 absolute top-4 end-4"><span class="iconify i-lucide:x shrink-0 size-5" aria-hidden="true"></span>
16+
<!--v-if-->
17+
<!--v-if-->
18+
</button>
19+
</div>
20+
<!--v-if-->
21+
<!--v-if-->
22+
</div>
23+
24+
25+
<!--teleport end-->"
26+
`;
27+
328
exports[`Modal > renders with body slot correctly 1`] = `
429
"<!--v-if-->
530
<!--teleport start-->

test/components/__snapshots__/Slideover-vue.spec.ts.snap

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`Slideover > renders with actions slot correctly 1`] = `
4+
"<!--v-if-->
5+
<!--teleport start-->
6+
7+
8+
<div data-state="open" style="pointer-events: auto;" class="fixed inset-0 bg-elevated/75 data-[state=open]:animate-[fade-in_200ms_ease-out] data-[state=closed]:animate-[fade-out_200ms_ease-in]"></div>
9+
<div data-dismissable-layer="" style="pointer-events: auto;" tabindex="-1" data-side="right" class="fixed bg-default divide-y divide-default sm:ring ring-default sm:shadow-lg flex flex-col focus:outline-none right-0 inset-y-0 w-full max-w-md data-[state=open]:animate-[slide-in-from-right_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-right_200ms_ease-in-out]" id="" role="dialog" aria-describedby="reka-dialog-description-v-1" aria-labelledby="reka-dialog-title-v-0" data-state="open">
10+
<!--v-if-->
11+
<div class="flex items-center gap-1.5 p-4 sm:px-6 min-h-16">
12+
<div class="">
13+
<!--v-if-->
14+
<!--v-if-->
15+
</div>Actions slot<button type="button" aria-label="Close" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors text-sm gap-1.5 text-default hover:bg-elevated focus:outline-none focus-visible:bg-elevated hover:disabled:bg-transparent dark:hover:disabled:bg-transparent hover:aria-disabled:bg-transparent dark:hover:aria-disabled:bg-transparent p-1.5 absolute top-4 end-4"><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" width="1em" height="1em" viewBox="0 0 16 16" class="shrink-0 size-5"></svg>
16+
<!--v-if-->
17+
<!--v-if-->
18+
</button>
19+
</div>
20+
<div class="flex-1 overflow-y-auto p-4 sm:p-6"></div>
21+
<!--v-if-->
22+
</div>
23+
24+
25+
<!--teleport end-->"
26+
`;
27+
328
exports[`Slideover > renders with body slot correctly 1`] = `
429
"<!--v-if-->
530
<!--teleport start-->

test/components/__snapshots__/Slideover.spec.ts.snap

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,30 @@
11
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
22

3+
exports[`Slideover > renders with actions slot correctly 1`] = `
4+
"<!--v-if-->
5+
<!--teleport start-->
6+
7+
8+
<div data-state="open" style="pointer-events: auto;" class="fixed inset-0 bg-elevated/75 data-[state=open]:animate-[fade-in_200ms_ease-out] data-[state=closed]:animate-[fade-out_200ms_ease-in]"></div>
9+
<div data-dismissable-layer="" style="pointer-events: auto;" tabindex="-1" data-side="right" class="fixed bg-default divide-y divide-default sm:ring ring-default sm:shadow-lg flex flex-col focus:outline-none right-0 inset-y-0 w-full max-w-md data-[state=open]:animate-[slide-in-from-right_200ms_ease-in-out] data-[state=closed]:animate-[slide-out-to-right_200ms_ease-in-out]" id="" role="dialog" aria-describedby="reka-dialog-description-v-0-0-1" aria-labelledby="reka-dialog-title-v-0-0-0" data-state="open">
10+
<!--v-if-->
11+
<div class="flex items-center gap-1.5 p-4 sm:px-6 min-h-16">
12+
<div class="">
13+
<!--v-if-->
14+
<!--v-if-->
15+
</div>Actions slot<button type="button" aria-label="Close" class="rounded-md font-medium inline-flex items-center disabled:cursor-not-allowed aria-disabled:cursor-not-allowed disabled:opacity-75 aria-disabled:opacity-75 transition-colors text-sm gap-1.5 text-default hover:bg-elevated focus:outline-none focus-visible:bg-elevated hover:disabled:bg-transparent dark:hover:disabled:bg-transparent hover:aria-disabled:bg-transparent dark:hover:aria-disabled:bg-transparent p-1.5 absolute top-4 end-4"><span class="iconify i-lucide:x shrink-0 size-5" aria-hidden="true"></span>
16+
<!--v-if-->
17+
<!--v-if-->
18+
</button>
19+
</div>
20+
<div class="flex-1 overflow-y-auto p-4 sm:p-6"></div>
21+
<!--v-if-->
22+
</div>
23+
24+
25+
<!--teleport end-->"
26+
`;
27+
328
exports[`Slideover > renders with body slot correctly 1`] = `
429
"<!--v-if-->
530
<!--teleport start-->

0 commit comments

Comments
 (0)