Skip to content

Commit

Permalink
feat: (Core) introduce dynamic side content (#3625)
Browse files Browse the repository at this point in the history
* in progress

* add documentation

* add tests

* minor

* add default size

* update component selectors

* rename variable

* add utils, fix stackblitz options
  • Loading branch information
dimamarksman committed Oct 26, 2020
1 parent 96d32a0 commit 2532520
Show file tree
Hide file tree
Showing 29 changed files with 988 additions and 1 deletion.
1 change: 1 addition & 0 deletions apps/docs/src/app/core/api-files.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export const API_FILES = {
'CardKpiAnalyticsLabelDirective',
'CardKpiAnalyticsContentDirective'
],
dynamicSideContent: ['DynamicSideContentComponent', 'DynamicSideContentSideComponent', 'DynamicSideContentMainComponent'],
breadcrumb: ['BreadcrumbComponent', 'BreadcrumbItemDirective', 'BreadcrumbLinkDirective'],
busyIndicator: ['BusyIndicatorComponent'],
button: ['ButtonComponent'],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<fd-docs-section-title
id="basic"
componentName="dynamicSideContent"
>
Basic usage
</fd-docs-section-title>
<description>
Use <code>fd-dynamic-side-content</code> component with <code>fd-dynamic-side-content-side</code> for additional
content and
<code>fd-dynamic-side-content-main</code> to hold the main content. By default <code>[position]</code> property is
not defined (<code>'none'</code>) and in this case the side content will be rendered accordingly to the order that
it's projected.
</description>
<component-example>
<fd-dynamic-side-content-basic-example></fd-dynamic-side-content-basic-example>
</component-example>
<code-example [exampleFiles]="basic"></code-example>

<separator></separator>
<fd-docs-section-title
id="positioning"
componentName="dynamicSideContent"
>
Positioning
</fd-docs-section-title>
<description>
Use <code>[position]</code> option to define the position mode for side content. Allowed values are
<code>'left' | 'right' | 'bottom' | 'equalSplit' | 'none'</code>.<br />
Position defined as <code>'left'</code>, <code>'right'</code> or <code>'bottom'</code> takes precedence over content
projection order.<br />
<code>[position]="equalSplit"</code> enables equal split mode which provides users with a 50:50 view of the main
content and side content.
</description>
<component-example>
<fd-dynamic-side-content-positioning-example></fd-dynamic-side-content-positioning-example>
</component-example>
<code-example [exampleFiles]="positioning"></code-example>

<separator></separator>
<fd-docs-section-title
id="size"
componentName="dynamicSideContent"
>
Responsiveness
</fd-docs-section-title>
<description>
Use <code>[size]</code> option to display the dynamic side content on specific screen sizes. Allowed values are
<code>'sm' | 'md' | 'lg' | 'xl'</code>.<br />
Note that according to the design the component looks the same on medium and large screens.
</description>
<component-example>
<fd-dynamic-side-content-size-example></fd-dynamic-side-content-size-example>
</component-example>
<code-example [exampleFiles]="size"></code-example>
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Component } from '@angular/core';

import { ExampleFile } from '../../../documentation/core-helpers/code-example/example-file';

import * as exampleScssCode from '!raw-loader!./examples/dynamic-side-content.component.scss';
import * as basicExampleHtmlCode from '!raw-loader!./examples/dynamic-side-content-basic-example.component.html';
import * as basicExampleTsCode from '!raw-loader!./examples/dynamic-side-content-basic-example.component.ts';
import * as positioningExampleHtmlCode from '!raw-loader!./examples/dynamic-side-content-positioning-example.component.html';
import * as positioningExampleTsCode from '!raw-loader!./examples/dynamic-side-content-positioning-example.component.ts';
import * as sizeExampleHtmlCode from '!raw-loader!./examples/dynamic-side-content-size-example.component.html';
import * as sizeExampleTsCode from '!raw-loader!./examples/dynamic-side-content-size-example.component.ts';

@Component({
templateUrl: './dynamic-side-content-docs.component.html'
})
export class DynamicSideContentDocsComponent {
basic: ExampleFile[] = [
{
language: 'html',
code: basicExampleHtmlCode,
fileName: 'dynamic-side-content-basic-example',
component: 'DynamicSideContentBasicExampleComponent',
typescriptFileCode: basicExampleTsCode,
scssFileCode: exampleScssCode
}
];

positioning: ExampleFile[] = [
{
language: 'html',
code: positioningExampleHtmlCode,
fileName: 'dynamic-side-content-positioning-example',
component: 'DynamicSideContentPositioningExampleComponent',
typescriptFileCode: positioningExampleTsCode,
scssFileCode: exampleScssCode
}
];

size: ExampleFile[] = [
{
language: 'html',
code: sizeExampleHtmlCode,
fileName: 'dynamic-side-content-size-example',
component: 'DynamicSideContentSizeExampleComponent',
typescriptFileCode: sizeExampleTsCode,
scssFileCode: exampleScssCode
}
];
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';

import { DynamicSideContentModule } from '@fundamental-ngx/core';

import { ApiComponent } from '../../../documentation/core-helpers/api/api.component';
import { API_FILES } from '../../api-files';
import { SharedDocumentationPageModule } from '../../../documentation/shared-documentation-page.module';

import { DynamicSideContentHeaderComponent } from './dynamic-side-content-header/dynamic-side-content-header.component';
import { DynamicSideContentDocsComponent } from './dynamic-side-content-docs.component';
import { DynamicSideContentBasicExampleComponent } from './examples/dynamic-side-content-basic-example.component';
import { DynamicSideContentPositioningExampleComponent } from './examples/dynamic-side-content-positioning-example.component';
import { DynamicSideContentSizeExampleComponent } from './examples/dynamic-side-content-size-example.component';

const routes: Routes = [
{
path: '',
component: DynamicSideContentHeaderComponent,
children: [
{ path: '', component: DynamicSideContentDocsComponent },
{ path: 'api', component: ApiComponent, data: { content: API_FILES.dynamicSideContent } }
]
}
];

@NgModule({
imports: [RouterModule.forChild(routes), SharedDocumentationPageModule, DynamicSideContentModule],
exports: [RouterModule],
declarations: [
DynamicSideContentHeaderComponent,
DynamicSideContentDocsComponent,
DynamicSideContentBasicExampleComponent,
DynamicSideContentPositioningExampleComponent,
DynamicSideContentSizeExampleComponent
]
})
export class DynamicSideContentDocsModule {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<header>Dynamic Side Content</header>
<description>
Dynamic side content is a layout control that displays supplemental content in a separate area to support the users'
understanding of the main content displayed.
</description>
<import module="DynamicSideContentModule"></import>

<fd-header-tabs></fd-header-tabs>

<router-outlet></router-outlet>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Component } from '@angular/core';

@Component({
selector: 'app-dynamic-side-content-header',
templateUrl: './dynamic-side-content-header.component.html'
})
export class DynamicSideContentHeaderComponent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<h4>Side content from the left</h4>
<fd-dynamic-side-content>
<fd-dynamic-side-content-side>
<div class="side-content">Side Content</div>
</fd-dynamic-side-content-side>
<fd-dynamic-side-content-main>
<div class="main-content">Main Content</div>
</fd-dynamic-side-content-main>
</fd-dynamic-side-content>

<h4>Side content from the right</h4>
<fd-dynamic-side-content>
<fd-dynamic-side-content-main>
<div class="main-content">Main Content</div>
</fd-dynamic-side-content-main>
<fd-dynamic-side-content-side>
<div class="side-content">Side Content</div>
</fd-dynamic-side-content-side>
</fd-dynamic-side-content>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
selector: 'fd-dynamic-side-content-basic-example',
templateUrl: './dynamic-side-content-basic-example.component.html',
styleUrls: ['./dynamic-side-content.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DynamicSideContentBasicExampleComponent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<h4>Left</h4>
<fd-dynamic-side-content position="left">
<fd-dynamic-side-content-main>
<div class="main-content">Main Content</div>
</fd-dynamic-side-content-main>
<fd-dynamic-side-content-side>
<div class="side-content">Side Content</div>
</fd-dynamic-side-content-side>
</fd-dynamic-side-content>

<h4>Right</h4>
<fd-dynamic-side-content position="right">
<fd-dynamic-side-content-side>
<div class="side-content">Side Content</div>
</fd-dynamic-side-content-side>
<fd-dynamic-side-content-main>
<div class="main-content">Main Content</div>
</fd-dynamic-side-content-main>
</fd-dynamic-side-content>

<h4>Bottom</h4>
<fd-dynamic-side-content position="bottom">
<fd-dynamic-side-content-side>
<div class="side-content">Side Content</div>
</fd-dynamic-side-content-side>
<fd-dynamic-side-content-main>
<div class="main-content">Main Content</div>
</fd-dynamic-side-content-main>
</fd-dynamic-side-content>

<h4>Equal Split</h4>
<fd-dynamic-side-content position="equalSplit">
<fd-dynamic-side-content-side>
<div class="side-content">Side Content</div>
</fd-dynamic-side-content-side>
<fd-dynamic-side-content-main>
<div class="main-content">Main Content</div>
</fd-dynamic-side-content-main>
</fd-dynamic-side-content>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
selector: 'fd-dynamic-side-content-positioning-example',
templateUrl: './dynamic-side-content-positioning-example.component.html',
styleUrls: ['./dynamic-side-content.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DynamicSideContentPositioningExampleComponent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<h4>On extra large screens use size="xl".</h4>
<fd-dynamic-side-content size="xl">
<fd-dynamic-side-content-side>
<div class="side-content">Side Content</div>
</fd-dynamic-side-content-side>
<fd-dynamic-side-content-main>
<div class="main-content">Main Content</div>
</fd-dynamic-side-content-main>
</fd-dynamic-side-content>

<h4>On medium-sized screens use size="md".</h4>
<fd-dynamic-side-content size="md">
<fd-dynamic-side-content-side>
<div class="side-content">Side Content</div>
</fd-dynamic-side-content-side>
<fd-dynamic-side-content-main>
<div class="main-content">Main Content</div>
</fd-dynamic-side-content-main>
</fd-dynamic-side-content>

<h4>On small screens use size="sm" (the side content gets hidden).</h4>
<fd-dynamic-side-content size="sm">
<fd-dynamic-side-content-side>
<div class="side-content">Side Content</div>
</fd-dynamic-side-content-side>
<fd-dynamic-side-content-main>
<div class="main-content">Main Content</div>
</fd-dynamic-side-content-main>
</fd-dynamic-side-content>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Component, ChangeDetectionStrategy } from '@angular/core';

@Component({
selector: 'fd-dynamic-side-content-size-example',
templateUrl: './dynamic-side-content-size-example.component.html',
styleUrls: ['./dynamic-side-content.component.scss'],
changeDetection: ChangeDetectionStrategy.OnPush
})
export class DynamicSideContentSizeExampleComponent {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.side-content,
.main-content {
display: flex;
justify-content: center;
align-items: center;
height: 5rem;
border: 0.0625rem solid var(--sapTile_SeparatorColor, #ccc);
}
7 changes: 7 additions & 0 deletions apps/docs/src/app/core/core-documentation.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ export const ROUTES: Routes = [
path: 'dialog',
loadChildren: () => import('./component-docs/dialog/dialog-docs.module').then((m) => m.DialogDocsModule)
},
{
path: 'dynamic-side-content',
loadChildren: () =>
import('./component-docs/dynamic-side-content/dynamic-side-content-docs.module').then(
(m) => m.DynamicSideContentDocsModule
)
},
{
path: 'file-input',
loadChildren: () =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export class CoreDocumentationComponent extends DocumentationBaseComponent {
];

this.layouts = [
{ url: 'core/dynamic-side-content', name: 'Dynamic Side Content' },
{ url: 'core/fixed-card-layout', name: 'Fixed Card Layout' },
{ url: 'core/layoutPanel', name: 'Layout Panel' },
{ url: 'core/layoutGrid', name: 'Layout Grid' }
Expand Down
1 change: 1 addition & 0 deletions libs/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,3 +63,4 @@ export * from './lib/object-identifier/public_api';
export * from './lib/card/public_api';
export * from './lib/object-number/public_api';
export * from './lib/message-toast/public_api';
export * from './lib/dynamic-side-content/public_api';
19 changes: 19 additions & 0 deletions libs/core/src/lib/dynamic-side-content/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { InjectionToken } from '@angular/core';

export const CLASS_NAME = {
container: 'fd-dynamic-side',
containerSizeSm: 'fd-dynamic-side--sm',
containerSizeMd: 'fd-dynamic-side--md',
containerSizeXl: 'fd-dynamic-side--xl',
containerSideBelow: 'fd-dynamic-side--below',
containerSideEqual: 'fd-dynamic-side--equal-split',

side: 'fd-dynamic-side__side',
main: 'fd-dynamic-side__main'
} as const;

export type DynamicSideContentPosition = 'left' | 'right' | 'bottom' | 'equalSplit' | 'none';

export type DynamicSideContentSize = 'sm' | 'md' | 'lg' | 'xl';

export const DYNAMIC_SIDE_CONTENT_CHILD_TOKEN = new InjectionToken<string>('DYNAMIC_SIDE_CONTENT_CHILDREN_TOKEN');
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { CommonModule } from '@angular/common';

import { DynamicSideContentMainComponent } from './dynamic-side-content-main.component';
import { CLASS_NAME } from './constants';

describe('DynamicSideContentMainComponent', () => {
let fixture: ComponentFixture<DynamicSideContentMainComponent>;
let component: DynamicSideContentMainComponent;

beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [CommonModule],
declarations: [DynamicSideContentMainComponent]
}).compileComponents();
}));

beforeEach(() => {
fixture = TestBed.createComponent(DynamicSideContentMainComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(fixture).toBeTruthy();
});

it('should add className to host', () => {
expect(fixture.debugElement.classes[CLASS_NAME.main]).toBeTrue();
});
});

0 comments on commit 2532520

Please sign in to comment.