mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-05-02 09:45:00 +00:00
314 lines
12 KiB
SCSS
314 lines
12 KiB
SCSS
// Button Component - Official Angular Material M3 SCSS (CSS Module)
|
|
// ==================================================================
|
|
// Re-exports Angular Material button classes as CSS Module locals
|
|
// so Button.tsx can reference them via styles['className'].
|
|
|
|
@use '../m3-scss/material/button/button-base';
|
|
@use '../m3-scss/material/core/style/private' as style-private;
|
|
@use '../m3-scss/material/core/style/vendor-prefixes';
|
|
@use '../m3-scss/material/core/tokens/token-utils';
|
|
@use '../m3-scss/material/core/focus-indicators/private' as focus-indicators-private;
|
|
@use '../m3-scss/material/button/m3-button';
|
|
|
|
$fallbacks: m3-button.get-tokens();
|
|
|
|
// ─── Base classes ───────────────────────────────────────────────
|
|
|
|
.mat-mdc-button-base {
|
|
text-decoration: none;
|
|
|
|
& .mat-icon {
|
|
min-height: fit-content;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
@media (hover: none) {
|
|
&:hover > span.mat-mdc-button-persistent-ripple::before {
|
|
opacity: 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
.mdc-button {
|
|
@include vendor-prefixes.user-select(none);
|
|
position: relative;
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
box-sizing: border-box;
|
|
min-width: 64px;
|
|
border: none;
|
|
outline: none;
|
|
line-height: inherit;
|
|
-webkit-appearance: none;
|
|
appearance: none;
|
|
overflow: hidden;
|
|
vertical-align: middle;
|
|
background: transparent;
|
|
padding: 0 8px;
|
|
font-family: inherit;
|
|
|
|
&::-moz-focus-inner { padding: 0; border: 0; }
|
|
&:active { outline: none; }
|
|
&:hover { cursor: pointer; }
|
|
&:disabled { cursor: default; pointer-events: none; }
|
|
&[hidden] { display: none; }
|
|
|
|
.mdc-button__label { position: relative; display: inline-flex; align-items: center; gap: 6px; }
|
|
}
|
|
|
|
// ─── Text button (default) ──────────────────────────────────────
|
|
|
|
.mat-mdc-button {
|
|
padding: 0 #{token-utils.slot(button-text-horizontal-padding, $fallbacks, true)};
|
|
height: token-utils.slot(button-text-container-height, $fallbacks);
|
|
font-family: token-utils.slot(button-text-label-text-font, $fallbacks);
|
|
font-size: token-utils.slot(button-text-label-text-size, $fallbacks);
|
|
letter-spacing: token-utils.slot(button-text-label-text-tracking, $fallbacks);
|
|
text-transform: token-utils.slot(button-text-label-text-transform, $fallbacks);
|
|
font-weight: token-utils.slot(button-text-label-text-weight, $fallbacks);
|
|
|
|
&, .mdc-button__ripple {
|
|
border-radius: token-utils.slot(button-text-container-shape, $fallbacks);
|
|
}
|
|
|
|
&:not(:disabled) {
|
|
color: token-utils.slot(button-text-label-text-color, $fallbacks);
|
|
}
|
|
|
|
@include button-base.mat-private-button-disabled {
|
|
color: token-utils.slot(button-text-disabled-label-text-color, $fallbacks);
|
|
}
|
|
|
|
@include button-base.mat-private-button-horizontal-layout(
|
|
button-text-icon-spacing, button-text-icon-offset,
|
|
button-text-with-icon-horizontal-padding, $fallbacks);
|
|
@include button-base.mat-private-button-ripple(
|
|
button-text-ripple-color, button-text-state-layer-color,
|
|
button-text-disabled-state-layer-color,
|
|
button-text-hover-state-layer-opacity, button-text-focus-state-layer-opacity,
|
|
button-text-pressed-state-layer-opacity, $fallbacks);
|
|
@include button-base.mat-private-button-touch-target(false,
|
|
button-text-touch-target-size, button-text-touch-target-display, $fallbacks);
|
|
}
|
|
|
|
// ─── Filled button (contained) ──────────────────────────────────
|
|
|
|
.mat-mdc-unelevated-button {
|
|
transition: box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
height: token-utils.slot(button-filled-container-height, $fallbacks);
|
|
font-family: token-utils.slot(button-filled-label-text-font, $fallbacks);
|
|
font-size: token-utils.slot(button-filled-label-text-size, $fallbacks);
|
|
letter-spacing: token-utils.slot(button-filled-label-text-tracking, $fallbacks);
|
|
text-transform: token-utils.slot(button-filled-label-text-transform, $fallbacks);
|
|
font-weight: token-utils.slot(button-filled-label-text-weight, $fallbacks);
|
|
padding: 0 #{token-utils.slot(button-filled-horizontal-padding, $fallbacks, true)};
|
|
|
|
@include button-base.mat-private-button-horizontal-layout(
|
|
button-filled-icon-spacing, button-filled-icon-offset, null, $fallbacks);
|
|
@include button-base.mat-private-button-ripple(
|
|
button-filled-ripple-color, button-filled-state-layer-color,
|
|
button-filled-disabled-state-layer-color,
|
|
button-filled-hover-state-layer-opacity, button-filled-focus-state-layer-opacity,
|
|
button-filled-pressed-state-layer-opacity, $fallbacks);
|
|
@include button-base.mat-private-button-touch-target(false,
|
|
button-filled-touch-target-size, button-filled-touch-target-display, $fallbacks);
|
|
|
|
&:not(:disabled) {
|
|
color: token-utils.slot(button-filled-label-text-color, $fallbacks);
|
|
background-color: token-utils.slot(button-filled-container-color, $fallbacks);
|
|
}
|
|
|
|
&, .mdc-button__ripple {
|
|
border-radius: token-utils.slot(button-filled-container-shape, $fallbacks);
|
|
}
|
|
|
|
@include button-base.mat-private-button-disabled {
|
|
color: token-utils.slot(button-filled-disabled-label-text-color, $fallbacks);
|
|
background-color: token-utils.slot(button-filled-disabled-container-color, $fallbacks);
|
|
}
|
|
}
|
|
|
|
// ─── Outlined button ────────────────────────────────────────────
|
|
|
|
.mat-mdc-outlined-button {
|
|
border-style: solid;
|
|
transition: border 280ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
height: token-utils.slot(button-outlined-container-height, $fallbacks);
|
|
font-family: token-utils.slot(button-outlined-label-text-font, $fallbacks);
|
|
font-size: token-utils.slot(button-outlined-label-text-size, $fallbacks);
|
|
letter-spacing: token-utils.slot(button-outlined-label-text-tracking, $fallbacks);
|
|
text-transform: token-utils.slot(button-outlined-label-text-transform, $fallbacks);
|
|
font-weight: token-utils.slot(button-outlined-label-text-weight, $fallbacks);
|
|
border-radius: token-utils.slot(button-outlined-container-shape, $fallbacks);
|
|
border-width: token-utils.slot(button-outlined-outline-width, $fallbacks);
|
|
padding: 0 #{token-utils.slot(button-outlined-horizontal-padding, $fallbacks, true)};
|
|
|
|
@include button-base.mat-private-button-horizontal-layout(
|
|
button-outlined-icon-spacing, button-outlined-icon-offset, null, $fallbacks);
|
|
@include button-base.mat-private-button-ripple(
|
|
button-outlined-ripple-color, button-outlined-state-layer-color,
|
|
button-outlined-disabled-state-layer-color,
|
|
button-outlined-hover-state-layer-opacity, button-outlined-focus-state-layer-opacity,
|
|
button-outlined-pressed-state-layer-opacity, $fallbacks);
|
|
@include button-base.mat-private-button-touch-target(false,
|
|
button-outlined-touch-target-size, button-outlined-touch-target-display, $fallbacks);
|
|
|
|
&:not(:disabled) {
|
|
color: token-utils.slot(button-outlined-label-text-color, $fallbacks);
|
|
border-color: token-utils.slot(button-outlined-outline-color, $fallbacks);
|
|
}
|
|
|
|
@include button-base.mat-private-button-disabled {
|
|
color: token-utils.slot(button-outlined-disabled-label-text-color, $fallbacks);
|
|
border-color: token-utils.slot(button-outlined-disabled-outline-color, $fallbacks);
|
|
}
|
|
}
|
|
|
|
// ─── Tonal button ───────────────────────────────────────────────
|
|
|
|
.mat-tonal-button {
|
|
transition: box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
height: token-utils.slot(button-tonal-container-height, $fallbacks);
|
|
font-family: token-utils.slot(button-tonal-label-text-font, $fallbacks);
|
|
font-size: token-utils.slot(button-tonal-label-text-size, $fallbacks);
|
|
letter-spacing: token-utils.slot(button-tonal-label-text-tracking, $fallbacks);
|
|
text-transform: token-utils.slot(button-tonal-label-text-transform, $fallbacks);
|
|
font-weight: token-utils.slot(button-tonal-label-text-weight, $fallbacks);
|
|
padding: 0 #{token-utils.slot(button-tonal-horizontal-padding, $fallbacks, true)};
|
|
|
|
&:not(:disabled) {
|
|
color: token-utils.slot(button-tonal-label-text-color, $fallbacks);
|
|
background-color: token-utils.slot(button-tonal-container-color, $fallbacks);
|
|
}
|
|
|
|
&, .mdc-button__ripple {
|
|
border-radius: token-utils.slot(button-tonal-container-shape, $fallbacks);
|
|
}
|
|
|
|
@include button-base.mat-private-button-disabled {
|
|
color: token-utils.slot(button-tonal-disabled-label-text-color, $fallbacks);
|
|
background-color: token-utils.slot(button-tonal-disabled-container-color, $fallbacks);
|
|
}
|
|
|
|
@include button-base.mat-private-button-horizontal-layout(
|
|
button-tonal-icon-spacing, button-tonal-icon-offset, null, $fallbacks);
|
|
@include button-base.mat-private-button-ripple(
|
|
button-tonal-ripple-color, button-tonal-state-layer-color,
|
|
button-tonal-disabled-state-layer-color,
|
|
button-tonal-hover-state-layer-opacity, button-tonal-focus-state-layer-opacity,
|
|
button-tonal-pressed-state-layer-opacity, $fallbacks);
|
|
@include button-base.mat-private-button-touch-target(false,
|
|
button-tonal-touch-target-size, button-tonal-touch-target-display, $fallbacks);
|
|
}
|
|
|
|
// ─── Shared interactive styles ──────────────────────────────────
|
|
|
|
.mat-mdc-button,
|
|
.mat-mdc-unelevated-button,
|
|
.mat-mdc-outlined-button,
|
|
.mat-tonal-button {
|
|
@include button-base.mat-private-button-interactive();
|
|
@include style-private.private-animation-noop();
|
|
|
|
& > .mat-icon {
|
|
$icon-size: 1.125rem;
|
|
display: inline-block;
|
|
position: relative;
|
|
vertical-align: top;
|
|
font-size: $icon-size;
|
|
height: $icon-size;
|
|
width: $icon-size;
|
|
}
|
|
}
|
|
|
|
// ─── Color classes ──────────────────────────────────────────────
|
|
|
|
.mat-primary {}
|
|
.mat-accent {}
|
|
.mat-warn {}
|
|
.mat-mdc-button-disabled {}
|
|
|
|
// ─── Ripple/touch/focus children ────────────────────────────────
|
|
|
|
.mat-mdc-button-touch-target {
|
|
position: absolute;
|
|
top: 50%;
|
|
height: 48px;
|
|
left: 0;
|
|
right: 0;
|
|
transform: translateY(-50%);
|
|
}
|
|
|
|
.mat-mdc-button-ripple,
|
|
.mat-mdc-button-persistent-ripple,
|
|
.mat-mdc-button-persistent-ripple::before {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
border-radius: inherit;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.mat-mdc-button-persistent-ripple::before {
|
|
content: '';
|
|
opacity: 0;
|
|
}
|
|
|
|
.mat-focus-indicator {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
right: 0;
|
|
bottom: 0;
|
|
pointer-events: none;
|
|
border-radius: inherit;
|
|
}
|
|
|
|
// ─── Outlined button ripple offset ──────────────────────────────
|
|
// Note: offset removed since overflow:hidden clips at bounds
|
|
|
|
.mat-mdc-outlined-button .mat-mdc-button-ripple,
|
|
.mat-mdc-outlined-button .mdc-button__ripple {
|
|
top: 0;
|
|
left: 0;
|
|
bottom: 0;
|
|
right: 0;
|
|
}
|
|
|
|
// ─── Focus indicator offsets ────────────────────────────────────
|
|
|
|
.mat-mdc-unelevated-button,
|
|
.mat-tonal-button {
|
|
.mat-focus-indicator::before {
|
|
$default-border-width: focus-indicators-private.$default-border-width;
|
|
$border-width: var(--mat-focus-indicator-border-width, #{$default-border-width});
|
|
$offset: calc(#{$border-width} + 2px);
|
|
margin: calc(#{$offset} * -1);
|
|
}
|
|
}
|
|
|
|
.mat-mdc-outlined-button .mat-focus-indicator::before {
|
|
$default-border-width: focus-indicators-private.$default-border-width;
|
|
$border-width: var(--mat-focus-indicator-border-width, #{$default-border-width});
|
|
$offset: calc(#{$border-width} + 3px);
|
|
margin: calc(#{$offset} * -1);
|
|
}
|
|
|
|
// ─── Utility classes ────────────────────────────────────────────
|
|
|
|
.fullWidth {
|
|
width: 100%;
|
|
}
|
|
|
|
.spinner {
|
|
margin-right: 8px;
|
|
}
|
|
|
|
@keyframes mat-button-spin {
|
|
from { transform: rotate(0deg); }
|
|
to { transform: rotate(360deg); }
|
|
}
|