Skip to content

Commit

Permalink
feat(core)!: Loader has new algorithm to calculate stroke-width (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
nsbarsukov authored Jan 29, 2024
1 parent 4cea4ea commit 6132683
Show file tree
Hide file tree
Showing 9 changed files with 116 additions and 57 deletions.
1 change: 1 addition & 0 deletions projects/core/components/loader/loader.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import {TUI_LOADER_OPTIONS, TuiLoaderOptions} from './loader.options';
})
export class TuiLoaderComponent {
@Input()
@HostBinding('attr.data-size')
size = this.options.size;

@Input()
Expand Down
97 changes: 45 additions & 52 deletions projects/core/components/loader/loader.style.less
Original file line number Diff line number Diff line change
@@ -1,26 +1,49 @@
@import '@taiga-ui/core/styles/taiga-ui-local';

@size-xs: 0.75rem;
@size-s: 1rem;
@size-m: 1.5rem;
@size-l: 2.5rem;
@size-xl: 3.5rem;
@size-xxl: 5rem;
@width-xs: 38;
@width-s: 25;
@width-m: 17;
@width-l: 15;
@width-xl: 14;
@width-xxl: 10;
// Safari doesn't support rem units for all properties of `<circle />`.
// `<circle />`'s wrapper has `font-size: 1rem` to use em units as rem ones interchangeably
@circle-diameter: {
xs: 0.75em;
s: 1em;
m: 1.5em;
l: 2.5em;
xl: 3.5em;
xxl: 5em;
};

:host {
position: relative;
display: flex;
min-width: 1.5rem;
--tui-thickness: calc(var(--t-diameter) / 12);

&._loading {
overflow: hidden;
}

&[data-size='xs'] {
--t-diameter: @circle-diameter[xs];
}

&[data-size='s'] {
--t-diameter: @circle-diameter[s];
}

&[data-size='m'] {
--t-diameter: @circle-diameter[m];
}

&[data-size='l'] {
--t-diameter: @circle-diameter[l];
}

&[data-size='xl'] {
--t-diameter: @circle-diameter[xl];
}

&[data-size='xxl'] {
--t-diameter: @circle-diameter[xxl];
}
}

.t-content {
Expand Down Expand Up @@ -48,11 +71,13 @@
align-items: center;
justify-content: center;
min-width: 100%;
min-height: var(--t-diameter);
flex-shrink: 0;
align-self: center;
color: var(--tui-text-01);
stroke: var(--tui-primary);
animation: tuiFadeIn var(--tui-duration);
font-size: 1rem; // to use em units as rem ones interchangeably (Safari)

&&_horizontal {
flex-direction: row;
Expand All @@ -62,36 +87,6 @@
color: inherit;
stroke: currentColor;
}

&[data-size='xs'] {
font-size: @size-xs;
stroke-width: @width-xs;
}

&[data-size='s'] {
font-size: @size-s;
stroke-width: @width-s;
}

&[data-size='m'] {
font-size: @size-m;
stroke-width: @width-m;
}

&[data-size='l'] {
font-size: @size-l;
stroke-width: @width-l;
}

&[data-size='xl'] {
font-size: @size-xl;
stroke-width: @width-xl;
}

&[data-size='xxl'] {
font-size: @size-xxl;
stroke-width: @width-xxl;
}
}

.t-text {
Expand Down Expand Up @@ -131,26 +126,24 @@
}
});
display: block;
min-width: 1em;
max-width: 1em;
min-height: 1em;
max-height: 1em;
margin: @space -0.5em;
width: var(--t-diameter);
height: var(--t-diameter);
margin: @space calc(var(--t-diameter) / -2);
border-radius: 100%;
overflow: hidden;
animation: tuiLoaderRotate 4s linear infinite;
}

@radius: 3.125em; // don't use rem units (Safari doesn't support rem units inside <circle />)
@circumference: 2 * pi() * @radius;
@radius: calc(var(--t-diameter) / 2 - var(--tui-thickness));
@circumference: calc(2 * pi() * @radius);

@keyframes tuiLoaderDashOffset {
0% {
stroke-dashoffset: @circumference;
}

50% {
stroke-dashoffset: 0.05 * @circumference;
stroke-dashoffset: calc(0.05 * @circumference);
}

100% {
Expand All @@ -159,11 +152,11 @@
}

.t-circle {
font-size: 1rem; // to use em units as rem ones interchangeably (Safari)
r: @radius;
stroke-dasharray: @circumference;
fill: none;
stroke: inherit;
stroke-width: inherit;
// Use native CSS max function instead LESS one
stroke-width: ~'max(var(--tui-thickness), 1.5px)';
animation: tuiLoaderDashOffset 4s linear infinite;
}
9 changes: 4 additions & 5 deletions projects/core/components/loader/loader.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,19 @@
<div
*ngIf="loading"
class="t-loader"
[attr.data-size]="size"
[class.t-loader_horizontal]="isHorizontal"
[class.t-loader_inherit-color]="inheritColor"
>
<svg
automation-id="tui-loader__loader"
focusable="false"
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
height="100%"
width="100%"
class="t-icon"
>
<circle
cx="50"
cy="50"
cx="50%"
cy="50%"
class="t-circle"
></circle>
</svg>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<tui-loader></tui-loader>
<tui-loader></tui-loader>
<tui-loader></tui-loader>
27 changes: 27 additions & 0 deletions projects/demo/src/modules/components/loader/examples/5/index.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
tui-loader {
min-width: 3.5rem;

&:nth-child(1) {
/**
Don't use `rem` units if you support Safari.
Safari doesn't support `rem` units for `stroke-*` properties of `<circle />`.
Use `em` units => they will be interpreted as `rem` ones
(`<circle />` has `font-size: 1rem`).
Or just use simple `px` units.
*/
--tui-thickness: 0.125em;
}

&:nth-child(2) {
--tui-thickness: 4px;
}

&:nth-child(3) {
--tui-thickness: 8px;
}
}

:host {
display: flex;
gap: 2rem;
}
14 changes: 14 additions & 0 deletions projects/demo/src/modules/components/loader/examples/5/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {Component} from '@angular/core';
import {changeDetection} from '@demo/emulate/change-detection';
import {encapsulation} from '@demo/emulate/encapsulation';
import {tuiLoaderOptionsProvider} from '@taiga-ui/core';

@Component({
selector: 'tui-loader-example-5',
templateUrl: './index.html',
styleUrls: ['./index.less'],
encapsulation,
changeDetection,
providers: [tuiLoaderOptionsProvider({size: 'xl'})],
})
export class TuiLoaderExample5 {}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ export class ExampleTuiLoaderComponent {
HTML: import('./examples/4/index.html?raw'),
};

readonly example5: TuiDocExample = {
HTML: import('./examples/5/index.html?raw'),
LESS: import('./examples/5/index.less?raw'),
TypeScript: import('./examples/5/index.ts?raw'),
};

showLoader = true;

inheritColor = false;
Expand Down
2 changes: 2 additions & 0 deletions projects/demo/src/modules/components/loader/loader.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {TuiLoaderExample1} from './examples/1';
import {TuiLoaderExample2} from './examples/2';
import {TuiLoaderExample3} from './examples/3';
import {TuiLoaderExample4} from './examples/4';
import {TuiLoaderExample5} from './examples/5';
import {ExampleTuiLoaderComponent} from './loader.component';

@NgModule({
Expand All @@ -32,6 +33,7 @@ import {ExampleTuiLoaderComponent} from './loader.component';
TuiLoaderExample2,
TuiLoaderExample3,
TuiLoaderExample4,
TuiLoaderExample5,
],
exports: [ExampleTuiLoaderComponent],
})
Expand Down
14 changes: 14 additions & 0 deletions projects/demo/src/modules/components/loader/loader.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,20 @@
>
<tui-loader-example-4></tui-loader-example-4>
</tui-doc-example>

<tui-doc-example
id="stroke-width"
heading="Custom stroke width"
[content]="example5"
[description]="strokeWidthDescription"
>
<ng-template #strokeWidthDescription>
Use css-variable
<code>--tui-thickness</code>
to customize width of the circle stroke. By default, it is 1/12 of diameter.
</ng-template>
<tui-loader-example-5></tui-loader-example-5>
</tui-doc-example>
</ng-template>

<ng-template pageTab>
Expand Down

0 comments on commit 6132683

Please sign in to comment.