Skip to content

Commit 2204226

Browse files
Christian QuinnChristian Quinn
authored andcommitted
Merge branch 'main' into RemoveLongerTimeDurations
2 parents e694a30 + bbb009b commit 2204226

File tree

5 files changed

+147
-0
lines changed

5 files changed

+147
-0
lines changed
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
@import 'mixins';
2+
3+
.collapsible-sidebar {
4+
height: inherit;
5+
width: 220px;
6+
position: relative;
7+
border: 1px solid $gray-2;
8+
border-radius: 8px;
9+
padding: 8px;
10+
11+
.content {
12+
@include fill-container;
13+
}
14+
15+
&.collapsed {
16+
width: 40px;
17+
18+
.content {
19+
@include center-contents;
20+
21+
* {
22+
transform: rotate(-90deg);
23+
}
24+
}
25+
}
26+
27+
.string-label {
28+
@include body-1-medium($gray-7);
29+
}
30+
31+
.toggle {
32+
position: absolute;
33+
display: flex;
34+
align-items: center;
35+
bottom: clamp(10px, 10%, 72px);
36+
right: -12px;
37+
height: 28px;
38+
width: 12px;
39+
border: 1px solid $gray-2;
40+
border-left-color: white;
41+
border-radius: 0 6px 6px 0;
42+
cursor: pointer;
43+
background: white;
44+
padding-right: 4px;
45+
46+
.icon {
47+
position: relative;
48+
right: 6px;
49+
}
50+
}
51+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { fakeAsync } from '@angular/core/testing';
2+
import { IconType } from '@hypertrace/assets-library';
3+
import { createHostFactory } from '@ngneat/spectator/jest';
4+
import { MockComponent } from 'ng-mocks';
5+
import { IconComponent } from '../icon/icon.component';
6+
import { CollapsibleSidebarComponent } from './collapsible-sidebar.component';
7+
8+
describe('Collapsible Sidebar Component', () => {
9+
const createHost = createHostFactory({
10+
component: CollapsibleSidebarComponent,
11+
shallow: true,
12+
declarations: [MockComponent(IconComponent)]
13+
});
14+
15+
test('should render content correclty', fakeAsync(() => {
16+
const spectator = createHost(
17+
`<ht-collapsible-sidebar label="test-label"><div class="test-content"></div></ht-collapsible-sidebar>`
18+
);
19+
20+
expect(spectator.query(IconComponent)?.icon).toBe(IconType.TriangleRight);
21+
expect(spectator.query('.test-content')).not.toExist();
22+
expect(spectator.query('.string-label')).toHaveText('test-label');
23+
24+
spectator.click(spectator.query('.toggle') as Element);
25+
spectator.tick();
26+
27+
expect(spectator.query(IconComponent)?.icon).toBe(IconType.TriangleLeft);
28+
expect(spectator.query('.test-content')).toExist();
29+
expect(spectator.query('.string-label')).not.toExist();
30+
}));
31+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { ChangeDetectionStrategy, Component, Input, OnChanges, TemplateRef } from '@angular/core';
2+
import { IconType } from '@hypertrace/assets-library';
3+
import { IconSize } from '../icon/icon-size';
4+
5+
@Component({
6+
selector: 'ht-collapsible-sidebar',
7+
styleUrls: ['./collapsible-sidebar.component.scss'],
8+
changeDetection: ChangeDetectionStrategy.OnPush,
9+
template: `
10+
<div class="collapsible-sidebar" [ngClass]="{ collapsed: !this.isExpanded }">
11+
<div class="content">
12+
<ng-container *ngIf="this.isExpanded; else labelTemplate"><ng-content></ng-content></ng-container>
13+
</div>
14+
<ng-template #stringLabelTemplate
15+
><span class="string-label">{{ this.label }}</span></ng-template
16+
>
17+
<ng-template #labelTemplate
18+
><ng-container *ngTemplateOutlet="this.isLabelATemplate ? this.label : stringLabelTemplate"></ng-container
19+
></ng-template>
20+
<div class="toggle" (click)="this.toggleCollapseExpand()">
21+
<ht-icon
22+
class="icon"
23+
[icon]="this.isExpanded ? '${IconType.TriangleLeft}' : '${IconType.TriangleRight}'"
24+
size="${IconSize.Small}"
25+
></ht-icon>
26+
</div>
27+
</div>
28+
`
29+
})
30+
export class CollapsibleSidebarComponent implements OnChanges {
31+
@Input()
32+
public label: string | TemplateRef<unknown> = '';
33+
34+
@Input()
35+
public expanded: boolean = false;
36+
37+
public isExpanded: boolean = false;
38+
39+
public ngOnChanges(): void {
40+
this.isExpanded = this.expanded;
41+
}
42+
43+
public get isLabelATemplate(): boolean {
44+
return typeof this.label !== 'string';
45+
}
46+
47+
public toggleCollapseExpand(): void {
48+
this.isExpanded = !this.isExpanded;
49+
}
50+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { CommonModule } from '@angular/common';
2+
import { NgModule } from '@angular/core';
3+
import { IconModule } from '../icon/icon.module';
4+
import { CollapsibleSidebarComponent } from './collapsible-sidebar.component';
5+
6+
@NgModule({
7+
imports: [CommonModule, IconModule],
8+
declarations: [CollapsibleSidebarComponent],
9+
exports: [CollapsibleSidebarComponent]
10+
})
11+
export class CollapsibleSidebarModule {}

projects/components/src/public-api.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export { ButtonRole, ButtonSize, ButtonStyle } from './button/button';
2020
export * from './checkbox/checkbox.component';
2121
export * from './checkbox/checkbox.module';
2222

23+
// Collapsible sidebar
24+
export * from './collapsible-sidebar/collapsible-sidebar.component';
25+
export * from './collapsible-sidebar/collapsible-sidebar.module';
26+
2327
// Combo Box
2428
export * from './combo-box/combo-box.module';
2529
export * from './combo-box/combo-box.component';

0 commit comments

Comments
 (0)