diff --git a/apps/demo/src/app/demo/demo.component.html b/apps/demo/src/app/demo/demo.component.html index 80e82b4..1312dc4 100644 --- a/apps/demo/src/app/demo/demo.component.html +++ b/apps/demo/src/app/demo/demo.component.html @@ -25,6 +25,7 @@ [attr.collapsed]="inputs.top.collapsed" [attr.resize-disabled]="inputs.top.resizeDisabled" [attr.animation-disabled]="inputs.top.animationDisabled" + [attr.hide-backdrop]="inputs.top.hideBackdrop" (resized)="onResized('top', $event)" (backdropClicked)="onBackdropClicked('top')" > @@ -41,6 +42,7 @@ [attr.collapsed]="inputs.right.collapsed" [attr.resize-disabled]="inputs.right.resizeDisabled" [attr.animation-disabled]="inputs.right.animationDisabled" + [attr.hide-backdrop]="inputs.right.hideBackdrop" (resized)="onResized('right', $event)" (backdropClicked)="onBackdropClicked('right')" > @@ -57,6 +59,7 @@ [attr.collapsed]="inputs.bottom.collapsed" [attr.resize-disabled]="inputs.bottom.resizeDisabled" [attr.animation-disabled]="inputs.bottom.animationDisabled" + [attr.hide-backdrop]="inputs.bottom.hideBackdrop" (resized)="onResized('bottom', $event)" (backdropClicked)="onBackdropClicked('bottom')" > @@ -73,6 +76,7 @@ [attr.collapsed]="inputs.left.collapsed" [attr.resize-disabled]="inputs.left.resizeDisabled" [attr.animation-disabled]="inputs.left.animationDisabled" + [attr.hide-backdrop]="inputs.left.hideBackdrop" (resized)="onResized('left', $event)" (backdropClicked)="onBackdropClicked('left')" > diff --git a/apps/demo/src/lib/components/editor/editor-form.component.html b/apps/demo/src/lib/components/editor/editor-form.component.html index 9d179d7..b4f2c95 100644 --- a/apps/demo/src/lib/components/editor/editor-form.component.html +++ b/apps/demo/src/lib/components/editor/editor-form.component.html @@ -189,4 +189,7 @@ Animation disabled + + Hide backdrop + diff --git a/apps/demo/src/lib/components/editor/editor-form.component.ts b/apps/demo/src/lib/components/editor/editor-form.component.ts index ec8c13e..53c2f98 100644 --- a/apps/demo/src/lib/components/editor/editor-form.component.ts +++ b/apps/demo/src/lib/components/editor/editor-form.component.ts @@ -76,6 +76,11 @@ export class EditorFormComponent { this.panelFormControls[slot].animationDisabled ); + connectFormValue( + this.layoutRx[slot].hideBackdrop, + this.panelFormControls[slot].hideBackdrop + ); + connectFormValue( this.layoutRx.remove[slot], this.panelFormControls[slot].remove @@ -159,6 +164,7 @@ export class EditorFormComponent { collapsed: new FormControl(), resizeDisabled: new FormControl(), animationDisabled: new FormControl(), + hideBackdrop: new FormControl(), }; } } diff --git a/libs/angular/package.json b/libs/angular/package.json index 9882bf4..9783b2d 100644 --- a/libs/angular/package.json +++ b/libs/angular/package.json @@ -1,6 +1,6 @@ { "name": "@berg-layout/angular", - "version": "5.4.1", + "version": "5.5.0", "license": "MIT", "repository": { "url": "https://github.com/blidblid/berg-layout" diff --git a/libs/angular/src/lib/components/panel/panel.component.html b/libs/angular/src/lib/components/panel/panel.component.html index 5d86a96..d1ecb09 100644 --- a/libs/angular/src/lib/components/panel/panel.component.html +++ b/libs/angular/src/lib/components/panel/panel.component.html @@ -7,6 +7,7 @@ [attr.min-size]="minSize" [attr.max-size]="maxSize" [attr.animation-disabled]="animationDisabled" + [attr.hide-backdrop]="hideBackdrop" [attr.event-binding-mode]="eventBindingMode" (afterCollapsed)="onAfterCollapsed($event)" (afterExpanded)="onAfterExpanded($event)" diff --git a/libs/angular/src/lib/components/panel/panel.component.ts b/libs/angular/src/lib/components/panel/panel.component.ts index 7bd5782..a4efc91 100644 --- a/libs/angular/src/lib/components/panel/panel.component.ts +++ b/libs/angular/src/lib/components/panel/panel.component.ts @@ -117,6 +117,17 @@ export class BergPanelComponent } private _animationDisabled = this.getDefaultInput('animationDisabled'); + @Input() + get hideBackdrop(): boolean { + return this._hideBackdrop; + } + set hideBackdrop(value: boolean | null) { + this._hideBackdrop = coerceBooleanProperty( + value ?? this.getDefaultInput('hideBackdrop') + ); + } + private _hideBackdrop = this.getDefaultInput('hideBackdrop'); + @Input() get eventBindingMode() { return this._eventBindingMode; diff --git a/libs/angular/src/lib/components/testing/layout.component.spec.ts b/libs/angular/src/lib/components/testing/layout.component.spec.ts index 1aca6b8..12546f0 100644 --- a/libs/angular/src/lib/components/testing/layout.component.spec.ts +++ b/libs/angular/src/lib/components/testing/layout.component.spec.ts @@ -180,6 +180,7 @@ describe('Angular implementation', () => { [absolute]="top.absolute" [collapsed]="top.collapsed" [resizeDisabled]="top.resizeDisabled" + [hideBackdrop]="top.hideBackdrop" (backdropClicked)="onBackdropClicked($event)" (resized)="onResized($event)" (afterCollapsed)="hasAfterCollapsedEmitted = true" @@ -197,6 +198,7 @@ describe('Angular implementation', () => { [absolute]="right.absolute" [collapsed]="right.collapsed" [resizeDisabled]="right.resizeDisabled" + [hideBackdrop]="right.hideBackdrop" > @@ -210,6 +212,7 @@ describe('Angular implementation', () => { [absolute]="bottom.absolute" [collapsed]="bottom.collapsed" [resizeDisabled]="bottom.resizeDisabled" + [hideBackdrop]="bottom.hideBackdrop" > @@ -223,6 +226,7 @@ describe('Angular implementation', () => { [absolute]="left.absolute" [collapsed]="left.collapsed" [resizeDisabled]="left.resizeDisabled" + [hideBackdrop]="left.hideBackdrop" > diff --git a/libs/core/package.json b/libs/core/package.json index 72a996c..0ac1a60 100644 --- a/libs/core/package.json +++ b/libs/core/package.json @@ -1,6 +1,6 @@ { "name": "@berg-layout/core", - "version": "5.4.1", + "version": "5.5.0", "license": "MIT", "repository": { "url": "https://github.com/blidblid/berg-layout" diff --git a/libs/core/src/lib/components/panel/panel-config.ts b/libs/core/src/lib/components/panel/panel-config.ts index 117cc14..d86c915 100644 --- a/libs/core/src/lib/components/panel/panel-config.ts +++ b/libs/core/src/lib/components/panel/panel-config.ts @@ -19,6 +19,7 @@ export const BERG_PANEL_DEFAULT_INPUTS: RequireAll = { minSize: 50, maxSize: null, animationDisabled: false, + hideBackdrop: false, }; export const BERG_PANEL_ATTRIBUTE_BY_INPUT: WebComponentAttributeByInput = @@ -32,6 +33,7 @@ export const BERG_PANEL_ATTRIBUTE_BY_INPUT: WebComponentAttributeByInput = diff --git a/libs/core/src/lib/components/panel/panel-model.ts b/libs/core/src/lib/components/panel/panel-model.ts index a8964e7..2db25e1 100644 --- a/libs/core/src/lib/components/panel/panel-model.ts +++ b/libs/core/src/lib/components/panel/panel-model.ts @@ -27,6 +27,9 @@ export interface BergPanelInputs { /** Whether panel animations are disabled. */ animationDisabled: boolean; + /** Whether the panel backdrop is hidden. */ + hideBackdrop: boolean; + /** * Controls how panel events update panel inputs. * With "auto", panel events automatically update panel inputs. diff --git a/libs/core/src/lib/components/panel/panel.ts b/libs/core/src/lib/components/panel/panel.ts index 815537b..b3308ca 100644 --- a/libs/core/src/lib/components/panel/panel.ts +++ b/libs/core/src/lib/components/panel/panel.ts @@ -171,21 +171,20 @@ export class BergPanelElement extends WebComponent { minSize: coerceNumberProperty, maxSize: coerceNumberProperty, animationDisabled: coerceBooleanProperty, + hideBackdrop: coerceBooleanProperty, eventBindingMode: (value: string) => validateOutputBindingMode(value), }, { absolute: () => { this.updateBackdrop(); this.layout.updateAbsolute(this.values.slot, this.values.absolute); + const absoluteZIndex = (BERG_PANEL_BACKDROP_Z_INDEX + 1).toString(); if (this.values.absolute) { // the z-index is animated despite not being a transitioned property, // update z-index with disabled transitions to avoid flickering this.disableTransitions(); - this.style.setProperty( - 'z-index', - (BERG_PANEL_BACKDROP_Z_INDEX + 1).toString() - ); + this.style.setProperty('z-index', absoluteZIndex); requestAnimationFrame(() => { this.enableTransitions(); @@ -194,11 +193,13 @@ export class BergPanelElement extends WebComponent { } else { this.classList.remove(BERG_PANEL_ABSOLUTE_CLASS); - this.timeouts.push( - setTimeout(() => { - this.style.removeProperty('z-index'); - }, BERG_PANEL_BACKDROP_ANIMATION_DURATION) - ); + if (this.style.zIndex === absoluteZIndex) { + this.timeouts.push( + setTimeout(() => { + this.style.removeProperty('z-index'); + }, BERG_PANEL_BACKDROP_ANIMATION_DURATION) + ); + } } }, collapsed: () => { @@ -226,6 +227,7 @@ export class BergPanelElement extends WebComponent { this.classList.remove(BERG_PANEL_NO_TRANSITION_CLASS); } }, + hideBackdrop: () => this.updateBackdrop(), slot: () => { this.classList.remove(...Object.values(BERG_PANEL_CLASSES_BY_SLOT)); this.classList.add(BERG_PANEL_CLASSES_BY_SLOT[this.values.slot]); @@ -256,6 +258,10 @@ export class BergPanelElement extends WebComponent { } private showBackdrop(): void { + if (this.values.hideBackdrop) { + return; + } + const backdrop = this.getBackdropElement(); if (!this.layout.shadowRoot || this.layout.shadowRoot.contains(backdrop)) { diff --git a/libs/react/package.json b/libs/react/package.json index 7074d39..8cea470 100644 --- a/libs/react/package.json +++ b/libs/react/package.json @@ -1,6 +1,6 @@ { "name": "@berg-layout/react", - "version": "5.4.1", + "version": "5.5.0", "license": "MIT", "repository": { "url": "https://github.com/blidblid/berg-layout" diff --git a/libs/react/src/lib/panel/panel.tsx b/libs/react/src/lib/panel/panel.tsx index 93e9d71..6bcceb5 100644 --- a/libs/react/src/lib/panel/panel.tsx +++ b/libs/react/src/lib/panel/panel.tsx @@ -22,6 +22,7 @@ export function BergPanel(props: BergPanelProps) { min-size={props.minSize} max-size={props.maxSize} animation-disabled={props.animationDisabled} + hide-backdrop={props.hideBackdrop} event-binding-mode={props.eventBindingMode} > {props.children} diff --git a/libs/testing/src/lib/run-layout-tests.ts b/libs/testing/src/lib/run-layout-tests.ts index 65458fb..a8482b7 100644 --- a/libs/testing/src/lib/run-layout-tests.ts +++ b/libs/testing/src/lib/run-layout-tests.ts @@ -7,6 +7,8 @@ export const runLayoutTests = ( render: Render ) => { describe('berg layout', () => { + const panelTransitionDuration = 500; + describe('alignment', () => { it('should render top panel above left', async () => { await render({ @@ -261,6 +263,8 @@ export const runLayoutTests = ( }, }); + await harness.tickDuration(panelTransitionDuration); + const backdrop = harness.getAssertedBackdrop('top'); const top = harness.assertedTop; const right = harness.assertedRight; @@ -291,8 +295,7 @@ export const runLayoutTests = ( }, }); - // there is some flake in this spec where the right panel z-index is not updated in time - harness.tickDuration(0); + await harness.tickDuration(panelTransitionDuration); const backdrop = harness.getAssertedBackdrop('right'); const top = harness.assertedTop; @@ -324,6 +327,8 @@ export const runLayoutTests = ( }, }); + await harness.tickDuration(panelTransitionDuration); + const backdrop = harness.getAssertedBackdrop('bottom'); const top = harness.assertedTop; const right = harness.assertedRight; @@ -354,6 +359,8 @@ export const runLayoutTests = ( }, }); + await harness.tickDuration(panelTransitionDuration); + const backdrop = harness.getAssertedBackdrop('left'); const top = harness.assertedTop; const right = harness.assertedRight; @@ -653,8 +660,6 @@ export const runLayoutTests = ( }); describe('with an absolute panel', () => { - const panelTransitionDuration = 500; - it('should create a backdrop that covers the layout', async () => { await render({ top: { @@ -669,6 +674,18 @@ export const runLayoutTests = ( ); }); + it('should not create a backdrop that covers the layout if it is set to be hidden', async () => { + await render({ + top: { + absolute: true, + hideBackdrop: true, + }, + }); + + await harness.tickDuration(panelTransitionDuration); + expect(harness.getBackdrop('top')).toBeNull(); + }); + it('should position top over content', async () => { await render({ top: { @@ -886,7 +903,7 @@ export const runLayoutTests = ( ); }); - fit('should overflow on the y-axis', async () => { + it('should overflow on the y-axis', async () => { await render({ layout: { overflow: 'y',