Skip to content

Commit

Permalink
feat(components): enable theming of SCION components
Browse files Browse the repository at this point in the history
SCION provides a set of design tokens to enable consistent design and theming of SCION components. Design tokens are provided by the  `@scion/components` SCSS module in the form of a light and dark theme. Applications can customize or replace the built-in themes.
See [SCION Design Tokens](https://github.com/SchweizerischeBundesbahnen/scion-toolkit/blob/master/docs/site/scion-design-tokens.md) for more information.

BREAKING CHANGE: Theming of SCION components has introduced deprecations that will break in the next major release.

To migrate:
  - Import the `@scion/components` SCSS module in `styles.scss`. Optionally, pass a configuration to customize the default look of SCION components or to support multiple themes. See [SCION Design Tokens](https://github.com/SchweizerischeBundesbahnen/scion-toolkit/blob/master/docs/site/scion-design-tokens.md) for more information. Note that this step is not required if using `@scion/workbench` as imported by the SCION Workbench.
  - For consistency, following CSS variables for styling the `sci-splitter` and `sci-sashbox` components have been renamed:
    - `--sci-splitter-bgcolor` ➜ `--sci-splitter-background-color`
    - `--sci-splitter-bgcolor_hover` ➜ `--sci-splitter-background-color-hover`
    - `--sci-splitter-size_hover` ➜ `--sci-splitter-size-hover`
    - `--sci-splitter-opacity_active` ➜ `--sci-splitter-opacity-active`
    - `--sci-splitter-opacity_hover` ➜ `--sci-splitter-opacity-hover`
    - `--sci-sashbox-splitter-bgcolor` ➜ `--sci-sashbox-splitter-background-color`
    - `--sci-sashbox-splitter-size_hover` ➜ `--sci-sashbox-splitter-size-hover`
    - `--sci-sashbox-splitter-opacity_hover` ➜ `--sci-sashbox-splitter-opacity-hover`
    - `--sci-sashbox-splitter-bgcolor_hover` ➜ `--sci-sashbox-splitter-background-color-hover`
    - `--sci-sashbox-splitter-opacity_active` ➜ `--sci-sashbox-splitter-opacity-active`
  - Scrollbar-related mixins have been moved to the `@scion/components/scrollbar` SCSS module. Migrate as follows:
     **Before:**
     ```scss
     @use '@scion/components' as sci-components;
     @include sci-components.scrollbar-hide-when-inactive()
     @include sci-components.scrollbar-position()
     ```
     **After:**
     ```scss
     @use '@scion/components/scrollbar' as sci-scrollbar;
     @include sci-scrollbar.scrollbar-hide-when-inactive()
     @include sci-scrollbar.scrollbar-position()
     ```
  • Loading branch information
danielwiehl committed Oct 9, 2023
1 parent 9fed733 commit a24c3a4
Show file tree
Hide file tree
Showing 114 changed files with 2,408 additions and 1,313 deletions.
12 changes: 11 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,17 @@
"plugin:@angular-eslint/template/recommended",
"plugin:@angular-eslint/template/accessibility"
],
"rules": {}
"rules": {
"@angular-eslint/template/label-has-associated-control": [
"error",
{
"controlComponents": [
"sci-checkbox",
"sci-toggle-button"
]
}
]
}
}
]
}
3 changes: 2 additions & 1 deletion angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@
],
"stylePreprocessorOptions": {
"includePaths": [
"projects/scion/components"
"projects/scion/components",
"projects/scion/components.internal"
]
},
"scripts": []
Expand Down
23 changes: 15 additions & 8 deletions apps/components/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
<nav>
<a *ngFor="let tool of tools$ | async"
[routerLink]="tool.routerPath"
[queryParamsHandling]="'merge'"
[class.internal]="tool.internal">
{{tool.name}}
</a>
</nav>
<header>
<nav>
<a *ngFor="let tool of tools$ | async"
[routerLink]="tool.routerPath"
[queryParamsHandling]="'merge'"
[class.internal]="tool.internal">
{{tool.name}}
</a>
</nav>
<div class="theme-switcher">
<button (click)="onActivateDarkTheme()" sciMaterialIcon>dark_mode</button>
<sci-toggle-button [formControl]="lightThemeFormControl"></sci-toggle-button>
<button (click)="onActivateLightTheme()" sciMaterialIcon>light_mode</button>
</div>
</header>

<main>
<router-outlet></router-outlet>
Expand Down
30 changes: 18 additions & 12 deletions apps/components/src/app/app.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,37 @@
display: flex;
flex-direction: column;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
inset: 0;

> nav {
> header {
flex: none;
border-bottom: 1px solid var(--sci-color-A900);
background-color: var(--sci-color-A800);
box-shadow: 0 0 3px 0 var(--sci-color-primary);
display: flex;
background-color: var(--sci-color-background-secondary);
border-bottom: 1px solid var(--sci-color-border);
padding: .25em 1em;
justify-content: space-between;
align-items: center;

> a {
color: var(--sci-color-A50);
> nav > a {
color: var(--sci-color-text);

&:not(:last-child)::after {
content: '|';
padding: 0 .5em;
color: var(--sci-color-A50);
color: var(--sci-color-text);
}

&.internal {
color: var(--sci-color-W400);
font-style: italic;
}
}

> div.theme-switcher {
display: flex;
gap: .25em;
align-items: center;
user-select: none;
}
}

> main {
Expand Down
45 changes: 41 additions & 4 deletions apps/components/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,18 @@
*
* SPDX-License-Identifier: EPL-2.0
*/
import {Component} from '@angular/core';
import {Component, inject} from '@angular/core';
import {ActivatedRoute, Router, RouterLink, RouterOutlet} from '@angular/router';
import {map} from 'rxjs/operators';
import {Observable} from 'rxjs';
import {coerceBooleanProperty} from '@angular/cdk/coercion';
import {sortArray} from '@scion/toolkit/operators';
import {AsyncPipe, NgFor} from '@angular/common';
import {SciMaterialIconDirective} from '@scion/components.internal/material-icon';
import {SciToggleButtonComponent} from '@scion/components.internal/toggle-button';
import {FormControl, ReactiveFormsModule} from '@angular/forms';
import {ThemeSwitcher} from './theme-switcher.service';
import {takeUntilDestroyed} from '@angular/core/rxjs-interop';

@Component({
selector: 'app-root',
Expand All @@ -25,14 +30,32 @@ import {AsyncPipe, NgFor} from '@angular/common';
AsyncPipe,
RouterLink,
RouterOutlet,
ReactiveFormsModule,
SciMaterialIconDirective,
SciToggleButtonComponent,
],
})
export class AppComponent {

public tools$: Observable<Tool[]>;
protected readonly tools$: Observable<Tool[]>;
protected readonly lightThemeFormControl = new FormControl<boolean>(true);

constructor(router: Router, activatedRoute: ActivatedRoute) {
this.tools$ = activatedRoute.queryParamMap
constructor(private _themeSwitcher: ThemeSwitcher) {
this.tools$ = this.observeTools$();
this.installThemeSwitcher();
}

protected onActivateLightTheme(): void {
this.lightThemeFormControl.setValue(true);
}

protected onActivateDarkTheme(): void {
this.lightThemeFormControl.setValue(false);
}

private observeTools$(): Observable<Tool[]> {
const router = inject(Router);
return inject(ActivatedRoute).queryParamMap
.pipe(
map(params => coerceBooleanProperty(params.get('internal'))),
map(includeInternalTools => router.config
Expand All @@ -47,6 +70,20 @@ export class AppComponent {
sortArray((tool1, tool2) => Number(tool1.internal) - Number(tool2.internal)),
);
}

private installThemeSwitcher(): void {
this._themeSwitcher.theme$
.pipe(takeUntilDestroyed())
.subscribe(theme => {
this.lightThemeFormControl.setValue(theme === 'scion-light', {emitEvent: false});
});

this.lightThemeFormControl.valueChanges
.pipe(takeUntilDestroyed())
.subscribe(lightTheme => {
this._themeSwitcher.switchTheme(lightTheme ? 'scion-light' : 'scion-dark');
});
}
}

export interface Tool {
Expand Down
13 changes: 9 additions & 4 deletions apps/components/src/app/app.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ export const routes: Routes = [
data: {internal: true},
},
{
path: 'sci-checkbox',
loadComponent: () => import('./sci-checkbox-page/sci-checkbox-page.component'),
path: 'sci-tabbar',
loadComponent: () => import('./sci-tabbar-page/sci-tabbar-page.component'),
data: {internal: true},
},
{
path: 'sci-tabbar',
loadComponent: () => import('./sci-tabbar-page/sci-tabbar-page.component'),
path: 'sci-checkbox',
loadComponent: () => import('./sci-checkbox-page/sci-checkbox-page.component'),
data: {internal: true},
},
{
Expand All @@ -75,4 +75,9 @@ export const routes: Routes = [
loadComponent: () => import('./sci-toggle-button-page/sci-toggle-button-page.component'),
data: {internal: true},
},
{
path: 'sci-styles',
loadComponent: () => import('./sci-styles-page/sci-styles-page.component'),
data: {internal: true},
},
];
Original file line number Diff line number Diff line change
@@ -1,32 +1,36 @@
<h1>sci-accordion (ɵ)</h1>
<main>
<h1>sci-accordion (ɵ)</h1>

<form [formGroup]="form">
<section class="settings">
<header>Settings</header>
<sci-accordion [variant]="form.controls.variant.value" [multi]="form.controls.multi.value">
<ng-container *ngFor="let item of items">
<!-- item -->
<ng-template sciAccordionItem [panel]="panel">
<header>{{item.title}}</header>
</ng-template>

<sci-form-field label="Variant">
<select [formControl]="form.controls.variant">
<option value="solid">solid</option>
<option value="bubble">bubble</option>
</select>
</sci-form-field>
<!-- item panel -->
<ng-template #panel>
{{item.description}}
</ng-template>
</ng-container>
</sci-accordion>
</main>

<sci-form-field label="Multi">
<sci-checkbox [formControl]="form.controls.multi"></sci-checkbox>
</sci-form-field>
</section>
</form>
<aside [formGroup]="form">
<sci-tabbar>
<ng-template sciTab label="Settings">
<div class="tab">
<sci-form-field label="Variant">
<select [formControl]="form.controls.variant">
<option value="solid">solid</option>
<option value="bubble">bubble</option>
</select>
</sci-form-field>

<sci-accordion [variant]="form.controls.variant.value" [multi]="form.controls.multi.value">
<ng-container *ngFor="let item of items">
<!-- item -->
<ng-template sciAccordionItem [panel]="panel">
<header>{{item.title}}</header>
<sci-form-field label="Multi">
<sci-checkbox [formControl]="form.controls.multi"></sci-checkbox>
</sci-form-field>
</div>
</ng-template>

<!-- item panel -->
<ng-template #panel>
{{item.description}}
</ng-template>
</ng-container>
</sci-accordion>
</sci-tabbar>
</aside>
Original file line number Diff line number Diff line change
@@ -1,44 +1,28 @@
@mixin panel {
display: grid;
gap: 1em;
grid-template-columns: 1fr;
grid-auto-rows: max-content;
border: 1px solid var(--sci-color-P400);
border-radius: 5px;
padding: 1em;

> header {
font-weight: bold;
margin-bottom: 1em;
}
}

:host {
display: flex;
flex-direction: column;

> h1 {
flex: none;
}
gap: 1em;

> form {
flex: none;
display: grid;
grid-auto-rows: max-content;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
> main {
flex: auto;
display: flex;
flex-direction: column;
gap: 1em;
margin-bottom: 2em;

> section.settings {
@include panel;
}
}

> sci-accordion {
> aside {
flex: none;
display: grid;
border: 1px solid var(--sci-color-border);
border-radius: var(--sci-corner);
background-color: var(--sci-color-background-secondary);
padding: 1em;
min-width: 350px;

&.solid header {
font-weight: bold;
> sci-tabbar div.tab {
display: flex;
flex-direction: column;
gap: 1em;
padding: .25em;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {NgFor} from '@angular/common';
import {SciFormFieldComponent} from '@scion/components.internal/form-field';
import {SciCheckboxComponent} from '@scion/components.internal/checkbox';
import {SciAccordionComponent, SciAccordionItemDirective} from '@scion/components.internal/accordion';
import {SciTabbarComponent, SciTabDirective} from '@scion/components.internal/tabbar';

@Component({
selector: 'sci-accordion-page',
Expand All @@ -26,6 +27,8 @@ import {SciAccordionComponent, SciAccordionItemDirective} from '@scion/component
SciCheckboxComponent,
SciAccordionComponent,
SciAccordionItemDirective,
SciTabDirective,
SciTabbarComponent,
],
})
export default class SciAccordionPageComponent {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
<h1>sci-checkbox (ɵ)</h1>
<main>
<h1>sci-checkbox (ɵ)</h1>

<h2>enabled</h2>
<sci-checkbox [disabled]="false"></sci-checkbox>
<sci-checkbox [formControl]="form.controls.checkbox"></sci-checkbox>
</main>

<h2>disabled</h2>
<sci-checkbox [disabled]="true"></sci-checkbox>
<aside [formGroup]="form">
<sci-tabbar>
<ng-template sciTab label="State">
<div class="tab">
<label>
<sci-checkbox [formControl]="form.controls.state.controls.disabled"></sci-checkbox>
Disabled
</label>
</div>
</ng-template>
</sci-tabbar>
</aside>
Loading

0 comments on commit a24c3a4

Please sign in to comment.