[+] A button

This commit is contained in:
2025-11-18 15:46:53 +08:00
parent 5d6500c54b
commit 6c80a76d65
10 changed files with 481 additions and 9 deletions
+30
View File
@@ -0,0 +1,30 @@
:root
font-family: 'Roboto', system-ui, sans-serif
// color-scheme: light
body
margin: 0
background: rgb(var(--m3-scheme-background))
.hbox
display: flex
flex-direction: row
align-items: center
.vbox
display: flex
flex-direction: column
.vcbox
@extend .vbox
align-items: center
.cbox
display: flex
justify-content: center
align-items: center
.p-content
// padding: 0 16px
padding-left: 16px
padding-right: 16px
+379
View File
@@ -0,0 +1,379 @@
/* Needed for elevation to work */
:root {
--m3-util-elevation-0: none;
--m3-util-elevation-1:
/* Spot */
0px 1px 2px 0px rgb(var(--m3-scheme-shadow) / 0.3),
/* Ambient */ 0px 1px 3px 1px rgb(var(--m3-scheme-shadow) / 0.15);
--m3-util-elevation-2:
0px 1px 2px 0px rgb(var(--m3-scheme-shadow) / 0.3),
0px 2px 6px 2px rgb(var(--m3-scheme-shadow) / 0.15);
--m3-util-elevation-3:
0px 1px 3px 0px rgb(var(--m3-scheme-shadow) / 0.3),
0px 4px 8px 3px rgb(var(--m3-scheme-shadow) / 0.15);
--m3-util-elevation-4:
0px 2px 3px 0px rgb(var(--m3-scheme-shadow) / 0.3),
0px 6px 10px 4px rgb(var(--m3-scheme-shadow) / 0.15);
--m3-util-elevation-5:
0px 4px 4px 0px rgb(var(--m3-scheme-shadow) / 0.3),
0px 8px 12px 6px rgb(var(--m3-scheme-shadow) / 0.15);
/* Sizing */
--m3-util-bottom-offset: 0;
--m3-util-density: 0;
--m3-util-density-term: calc(var(--m3-util-density) * 0.25rem);
/* Shapes */
--m3-util-rounding-none: 0;
--m3-util-rounding-extra-small: 4px;
--m3-util-rounding-small: 8px;
--m3-util-rounding-medium: 12px;
--m3-util-rounding-large: 16px;
--m3-util-rounding-extra-large: 28px;
--m3-util-rounding-full: calc(infinity * 1px);
--m3-util-optical-centering-coefficient: 0.11;
--m3-font: Roboto, system-ui;
--m3-font-mono: "Google Sans Code", "Roboto Mono", monospace;
/* Expressive easing */
--m3-util-timing-function-fast-spatial: cubic-bezier(0.42, 1.67, 0.21, 0.9);
--m3-util-duration-fast-spatial: 350ms;
--m3-util-easing-fast-spatial: var(--m3-util-timing-function-fast-spatial)
var(--m3-util-duration-fast-spatial);
--m3-util-timing-function-spatial: cubic-bezier(0.38, 1.21, 0.22, 1);
--m3-util-duration-spatial: 500ms;
--m3-util-easing-spatial: var(--m3-util-timing-function-spatial) var(--m3-util-duration-spatial);
--m3-util-timing-function-slow-spatial: cubic-bezier(0.39, 1.29, 0.35, 0.98);
--m3-util-duration-slow-spatial: 650ms;
--m3-util-easing-slow-spatial: var(--m3-util-timing-function-slow-spatial)
var(--m3-util-duration-slow-spatial);
--m3-util-timing-function-fast: cubic-bezier(0.31, 0.94, 0.34, 1);
--m3-util-duration-fast: 150ms;
--m3-util-easing-fast: var(--m3-util-timing-function-fast) var(--m3-util-duration-fast);
--m3-util-timing-function: cubic-bezier(0.34, 0.8, 0.34, 1);
--m3-util-duration: 200ms;
--m3-util-easing: var(--m3-util-timing-function) var(--m3-util-duration);
--m3-util-timing-function-slow: cubic-bezier(0.34, 0.88, 0.34, 1);
--m3-util-duration-slow: 300ms;
--m3-util-easing-slow: var(--m3-util-timing-function-slow) var(--m3-util-duration-slow);
--m3-util-timing-function-emphasized: linear(
0,
0.034 6%,
0.073 9%,
0.126 11%,
0.194 13%,
0.273 15%,
0.351 16%,
0.541 18%,
0.652 20%,
0.755 24%,
0.839 30%,
0.91 39%,
0.959 53%,
0.989 72%,
1
);
--m3-util-timing-function-emphasized-accel: cubic-bezier(0.3, 0, 0.8, 0.15);
--m3-util-timing-function-emphasized-decel: cubic-bezier(0.05, 0.7, 0.1, 1);
/* deprecated */
--m3-util-curve: var(--m3-util-timing-function-emphasized);
--m3-util-curve-accel: var(--m3-util-timing-function-emphasized-accel);
--m3-util-curve-decel: var(--m3-util-timing-function-emphasized-decel);
accent-color: rgb(var(--m3-scheme-primary));
}
.m3-font-display-large,
.m3-font-display-medium,
.m3-font-display-small {
font-family: var(--m3-font-display, var(--m3-font));
}
.m3-font-headline-large,
.m3-font-headline-medium,
.m3-font-headline-small {
font-family: var(--m3-font-headline, var(--m3-font));
}
.m3-font-title-large,
.m3-font-title-medium,
.m3-font-title-small {
font-family: var(--m3-font-title, var(--m3-font));
}
.m3-font-label-large,
.m3-font-label-medium,
.m3-font-label-small {
font-family: var(--m3-font-label, var(--m3-font));
}
.m3-font-body-large,
.m3-font-body-medium,
.m3-font-body-small {
font-family: var(--m3-font-body, var(--m3-font));
}
/* As the largest text on the screen, display styles are reserved for short, important text or numerals. */
.m3-font-display-large {
font-size: var(--m3-font-display-large-size, 3.563rem);
line-height: var(--m3-font-display-large-height, 1.123);
letter-spacing: var(--m3-font-display-large-tracking, 0);
font-weight: var(--m3-font-display-large-weight, 400);
}
.m3-font-display-medium {
font-size: var(--m3-font-display-medium-size, 2.813rem);
line-height: var(--m3-font-display-medium-height, 1.156);
letter-spacing: var(--m3-font-display-medium-tracking, 0);
font-weight: var(--m3-font-display-medium-weight, 400);
}
.m3-font-display-small {
font-size: var(--m3-font-display-small-size, 2.25rem);
line-height: var(--m3-font-display-small-height, 1.222);
letter-spacing: var(--m3-font-display-small-tracking, 0);
font-weight: var(--m3-font-display-small-weight, 400);
}
/* Headlines are best-suited for short, high-emphasis text on smaller screens. */
.m3-font-headline-large {
font-size: var(--m3-font-headline-large-size, 2rem);
line-height: var(--m3-font-headline-large-height, 1.25);
letter-spacing: var(--m3-font-headline-large-tracking, 0);
font-weight: var(--m3-font-headline-large-weight, 400);
}
.m3-font-headline-medium {
font-size: var(--m3-font-headline-medium-size, 1.75rem);
line-height: var(--m3-font-headline-medium-height, 1.286);
letter-spacing: var(--m3-font-headline-medium-tracking, 0);
font-weight: var(--m3-font-headline-medium-weight, 400);
}
.m3-font-headline-small {
font-size: var(--m3-font-headline-small-size, 1.5rem);
line-height: var(--m3-font-headline-small-height, 1.333);
letter-spacing: var(--m3-font-headline-small-tracking, 0);
font-weight: var(--m3-font-headline-small-weight, 400);
}
/* Titles are smaller than headline styles, and should be used for medium-emphasis text that remains relatively short. */
.m3-font-title-large {
font-size: var(--m3-font-title-large-size, 1.375rem);
line-height: var(--m3-font-title-large-height, 1.273);
letter-spacing: var(--m3-font-title-large-tracking, 0);
font-weight: var(--m3-font-title-large-weight, 400);
}
.m3-font-title-medium {
font-size: var(--m3-font-title-medium-size, 1rem);
line-height: var(--m3-font-title-medium-height, 1.5);
letter-spacing: var(--m3-font-title-medium-tracking, 0);
font-weight: var(--m3-font-title-medium-weight, 500);
}
.m3-font-title-small {
font-size: var(--m3-font-title-small-size, 0.875rem);
line-height: var(--m3-font-title-small-height, 1.429);
letter-spacing: var(--m3-font-title-small-tracking, 0.006rem);
font-weight: var(--m3-font-title-small-weight, 500);
}
/* Label styles are smaller, utilitarian styles, used for things like the text inside components
or for very small text in the content body, such as captions. */
.m3-font-label-large {
font-size: var(--m3-font-label-large-size, 0.875rem);
line-height: var(--m3-font-label-large-height, 1.429);
letter-spacing: var(--m3-font-label-large-tracking, 0.006rem);
font-weight: var(--m3-font-label-large-weight, 500);
}
.m3-font-label-medium {
font-size: var(--m3-font-label-medium-size, 0.75rem);
line-height: var(--m3-font-label-medium-height, 1.333);
letter-spacing: var(--m3-font-label-medium-tracking, 0.031rem);
font-weight: var(--m3-font-label-medium-weight, 500);
}
.m3-font-label-small {
font-size: var(--m3-font-label-small-size, 0.688rem);
line-height: var(--m3-font-label-small-height, 1.455);
letter-spacing: var(--m3-font-label-small-tracking, 0.031rem);
font-weight: var(--m3-font-label-small-weight, 500);
}
/* Body styles are used for longer passages of text in your app. */
.m3-font-body-large {
font-size: var(--m3-font-body-large-size, 1rem);
line-height: var(--m3-font-body-large-height, 1.5);
letter-spacing: var(--m3-font-body-large-tracking, 0);
font-weight: var(--m3-font-body-large-weight, 400);
}
.m3-font-body-medium {
font-size: var(--m3-font-body-medium-size, 0.875rem);
line-height: var(--m3-font-body-medium-height, 1.429);
letter-spacing: var(--m3-font-body-medium-tracking, 0.016rem);
font-weight: var(--m3-font-body-medium-weight, 400);
}
.m3-font-body-small {
font-size: var(--m3-font-body-small-size, 0.75rem);
line-height: var(--m3-font-body-small-height, 1.333);
letter-spacing: var(--m3-font-body-small-tracking, 0.025rem);
font-weight: var(--m3-font-body-small-weight, 400);
}
/* Reset a few things */
@layer base {
*,
*::before,
*::after {
box-sizing: inherit;
}
.m3-container {
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
.m3-container a,
a.m3-container {
text-decoration: none;
}
.m3-container dialog,
dialog.m3-container {
margin: auto;
}
}
/* Emphasized easing timing function derived from this code:
const createBezierLUT = (points: number[][], pointCount: number = 100): number[][] => {
const lut: number[][] = [];
for (let t = 0; t < 1; t += 1 / pointCount) {
const a = (1 - t) * (1 - t) * (1 - t);
const b = (1 - t) * (1 - t) * t;
const c = (1 - t) * t * t;
const d = t * t * t;
const x = a * points[0][0] + 3 * b * points[1][0] + 3 * c * points[2][0] + d * points[3][0];
const y = a * points[0][1] + 3 * b * points[1][1] + 3 * c * points[2][1] + d * points[3][1];
lut.push([x, y]);
}
return lut;
};
const createCSSEaseOptimized = (
lutOptions: number[][][],
maxErrorThreshold: number = 0.01
): string => {
// Create the full lookup table
const lut = lutOptions.map((args) => createBezierLUT(args)).flat();
// Find key points using Douglas-Peucker algorithm
const keyPoints: number[][] = [lut[0], lut[lut.length - 1]];
const segments: number[][] = [[0, lut.length - 1]];
while (segments.length > 0) {
const [startIdx, endIdx] = segments.pop() || [0, 0];
let maxError = 0;
let maxErrorIdx = -1;
// Skip if segment is too small
if (endIdx - startIdx <= 1) continue;
const [startX, startY] = lut[startIdx];
const [endX, endY] = lut[endIdx];
// Find point with maximum error
for (let i = startIdx + 1; i < endIdx; i++) {
const [x, y] = lut[i];
// Linear interpolation
const t = (x - startX) / (endX - startX);
const interpolatedY = startY + t * (endY - startY);
const error = Math.abs(y - interpolatedY);
if (error > maxError) {
maxError = error;
maxErrorIdx = i;
}
}
// If error exceeds threshold, add point and split segment
if (maxError > maxErrorThreshold) {
keyPoints.push(lut[maxErrorIdx]);
segments.push([startIdx, maxErrorIdx]);
segments.push([maxErrorIdx, endIdx]);
}
}
// Sort by x value
keyPoints.sort((a, b) => a[0] - b[0]);
// Format result using CSS linear() with explicit percentages
let result = "linear(";
// First point (no percentage for first point)
result += keyPoints[0][1].toFixed(3);
// Middle points with explicit percentages
for (let i = 1; i < keyPoints.length - 1; i++) {
const [x, y] = keyPoints[i];
const percentage = (x * 100).toFixed(0) + "%";
result += `, ${y.toFixed(3)} ${percentage}`;
}
// Last point (no percentage for last point)
result += `, ${keyPoints[keyPoints.length - 1][1].toFixed(3)}`;
result += ")";
return result;
};
// Example usage
const testInput = [
[
[0, 0],
[0.05, 0],
[0.133, 0.06],
[0.166, 0.4],
],
[
[0.166, 0.4],
[0.208, 0.82],
[0.25, 1],
[1, 1],
],
];
// Run optimized function with a more relaxed threshold for smaller size
const optimizedSmallResult = createCSSEaseOptimized(testInput, 0.01);
console.log("Optimized result (relaxed threshold 0.01):");
console.log(optimizedSmallResult);
*/
:root {
--m3-util-refocus: refocus-outward 0.6s cubic-bezier(0.14, 5.63, 0.4, 0.5) forwards;
}
:focus-visible:not(.focus-inset, .focus-none) {
animation: var(--m3-util-refocus);
outline: none;
}
:focus-visible:is(.focus-inset):not(.focus-none) {
animation: refocus-inward 0.6s cubic-bezier(0.14, 5.63, 0.4, 0.5) forwards;
outline: none;
}
:focus-visible.focus-none {
outline: none;
}
@keyframes refocus-outward {
0% {
box-shadow: 0 0 0 0px rgb(var(--m3-scheme-secondary));
}
100% {
box-shadow: 0 0 0 3px rgb(var(--m3-scheme-secondary));
}
}
@keyframes refocus-inward {
0% {
box-shadow: inset 0 0 0 0px rgb(var(--m3-scheme-secondary));
}
100% {
box-shadow: inset 0 0 0 3px rgb(var(--m3-scheme-secondary));
}
}
[placeholder]::placeholder {
color: rgb(var(--m3-scheme-on-background) / 0.5);
opacity: 1;
}
::selection {
background-color: rgb(var(--m3-scheme-tertiary-container));
color: rgb(var(--m3-scheme-on-tertiary-container));
}
+135
View File
@@ -0,0 +1,135 @@
@import "m3-styles.css";
@media (prefers-color-scheme: light) {
:root {
color-scheme: light;
}
:root, ::backdrop {
--m3-scheme-background: 254 247 255;
--m3-scheme-on-background: 52 49 58;
--m3-scheme-surface: 254 247 255;
--m3-scheme-surface-dim: 222 215 228;
--m3-scheme-surface-bright: 253 247 254;
--m3-scheme-surface-container-lowest: 255 255 255;
--m3-scheme-surface-container-low: 248 241 250;
--m3-scheme-surface-container: 242 236 245;
--m3-scheme-surface-container-high: 236 230 240;
--m3-scheme-surface-container-highest: 231 224 236;
--m3-scheme-on-surface: 52 49 58;
--m3-scheme-on-surface-variant: 97 93 103;
--m3-scheme-outline: 126 121 131;
--m3-scheme-outline-variant: 182 176 187;
--m3-scheme-inverse-surface: 15 13 18;
--m3-scheme-inverse-on-surface: 160 155 161;
--m3-scheme-primary: 101 87 137;
--m3-scheme-primary-dim: 89 75 124;
--m3-scheme-on-primary: 253 247 255;
--m3-scheme-primary-container: 210 192 249;
--m3-scheme-on-primary-container: 72 58 106;
--m3-scheme-primary-fixed: 210 192 249;
--m3-scheme-primary-fixed-dim: 196 179 235;
--m3-scheme-on-primary-fixed: 51 38 84;
--m3-scheme-on-primary-fixed-variant: 81 67 115;
--m3-scheme-inverse-primary: 210 192 249;
--m3-scheme-secondary: 99 92 113;
--m3-scheme-secondary-dim: 86 80 101;
--m3-scheme-on-secondary: 253 247 255;
--m3-scheme-secondary-container: 232 222 248;
--m3-scheme-on-secondary-container: 85 78 99;
--m3-scheme-secondary-fixed: 232 222 248;
--m3-scheme-secondary-fixed-dim: 218 208 234;
--m3-scheme-on-secondary-fixed: 66 60 80;
--m3-scheme-on-secondary-fixed-variant: 95 88 109;
--m3-scheme-tertiary: 124 82 112;
--m3-scheme-tertiary-dim: 111 70 99;
--m3-scheme-on-tertiary: 255 247 249;
--m3-scheme-tertiary-container: 244 191 226;
--m3-scheme-on-tertiary-container: 96 57 85;
--m3-scheme-tertiary-fixed: 244 191 226;
--m3-scheme-tertiary-fixed-dim: 229 178 212;
--m3-scheme-on-tertiary-fixed: 74 38 65;
--m3-scheme-on-tertiary-fixed-variant: 106 66 95;
--m3-scheme-error: 168 54 75;
--m3-scheme-error-dim: 107 2 33;
--m3-scheme-on-error: 255 247 247;
--m3-scheme-error-container: 249 115 134;
--m3-scheme-on-error-container: 110 5 35;
--m3-scheme-shadow: 0 0 0;
--m3-scheme-scrim: 0 0 0;
--m3-scheme-on-on-primary: 101 87 136;
--m3-scheme-primary-container-subtle: 226 211 255;
--m3-scheme-on-primary-container-subtle: 83 69 117;
--m3-scheme-secondary-container-subtle: 224 214 239;
--m3-scheme-on-secondary-container-subtle: 80 73 94;
--m3-scheme-tertiary-container-subtle: 255 203 237;
--m3-scheme-on-tertiary-container-subtle: 103 64 93;
--m3-scheme-error-container-subtle: 255 206 210;
--m3-scheme-on-error-container-subtle: 143 35 57;
}
}
@media (prefers-color-scheme: dark) {
:root {
color-scheme: dark;
}
:root, ::backdrop {
--m3-scheme-background: 15 13 18;
--m3-scheme-on-background: 234 227 239;
--m3-scheme-surface: 15 13 18;
--m3-scheme-surface-dim: 15 13 18;
--m3-scheme-surface-bright: 46 43 52;
--m3-scheme-surface-container-lowest: 0 0 0;
--m3-scheme-surface-container-low: 20 18 24;
--m3-scheme-surface-container: 27 24 31;
--m3-scheme-surface-container-high: 33 30 38;
--m3-scheme-surface-container-highest: 39 36 45;
--m3-scheme-on-surface: 234 227 239;
--m3-scheme-on-surface-variant: 175 169 180;
--m3-scheme-outline: 120 115 126;
--m3-scheme-outline-variant: 74 70 80;
--m3-scheme-inverse-surface: 253 247 254;
--m3-scheme-inverse-on-surface: 87 84 89;
--m3-scheme-primary: 206 192 236;
--m3-scheme-primary-dim: 192 178 222;
--m3-scheme-on-primary: 69 58 95;
--m3-scheme-primary-container: 87 76 114;
--m3-scheme-on-primary-container: 234 222 255;
--m3-scheme-primary-fixed: 220 205 250;
--m3-scheme-primary-fixed-dim: 206 192 236;
--m3-scheme-on-primary-fixed: 59 48 84;
--m3-scheme-on-primary-fixed-variant: 87 77 114;
--m3-scheme-inverse-primary: 100 89 127;
--m3-scheme-secondary: 204 194 219;
--m3-scheme-secondary-dim: 190 181 205;
--m3-scheme-on-secondary: 67 61 81;
--m3-scheme-secondary-container: 62 56 76;
--m3-scheme-on-secondary-container: 196 187 212;
--m3-scheme-secondary-fixed: 232 222 248;
--m3-scheme-secondary-fixed-dim: 218 208 234;
--m3-scheme-on-secondary-fixed: 66 60 80;
--m3-scheme-on-secondary-fixed-variant: 95 88 109;
--m3-scheme-tertiary: 255 207 238;
--m3-scheme-tertiary-dim: 244 191 226;
--m3-scheme-on-tertiary: 105 65 95;
--m3-scheme-tertiary-container: 244 191 226;
--m3-scheme-on-tertiary-container: 96 57 85;
--m3-scheme-tertiary-fixed: 244 191 226;
--m3-scheme-tertiary-fixed-dim: 229 178 212;
--m3-scheme-on-tertiary-fixed: 74 38 65;
--m3-scheme-on-tertiary-fixed-variant: 106 66 95;
--m3-scheme-error: 249 115 134;
--m3-scheme-error-dim: 196 75 95;
--m3-scheme-on-error: 73 0 19;
--m3-scheme-error-container: 135 28 52;
--m3-scheme-on-error-container: 255 151 163;
--m3-scheme-shadow: 0 0 0;
--m3-scheme-scrim: 0 0 0;
--m3-scheme-on-on-primary: 206 191 236;
--m3-scheme-primary-container-subtle: 48 38 73;
--m3-scheme-on-primary-container-subtle: 178 164 207;
--m3-scheme-secondary-container-subtle: 47 41 60;
--m3-scheme-on-secondary-container-subtle: 176 167 191;
--m3-scheme-tertiary-container-subtle: 67 32 59;
--m3-scheme-on-tertiary-container-subtle: 206 156 190;
--m3-scheme-error-container-subtle: 95 0 28;
--m3-scheme-on-error-container-subtle: 255 135 150;
}
}