Skip to content

Commit

Permalink
Desktop ready modal (#2889)
Browse files Browse the repository at this point in the history
  • Loading branch information
mark-drastrup authored and SigurdVilstrup committed Mar 21, 2023
1 parent 676119c commit 9576718
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 134 deletions.
55 changes: 55 additions & 0 deletions libs/core/src/scss/_global-styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -234,3 +234,58 @@ ion-loading.kirby-loading-overlay {
// Place icon to the right of text, with icons own width + the actual spacing
padding-right: calc(#{$icon-scaling-factor} + #{utils.size('xxxs')});
}

/*
* Experimental modal.
*/
$modal-max-height: 928px;
$modal-max-width: 594px;
$modal-border-radius: 32px;

html.ios ion-modal.kirby-modal-experimental {
--background: var(--kirby-modal-background, #{utils.get-color('background-color')});
--max-height: #{$modal-max-height};
--min-height: #{$modal-max-width};

@include utils.media('>=medium') {
--border-radius: #{$modal-border-radius};

&::part(content) {
margin: 15px;
}

&.xxs {
--width: #{map.get(utils.$experimental-modal-widths, 'xxs')};
--height: #{map.get(utils.$experimental-modal-heights, 'xxs')};
}

&.xs {
--width: #{map.get(utils.$experimental-modal-widths, 'xs')};
--height: #{map.get(utils.$experimental-modal-heights, 'xs')};
}

&.sm {
--width: #{map.get(utils.$experimental-modal-widths, 's')};
--height: #{map.get(utils.$experimental-modal-heights, 's')};
}

&.md {
--width: #{map.get(utils.$experimental-modal-widths, 'm')};
--height: #{map.get(utils.$experimental-modal-heights, 'm')};
}

&.lg {
--width: #{map.get(utils.$experimental-modal-widths, 'l')};
--height: #{map.get(utils.$experimental-modal-heights, 'l')};
}
}

ion-toolbar {
padding-right: 0;
padding-left: 0;
}

.kirby-grid {
display: flex;
}
}
17 changes: 17 additions & 0 deletions libs/core/src/scss/base/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,23 @@ $modal-heights: (
$modal-default-height: map.get($modal-heights, 'm');
$drawer-default-height: map.get($modal-heights, 's');

/* Modal Experimental
****************************************************************************/
$experimental-modal-widths: (
l: 960px,
m: 800px,
s: 720px,
xs: 600px,
xxs: 343px,
) !default;
$experimental-modal-heights: (
l: math.floor(map.get($experimental-modal-widths, 'l') * 0.75),
m: math.floor(map.get($experimental-modal-widths, 'm') * 0.75),
s: math.floor(map.get($experimental-modal-widths, 's') * 0.75),
xs: math.floor(map.get($experimental-modal-widths, 'xs') * 0.75),
xxs: math.floor(map.get($experimental-modal-widths, 'xxs') * 0.75),
) !default;

/* Item
****************************************************************************/
$item-heights: (
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@
<ion-footer>
<ng-content></ng-content>
<div class="nav-button">
<ng-content select="[nav-prev]"></ng-content>
</div>

<div class="default-content">
<ng-content></ng-content>
</div>

<div class="nav-button">
<ng-content select="[nav-next]"></ng-content>
</div>
</ion-footer>
Original file line number Diff line number Diff line change
@@ -1,20 +1,33 @@
@use '@kirbydesign/core/src/scss/utils';
@use '@kirbydesign/core/src/scss/themes';

$padding-horizontal: utils.size('s');
$padding-vertical: utils.size('xxs');
$padding: utils.size('m');

ion-footer {
@include themes.apply-white-theme;

box-shadow: utils.get-elevation(8);
display: flex;
display: grid;
grid-template-rows: utils.size('xl');
grid-template-columns: utils.size('xl') 1fr utils.size('xl');
justify-content: var(--kirby-modal-footer-justify-content, center);
align-items: center;
background-color: var(--kirby-modal-footer-background, utils.get-color('white'));
color: var(--kirby-modal-footer-color, utils.get-color('white-contrast'));
padding: $padding-vertical $padding-horizontal;
padding-bottom: calc(#{$padding-vertical} + var(--kirby-modal-footer-safe-area-bottom, 0px));
padding: $padding;
padding-bottom: calc(#{$padding} + var(--kirby-modal-footer-safe-area-bottom, 0px));

.default-content {
display: flex;
align-items: center;
justify-content: center;
}

.nav-button {
display: flex;
justify-content: center;
align-items: center;
}
}

@include utils.media('<medium') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import { ModalFooterExperimentalComponent } from './footer.component';
const size = DesignTokenHelper.size;

const KEYBOARD_HEIGHT = 216; // sample value, depends upon device
const BASE_PADDING_VERTICAL_PX = size('xxs');
const BASE_PADDING_VERTICAL_PX = size('m');
const BASE_PADDING_VERTICAL = parseInt(BASE_PADDING_VERTICAL_PX);
const BASE_PADDING_HORIZONTAL_PX = size('s');
const BASE_PADDING_HORIZONTAL_PX = size('m');
const SAFE_AREA_BOTTOM = 22;
const SAFE_AREA_BOTTOM_PX = `${SAFE_AREA_BOTTOM}px`;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
<ion-modal
class="kirby-modal-experimental"
[isOpen]="open"
[canDismiss]="canDismiss"
[ngClass]="size"
(willPresent)="_onWillPresent($event)"
(didPresent)="_onDidPresent($event)"
(willDismiss)="_onWillDismiss($event)"
(didDismiss)="_onDidDismiss($event)"
>
<ng-template>
<ion-header>
<ion-header class="modal-header">
<ion-toolbar>
<ng-content select="[header-start]"></ng-content>
<ion-title>{{ title }}</ion-title>
<ion-title class="kirby-text-medium">
{{ title }}
</ion-title>
<ion-buttons slot="end">
<button kirby-button [noDecoration]="true" size="md" (click)="_closeModal()">
<button kirby-button attentionLevel="1" size="md" (click)="_closeModal()">
<kirby-icon [name]="'close'"></kirby-icon>
</button>
</ion-buttons>
Expand Down
96 changes: 35 additions & 61 deletions libs/designsystem/modal/experimental/src/modal/modal.component.scss
Original file line number Diff line number Diff line change
@@ -1,54 +1,43 @@
@use 'sass:map';
@use '@kirbydesign/core/src/scss/utils';
@use '@kirbydesign/core/src/scss/themes';

// Global modal styling can be found at scss/base/_ionic.scss

@mixin contain-content() {
padding-top: 0;
position: relative;
contain: inherit;
min-height: min(var(--min-height), calc(var(--vh100) - var(--kirby-modal-padding-top, 0px)));

ion-content {
contain: content;
max-height: calc(
var(--vh100) - var(--kirby-modal-padding-top, 0px) - var(--header-height) -
var(--footer-height)
);

&::part(scroll) {
height: '100%';
position: relative;
}
}
}

$toolbar-padding-inline: utils.size('s');
$toolbar-padding-block: utils.size('xs');

@mixin phablet-toolbar-padding() {
$toolbar-padding-top: utils.size('xxs');
@include utils.media('>=medium') {
padding-top: $toolbar-padding-top;
}
}
$toolbar-mobile-padding-inline: utils.size('s');
$toolbar-mobile-padding-block: utils.size('xs');
$toolbar-desktop-padding: utils.size('m');
$modal-header-border-bottom: 1px solid utils.get-color('medium');

ion-header {
@include themes.apply-light-theme;

box-sizing: border-box;

ion-toolbar {
--padding-start: #{$toolbar-padding-inline};
--padding-end: #{$toolbar-padding-inline};
--padding-bottom: #{$toolbar-padding-block};
--padding-top: #{$toolbar-padding-block};
--padding-start: #{$toolbar-mobile-padding-inline};
--padding-end: #{$toolbar-mobile-padding-inline};
--padding-bottom: #{$toolbar-mobile-padding-block};
--padding-top: #{$toolbar-mobile-padding-block};
--border-width: 0;
--background: transparent;
--color: var(--kirby-modal-color, #{utils.get-color('black')});

button {
color: var(--color);
background-color: utils.get-color('white');
}
}

@include phablet-toolbar-padding;
&.modal-header {
border-bottom: $modal-header-border-bottom;
}

@include utils.media('>=medium') {
ion-toolbar {
--padding-start: #{$toolbar-desktop-padding};
--padding-end: #{$toolbar-desktop-padding};
--padding-bottom: #{$toolbar-desktop-padding};
--padding-top: #{$toolbar-desktop-padding};
}
}
}

Expand All @@ -58,27 +47,19 @@ ion-header {
--footer-height: 0px;
}

:host-context(ion-modal) {
@include utils.media('>=medium') {
@include contain-content;
}
}

ion-modal {
--background: var(--kirby-modal-background, #{utils.get-color('background-color')});
}

ion-title {
box-sizing: border-box;
padding-inline-start: calc(48px + var(--padding-start));
padding-inline-end: calc(48px + var(--padding-end));
font-size: utils.font-size('l');
font-weight: utils.font-weight('bold');
}

ion-content {
--background: transparent;
--color: var(--kirby-modal-color, #{utils.get-color('black')});
--padding-top: #{utils.size('m')};
--padding-bottom: #{utils.size('m')};
--padding-start: #{utils.size('s')};
--padding-end: #{utils.size('s')};

display: flex;
flex-direction: column;
Expand All @@ -88,22 +69,15 @@ ion-content {
display: block;
}

--padding-top: #{utils.size('m')};
--padding-bottom: #{utils.size('m')};
--padding-start: #{utils.size('s')};
--padding-end: #{utils.size('s')};
@include utils.media('>=medium') {
--padding-top: #{utils.size('xl')};
--padding-bottom: #{utils.size('xl')};
--padding-start: #{utils.size('xxl')};
--padding-end: #{utils.size('xxl')};
}
}

// Ensure padding-rules are not merged with other media query,
// as this rule has to come AFTER the default mobile-first rule in order to override:

/* clean-css ignore:start */
@include utils.media('>=medium') {
ion-content {
--padding-start: #{utils.size('xxxl')};
--padding-end: #{utils.size('xxxl')};
}
}

:host(.collapsible-title) {
ion-content {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,33 @@
import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { Component, ElementRef, EventEmitter, Input, Output, ViewChild } from '@angular/core';
import { IonContent, IonModal } from '@ionic/angular';
import { OverlayEventDetail } from '@ionic/core/components';
import { KirbyAnimation } from '@kirbydesign/designsystem/helpers';

type Size = 'xxs' | 'xs' | 'sm' | 'md' | 'lg';
type SizeTemp = 'md';

@Component({
selector: 'kirby-modal-experimental',
templateUrl: './modal.component.html',
styleUrls: ['./modal.component.scss'],
})
export class ModalExperimentalComponent {
@ViewChild(IonModal) modal: IonModal;
@ViewChild(IonModal, { static: true, read: ElementRef })
modalElement: ElementRef<HTMLElement>;
@ViewChild(IonContent) ionContent: IonContent;

@Input() open = false;
@Input() canDismiss: boolean | (() => Promise<boolean>) = true;
@Input() title = '';
@Input() hasCollapsibleTitle = false;
@Input() scrollDisabled = false;
@Input() size: SizeTemp = 'md';
@Input() set height(userDefinedHeight: string) {
// If the user has defined a height, then we override the --height
// specified by the 'size' classes in /core/src/scss/_global-styles.scss
this.modalElement.nativeElement.style.setProperty('--height', userDefinedHeight);
}

@Output() willPresent = new EventEmitter<CustomEvent<OverlayEventDetail>>();
@Output() didPresent = new EventEmitter<CustomEvent<OverlayEventDetail>>();
Expand Down
Loading

0 comments on commit 9576718

Please sign in to comment.