feat(ui): Implement Dynamic Color system and M3 Forms (Stage 2)

- Integrated @material/material-color-utilities for HCT-based color generation
- Implemented M3 Filled Text Field with floating labels and state layers
- Added Seed Color picker and palette preview to Settings
- Updated Login page with new M3 components
- Enhanced ThemeProvider with system preference listeners

Refs #3
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-04-11 01:16:36 +03:00
parent db0b93b007
commit b71076450c
11 changed files with 493 additions and 82 deletions

View File

@@ -12,7 +12,11 @@
--md-sys-color-surface-variant: #dfe2eb;
--md-sys-color-on-surface-variant: #43474e;
--md-sys-color-outline: #73777f;
--md-sys-color-outline-variant: #c3c7cf;
--md-sys-color-error: #ba1a1a;
--md-sys-color-on-error: #ffffff;
--md-sys-color-background: #fdfcff;
--md-sys-color-on-background: #1a1c1e;
--nav-rail-width: 80px;
--nav-rail-expanded-width: 280px;
@@ -33,7 +37,11 @@
--md-sys-color-surface-variant: #43474e;
--md-sys-color-on-surface-variant: #c3c7cf;
--md-sys-color-outline: #8d9199;
--md-sys-color-outline-variant: #43474e;
--md-sys-color-error: #ffb4ab;
--md-sys-color-on-error: #690005;
--md-sys-color-background: #1a1c1e;
--md-sys-color-on-background: #e2e2e6;
}
* {
@@ -44,8 +52,8 @@
body {
font-family: 'Roboto', 'Segoe UI', system-ui, -apple-system, sans-serif;
background-color: var(--md-sys-color-surface);
color: var(--md-sys-color-on-surface);
background-color: var(--md-sys-color-background);
color: var(--md-sys-color-on-background);
line-height: 1.5;
transition: background-color 0.3s, color 0.3s;
}
@@ -57,7 +65,7 @@ body {
top: -4px;
right: -4px;
background-color: var(--md-sys-color-error);
color: white;
color: var(--md-sys-color-on-error);
font-size: 10px;
font-weight: 500;
min-width: 16px;
@@ -80,10 +88,13 @@ body {
border: none;
color: var(--md-sys-color-on-surface-variant);
transition: background-color 0.2s;
cursor: pointer;
position: relative;
overflow: hidden;
}
.icon-button:hover {
background-color: var(--md-sys-color-surface-variant);
background-color: rgba(var(--md-sys-color-on-surface-variant-rgb, 67, 71, 78), 0.08);
}
.m3-button {
@@ -97,10 +108,11 @@ body {
font-weight: 500;
font-size: 14px;
letter-spacing: 0.1px;
transition: box-shadow 0.2s, background-color 0.2s;
transition: all 0.2s;
background-color: transparent;
color: var(--md-sys-color-primary);
text-decoration: none;
cursor: pointer;
}
.m3-button-filled {
@@ -108,11 +120,20 @@ body {
color: var(--md-sys-color-on-primary);
}
.m3-button-filled:hover {
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
}
.m3-button-tonal {
background-color: var(--md-sys-color-secondary-container);
color: var(--md-sys-color-on-secondary-container);
}
.m3-button-outlined {
border: 1px solid var(--md-sys-color-outline);
color: var(--md-sys-color-primary);
}
.m3-card {
background-color: var(--md-sys-color-surface-variant);
color: var(--md-sys-color-on-surface-variant);
@@ -121,16 +142,98 @@ body {
margin-bottom: 16px;
}
.m3-text-field {
/* M3 Filled Text Field */
.m3-text-field-container {
display: flex;
flex-direction: column;
margin-bottom: 16px;
width: 100%;
padding: 12px 16px;
border-radius: 4px 4px 0 0;
border: none;
border-bottom: 1px solid var(--md-sys-color-outline);
}
.m3-text-field-field {
position: relative;
height: 56px;
background-color: var(--md-sys-color-surface-variant);
border-radius: 4px 4px 0 0;
overflow: hidden;
}
.m3-text-field-input {
width: 100%;
height: 100%;
padding: 24px 16px 8px;
border: none;
background: transparent;
color: var(--md-sys-color-on-surface);
font-size: 16px;
outline: none;
z-index: 1;
}
.m3-text-field-label {
position: absolute;
left: 16px;
top: 16px;
color: var(--md-sys-color-on-surface-variant);
font-size: 16px;
margin-bottom: 16px;
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
pointer-events: none;
z-index: 2;
}
.m3-text-field-container.focused .m3-text-field-label,
.m3-text-field-container.filled .m3-text-field-label {
top: 8px;
font-size: 12px;
color: var(--md-sys-color-primary);
}
.m3-text-field-active-indicator {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 1px;
background-color: var(--md-sys-color-on-surface-variant);
transition: height 0.2s, background-color 0.2s;
}
.m3-text-field-container.focused .m3-text-field-active-indicator {
height: 2px;
background-color: var(--md-sys-color-primary);
}
.m3-text-field-state-layer {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: var(--md-sys-color-on-surface);
opacity: 0;
transition: opacity 0.2s;
pointer-events: none;
}
.m3-text-field-field:hover .m3-text-field-state-layer {
opacity: 0.08;
}
.m3-text-field-container.error .m3-text-field-label,
.m3-text-field-container.error .m3-text-field-active-indicator {
color: var(--md-sys-color-error);
background-color: var(--md-sys-color-error);
}
.m3-text-field-supporting-text {
font-size: 12px;
padding: 4px 16px 0;
color: var(--md-sys-color-on-surface-variant);
}
.m3-text-field-container.error .m3-text-field-supporting-text {
color: var(--md-sys-color-error);
}
/* Layout */
@@ -191,7 +294,7 @@ body {
display: flex;
flex-direction: column;
padding: 16px 0;
border-right: 1px solid var(--md-sys-color-outline);
border-right: 1px solid var(--md-sys-color-outline-variant);
z-index: 100;
transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
overflow-x: hidden;
@@ -216,6 +319,46 @@ body {
white-space: nowrap;
}
.user-info {
display: flex;
align-items: center;
padding: 16px;
gap: 12px;
margin-bottom: 8px;
}
.user-avatar {
width: 40px;
height: 40px;
border-radius: 20px;
background-color: var(--md-sys-color-primary-container);
color: var(--md-sys-color-on-primary-container);
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
flex-shrink: 0;
}
.user-details {
display: flex;
flex-direction: column;
overflow: hidden;
}
.user-name {
font-size: 14px;
font-weight: 500;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.user-group {
font-size: 12px;
opacity: 0.7;
}
.rail-items {
display: flex;
flex-direction: column;