refactor(ui): localize progress and loading styles

This commit is contained in:
2026-08-09 13:42:09 +05:30
parent fdf6282aed
commit b6bd5cfcb7
6 changed files with 151 additions and 63 deletions
+43 -3
View File
@@ -9,9 +9,49 @@ component Progress {
class: string = ""
}
view {
<div class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--progress {class}">
<div class="wire-next__row"><span>{label}</span>{#if showValue}<strong>{value}%</strong>{/if}</div>
<progress value="{value}" max="{max}"></progress>
<div class="wire-progress-component {class}" data-color="{color}" data-size="{size}">
<div class="wire-progress-component__row"><span>{label}</span>{#if showValue}<strong>{value}%</strong>{/if}</div>
<progress class="wire-progress-component__track" value="{value}" max="{max}" aria-label="{label}"></progress>
</div>
}
style {
.wire-progress-component {
--wire-progress-color: var(--wire-color-primary);
display: grid;
width: 100%;
gap: 0.5rem;
color: var(--wire-color-text);
font-size: 0.875rem;
}
.wire-progress-component[data-color="secondary"] { --wire-progress-color: var(--wire-color-secondary); }
.wire-progress-component[data-color="success"] { --wire-progress-color: var(--wire-color-success); }
.wire-progress-component[data-color="warning"] { --wire-progress-color: var(--wire-color-warning); }
.wire-progress-component[data-color="danger"] { --wire-progress-color: var(--wire-color-danger); }
.wire-progress-component[data-color="info"] { --wire-progress-color: var(--wire-color-info); }
.wire-progress-component[data-size="xs"] { font-size: 0.75rem; }
.wire-progress-component[data-size="lg"],
.wire-progress-component[data-size="xl"] { font-size: 1rem; }
.wire-progress-component__row {
display: flex;
justify-content: space-between;
gap: 1rem;
}
.wire-progress-component__track {
width: 100%;
height: 0.6rem;
overflow: hidden;
border: 0;
border-radius: 999px;
background: var(--wire-color-surface-2);
accent-color: var(--wire-progress-color);
}
.wire-progress-component__track::-webkit-progress-bar { background: var(--wire-color-surface-2); }
.wire-progress-component__track::-webkit-progress-value { background: var(--wire-progress-color); }
.wire-progress-component__track::-moz-progress-bar { background: var(--wire-progress-color); }
}
}
+36 -2
View File
@@ -7,8 +7,42 @@ component Skeleton {
class: string = ""
}
view {
<div class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--skeleton wire-next--size-{size} {class}" role="status" aria-label="{label}">
{#if "Skeleton" === "Skeleton"}{#each Array(lines).fill(0) as line}<span></span>{/each}{:else}<i aria-hidden="true"></i>{/if}
<div class="wire-skeleton-component {class}" data-color="{color}" data-size="{size}" role="status" aria-label="{label}">
{#each Array(lines).fill(0) as line}<span class="wire-skeleton-component__line"></span>{/each}
</div>
}
style {
.wire-skeleton-component {
--wire-skeleton-highlight: var(--wire-color-border);
display: grid;
width: min(100%, 24rem);
gap: 0.55rem;
}
.wire-skeleton-component[data-size="xs"] { gap: 0.35rem; }
.wire-skeleton-component[data-size="lg"],
.wire-skeleton-component[data-size="xl"] { gap: 0.75rem; }
.wire-skeleton-component[data-color="secondary"] { --wire-skeleton-highlight: var(--wire-color-secondary-soft); }
.wire-skeleton-component[data-color="primary"] { --wire-skeleton-highlight: var(--wire-color-primary-soft); }
.wire-skeleton-component__line {
height: 0.8rem;
border-radius: 999px;
background: linear-gradient(90deg, var(--wire-color-surface-2), var(--wire-skeleton-highlight), var(--wire-color-surface-2));
background-size: 200% 100%;
animation: wire-skeleton-component-shimmer 1.4s infinite;
}
.wire-skeleton-component__line:last-child { width: 68%; }
@keyframes wire-skeleton-component-shimmer {
from { background-position: 200% 0; }
to { background-position: -200% 0; }
}
@media (prefers-reduced-motion: reduce) {
.wire-skeleton-component__line { animation: none; }
}
}
}
+37 -2
View File
@@ -7,8 +7,43 @@ component Spinner {
class: string = ""
}
view {
<div class="wire-next wire-next--color-{color} wire-next--size-{size} wire-next--spinner wire-next--size-{size} {class}" role="status" aria-label="{label}">
{#if "Spinner" === "Skeleton"}{#each Array(lines).fill(0) as line}<span></span>{/each}{:else}<i aria-hidden="true"></i>{/if}
<div class="wire-spinner-component {class}" data-color="{color}" data-size="{size}" role="status" aria-label="{label}">
<i class="wire-spinner-component__indicator" aria-hidden="true"></i>
</div>
}
style {
.wire-spinner-component {
--wire-spinner-size: 1.5rem;
--wire-spinner-color: var(--wire-color-primary);
display: inline-grid;
place-items: center;
}
.wire-spinner-component[data-size="xs"] { --wire-spinner-size: 0.875rem; }
.wire-spinner-component[data-size="sm"] { --wire-spinner-size: 1.125rem; }
.wire-spinner-component[data-size="lg"] { --wire-spinner-size: 2rem; }
.wire-spinner-component[data-size="xl"] { --wire-spinner-size: 2.5rem; }
.wire-spinner-component[data-color="secondary"] { --wire-spinner-color: var(--wire-color-secondary); }
.wire-spinner-component[data-color="success"] { --wire-spinner-color: var(--wire-color-success); }
.wire-spinner-component[data-color="warning"] { --wire-spinner-color: var(--wire-color-warning); }
.wire-spinner-component[data-color="danger"] { --wire-spinner-color: var(--wire-color-danger); }
.wire-spinner-component[data-color="info"] { --wire-spinner-color: var(--wire-color-info); }
.wire-spinner-component__indicator {
display: block;
width: var(--wire-spinner-size);
height: var(--wire-spinner-size);
border: 2px solid var(--wire-color-border);
border-top-color: var(--wire-spinner-color);
border-radius: 50%;
animation: wire-spinner-component-spin 700ms linear infinite;
}
@keyframes wire-spinner-component-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
.wire-spinner-component__indicator { animation-duration: 1.8s; }
}
}
}
+5
View File
@@ -1,4 +1,5 @@
import { expect, test } from "bun:test";
import { gzipSync } from "bun";
import { readFileSync } from "node:fs";
import { join } from "node:path";
import { compileWireFile, parse } from "../../compiler/src/index.ts";
@@ -18,6 +19,10 @@ test("bundled UI assets are discoverable and readable", () => {
expect(uiCss()).toContain("--wire-");
});
test("global UI CSS stays below its migration ratchet", () => {
expect(gzipSync(new TextEncoder().encode(uiCss())).length).toBeLessThanOrEqual(26_004);
});
test("generated component reference documents every bundled component and its props", () => {
const reference = JSON.parse(
readFileSync(join(uiComponentsDir(), "..", "component-reference.json"), "utf8"),
-26
View File
@@ -3936,32 +3936,6 @@
height: min(3rem, 14vw);
}
}
.wire-next--spinner i {
display: block;
width: 1.5rem;
height: 1.5rem;
border: 2px solid var(--wire-color-border);
border-top-color: var(--wire-color-primary);
border-radius: 50%;
animation: wire-spin 700ms linear infinite;
}
.wire-next--skeleton {
display: grid;
width: min(100%, 24rem);
gap: 0.55rem;
}
.wire-next--skeleton span {
height: 0.8rem;
border-radius: 999px;
background: linear-gradient(
90deg,
var(--wire-color-surface-2),
var(--wire-color-border),
var(--wire-color-surface-2)
);
background-size: 200% 100%;
animation: wire-shimmer 1.4s infinite;
}
.wire-next--navbar,
.wire-next--mega-menu,
.wire-next--nav,