feat(overlays): create BottomsheetController

This commit is contained in:
qa46hx 2019-09-23 14:38:47 +02:00 committed by Thijs Louisse
parent 1cc92fbd6e
commit 4b858cbea7
9 changed files with 168 additions and 24 deletions

View file

@ -26,9 +26,17 @@ const myCtrl = overlays.add(
); );
``` ```
### BottomsheetController
A specific extension of GlobalOverlayController configured to create accessible dialogs at the bottom of the screen.
```js
import { BottomsheetController } from '@lion/overlays';
```
### ModalDialogController ### ModalDialogController
A specific extension of GlobalOverlayController configured to create accessible modal dialogs. A specific extension of GlobalOverlayController configured to create accessible modal dialogs placed in the center of the screen.
```js ```js
import { ModalDialogController } from '@lion/overlays'; import { ModalDialogController } from '@lion/overlays';

View file

@ -2,6 +2,7 @@ export { DynamicOverlayController } from './src/DynamicOverlayController.js';
export { GlobalOverlayController } from './src/GlobalOverlayController.js'; export { GlobalOverlayController } from './src/GlobalOverlayController.js';
export { globalOverlaysStyle } from './src/globalOverlaysStyle.js'; export { globalOverlaysStyle } from './src/globalOverlaysStyle.js';
export { LocalOverlayController } from './src/LocalOverlayController.js'; export { LocalOverlayController } from './src/LocalOverlayController.js';
export { BottomsheetController } from './src/BottomsheetController.js';
export { ModalDialogController } from './src/ModalDialogController.js'; export { ModalDialogController } from './src/ModalDialogController.js';
export { overlays } from './src/overlays.js'; export { overlays } from './src/overlays.js';
export { OverlaysManager } from './src/OverlaysManager.js'; export { OverlaysManager } from './src/OverlaysManager.js';

View file

@ -0,0 +1,16 @@
import { GlobalOverlayController } from './GlobalOverlayController.js';
export class BottomsheetController extends GlobalOverlayController {
constructor(params) {
super({
hasBackdrop: true,
preventsScroll: true,
trapsKeyboardFocus: true,
hidesOnEsc: true,
viewportConfig: {
placement: 'bottom',
},
...params,
});
}
}

View file

@ -4,11 +4,6 @@ export const globalOverlaysStyle = css`
.global-overlays { .global-overlays {
position: fixed; position: fixed;
z-index: 200; z-index: 200;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
pointer-events: none;
} }
.global-overlays__overlay, .global-overlays__overlay,
@ -16,6 +11,60 @@ export const globalOverlaysStyle = css`
pointer-events: auto; pointer-events: auto;
} }
.global-overlays__overlay-container {
display: flex;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
}
.global-overlays__overlay-container--top-left {
justify-content: flex-start;
align-items: flex-start;
}
.global-overlays__overlay-container--top {
justify-content: center;
align-items: flex-start;
}
.global-overlays__overlay-container--top-right {
justify-content: flex-end;
align-items: flex-start;
}
.global-overlays__overlay-container--right {
justify-content: flex-end;
align-items: center;
}
.global-overlays__overlay-container--bottom-left {
justify-content: flex-start;
align-items: flex-end;
}
.global-overlays__overlay-container--bottom {
justify-content: center;
align-items: flex-end;
}
.global-overlays__overlay-container--bottom-right {
justify-content: flex-end;
align-items: flex-end;
}
.global-overlays__overlay-container--left {
justify-content: flex-start;
align-items: center;
}
.global-overlays__overlay-container--center {
justify-content: center;
align-items: center;
}
.global-overlays.global-overlays--blocking-opened .global-overlays__overlay { .global-overlays.global-overlays--blocking-opened .global-overlays__overlay {
display: none; display: none;
} }
@ -30,9 +79,10 @@ export const globalOverlaysStyle = css`
content: ''; content: '';
position: fixed; position: fixed;
top: 0; top: 0;
right: 0;
bottom: 0;
left: 0; left: 0;
width: 100%;
height: 100%;
z-index: -1;
background-color: #333333; background-color: #333333;
opacity: 0.3; opacity: 0.3;
} }
@ -46,19 +96,6 @@ export const globalOverlaysStyle = css`
opacity: 0; opacity: 0;
} }
.global-overlays.global-overlays--backdrop-fade-out {
content: '';
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: #333333;
opacity: 0;
pointer-events: none;
animation: global-overlays-backdrop-fade-out 300ms;
}
@keyframes global-overlays-backdrop-fade-in { @keyframes global-overlays-backdrop-fade-in {
from { from {
opacity: 0; opacity: 0;

View file

@ -0,0 +1,47 @@
import { storiesOf, html } from '@open-wc/demoing-storybook';
import { css } from '@lion/core';
import { overlays, BottomsheetController } from '../index.js';
const bottomsheetDemoStyle = css`
.demo-overlay {
width: 100%;
background-color: white;
border: 1px solid lightgrey;
text-align: center;
height: 800px;
}
`;
storiesOf('Global Overlay System|Bottomsheet', module).add('Default', () => {
const bottomsheetCtrl = overlays.add(
new BottomsheetController({
contentTemplate: () => html`
<div class="demo-overlay">
<p>Bottomsheet</p>
<button @click="${() => bottomsheetCtrl.hide()}">Close</button>
</div>
`,
}),
);
return html`
<style>
${bottomsheetDemoStyle}
</style>
<a href="#">Anchor 1</a>
<button
@click="${event => bottomsheetCtrl.show(event.target)}"
aria-haspopup="dialog"
aria-expanded="false"
>
Open dialog
</button>
<a href="#">Anchor 2</a>
${Array(50).fill(
html`
<p>Lorem ipsum</p>
`,
)}
`;
});

View file

@ -1,5 +1,6 @@
import './global-overlay.stories.js'; import './global-overlay.stories.js';
import './modal-dialog.stories.js'; import './modal-dialog.stories.js';
import './bottomsheet.stories.js';
import './local-overlay.stories.js'; import './local-overlay.stories.js';
import './local-overlay-placement.stories.js'; import './local-overlay-placement.stories.js';
import './dynamic-overlay.stories.js'; import './dynamic-overlay.stories.js';

View file

@ -0,0 +1,32 @@
import { expect, html } from '@open-wc/testing';
import { GlobalOverlayController } from '../src/GlobalOverlayController.js';
import { BottomsheetController } from '../src/BottomsheetController.js';
describe('BottomsheetController', () => {
let defaultOptions;
before(() => {
defaultOptions = {
contentTemplate: () => html`
<p>my content</p>
`,
};
});
it('extends GlobalOverlayController', () => {
expect(new BottomsheetController(defaultOptions)).to.be.instanceof(GlobalOverlayController);
});
it('has correct defaults', () => {
const controller = new BottomsheetController(defaultOptions);
expect(controller.hasBackdrop).to.equal(true);
expect(controller.isBlocking).to.equal(false);
expect(controller.preventsScroll).to.equal(true);
expect(controller.trapsKeyboardFocus).to.equal(true);
expect(controller.hidesOnEsc).to.equal(true);
expect(controller.overlayContainerPlacementClass).to.equal(
'global-overlays__overlay-container--bottom',
);
});
});

View file

@ -349,7 +349,7 @@ describe('GlobalOverlayController', () => {
}); });
controller.show(); controller.show();
expect(controller.overlayContainerClass).to.equal( expect(controller.overlayContainerPlacementClass).to.equal(
'global-overlays__overlay-container--center', 'global-overlays__overlay-container--center',
); );
}); });
@ -377,7 +377,7 @@ describe('GlobalOverlayController', () => {
`, `,
}); });
controller.show(); controller.show();
expect(controller.overlayContainerClass).to.equal( expect(controller.overlayContainerPlacementClass).to.equal(
`global-overlays__overlay-container--${viewportPlacement}`, `global-overlays__overlay-container--${viewportPlacement}`,
); );
}); });

View file

@ -25,6 +25,8 @@ describe('ModalDialogController', () => {
expect(ctrl.preventsScroll).to.be.true; expect(ctrl.preventsScroll).to.be.true;
expect(ctrl.trapsKeyboardFocus).to.be.true; expect(ctrl.trapsKeyboardFocus).to.be.true;
expect(ctrl.hidesOnEsc).to.be.true; expect(ctrl.hidesOnEsc).to.be.true;
expect(ctrl.overlayContainerClass).to.equal('global-overlays__overlay-container--center'); expect(ctrl.overlayContainerPlacementClass).to.equal(
'global-overlays__overlay-container--center',
);
}); });
}); });