diff --git a/projects/components/src/overlay/sheet/sheet-overlay.component.scss b/projects/components/src/overlay/sheet/sheet-overlay.component.scss index f0301234c..35bee4c58 100644 --- a/projects/components/src/overlay/sheet/sheet-overlay.component.scss +++ b/projects/components/src/overlay/sheet/sheet-overlay.component.scss @@ -1,10 +1,13 @@ @import 'color-palette'; @import 'font'; +$box-shadow: -3px 0px 24px rgba(0, 0, 0, 0.12), -1px 0px 8px rgba(0, 0, 0, 0.08); + .sheet-overlay { - box-shadow: -3px 1px 24px rgba(0, 0, 0, 0.12), -1px -1px 8px rgba(0, 0, 0, 0.08); + box-shadow: $box-shadow; border-radius: 16px 0 0 16px; height: 100%; + width: 100%; overflow: hidden; padding: 24px; @@ -13,26 +16,6 @@ flex-direction: column; z-index: 1; - &.sheet-size-responsive-extra-large { - width: 100%; - } - - &.sheet-size-small { - width: 320px; - } - - &.sheet-size-medium { - width: 600px; - } - - &.sheet-size-large { - width: 840px; - } - - &.sheet-size-extra-large { - width: 1280px; - } - .header { display: flex; justify-content: space-between; @@ -62,3 +45,24 @@ } } } + +.attached-trigger { + cursor: pointer; + box-shadow: $box-shadow; + clip-path: inset(-20px -20px 0px -20px); + background: white; + width: 200px; + height: 40px; + transform: translate(calc(-50% - 20px), 0px) rotate(270deg); + position: relative; + top: -50%; + border-radius: 6px; + + display: flex; + align-items: center; + padding: 0px 12px; + + .trigger-icon { + margin-right: 14px; + } +} diff --git a/projects/components/src/overlay/sheet/sheet-overlay.component.test.ts b/projects/components/src/overlay/sheet/sheet-overlay.component.test.ts index 5692f2d0c..1e4e18b70 100644 --- a/projects/components/src/overlay/sheet/sheet-overlay.component.test.ts +++ b/projects/components/src/overlay/sheet/sheet-overlay.component.test.ts @@ -48,6 +48,7 @@ describe('Sheet Overlay component', () => { provide: PopoverRef, useValue: { height: jest.fn(), + width: jest.fn(), close: jest.fn() } }, @@ -86,11 +87,39 @@ describe('Sheet Overlay component', () => { expect(spectator.query('.header')).toHaveText('expected title'); }); - test('uses the requested size', () => { + test('uses the requested size for small', () => { + spectator = createConfiguredHost({ + size: SheetSize.Small + }); + expect(spectator.inject(PopoverRef)?.width).toHaveBeenCalledWith('320px'); + }); + + test('uses the requested size for medium', () => { + spectator = createConfiguredHost({ + size: SheetSize.Medium + }); + expect(spectator.inject(PopoverRef)?.width).toHaveBeenCalledWith('600px'); + }); + + test('uses the requested size for large', () => { spectator = createConfiguredHost({ size: SheetSize.Large }); - expect(spectator.query('.sheet-overlay')).toHaveClass('sheet-size-large'); + expect(spectator.inject(PopoverRef)?.width).toHaveBeenCalledWith('840px'); + }); + + test('uses the requested size for extra large', () => { + spectator = createConfiguredHost({ + size: SheetSize.ExtraLarge + }); + expect(spectator.inject(PopoverRef)?.width).toHaveBeenCalledWith('1280px'); + }); + + test('uses the requested size for responsive extra large', () => { + spectator = createConfiguredHost({ + size: SheetSize.ResponsiveExtraLarge + }); + expect(spectator.inject(PopoverRef)?.width).toHaveBeenCalledWith('60%'); }); test('closes on close button click', () => { diff --git a/projects/components/src/overlay/sheet/sheet-overlay.component.ts b/projects/components/src/overlay/sheet/sheet-overlay.component.ts index f9f2e3937..29c4ae51f 100644 --- a/projects/components/src/overlay/sheet/sheet-overlay.component.ts +++ b/projects/components/src/overlay/sheet/sheet-overlay.component.ts @@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, Component, HostListener, Inject, Injector, Tem import { IconType } from '@hypertrace/assets-library'; import { GLOBAL_HEADER_HEIGHT, LayoutChangeService } from '@hypertrace/common'; import { ButtonStyle } from '../../button/button'; +import { IconSize } from '../../icon/icon-size'; import { PopoverFixedPositionLocation, POPOVER_DATA } from '../../popover/popover'; import { PopoverRef } from '../../popover/popover-ref'; import { SheetConstructionData } from '../overlay.service'; @@ -12,29 +13,42 @@ import { SheetOverlayConfig, SheetSize } from './sheet'; styleUrls: ['./sheet-overlay.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, template: ` -
-
-

{{ sheetTitle }}

- - + +
+ +
+

{{ sheetTitle }}

+ + +
+
+
+ + + + + + +
+
+
-
-
- - - - - - -
+
+ +
-
+
` }) export class SheetOverlayComponent { @@ -46,6 +60,8 @@ export class SheetOverlayComponent { public readonly rendererInjector: Injector; public visible: boolean = true; public readonly closeOnEscape: boolean; + public readonly attachedTriggerTemplate?: TemplateRef; + public isViewCollapsed: boolean; public constructor( private readonly popoverRef: PopoverRef, @@ -58,13 +74,13 @@ export class SheetOverlayComponent { this.sheetTitle = sheetConfig.title === undefined ? '' : sheetConfig.title; this.size = sheetConfig.size; this.closeOnEscape = sheetConfig.closeOnEscapeKey ?? true; + this.attachedTriggerTemplate = sheetConfig.attachedTriggerTemplate; + this.isViewCollapsed = !!this.attachedTriggerTemplate; + this.isComponentSheet = !(sheetConfig.content instanceof TemplateRef); this.renderer = sheetConfig.content; this.popoverRef.height(this.getHeightForPopover(globalHeaderHeight, sheetConfig.position)); - - if (this.size === SheetSize.ResponsiveExtraLarge) { - this.popoverRef.width('60%'); - } + this.setWidth(); this.rendererInjector = Injector.create({ providers: [ @@ -89,6 +105,33 @@ export class SheetOverlayComponent { this.popoverRef.close(); } + public toggleCollapseExpand(): void { + this.isViewCollapsed = !this.isViewCollapsed; + + this.setWidth(); + } + + private setWidth(): void { + this.popoverRef.width(this.isViewCollapsed ? '0px' : this.getWidthForPopover()); + } + + private getWidthForPopover(): string { + switch (this.size) { + case SheetSize.Small: + return '320px'; + case SheetSize.Medium: + return '600px'; + case SheetSize.Large: + return '840px'; + case SheetSize.ExtraLarge: + return '1280px'; + case SheetSize.ResponsiveExtraLarge: + return '60%'; + default: + return '100%'; + } + } + private getHeightForPopover(globalHeaderHeight: string, position?: PopoverFixedPositionLocation): string { return position === PopoverFixedPositionLocation.Right ? '100vh' : `calc(100vh - ${globalHeaderHeight})`; } diff --git a/projects/components/src/overlay/sheet/sheet-overlay.module.ts b/projects/components/src/overlay/sheet/sheet-overlay.module.ts index b3cb5887a..2a1d466eb 100644 --- a/projects/components/src/overlay/sheet/sheet-overlay.module.ts +++ b/projects/components/src/overlay/sheet/sheet-overlay.module.ts @@ -1,11 +1,12 @@ import { CommonModule } from '@angular/common'; import { NgModule } from '@angular/core'; import { ButtonModule } from '../../button/button.module'; +import { IconModule } from '../../icon/icon.module'; import { TooltipModule } from '../../tooltip/tooltip.module'; import { SheetOverlayComponent } from './sheet-overlay.component'; @NgModule({ - imports: [CommonModule, ButtonModule, TooltipModule], + imports: [CommonModule, ButtonModule, TooltipModule, IconModule], declarations: [SheetOverlayComponent], exports: [SheetOverlayComponent] }) diff --git a/projects/components/src/overlay/sheet/sheet.ts b/projects/components/src/overlay/sheet/sheet.ts index c76cc2bf5..b6cf343ba 100644 --- a/projects/components/src/overlay/sheet/sheet.ts +++ b/projects/components/src/overlay/sheet/sheet.ts @@ -1,4 +1,4 @@ -import { InjectionToken } from '@angular/core'; +import { InjectionToken, TemplateRef } from '@angular/core'; import { Observable } from 'rxjs'; import { PopoverFixedPositionLocation } from '../../popover/popover'; import { OverlayConfig } from './../overlay'; @@ -8,6 +8,7 @@ export interface SheetOverlayConfig extends OverlayConfig { data?: TData; position?: PopoverFixedPositionLocation.Right | PopoverFixedPositionLocation.RightUnderHeader; closeOnEscapeKey?: boolean; + attachedTriggerTemplate?: TemplateRef; } export const enum SheetSize {