Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(loader): add determinate-value type #9957

Merged
merged 5 commits into from
Aug 19, 2024
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
8 changes: 4 additions & 4 deletions packages/calcite-components/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3312,9 +3312,9 @@ export namespace Components {
*/
"text": string;
/**
* Specifies the component type. Use `"indeterminate"` if finding actual progress value is impossible.
* Specifies the component type. Use `"indeterminate"` if finding actual progress value is impossible. Otherwise, use `"determinate"` to have the value indicate the progress or `"determinate-value"` to have the value label displayed along the progress.
*/
"type": "indeterminate" | "determinate";
"type": "indeterminate" | "determinate" | "determinate-value";
/**
* The component's value. Valid only for `"determinate"` indicators. Percent complete of 100.
*/
Expand Down Expand Up @@ -11404,9 +11404,9 @@ declare namespace LocalJSX {
*/
"text"?: string;
/**
* Specifies the component type. Use `"indeterminate"` if finding actual progress value is impossible.
* Specifies the component type. Use `"indeterminate"` if finding actual progress value is impossible. Otherwise, use `"determinate"` to have the value indicate the progress or `"determinate-value"` to have the value label displayed along the progress.
*/
"type"?: "indeterminate" | "determinate";
"type"?: "indeterminate" | "determinate" | "determinate-value";
/**
* The component's value. Valid only for `"determinate"` indicators. Percent complete of 100.
*/
Expand Down
17 changes: 10 additions & 7 deletions packages/calcite-components/src/components/loader/loader.scss
Original file line number Diff line number Diff line change
Expand Up @@ -36,21 +36,24 @@ $loader-circumference: ($loader-scale - (2 * $stroke-width)) * 3.14159;
}

:host([scale="s"]) {
--calcite-loader-font-size: theme("fontSize.n2");
--calcite-loader-font-size: var(--calcite-font-size--3);
--calcite-loader-size: theme("spacing.8");
--calcite-loader-size-inline: theme("spacing.3");
--calcite-internal-loader-value-line-height: 0.625rem; // 10px
}

:host([scale="m"]) {
--calcite-loader-font-size: theme("fontSize.0");
--calcite-loader-size: theme("spacing.16");
--calcite-loader-size-inline: theme("spacing.4");
--calcite-internal-loader-value-line-height: 1.375rem; // 22px
}

:host([scale="l"]) {
--calcite-loader-font-size: theme("fontSize.2");
--calcite-loader-size: theme("spacing.24");
--calcite-loader-size-inline: theme("spacing.6");
--calcite-internal-loader-value-line-height: 1.71875rem; // 27.5px
}

:host([no-padding]) {
Expand All @@ -70,13 +73,11 @@ $loader-circumference: ($loader-scale - (2 * $stroke-width)) * 3.14159;
}

.loader__percentage {
@apply text-color-1 absolute block text-center;
@apply block text-center text-color-1;
font-size: var(--calcite-loader-font-size);
inline-size: var(--calcite-loader-size);
inset-inline-start: 50%;
margin-inline-start: calc(var(--calcite-loader-size) / 2 * -1);
line-height: 0.25;
transform: scale(1, 1);
line-height: var(--calcite-internal-loader-value-line-height);
align-self: center;
}

.loader__svgs {
Expand All @@ -89,6 +90,7 @@ $loader-circumference: ($loader-scale - (2 * $stroke-width)) * 3.14159;
animation-timing-function: linear;
animation-duration: scaleDuration(--calcite-internal-animation-timing-slow, 6.66);
animation-name: loader-clockwise;
display: flex;
}

.loader__svg {
Expand All @@ -110,7 +112,8 @@ $loader-circumference: ($loader-scale - (2 * $stroke-width)) * 3.14159;
}
}

:host([type="determinate"]) {
:host([type="determinate"]),
:host([type="determinate-value"]) {
@apply animate-none;
stroke: var(--calcite-color-border-3);
.loader__svgs {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,44 @@ export const inline_TestOnly = (): string => html`
</div>
`;

export const determinate = (): string => html`
<style>
.scales {
display: flex;
flex-direction: row;
gap: 50px;
}

calcite-loader {
/* provide dimensions for consistent screenshots */
height: 100px;
width: 100px;
}
</style>
<h1>determinate</h1>
<div class="scales">
<h2>s</h2>
<calcite-loader scale="s" type="determinate" value="50"></calcite-loader>
<h2>m</h2>
<calcite-loader scale="m" type="determinate" value="50"></calcite-loader>
<h2>l</h2>
<calcite-loader scale="l" type="determinate" value="50"></calcite-loader>
</div>
<br>
<h1>determinate-value</h1>
<div class="scales">
<h2>s</h2>
<calcite-loader scale="s" type="determinate-value" value="50" />
</calcite-loader>
<h2>m</h2>
<calcite-loader scale="m" type="determinate-value" value="50" />
</calcite-loader>
<h2>l</h2>
<calcite-loader scale="l" type="determinate-value" value="50" />
</calcite-loader>
</div>
`;

export const customTheme_TestOnly = (): string => html`
<calcite-loader
type="indeterminate"
Expand Down
54 changes: 48 additions & 6 deletions packages/calcite-components/src/components/loader/loader.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Component, Element, h, Host, Prop, VNode } from "@stencil/core";
import { Component, Element, h, Host, Prop, State, VNode, Watch } from "@stencil/core";
import { guid } from "../../utils/guid";
import { Scale } from "../interfaces";
import { connectLocalized, disconnectLocalized, LocalizedComponent } from "../../utils/locale";
import { CSS } from "./resources";

@Component({
tag: "calcite-loader",
styleUrl: "loader.scss",
shadow: true,
})
export class Loader {
export class Loader implements LocalizedComponent {
//--------------------------------------------------------------------------
//
// Properties
Expand All @@ -27,10 +28,10 @@ export class Loader {
/**
* Specifies the component type.
*
* Use `"indeterminate"` if finding actual progress value is impossible.
* Use `"indeterminate"` if finding actual progress value is impossible. Otherwise, use `"determinate"` to have the value indicate the progress or `"determinate-value"` to have the value label displayed along the progress.
*
*/
@Prop({ reflect: true }) type: "indeterminate" | "determinate";
@Prop({ reflect: true }) type: "indeterminate" | "determinate" | "determinate-value";

/** The component's value. Valid only for `"determinate"` indicators. Percent complete of 100. */
@Prop() value = 0;
Expand All @@ -44,6 +45,16 @@ export class Loader {
//
//--------------------------------------------------------------------------

connectedCallback(): void {
connectLocalized(this);

this.updateFormatter();
}

disconnectedCallback(): void {
disconnectLocalized(this);
}

render(): VNode {
const { el, inline, label, scale, text, type, value } = this;

Expand All @@ -52,7 +63,7 @@ export class Loader {
const size = inline ? this.getInlineSize(scale) : this.getSize(scale);
const radius = size * radiusRatio;
const viewbox = `0 0 ${size} ${size}`;
const isDeterminate = type === "determinate";
const isDeterminate = type?.startsWith("determinate");
const circumference = 2 * radius * Math.PI;
const progress = (value / 100) * circumference;
const remaining = circumference - progress;
Expand Down Expand Up @@ -87,13 +98,21 @@ export class Loader {
<circle {...svgAttributes} />
</svg>
))}
{isDeterminate && <div class={CSS.loaderPercentage}>{this.formatValue()}</div>}
</div>
{text && <div class={CSS.loaderText}>{text}</div>}
{isDeterminate && <div class={CSS.loaderPercentage}>{value}</div>}
</Host>
);
}

private formatValue = (): string => {
if (this.type !== "determinate-value") {
return `${this.value}`;
}

return this.formatter.format(this.value / 100);
};

//--------------------------------------------------------------------------
//
// Private Properties
Expand All @@ -102,6 +121,16 @@ export class Loader {

@Element() el: HTMLCalciteLoaderElement;

@State() effectiveLocale = "";

@Watch("effectiveLocale")
@Watch("type")
formatterPropsChange(): void {
this.updateFormatter();
}

private formatter: Intl.NumberFormat;

//--------------------------------------------------------------------------
//
// Private Methods
Expand All @@ -128,4 +157,17 @@ export class Loader {
l: 20,
}[scale];
}

private updateFormatter(): void {
if (
this.type !== "determinate-value" ||
this.formatter?.resolvedOptions().locale === this.effectiveLocale
) {
return;
}

this.formatter = new Intl.NumberFormat(this.effectiveLocale, {
style: "percent",
});
}
}
Loading