Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions packages/docs/components/Modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,15 +44,18 @@ The component supports the W3C ARIA APG [Dialog (Modal) Pattern](https://www.w3.
| component | Component to be injected.<br/>Close the component by emitting a 'close' event — `$emit('close')` | Component | - | |
| content | Text content, unnecessary when default slot is used | string | - | |
| events | Events to be binded to the injected component | {} | - | |
| fullScreen | Display modal as full screen | boolean | - | <code style='white-space: nowrap; padding: 0;'>false</code> |
| fullheight | Display modal in fullheight | boolean | - | <code style='white-space: nowrap; padding: 0;'>false</code> |
| fullscreen | Display modal in fullwidth and fullheight | boolean | - | <code style='white-space: nowrap; padding: 0;'>false</code> |
| fullwidth | Display modal in fullwidth | boolean | - | <code style='white-space: nowrap; padding: 0;'>false</code> |
| height | Height of the modal | Numberish | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>modal: {<br>&nbsp;&nbsp;height: undefined<br>}</code> |
| iconPack | Icon pack to use | string | `mdi`, `fa`, `fas and any other custom icon pack` | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>modal: {<br>&nbsp;&nbsp;iconPack: undefined<br>}</code> |
| mobileBreakpoint | Mobile breakpoint as `max-width` value | string | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>modal: {<br>&nbsp;&nbsp;mobileBreakpoint: undefined<br>}</code> |
| overlay | Show an overlay | boolean | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>modal: {<br>&nbsp;&nbsp;overlay: true<br>}</code> |
| override | Override existing theme classes completely | boolean | - | |
| props | Props to be binded to the injected component | any | - | |
| teleport | Append the component to another part of the DOM.<br/>Set `true` to append the component to the body.<br/>In addition, any CSS selector string or an actual DOM node can be used. | boolean \| object \| string | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>modal: {<br>&nbsp;&nbsp;teleport: false<br>}</code> |
| trapFocus | Trap focus inside the modal | boolean | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>modal: {<br>&nbsp;&nbsp;trapFocus: true<br>}</code> |
| width | Width of the Modal | Numberish | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>modal: {<br>&nbsp;&nbsp;width: 960<br>}</code> |
| width | Width of the modal | Numberish | - | <div><small>From <b>config</b>:</small></div><code style='white-space: nowrap; padding: 0;'>modal: {<br>&nbsp;&nbsp;width: undefined<br>}</code> |

### Events

Expand Down
79 changes: 58 additions & 21 deletions packages/oruga/src/components/modal/Modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,14 @@ defineOptions({
const props = withDefaults(defineProps<ModalProps<C>>(), {
override: undefined,
active: false,
fullScreen: false,
content: undefined,
width: () => getDefault("modal.width", 960),
animation: () => getDefault("modal.animation", "zoom-out"),
overlay: () => getDefault("modal.overlay", true),
width: () => getDefault("modal.width"),
height: () => getDefault("modal.height"),
fullscreen: false,
fullheight: false,
fullwidth: false,
cancelable: () =>
getDefault("modal.cancelable", ["escape", "x", "outside"]),
trapFocus: () => getDefault("modal.trapFocus", true),
Expand Down Expand Up @@ -98,9 +101,17 @@ const showX = computed(() =>
: props.cancelable,
);

const customStyle = computed(() =>
!props.fullScreen ? { maxWidth: toCssDimension(props.width) } : null,
);
// TODO: Maybe remove?!
const contentStyle = computed(() => ({
width:
!props.fullscreen && !props.fullwidth
? toCssDimension(props.width)
: undefined,
height:
!props.fullscreen && !props.fullheight
? toCssDimension(props.height)
: undefined,
}));

const toggleScroll = usePreventScrolling(props.clipScroll);

Expand All @@ -117,7 +128,7 @@ onMounted(() => {
if (isActive.value && props.overlay) toggleScroll(isActive.value);
});

// --- Events Feature ---
// #region --- Close Events Feature ---

if (isClient)
if (!props.overlay)
Expand Down Expand Up @@ -165,7 +176,9 @@ function close(...args: [] | [string] | CloseEventArgs<C>): void {
emits("close", ...args);
}

// --- Animation Feature ---
// #endregion --- Close Events Feature ---

// #region --- Animation Feature ---

const isAnimated = ref(props.active);

Expand All @@ -179,12 +192,20 @@ function beforeLeave(): void {
isAnimated.value = false;
}

// --- Computed Component Classes ---
// #endregion --- Animation Feature ---

// #region --- Computed Component Classes ---

const rootClasses = defineClasses(
["rootClass", "o-modal"],
["mobileClass", "o-modal--mobile", null, isMobile],
["activeClass", "o-modal--active", null, isActive],
[
"teleportClass",
"o-modal--teleport",
null,
computed(() => !!props.teleport),
],
);

const overlayClasses = defineClasses(["overlayClass", "o-modal__overlay"]);
Expand All @@ -195,16 +216,32 @@ const contentClasses = defineClasses(
"fullScreenClass",
"o-modal__content--full-screen",
null,
computed(() => props.fullScreen),
computed(() => props.fullscreen),
],
[
"fullheightClass",
"o-modal__content--fullheight",
null,
computed(() => props.fullheight || props.fullscreen),
],
[
"fullwidthClass",
"o-modal__content--fullwidth",
null,
computed(() => props.fullwidth || props.fullscreen),
],
);

const closeClasses = defineClasses(["closeClass", "o-modal__close"]);

// --- Expose Public Functionalities ---
// #endregion --- Computed Component Classes ---

// #region --- Expose Public Functionalities ---

/** expose functionalities for programmatic usage */
defineExpose({ close });

// #endregion --- Expose Public Functionalities ---
</script>

<template>
Expand Down Expand Up @@ -234,21 +271,21 @@ defineExpose({ close });
<div
ref="contentElement"
:class="contentClasses"
:style="customStyle">
<!-- injected component for programmatic usage -->
<component
:is="$props.component"
v-if="$props.component"
v-bind="$props.props"
v-on="$props.events || {}"
@close="close" />

:style="contentStyle">
<!--
@slot Modal default content, default is content prop
@binding {(...args): void} close - function to close the component
-->
<slot v-else :close="close">
<div v-if="content">{{ content }}</div>
<slot :close="close">
<!-- injected component for programmatic usage -->
<component
:is="$props.component"
v-if="$props.component"
v-bind="$props.props"
v-on="$props.events || {}"
@close="close" />

<div v-else-if="content">{{ content }}</div>
</slot>

<CloseButton
Expand Down
19 changes: 14 additions & 5 deletions packages/oruga/src/components/modal/examples/inspector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,22 @@ const inspectData: InspectData<ModalClasses, ModalProps> = {
data.active = true;
},
},
fullScreenClass: {
class: "fullScreenClass",
description: "Class of the content element when fullscreen.",
properties: ["fullScreen"],
fullheightClass: {
class: "fullheightClass",
description: "Class of the content element when fullheight.",
properties: ["fullheight"],
action: (data): void => {
data.active = true;
data.fullScreen = true;
data.fullheight = true;
},
},
fullwidthClass: {
class: "fullwidthClass",
description: "Class of the content element when fullwidth.",
properties: ["fullwidth"],
action: (data): void => {
data.active = true;
data.fullwidth = true;
},
},
closeClass: {
Expand Down
7 changes: 6 additions & 1 deletion packages/oruga/src/components/modal/examples/teleport.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ const isActive = ref(false);
variant="primary"
@click="isActive = true" />

<o-modal v-model:active="isActive" teleport>
<o-modal
v-model:active="isActive"
teleport
full-screen
fullheight
fillwidth>
<div style="padding: 10px; background-color: white">
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Expand Down
20 changes: 14 additions & 6 deletions packages/oruga/src/components/modal/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,22 @@ export type ModalProps<C extends Component = Component> = {
override?: boolean;
/** Whether modal is active or not, use v-model:active to make it two-way binding */
active?: boolean;
/** Display modal as full screen */
fullScreen?: boolean;
/** Text content, unnecessary when default slot is used */
content?: string;
/** Width of the Modal */
width?: Numberish;
/** Custom animation (transition name) */
animation?: string;
/** Show an overlay */
overlay?: boolean;
/** Width of the modal */
width?: Numberish;
/** Height of the modal */
height?: Numberish;
/** Display modal in fullwidth and fullheight */
fullscreen?: boolean;
/** Display modal in fullheight */
fullheight?: boolean;
/** Display modal in fullwidth */
fullwidth?: boolean;
/**
* Is Modal cancleable by clicking 'X', pressing escape or clicking outside
* @values escape, x, outside, button, true, false
Expand Down Expand Up @@ -89,8 +95,10 @@ export type ModalClasses = Partial<{
overlayClass: ComponentClass;
/** Class of the content element */
contentClass: ComponentClass;
/** Class of the content element when fullscreen */
fullScreenClass: ComponentClass;
/** Class of the content element when fullheght */
fullheightClass: ComponentClass;
/** Class of the content element when fullwidth */
fullwidthClass: ComponentClass;
/** Class of the close button element */
closeClass: ComponentClass;
/** Class of the body when modal is open and scroll is clipped */
Expand Down
12 changes: 8 additions & 4 deletions packages/oruga/src/components/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -864,12 +864,14 @@ Use menu only in situations where your dropdown is related to a navigation menu.
}>;
modal?: ComponentConfigBase &
Partial<{
/** Width of the Modal */
width: Numberish;
/** Custom animation (transition name) */
animation: string;
/** Show an overlay */
overlay: boolean;
/** Width of the modal */
width: Numberish;
/** Height of the modal */
height: Numberish;
/** Is Modal cancleable by clicking 'X', pressing escape or clicking outside */
cancelable: boolean | string[];
/** Set `true` to remove the body scrollbar.
Expand Down Expand Up @@ -909,8 +911,10 @@ In addition, any CSS selector string or an actual DOM node can be used. */
overlayClass: ClassDefinition;
/** Class of the content element */
contentClass: ClassDefinition;
/** Class of the content element when fullscreen */
fullScreenClass: ClassDefinition;
/** Class of the content element when fullheght */
fullheightClass: ClassDefinition;
/** Class of the content element when fullwidth */
fullwidthClass: ClassDefinition;
/** Class of the close button element */
closeClass: ClassDefinition;
/** Class of the body when modal is open and scroll is clipped */
Expand Down
Loading