Skip to content

Commit 6df194f

Browse files
authored
Merge pull request ceph#63872 from rhcs-dashboard/side-panel-carbon
mgr/dashboard: introduce side panel as a reusable component
2 parents edf8b22 + 36a2cce commit 6df194f

File tree

7 files changed

+151
-5
lines changed

7 files changed

+151
-5
lines changed

src/pybind/mgr/dashboard/frontend/src/app/shared/components/components.module.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ import {
3535
DropdownModule,
3636
SelectModule,
3737
ComboBoxModule,
38-
ProgressIndicatorModule
38+
ProgressIndicatorModule,
39+
PanelModule
3940
} from 'carbon-components-angular';
4041

4142
import { MotdComponent } from '~/app/shared/components/motd/motd.component';
@@ -80,6 +81,7 @@ import { HelpTextComponent } from './help-text/help-text.component';
8081
import { FormAdvancedFieldsetComponent } from './form-advanced-fieldset/form-advanced-fieldset.component';
8182
import { UpgradableComponent } from './upgradable/upgradable.component';
8283
import { ProgressComponent } from './progress/progress.component';
84+
import { SidePanelComponent } from './side-panel/side-panel.component';
8385

8486
// Icons
8587
import InfoIcon from '@carbon/icons/es/information/16';
@@ -122,7 +124,8 @@ import CopyIcon from '@carbon/icons/es/copy/32';
122124
SelectModule,
123125
ComboBoxModule,
124126
ProgressIndicatorModule,
125-
BaseChartDirective
127+
BaseChartDirective,
128+
PanelModule
126129
],
127130
declarations: [
128131
SparklineComponent,
@@ -164,7 +167,8 @@ import CopyIcon from '@carbon/icons/es/copy/32';
164167
HelpTextComponent,
165168
FormAdvancedFieldsetComponent,
166169
UpgradableComponent,
167-
ProgressComponent
170+
ProgressComponent,
171+
SidePanelComponent
168172
],
169173
providers: [provideCharts(withDefaultRegisterables())],
170174
exports: [
@@ -203,7 +207,8 @@ import CopyIcon from '@carbon/icons/es/copy/32';
203207
HelpTextComponent,
204208
FormAdvancedFieldsetComponent,
205209
UpgradableComponent,
206-
ProgressComponent
210+
ProgressComponent,
211+
SidePanelComponent
207212
]
208213
})
209214
export class ComponentsModule {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<div class="overlay"
2+
(click)="close()"
3+
*ngIf="expanded && overlay"></div>
4+
5+
<cds-panel [expanded]="expanded"
6+
[attr.panel-size]="size">
7+
<cds-icon-button
8+
kind="ghost"
9+
class="float-end"
10+
title="Close"
11+
(click)="close()">
12+
<svg
13+
class="cds--btn__icon"
14+
cdsIcon="close"></svg>
15+
</cds-icon-button>
16+
17+
<div
18+
class="panel-header spacing-03"
19+
*ngIf="headerText">
20+
{{ headerText }}
21+
</div>
22+
23+
<div class="spacing-03">
24+
<ng-content select=".panel-content"></ng-content>
25+
</div>
26+
</cds-panel>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
@use './src/styles/vendor/variables' as vv;
2+
3+
:host ::ng-deep cds-panel {
4+
&[panel-size='sm'] .cds--header-panel--expanded {
5+
inline-size: 20rem;
6+
}
7+
8+
&[panel-size='md'] .cds--header-panel--expanded {
9+
inline-size: 30rem;
10+
}
11+
12+
&[panel-size='lg'] .cds--header-panel--expanded {
13+
inline-size: 40rem;
14+
}
15+
16+
.cds--header-panel--expanded {
17+
background-color: vv.$white;
18+
max-inline-size: 100%;
19+
}
20+
}
21+
22+
.overlay {
23+
background-color: vv.$side-panel-overlay-bg;
24+
bottom: 0;
25+
left: 0;
26+
position: fixed;
27+
right: 0;
28+
top: 0;
29+
z-index: 1000;
30+
}
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { SidePanelComponent } from './side-panel.component';
4+
import { configureTestBed } from '~/testing/unit-test-helper';
5+
6+
describe('SidePanelComponent', () => {
7+
let component: SidePanelComponent;
8+
let fixture: ComponentFixture<SidePanelComponent>;
9+
10+
configureTestBed({
11+
declarations: [SidePanelComponent]
12+
});
13+
14+
beforeEach(() => {
15+
fixture = TestBed.createComponent(SidePanelComponent);
16+
component = fixture.componentInstance;
17+
fixture.detectChanges();
18+
});
19+
20+
it('should create', () => {
21+
expect(component).toBeTruthy();
22+
});
23+
24+
it('should show overlay only when expanded is true and slideOver is false', () => {
25+
component.expanded = true;
26+
component.overlay = true;
27+
fixture.detectChanges();
28+
29+
const overlay = fixture.nativeElement.querySelector('.overlay');
30+
expect(overlay).toBeTruthy();
31+
});
32+
33+
it('should call close when overlay is clicked', () => {
34+
spyOn(component, 'close');
35+
component.expanded = true;
36+
component.overlay = true;
37+
fixture.detectChanges();
38+
39+
const overlay = fixture.nativeElement.querySelector('.overlay');
40+
overlay.click();
41+
expect(component.close).toHaveBeenCalled();
42+
});
43+
44+
it('should call close when close button is clicked', () => {
45+
spyOn(component, 'close');
46+
component.expanded = true;
47+
fixture.detectChanges();
48+
49+
const button = fixture.nativeElement.querySelector('cds-icon-button');
50+
button.click();
51+
expect(component.close).toHaveBeenCalled();
52+
});
53+
54+
it('should show header text when headerText is provided', () => {
55+
component.headerText = 'Test header text';
56+
fixture.detectChanges();
57+
58+
const header = fixture.nativeElement.querySelector('.panel-header');
59+
expect(header.textContent).toContain('Test header text');
60+
});
61+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { Component, EventEmitter, Input, Output } from '@angular/core';
2+
3+
@Component({
4+
selector: 'cd-side-panel',
5+
templateUrl: './side-panel.component.html',
6+
styleUrl: './side-panel.component.scss'
7+
})
8+
export class SidePanelComponent {
9+
@Input() expanded = false;
10+
@Input() headerText = '';
11+
@Input() overlay = true;
12+
@Input() size: 'sm' | 'md' | 'lg' = 'lg';
13+
14+
@Output() closed = new EventEmitter<void>();
15+
16+
close() {
17+
this.closed.emit();
18+
}
19+
}

src/pybind/mgr/dashboard/frontend/src/styles/_carbon-defaults.scss

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ Overflow menu
8787
/******************************************
8888
Forms
8989
******************************************/
90-
.form-header {
90+
.form-header,
91+
.panel-header {
9192
@include type.type-style('heading-04');
9293
margin-bottom: 40px;
9394
}

src/pybind/mgr/dashboard/frontend/src/styles/defaults/_bootstrap-defaults.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// Color system
2+
@use '@carbon/colors';
23

34
$white: #fff !default;
45
$gray-100: #f8f9fa !default;
@@ -140,6 +141,9 @@ $tooltip-color: $white !default;
140141
$tooltip-bg: $body-color !default;
141142
$tooltip-opacity: 1 !default;
142143

144+
// Side panel
145+
$side-panel-overlay-bg: rgba(colors.$gray-100, 50%) !default;
146+
143147
// Misc
144148

145149
$screen-sm-min: 576px !default;

0 commit comments

Comments
 (0)