diff --git a/packages/overlays/docs/GlobalOverlayController.md b/packages/overlays/docs/GlobalOverlayController.md index 86d913845..b71fad00a 100644 --- a/packages/overlays/docs/GlobalOverlayController.md +++ b/packages/overlays/docs/GlobalOverlayController.md @@ -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 -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 import { ModalDialogController } from '@lion/overlays'; diff --git a/packages/overlays/index.js b/packages/overlays/index.js index 03c9d5595..8c1e18018 100644 --- a/packages/overlays/index.js +++ b/packages/overlays/index.js @@ -2,6 +2,7 @@ export { DynamicOverlayController } from './src/DynamicOverlayController.js'; export { GlobalOverlayController } from './src/GlobalOverlayController.js'; export { globalOverlaysStyle } from './src/globalOverlaysStyle.js'; export { LocalOverlayController } from './src/LocalOverlayController.js'; +export { BottomsheetController } from './src/BottomsheetController.js'; export { ModalDialogController } from './src/ModalDialogController.js'; export { overlays } from './src/overlays.js'; export { OverlaysManager } from './src/OverlaysManager.js'; diff --git a/packages/overlays/src/BottomsheetController.js b/packages/overlays/src/BottomsheetController.js new file mode 100644 index 000000000..12e2c2dc1 --- /dev/null +++ b/packages/overlays/src/BottomsheetController.js @@ -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, + }); + } +} diff --git a/packages/overlays/src/globalOverlaysStyle.js b/packages/overlays/src/globalOverlaysStyle.js index ff872fe31..f9667c9b2 100644 --- a/packages/overlays/src/globalOverlaysStyle.js +++ b/packages/overlays/src/globalOverlaysStyle.js @@ -4,11 +4,6 @@ export const globalOverlaysStyle = css` .global-overlays { position: fixed; z-index: 200; - left: 0; - top: 0; - width: 100vw; - height: 100vh; - pointer-events: none; } .global-overlays__overlay, @@ -16,6 +11,60 @@ export const globalOverlaysStyle = css` 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 { display: none; } @@ -30,9 +79,10 @@ export const globalOverlaysStyle = css` content: ''; position: fixed; top: 0; - right: 0; - bottom: 0; left: 0; + width: 100%; + height: 100%; + z-index: -1; background-color: #333333; opacity: 0.3; } @@ -46,19 +96,6 @@ export const globalOverlaysStyle = css` 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 { from { opacity: 0; diff --git a/packages/overlays/stories/bottomsheet.stories.js b/packages/overlays/stories/bottomsheet.stories.js new file mode 100644 index 000000000..fd6d363fe --- /dev/null +++ b/packages/overlays/stories/bottomsheet.stories.js @@ -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` +
+ `, + }), + ); + + return html` + + Anchor 1 + + Anchor 2 + ${Array(50).fill( + html` +Lorem ipsum
+ `, + )} + `; +}); diff --git a/packages/overlays/stories/index.stories.js b/packages/overlays/stories/index.stories.js index 68ba08504..a92071c3a 100644 --- a/packages/overlays/stories/index.stories.js +++ b/packages/overlays/stories/index.stories.js @@ -1,5 +1,6 @@ import './global-overlay.stories.js'; import './modal-dialog.stories.js'; +import './bottomsheet.stories.js'; import './local-overlay.stories.js'; import './local-overlay-placement.stories.js'; import './dynamic-overlay.stories.js'; diff --git a/packages/overlays/test/BottomsheetController.test.js b/packages/overlays/test/BottomsheetController.test.js new file mode 100644 index 000000000..ad4152f78 --- /dev/null +++ b/packages/overlays/test/BottomsheetController.test.js @@ -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` +my content
+ `, + }; + }); + + 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', + ); + }); +}); diff --git a/packages/overlays/test/GlobalOverlayController.test.js b/packages/overlays/test/GlobalOverlayController.test.js index eced02a92..62f2c8010 100644 --- a/packages/overlays/test/GlobalOverlayController.test.js +++ b/packages/overlays/test/GlobalOverlayController.test.js @@ -349,7 +349,7 @@ describe('GlobalOverlayController', () => { }); controller.show(); - expect(controller.overlayContainerClass).to.equal( + expect(controller.overlayContainerPlacementClass).to.equal( 'global-overlays__overlay-container--center', ); }); @@ -377,7 +377,7 @@ describe('GlobalOverlayController', () => { `, }); controller.show(); - expect(controller.overlayContainerClass).to.equal( + expect(controller.overlayContainerPlacementClass).to.equal( `global-overlays__overlay-container--${viewportPlacement}`, ); }); diff --git a/packages/overlays/test/ModalDialogController.test.js b/packages/overlays/test/ModalDialogController.test.js index 8beaeb935..1a01c3bd3 100644 --- a/packages/overlays/test/ModalDialogController.test.js +++ b/packages/overlays/test/ModalDialogController.test.js @@ -25,6 +25,8 @@ describe('ModalDialogController', () => { expect(ctrl.preventsScroll).to.be.true; expect(ctrl.trapsKeyboardFocus).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', + ); }); });