Files
metabuilder/scss/atoms/mat-progress.module.scss
2026-03-09 22:30:41 +00:00

505 lines
16 KiB
SCSS

// Progress Component - Official Angular Material M3 SCSS (CSS Module)
// ===================================================================
// Re-exports Angular Material progress-bar and progress-spinner classes
// as CSS Module locals so Progress.tsx can reference them via styles['className'].
//
// Pattern: All M3 class declarations live directly in this file (not via @use
// of other .module.scss files) so CSS Modules exports them as locals and
// parent-child selectors share the same hashed namespace.
@use 'cdk';
@use '../m3-scss/material/core/tokens/token-utils';
@use '../m3-scss/material/progress-bar/m3-progress-bar';
@use '../m3-scss/material/progress-spinner/m3-progress-spinner';
$bar-fallbacks: m3-progress-bar.get-tokens();
$spinner-fallbacks: m3-progress-spinner.get-tokens();
// ============================================
// Local wrapper class for CSS Modules purity
// ============================================
.matProgress {
// Exists for CSS Modules export. Actual styling via M3 classes below.
}
// =====================================================================
// Linear Progress - inlined from progress-bar.module.scss
// =====================================================================
.mat-mdc-progress-bar {
--mat-progress-bar-animation-multiplier: 1;
display: block;
text-align: start;
&[mode='query'] {
transform: scaleX(-1);
}
}
.mdc-linear-progress {
position: relative;
width: 100%;
transform: translateZ(0);
outline: 1px solid transparent;
overflow-x: hidden;
transition: opacity 250ms 0ms cubic-bezier(0.4, 0, 0.6, 1);
$track-variable: token-utils.slot(progress-bar-track-height, $bar-fallbacks);
$indicator-height-variable: token-utils.slot(progress-bar-active-indicator-height, $bar-fallbacks);
height: max(#{$track-variable}, #{$indicator-height-variable});
@include cdk.high-contrast {
outline-color: CanvasText;
}
}
.mdc-linear-progress__bar {
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
width: 100%;
animation: none;
transform-origin: top left;
transition: transform 250ms 0ms cubic-bezier(0.4, 0, 0.6, 1);
height: token-utils.slot(progress-bar-active-indicator-height, $bar-fallbacks);
.mdc-linear-progress--indeterminate & {
transition: none;
}
[dir='rtl'] & {
right: 0;
transform-origin: center right;
}
}
.mdc-linear-progress__bar-inner {
display: inline-block;
position: absolute;
width: 100%;
animation: none;
border-top-style: solid;
border-color: token-utils.slot(progress-bar-active-indicator-color, $bar-fallbacks);
border-top-width: token-utils.slot(progress-bar-active-indicator-height, $bar-fallbacks);
}
.mdc-linear-progress__buffer {
display: flex;
position: absolute;
top: 0;
bottom: 0;
margin: auto 0;
width: 100%;
overflow: hidden;
height: token-utils.slot(progress-bar-track-height, $bar-fallbacks);
border-radius: token-utils.slot(progress-bar-track-shape, $bar-fallbacks);
}
.mdc-linear-progress__buffer-dots {
$circle-color: token-utils.slot(progress-bar-track-color, $bar-fallbacks);
$circle-size: calc(#{token-utils.slot(progress-bar-track-height, $bar-fallbacks)} / 2);
background-image: radial-gradient(circle, #{$circle-color} #{$circle-size}, transparent 0);
background-repeat: repeat-x;
background-size: calc(#{$circle-size} * 5);
background-position: left;
flex: auto;
transform: rotate(180deg);
animation: mdc-linear-progress-buffering
calc(250ms * var(--mat-progress-bar-animation-multiplier)) infinite linear;
@include cdk.high-contrast {
background-color: ButtonBorder;
}
[dir='rtl'] & {
animation: mdc-linear-progress-buffering-reverse
calc(250ms * var(--mat-progress-bar-animation-multiplier)) infinite linear;
transform: rotate(0);
}
}
.mdc-linear-progress__buffer-bar {
flex: 0 1 100%;
transition: flex-basis 250ms 0ms cubic-bezier(0.4, 0, 0.6, 1);
background-color: token-utils.slot(progress-bar-track-color, $bar-fallbacks);
}
.mdc-linear-progress__primary-bar {
transform: scaleX(0);
.mdc-linear-progress--indeterminate & {
left: -145.166611%;
}
.mdc-linear-progress--indeterminate.mdc-linear-progress--animation-ready & {
animation: mdc-linear-progress-primary-indeterminate-translate
calc(2s * var(--mat-progress-bar-animation-multiplier)) infinite linear;
}
.mdc-linear-progress--indeterminate.mdc-linear-progress--animation-ready & {
> .mdc-linear-progress__bar-inner {
animation: mdc-linear-progress-primary-indeterminate-scale
calc(2s * var(--mat-progress-bar-animation-multiplier)) infinite linear;
}
}
[dir='rtl'] .mdc-linear-progress.mdc-linear-progress--animation-ready & {
animation-name: mdc-linear-progress-primary-indeterminate-translate-reverse;
}
[dir='rtl'] .mdc-linear-progress.mdc-linear-progress--indeterminate & {
right: -145.166611%;
left: auto;
}
}
.mdc-linear-progress__secondary-bar {
display: none;
.mdc-linear-progress--indeterminate & {
left: -54.888891%;
display: block;
}
.mdc-linear-progress--indeterminate.mdc-linear-progress--animation-ready & {
animation: mdc-linear-progress-secondary-indeterminate-translate
calc(2s * var(--mat-progress-bar-animation-multiplier)) infinite linear;
}
.mdc-linear-progress--indeterminate.mdc-linear-progress--animation-ready & {
> .mdc-linear-progress__bar-inner {
animation: mdc-linear-progress-secondary-indeterminate-scale
calc(2s * var(--mat-progress-bar-animation-multiplier)) infinite linear;
}
}
[dir='rtl'] .mdc-linear-progress.mdc-linear-progress--animation-ready & {
animation-name: mdc-linear-progress-secondary-indeterminate-translate-reverse;
}
[dir='rtl'] .mdc-linear-progress.mdc-linear-progress--indeterminate & {
right: -54.888891%;
left: auto;
}
}
// Modifier classes (must be declared for CSS Module export)
.mdc-linear-progress--indeterminate {}
.mdc-linear-progress--animation-ready {}
// ─── Linear progress keyframes ─────────────────────────────────
@keyframes mdc-linear-progress-buffering {
from {
$track-variable: token-utils.slot(progress-bar-track-height, $bar-fallbacks);
transform: rotate(180deg) translateX(calc(#{$track-variable} * -2.5));
}
}
@keyframes mdc-linear-progress-primary-indeterminate-translate {
0% { transform: translateX(0); }
20% { animation-timing-function: cubic-bezier(0.5, 0, 0.701732, 0.495819); transform: translateX(0); }
59.15% { animation-timing-function: cubic-bezier(0.302435, 0.381352, 0.55, 0.956352); transform: translateX(83.67142%); }
100% { transform: translateX(200.611057%); }
}
@keyframes mdc-linear-progress-primary-indeterminate-scale {
0% { transform: scaleX(0.08); }
36.65% { animation-timing-function: cubic-bezier(0.334731, 0.12482, 0.785844, 1); transform: scaleX(0.08); }
69.15% { animation-timing-function: cubic-bezier(0.06, 0.11, 0.6, 1); transform: scaleX(0.661479); }
100% { transform: scaleX(0.08); }
}
@keyframes mdc-linear-progress-secondary-indeterminate-translate {
0% { animation-timing-function: cubic-bezier(0.15, 0, 0.515058, 0.409685); transform: translateX(0); }
25% { animation-timing-function: cubic-bezier(0.31033, 0.284058, 0.8, 0.733712); transform: translateX(37.651913%); }
48.35% { animation-timing-function: cubic-bezier(0.4, 0.627035, 0.6, 0.902026); transform: translateX(84.386165%); }
100% { transform: translateX(160.277782%); }
}
@keyframes mdc-linear-progress-secondary-indeterminate-scale {
0% { animation-timing-function: cubic-bezier(0.205028, 0.057051, 0.57661, 0.453971); transform: scaleX(0.08); }
19.15% { animation-timing-function: cubic-bezier(0.152313, 0.196432, 0.648374, 1.004315); transform: scaleX(0.457104); }
44.15% { animation-timing-function: cubic-bezier(0.257759, -0.003163, 0.211762, 1.38179); transform: scaleX(0.72796); }
100% { transform: scaleX(0.08); }
}
@keyframes mdc-linear-progress-primary-indeterminate-translate-reverse {
0% { transform: translateX(0); }
20% { animation-timing-function: cubic-bezier(0.5, 0, 0.701732, 0.495819); transform: translateX(0); }
59.15% { animation-timing-function: cubic-bezier(0.302435, 0.381352, 0.55, 0.956352); transform: translateX(-83.67142%); }
100% { transform: translateX(-200.611057%); }
}
@keyframes mdc-linear-progress-secondary-indeterminate-translate-reverse {
0% { animation-timing-function: cubic-bezier(0.15, 0, 0.515058, 0.409685); transform: translateX(0); }
25% { animation-timing-function: cubic-bezier(0.31033, 0.284058, 0.8, 0.733712); transform: translateX(-37.651913%); }
48.35% { animation-timing-function: cubic-bezier(0.4, 0.627035, 0.6, 0.902026); transform: translateX(-84.386165%); }
100% { transform: translateX(-160.277782%); }
}
@keyframes mdc-linear-progress-buffering-reverse {
from { transform: translateX(-10px); }
}
// =====================================================================
// Circular Progress - inlined from progress-spinner.module.scss
// =====================================================================
.mat-mdc-progress-spinner {
--mat-progress-spinner-animation-multiplier: 1;
display: block;
overflow: hidden;
line-height: 0;
position: relative;
direction: ltr;
transition: opacity 250ms cubic-bezier(0.4, 0, 0.6, 1);
circle {
stroke-width: token-utils.slot(progress-spinner-active-indicator-width, $spinner-fallbacks);
}
@include cdk.high-contrast {
.mdc-circular-progress__indeterminate-circle-graphic,
.mdc-circular-progress__determinate-circle {
stroke: currentColor;
stroke: CanvasText;
}
}
}
.mdc-circular-progress__determinate-container,
.mdc-circular-progress__indeterminate-circle-graphic,
.mdc-circular-progress__indeterminate-container,
.mdc-circular-progress__spinner-layer {
position: absolute;
width: 100%;
height: 100%;
}
.mdc-circular-progress__determinate-container {
transform: rotate(-90deg);
.mdc-circular-progress--indeterminate & {
opacity: 0;
}
}
.mdc-circular-progress__indeterminate-container {
font-size: 0;
letter-spacing: 0;
white-space: nowrap;
opacity: 0;
.mdc-circular-progress--indeterminate & {
opacity: 1;
animation: mdc-circular-progress-container-rotate
calc(1568.2352941176ms * var(--mat-progress-spinner-animation-multiplier)) linear infinite;
}
}
.mdc-circular-progress__determinate-circle-graphic,
.mdc-circular-progress__indeterminate-circle-graphic {
fill: transparent;
}
.mat-mdc-progress-spinner .mdc-circular-progress__determinate-circle,
.mat-mdc-progress-spinner .mdc-circular-progress__indeterminate-circle-graphic {
stroke: token-utils.slot(progress-spinner-active-indicator-color, $spinner-fallbacks);
@include cdk.high-contrast {
stroke: CanvasText;
}
}
.mdc-circular-progress__determinate-circle {
transition: stroke-dashoffset 500ms cubic-bezier(0, 0, 0.2, 1);
}
.mdc-circular-progress__gap-patch {
position: absolute;
top: 0;
left: 47.5%;
box-sizing: border-box;
width: 5%;
height: 100%;
overflow: hidden;
}
.mdc-circular-progress__indeterminate-circle-graphic {
.mdc-circular-progress__gap-patch & {
left: -900%;
width: 2000%;
transform: rotate(180deg);
}
.mdc-circular-progress__circle-clipper & {
width: 200%;
}
.mdc-circular-progress__circle-right & {
left: -100%;
}
.mdc-circular-progress--indeterminate .mdc-circular-progress__circle-left & {
animation: mdc-circular-progress-left-spin
calc(1333ms * var(--mat-progress-spinner-animation-multiplier))
cubic-bezier(0.4, 0, 0.2, 1) infinite both;
}
.mdc-circular-progress--indeterminate .mdc-circular-progress__circle-right & {
animation: mdc-circular-progress-right-spin
calc(1333ms * var(--mat-progress-spinner-animation-multiplier))
cubic-bezier(0.4, 0, 0.2, 1) infinite both;
}
}
.mdc-circular-progress__circle-clipper {
display: inline-flex;
position: relative;
width: 50%;
height: 100%;
overflow: hidden;
}
.mdc-circular-progress__spinner-layer {
.mdc-circular-progress--indeterminate & {
animation: mdc-circular-progress-spinner-layer-rotate
calc(5332ms * var(--mat-progress-spinner-animation-multiplier)) cubic-bezier(0.4, 0, 0.2, 1)
infinite both;
}
}
// Modifier classes (must be declared for CSS Module export)
.mdc-circular-progress--indeterminate {}
.mdc-circular-progress__circle-left {}
.mdc-circular-progress__circle-right {}
// ─── Circular progress keyframes ───────────────────────────────
@keyframes mdc-circular-progress-container-rotate {
to { transform: rotate(360deg); }
}
@keyframes mdc-circular-progress-spinner-layer-rotate {
12.5% { transform: rotate(135deg); }
25% { transform: rotate(270deg); }
37.5% { transform: rotate(405deg); }
50% { transform: rotate(540deg); }
62.5% { transform: rotate(675deg); }
75% { transform: rotate(810deg); }
87.5% { transform: rotate(945deg); }
100% { transform: rotate(1080deg); }
}
@keyframes mdc-circular-progress-left-spin {
from { transform: rotate(265deg); }
50% { transform: rotate(130deg); }
to { transform: rotate(265deg); }
}
@keyframes mdc-circular-progress-right-spin {
from { transform: rotate(-265deg); }
50% { transform: rotate(-130deg); }
to { transform: rotate(-265deg); }
}
// ============================================
// Linear Progress React-specific Extensions
// ============================================
// Container for progress with label
.withLabel {
display: flex;
align-items: center;
gap: 12px;
}
.withLabel .matProgress {
flex: 1;
}
.label {
font-family: var(--mat-sys-label-medium-font);
font-size: var(--mat-sys-label-medium-size);
font-weight: var(--mat-sys-label-medium-weight);
color: var(--mat-sys-on-surface-variant);
min-width: 40px;
text-align: right;
}
// ============================================
// Size Variants (extends Angular Material)
// ============================================
.thin {
--mat-progress-bar-track-height: 2px;
--mat-progress-bar-active-indicator-height: 2px;
}
.thick {
--mat-progress-bar-track-height: 8px;
--mat-progress-bar-active-indicator-height: 8px;
}
// ============================================
// Color Variants (extends Angular Material)
// ============================================
.colorSecondary {
--mat-progress-bar-active-indicator-color: var(--mat-sys-secondary);
--mat-progress-spinner-active-indicator-color: var(--mat-sys-secondary);
}
.colorTertiary {
--mat-progress-bar-active-indicator-color: var(--mat-sys-tertiary);
--mat-progress-spinner-active-indicator-color: var(--mat-sys-tertiary);
}
.colorSuccess {
--mat-progress-bar-active-indicator-color: var(--color-success, #4caf50);
--mat-progress-spinner-active-indicator-color: var(--color-success, #4caf50);
}
.colorWarning {
--mat-progress-bar-active-indicator-color: var(--color-warning, #ff9800);
--mat-progress-spinner-active-indicator-color: var(--color-warning, #ff9800);
}
.colorError {
--mat-progress-bar-active-indicator-color: var(--mat-sys-error);
--mat-progress-spinner-active-indicator-color: var(--mat-sys-error);
}
.colorInfo {
--mat-progress-bar-active-indicator-color: var(--color-info, #2196f3);
--mat-progress-spinner-active-indicator-color: var(--color-info, #2196f3);
}
.colorInherit {
--mat-progress-bar-active-indicator-color: currentColor;
--mat-progress-spinner-active-indicator-color: currentColor;
}
// ============================================
// Circular Progress React-specific Extensions
// ============================================
// Wrapper for circular progress with label
.circularWithLabel {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
}
.circularLabel {
position: absolute;
font-family: var(--mat-sys-label-medium-font);
font-size: var(--mat-sys-label-medium-size);
font-weight: var(--mat-sys-label-medium-weight);
color: var(--mat-sys-on-surface);
}