Skip to content

Commit

Permalink
feat(modal,wizard): add full-screen size option
Browse files Browse the repository at this point in the history
A full-screen modal or wizard will take up all available screen space
except for some padding on all four sides.

This PR also adds an option for long content inside the modal to test
scrolling within the modal.

CDE-1789
  • Loading branch information
kevinbuhmann committed Mar 26, 2024
1 parent 7cf02ac commit 95c28f2
Show file tree
Hide file tree
Showing 13 changed files with 89 additions and 8 deletions.
15 changes: 12 additions & 3 deletions .storybook/stories/modal/modal-static.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default {
}),
],
argTypes: {
size: { defaultValue: 'md', control: { type: 'radio', options: ['sm', 'md', 'lg', 'xl'] } },
size: { defaultValue: 'md', control: { type: 'radio', options: ['sm', 'md', 'lg', 'xl', 'full-screen'] } },
},
args: {
title: 'Small Modal',
Expand All @@ -33,7 +33,7 @@ const ModalStaticTemplate: Story = args => ({
position: relative;
padding: 24px;
}
.modal.static {
.modal:not(.modal-full-screen).static {
position: relative;
padding: 72px;
}
Expand All @@ -47,7 +47,7 @@ const ModalStaticTemplate: Story = args => ({
}
</style>
<div class="backdrop-example-container">
<div class="modal static">
<div class="modal modal-{{size}} static">
<div class="modal-dialog modal-{{size}}" role="dialog" aria-hidden="true">
<div class="modal-content">
<div class="modal-header">
Expand Down Expand Up @@ -99,3 +99,12 @@ export const ExtraLargeModal: StoryObj = {
size: 'xl',
},
};

export const FullScreenModal: StoryObj = {
render: ModalStaticTemplate,
args: {
title: 'Full-Screen Modal',
body: 'This is a full-screen modal.',
size: 'full-screen',
},
};
20 changes: 19 additions & 1 deletion .storybook/stories/modal/modal.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default {
// inputs
clrModalCloseButtonAriaLabel: { type: 'string', defaultValue: commonStringsDefault.close },
clrModalLabelledById: { defaultValue: '' },
clrModalSize: { defaultValue: 'md', control: { type: 'radio', options: ['sm', 'md', 'lg', 'xl'] } },
clrModalSize: { defaultValue: 'md', control: { type: 'radio', options: ['sm', 'md', 'lg', 'xl', 'full-screen'] } },
clrModalSkipAnimation: { defaultValue: false, control: { type: 'boolean' } },
// outputs
clrModalAlternateClose: { control: { disable: true } },
Expand All @@ -44,6 +44,7 @@ export default {
title: 'Modal Title',
body: 'Hello World!',
showLongPageContent: true,
showLongModalContent: false,
},
};

Expand Down Expand Up @@ -71,6 +72,12 @@ const ModalTemplate: Story = args => ({
<h3 class="modal-title">{{title}}</h3>
<div class="modal-body">
{{body}}
<div *ngIf="showLongModalContent" cds-layout="m-t:md">
This list is provided to demonstrate scrolling capability within the modal.
<ul>
<li *ngFor="let _ of createArray(100); let i = index">{{i + 1}}</li>
</ul>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline" (click)="clrModalOpen = false">Cancel</button>
Expand Down Expand Up @@ -133,6 +140,17 @@ export const OpenExtraLargeModal: StoryObj = {
},
};

export const OpenFullScreenModal: StoryObj = {
render: ModalTemplate,
play: removeFocusOutline,
args: {
clrModalOpen: true,
clrModalSize: 'full-screen',
title: 'Full-Screen Modal',
body: 'This is a full-screen modal.',
},
};

function removeFocusOutline({ canvasElement }: StoryContext) {
// remove keyboard focus outline from modal title
canvasElement.querySelector<HTMLElement>(':focus').blur();
Expand Down
12 changes: 11 additions & 1 deletion .storybook/stories/wizard/wizard.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,10 @@ export default {
clrWizardPreventDefaultNext: { defaultValue: false },
clrWizardPreventDefaultCancel: { defaultValue: false },
clrWizardStepnavAriaLabel: { defaultValue: commonStringsDefault.wizardStepnavAriaLabel },
clrWizardSize: { defaultValue: 'xl', control: { type: 'inline-radio', options: ['sm', 'md', 'lg', 'xl'] } },
clrWizardSize: {
defaultValue: 'xl',
control: { type: 'inline-radio', options: ['sm', 'md', 'lg', 'xl', 'full-screen'] },
},
// outputs
clrWizardOpenChange: { control: { disable: true } },
clrWizardCurrentPageChanged: { control: { disable: true } },
Expand Down Expand Up @@ -109,3 +112,10 @@ const WizardTemplate: Story = args => ({
export const Wizard: StoryObj = {
render: WizardTemplate,
};

export const FullScreenWizard: StoryObj = {
render: WizardTemplate,
args: {
clrWizardSize: 'full-screen',
},
};
1 change: 1 addition & 0 deletions projects/angular/src/modal/STYLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
| --clr-modal-lg-width | Width of the modal on large layout |
| --clr-modal-xl-width | Width of the modal on extra large layout |
| --clr-modal-content-box-shadow | Shadow of modal content |
| --clr-modal-full-screen-padding | Padding for full-screen modals |

## CSS Classes

Expand Down
16 changes: 16 additions & 0 deletions projects/angular/src/modal/_modal.clarity.scss
Original file line number Diff line number Diff line change
Expand Up @@ -185,4 +185,20 @@
.modal .modal-nav {
display: none;
}

// full-screen modals
.modal.modal-full-screen {
padding: modal-variables.$clr-modal-full-screen-padding;

.modal-dialog {
width: 100%;
height: 100%;
}

.modal-footer {
position: absolute;
bottom: modal-variables.$clr-modal-default-space;
right: modal-variables.$clr-modal-default-space;
}
}
}
3 changes: 3 additions & 0 deletions projects/angular/src/modal/_properties.modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@
--clr-modal-title-font-weight: #{tokens.$cds-alias-typography-section-font-weight};
--clr-modal-title-line-height: #{tokens.$cds-alias-typography-section-line-height};
--clr-modal-title-letter-spacing: #{tokens.$cds-alias-typography-section-letter-spacing};

// full-screen modal
--clr-modal-full-screen-padding: #{tokens.$cds-global-space-6};
}
}
}
1 change: 1 addition & 0 deletions projects/angular/src/modal/_variables.modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,4 @@ $clr-modal-title-font-family: var(--clr-modal-title-font-family) !default;
$clr-modal-title-font-weight: var(--clr-modal-title-font-weight) !default;
$clr-modal-title-line-height: var(--clr-modal-title-line-height) !default;
$clr-modal-title-letter-spacing: var(--clr-modal-title-letter-spacing) !default;
$clr-modal-full-screen-padding: var(--clr-modal-full-screen-padding) !default;
2 changes: 1 addition & 1 deletion projects/angular/src/modal/modal.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
~ The full license information can be found in LICENSE in the root directory of this project.
-->

<div class="modal" *ngIf="_open">
<div *ngIf="_open" class="modal" [class.modal-full-screen]="size == 'full-screen'">
<!--fixme: revisit when ngClass works with exit animation-->
<div
cdkTrapFocus
Expand Down
6 changes: 6 additions & 0 deletions projects/angular/src/modal/modal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,12 @@ describe('Modal', () => {

expect(compiled.querySelector('.modal-sm')).toBeNull();
expect(compiled.querySelector('.modal-lg')).not.toBeNull();

fixture.componentInstance.size = 'full-screen';
fixture.detectChanges();

expect(compiled.querySelector('.modal-lg')).toBeNull();
expect(compiled.querySelector('.modal-full-screen')).not.toBeNull();
}));

it('supports a clrModalClosable option', fakeAsync(() => {
Expand Down
9 changes: 8 additions & 1 deletion projects/demo/src/app/modal/modal-angular-show.demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,16 @@

<p>
Try it live:
<clr-toggle-container>
<label>Size</label>
<clr-toggle-wrapper>
<label>Full Screen</label>
<input clrToggle type="checkbox" [(ngModel)]="fullScreen" name="full-screen" />
</clr-toggle-wrapper>
</clr-toggle-container>
<button class="btn btn-primary" (click)="basic = true">Show modal</button>
</p>
<clr-modal [(clrModalOpen)]="basic">
<clr-modal [clrModalSize]="fullScreen ? 'full-screen' : 'md'" [(clrModalOpen)]="basic">
<h3 class="modal-title">I have a nice title</h3>
<div class="modal-body">
<p>But not much to say...</p>
Expand Down
1 change: 1 addition & 0 deletions projects/demo/src/app/modal/modal-angular-show.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { Component } from '@angular/core';
export class ModalAngularShowDemo {
// Booleans to open each example modal
basic = false;
fullScreen = false;

onModalClose() {
console.log('modal change event');
Expand Down
10 changes: 9 additions & 1 deletion projects/demo/src/app/wizard/wizard-basic.demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,17 @@
~ The full license information can be found in LICENSE in the root directory of this project.
-->

<clr-toggle-container>
<label>Size</label>
<clr-toggle-wrapper>
<label>Full Screen</label>
<input clrToggle type="checkbox" [(ngModel)]="fullScreen" name="full-screen" />
</clr-toggle-wrapper>
</clr-toggle-container>

<button class="btn btn-primary" (click)="wizard.open()">Open Wizard</button>

<clr-wizard #wizard [(clrWizardOpen)]="open">
<clr-wizard #wizard [clrWizardSize]="fullScreen ? 'full-screen' : 'xl'" [(clrWizardOpen)]="open">
<clr-wizard-title>Wizard Title</clr-wizard-title>

<clr-wizard-button [type]="'cancel'">Cancel</clr-wizard-button>
Expand Down
1 change: 1 addition & 0 deletions projects/demo/src/app/wizard/wizard-basic.demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ import { ClrWizard } from '@clr/angular';
export class WizardBasicDemo {
@ViewChild('wizard') wizard: ClrWizard;
open = false;
fullScreen = false;
}

0 comments on commit 95c28f2

Please sign in to comment.