DropdownModule,
SelectModule,
ComboBoxModule,
- ProgressIndicatorModule
+ ProgressIndicatorModule,
+ PanelModule
} from 'carbon-components-angular';
import { MotdComponent } from '~/app/shared/components/motd/motd.component';
import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset/form-advanced-fieldset.component';
import { UpgradableComponent } from './upgradable/upgradable.component';
import { ProgressComponent } from './progress/progress.component';
+import { SidePanelComponent } from './side-panel/side-panel.component';
// Icons
import InfoIcon from '@carbon/icons/es/information/16';
SelectModule,
ComboBoxModule,
ProgressIndicatorModule,
- BaseChartDirective
+ BaseChartDirective,
+ PanelModule
],
declarations: [
SparklineComponent,
HelpTextComponent,
FormAdvancedFieldsetComponent,
UpgradableComponent,
- ProgressComponent
+ ProgressComponent,
+ SidePanelComponent
],
providers: [provideCharts(withDefaultRegisterables())],
exports: [
HelpTextComponent,
FormAdvancedFieldsetComponent,
UpgradableComponent,
- ProgressComponent
+ ProgressComponent,
+ SidePanelComponent
]
})
export class ComponentsModule {
--- /dev/null
+<div class="overlay"
+ (click)="close()"
+ *ngIf="expanded && overlay"></div>
+
+<cds-panel [expanded]="expanded"
+ [attr.panel-size]="size">
+ <cds-icon-button
+ kind="ghost"
+ class="float-end"
+ title="Close"
+ (click)="close()">
+ <svg
+ class="cds--btn__icon"
+ cdsIcon="close"></svg>
+ </cds-icon-button>
+
+ <div
+ class="panel-header spacing-03"
+ *ngIf="headerText">
+ {{ headerText }}
+ </div>
+
+ <div class="spacing-03">
+ <ng-content select=".panel-content"></ng-content>
+ </div>
+</cds-panel>
--- /dev/null
+@use './src/styles/vendor/variables' as vv;
+
+:host ::ng-deep cds-panel {
+ &[panel-size='sm'] .cds--header-panel--expanded {
+ inline-size: 20rem;
+ }
+
+ &[panel-size='md'] .cds--header-panel--expanded {
+ inline-size: 30rem;
+ }
+
+ &[panel-size='lg'] .cds--header-panel--expanded {
+ inline-size: 40rem;
+ }
+
+ .cds--header-panel--expanded {
+ background-color: vv.$white;
+ max-inline-size: 100%;
+ }
+}
+
+.overlay {
+ background-color: vv.$side-panel-overlay-bg;
+ bottom: 0;
+ left: 0;
+ position: fixed;
+ right: 0;
+ top: 0;
+ z-index: 1000;
+}
--- /dev/null
+import { ComponentFixture, TestBed } from '@angular/core/testing';
+
+import { SidePanelComponent } from './side-panel.component';
+import { configureTestBed } from '~/testing/unit-test-helper';
+
+describe('SidePanelComponent', () => {
+ let component: SidePanelComponent;
+ let fixture: ComponentFixture<SidePanelComponent>;
+
+ configureTestBed({
+ declarations: [SidePanelComponent]
+ });
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(SidePanelComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create', () => {
+ expect(component).toBeTruthy();
+ });
+
+ it('should show overlay only when expanded is true and slideOver is false', () => {
+ component.expanded = true;
+ component.overlay = true;
+ fixture.detectChanges();
+
+ const overlay = fixture.nativeElement.querySelector('.overlay');
+ expect(overlay).toBeTruthy();
+ });
+
+ it('should call close when overlay is clicked', () => {
+ spyOn(component, 'close');
+ component.expanded = true;
+ component.overlay = true;
+ fixture.detectChanges();
+
+ const overlay = fixture.nativeElement.querySelector('.overlay');
+ overlay.click();
+ expect(component.close).toHaveBeenCalled();
+ });
+
+ it('should call close when close button is clicked', () => {
+ spyOn(component, 'close');
+ component.expanded = true;
+ fixture.detectChanges();
+
+ const button = fixture.nativeElement.querySelector('cds-icon-button');
+ button.click();
+ expect(component.close).toHaveBeenCalled();
+ });
+
+ it('should show header text when headerText is provided', () => {
+ component.headerText = 'Test header text';
+ fixture.detectChanges();
+
+ const header = fixture.nativeElement.querySelector('.panel-header');
+ expect(header.textContent).toContain('Test header text');
+ });
+});
--- /dev/null
+import { Component, EventEmitter, Input, Output } from '@angular/core';
+
+@Component({
+ selector: 'cd-side-panel',
+ templateUrl: './side-panel.component.html',
+ styleUrl: './side-panel.component.scss'
+})
+export class SidePanelComponent {
+ @Input() expanded = false;
+ @Input() headerText = '';
+ @Input() overlay = true;
+ @Input() size: 'sm' | 'md' | 'lg' = 'lg';
+
+ @Output() closed = new EventEmitter<void>();
+
+ close() {
+ this.closed.emit();
+ }
+}
/******************************************
Forms
******************************************/
-.form-header {
+.form-header,
+.panel-header {
@include type.type-style('heading-04');
margin-bottom: 40px;
}
// Color system
+@use '@carbon/colors';
$white: #fff !default;
$gray-100: #f8f9fa !default;
$tooltip-bg: $body-color !default;
$tooltip-opacity: 1 !default;
+// Side panel
+$side-panel-overlay-bg: rgba(colors.$gray-100, 50%) !default;
+
// Misc
$screen-sm-min: 576px !default;