Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
@import 'mixins';

.collapsible-sidebar {
height: inherit;
width: 220px;
position: relative;
border: 1px solid $gray-2;
border-radius: 8px;
padding: 8px;

.content {
@include fill-container;
}

&.collapsed {
width: 40px;

.content {
@include center-contents;

* {
transform: rotate(-90deg);
}
}
}

.string-label {
@include body-1-medium($gray-7);
}

.toggle {
position: absolute;
display: flex;
align-items: center;
bottom: clamp(10px, 10%, 72px);
right: -12px;
height: 28px;
width: 12px;
border: 1px solid $gray-2;
border-left-color: white;
border-radius: 0 6px 6px 0;
cursor: pointer;
background: white;
padding-right: 4px;

.icon {
position: relative;
right: 6px;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { fakeAsync } from '@angular/core/testing';
import { IconType } from '@hypertrace/assets-library';
import { createHostFactory } from '@ngneat/spectator/jest';
import { MockComponent } from 'ng-mocks';
import { IconComponent } from '../icon/icon.component';
import { CollapsibleSidebarComponent } from './collapsible-sidebar.component';

describe('Collapsible Sidebar Component', () => {
const createHost = createHostFactory({
component: CollapsibleSidebarComponent,
shallow: true,
declarations: [MockComponent(IconComponent)]
});

test('should render content correclty', fakeAsync(() => {
const spectator = createHost(
`<ht-collapsible-sidebar label="test-label"><div class="test-content"></div></ht-collapsible-sidebar>`
);

expect(spectator.query(IconComponent)?.icon).toBe(IconType.TriangleRight);
expect(spectator.query('.test-content')).not.toExist();
expect(spectator.query('.string-label')).toHaveText('test-label');

spectator.click(spectator.query('.toggle') as Element);
spectator.tick();

expect(spectator.query(IconComponent)?.icon).toBe(IconType.TriangleLeft);
expect(spectator.query('.test-content')).toExist();
expect(spectator.query('.string-label')).not.toExist();
}));
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { ChangeDetectionStrategy, Component, Input, OnChanges, TemplateRef } from '@angular/core';
import { IconType } from '@hypertrace/assets-library';
import { IconSize } from '../icon/icon-size';

@Component({
selector: 'ht-collapsible-sidebar',
styleUrls: ['./collapsible-sidebar.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush,
template: `
<div class="collapsible-sidebar" [ngClass]="{ collapsed: !this.isExpanded }">
<div class="content">
<ng-container *ngIf="this.isExpanded; else labelTemplate"><ng-content></ng-content></ng-container>
</div>
<ng-template #stringLabelTemplate
><span class="string-label">{{ this.label }}</span></ng-template
>
<ng-template #labelTemplate
><ng-container *ngTemplateOutlet="this.isLabelATemplate ? this.label : stringLabelTemplate"></ng-container
></ng-template>
<div class="toggle" (click)="this.toggleCollapseExpand()">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you could add another input for setting the position(top/bottom) of the toggle button/icon, then we can use this component in our navigation list component

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I thought of doing that, but since this is a full border component, we need to do some style changes as well but we can iterate over it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

makes sense. please create a tech debt
cc @Christian862

<ht-icon
class="icon"
[icon]="this.isExpanded ? '${IconType.TriangleLeft}' : '${IconType.TriangleRight}'"
size="${IconSize.Small}"
></ht-icon>
</div>
</div>
`
})
export class CollapsibleSidebarComponent implements OnChanges {
@Input()
public label: string | TemplateRef<unknown> = '';

@Input()
public expanded: boolean = false;

public isExpanded: boolean = false;

public ngOnChanges(): void {
this.isExpanded = this.expanded;
}

public get isLabelATemplate(): boolean {
return typeof this.label !== 'string';
}

public toggleCollapseExpand(): void {
this.isExpanded = !this.isExpanded;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { IconModule } from '../icon/icon.module';
import { CollapsibleSidebarComponent } from './collapsible-sidebar.component';

@NgModule({
imports: [CommonModule, IconModule],
declarations: [CollapsibleSidebarComponent],
exports: [CollapsibleSidebarComponent]
})
export class CollapsibleSidebarModule {}
4 changes: 4 additions & 0 deletions projects/components/src/public-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ export { ButtonRole, ButtonSize, ButtonStyle } from './button/button';
export * from './checkbox/checkbox.component';
export * from './checkbox/checkbox.module';

// Collapsible sidebar
export * from './collapsible-sidebar/collapsible-sidebar.component';
export * from './collapsible-sidebar/collapsible-sidebar.module';

// Combo Box
export * from './combo-box/combo-box.module';
export * from './combo-box/combo-box.component';
Expand Down