Fix Color Animation Implementation

This commit is contained in:
copecone committed 2026-04-07 16:02:58 +09:00
1 parent 7cf7c49937
commit 57588d4604
5 files changed
+98 -27

No files matched your search

+24 -13
View File
@@ -3,32 +3,43 @@ import { RouterOutlet } from '@angular/router';
import { HeaderMenu } from './features/header-menu/header-menu'; import { HeaderMenu } from './features/header-menu/header-menu';
import { PopupService } from './services/popup.service'; import { PopupService } from './services/popup.service';
import { SettingsService } from './services/settings.service'; import { SettingsService } from './services/settings.service';
import { NgComponentOutlet, isPlatformBrowser } from '@angular/common'; import { NgComponentOutlet, isPlatformBrowser, isPlatformServer, DOCUMENT } from '@angular/common';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
imports: [RouterOutlet, HeaderMenu, NgComponentOutlet], imports: [RouterOutlet, HeaderMenu, NgComponentOutlet],
templateUrl: './app.html', templateUrl: './app.html',
styleUrl: './app.scss' styleUrl: './app.scss',
}) })
export class App { export class App {
protected popupService = inject(PopupService); protected popupService = inject(PopupService);
protected settingsService = inject(SettingsService); protected settingsService = inject(SettingsService);
private platformId = inject(PLATFORM_ID); private platformId = inject(PLATFORM_ID);
private document = inject(DOCUMENT);
private rootHtmlElement!: HTMLElement;
constructor() { constructor() {
if (isPlatformServer(this.platformId)) {
this.rootHtmlElement = this.document.documentElement;
} else if (isPlatformBrowser(this.platformId)) {
this.rootHtmlElement = document.documentElement;
}
effect(() => { effect(() => {
if (isPlatformBrowser(this.platformId)) { this.initializeStatus();
const isDark = this.settingsService.darkMode();
document.documentElement.classList.toggle('dark-theme', isDark);
document.documentElement.classList.toggle('light-theme', !isDark);
const lang = this.settingsService.language();
document.documentElement.lang = lang.toLowerCase();
const reduceMotion = this.settingsService.reduceAnimation();
document.documentElement.classList.toggle('reduce-motion', reduceMotion);
}
}); });
} }
initializeStatus() {
const isDark = this.settingsService.darkMode();
this.rootHtmlElement.classList.toggle('dark-theme', isDark);
this.rootHtmlElement.classList.toggle('light-theme', !isDark);
const lang = this.settingsService.language();
this.rootHtmlElement.lang = lang.toLowerCase();
const reduceMotion = this.settingsService.reduceAnimation();
this.rootHtmlElement.classList.toggle('reduce-motion', reduceMotion);
}
} }
+27 -3
View File
@@ -13,6 +13,18 @@ $border_radius: 8px;
$animation_timing: cubic-bezier(0.4, 0, 0.2, 1); $animation_timing: cubic-bezier(0.4, 0, 0.2, 1);
$default_animation_duration: 0.2s; $default_animation_duration: 0.2s;
@property --hover-state {
syntax: '<number>';
inherits: false;
initial-value: 0;
}
@property --selected-state {
syntax: '<number>';
inherits: false;
initial-value: 0;
}
:host { :host {
display: inline-block; display: inline-block;
position: relative; position: relative;
@@ -113,15 +125,27 @@ $default_animation_duration: 0.2s;
padding: 0 16px; padding: 0 16px;
position: relative; position: relative;
align-content: center; align-content: center;
transition: background-color var(--animation-duration) $animation_timing; transition: --hover-state var(--animation-duration) $animation_timing, --selected-state var(--animation-duration) $animation_timing;
font-size: 16px; font-size: 16px;
background-color: color-mix(
in oklch,
color-mix(
in oklch,
transparent,
light-dark($hover_bg, $hover_dark_bg)
calc(var(--hover-state) * 100%)
),
light-dark(list.nth(library.$brand_palette, 1), list.nth(library.$brand_palette, 11))
calc(var(--selected-state) * 100%)
);
&:hover, &.focused { &:hover, &.focused {
background-color: light-dark($hover_bg, $hover_dark_bg); --hover-state: 1;
} }
&.selected { &.selected {
background-color: light-dark(list.nth(library.$brand_palette, 1), list.nth(library.$brand_palette, 11)); --selected-state: 1;
color: list.nth(library.$brand_palette, 5); color: list.nth(library.$brand_palette, 5);
font-weight: 600; font-weight: 600;
} }
+23 -5
View File
@@ -1,6 +1,12 @@
$animation_timing: cubic-bezier(0.16, 1, 0.3, 1); $animation_timing: cubic-bezier(0.16, 1, 0.3, 1);
$default_animation_duration: 0.2s; $default_animation_duration: 0.2s;
@property --close-hover-state {
syntax: '<number>';
inherits: false;
initial-value: 0;
}
:host { :host {
display: block; display: block;
--animation-duration: calc(#{$default_animation_duration} * var(--motion-duration-multiplier)); --animation-duration: calc(#{$default_animation_duration} * var(--motion-duration-multiplier));
@@ -77,17 +83,29 @@ $default_animation_duration: 0.2s;
.header-right { .header-right {
.close-btn { .close-btn {
background: none; --close-hover-state: 0;
border: none; border: none;
padding: 4px; padding: 4px;
cursor: pointer; cursor: pointer;
border-radius: 50%; border-radius: 50%;
color: oklch(0.4 0 0);
transition: background-color 0.2s, color 0.2s; background: color-mix(
in oklch,
transparent,
light-dark(oklch(0 0 0 / 5%), oklch(1 0 0 / 5%))
calc(var(--close-hover-state) * 100%)
);
color: color-mix(
in oklch,
light-dark(oklch(0.4 0 0), oklch(0.6 0 0)),
light-dark(oklch(0 0 0), oklch(1 0 0))
calc(var(--close-hover-state) * 100%)
);
transition: --close-hover-state 0.2s;
&:hover { &:hover {
background-color: oklch(0 0 0 / 5%); --close-hover-state: 1;
color: oklch(0 0 0);
} }
} }
} }
+23 -5
View File
@@ -16,16 +16,35 @@ $border_dark_color: oklch(1 0 0 / 40%);
$animation_timing: cubic-bezier(0.4, 0, 0.2, 1); $animation_timing: cubic-bezier(0.4, 0, 0.2, 1);
$default_animation_duration: 0.2s; $default_animation_duration: 0.2s;
@property --animation-state {
syntax: '<number>';
inherits: false;
initial-value: 0;
}
:host { :host {
display: inline-block; display: inline-block;
width: list.nth($dimension, 1); height: list.nth($dimension, 2); width: list.nth($dimension, 1); height: list.nth($dimension, 2);
border-radius: $border_radius; border-radius: $border_radius;
background-color: light-dark($off_bg, $off_dark_bg); background-color: color-mix(
box-shadow: 0 0 0 1px light-dark($border_color, $border_dark_color) inset; in oklch,
light-dark($off_bg, $off_dark_bg),
light-dark(list.nth(library.$brand_palette, 5), list.nth(library.$brand_palette, 8))
calc(var(--animation-state) * 100%)
);
box-shadow: 0 0 0 1px color-mix(
in oklch,
light-dark($border_color, $border_dark_color),
light-dark($border_color, list.nth(library.$brand_palette, 10))
calc(var(--animation-state) * 100%)
) inset;
--animation-state: 0;
--animation-duration: calc(#{$default_animation_duration} * var(--motion-duration-multiplier)); --animation-duration: calc(#{$default_animation_duration} * var(--motion-duration-multiplier));
transition: background-color var(--animation-duration) $animation_timing, box-shadow var(--animation-duration) $animation_timing; // transition: background-color var(--animation-duration) $animation_timing, box-shadow var(--animation-duration) $animation_timing;
transition: --animation-state var(--animation-duration) $animation_timing;
cursor: pointer; cursor: pointer;
position: relative; position: relative;
@@ -38,8 +57,7 @@ $default_animation_duration: 0.2s;
} }
&.active { &.active {
background-color: light-dark(list.nth(library.$brand_palette, 5), list.nth(library.$brand_palette, 9)); --animation-state: 1;
box-shadow: var(--if-dark, 0 0 0 1px list.nth(library.$brand_palette, 10) inset);
.switch-knob { .switch-knob {
transform: translate( transform: translate(
+1 -1
View File
@@ -13,7 +13,7 @@
.avatar { .avatar {
border-radius: 50%; border-radius: 50%;
border: 1px solid oklch(0 0 0 / 20%); outline: 1px solid oklch(0 0 0 / 20%);
object-fit: cover; object-fit: cover;
} }
} }