= 2 ? 1 : 0,
+ transform: stage >= 2 ? "translateY(0)" : "translateY(-20px)",
+ transition: "opacity 0.3s ease-out, transform 0.3s ease-out",
}}
>
- {/* X button */}
+
+ esc
+
+
+
+
{/* Bottom line / loading wave */}
@@ -1186,7 +1229,7 @@ export default function SearchOverlay({
Showing{" "}
updateFilters({ section: (section || null) as SearchFilters["section"] })}
@@ -1194,14 +1237,14 @@ export default function SearchOverlay({
from{" "}
updateFilters({ range: range as SearchFilters["range"] })}
/>,{" "}
updateFilters({ sort: sort as SearchFilters["sort"] })}
diff --git a/components/ThemeStyle.tsx b/components/ThemeStyle.tsx
index b0d75c8..ac8fbd8 100644
--- a/components/ThemeStyle.tsx
+++ b/components/ThemeStyle.tsx
@@ -1,8 +1,9 @@
-import type { ThemeColors } from '@/lib/getTheme'
+import type { HeaderAnimationConfig, ThemeColors } from '@/lib/getTheme'
type Props = {
lightMode: ThemeColors
darkMode: ThemeColors
+ headerAnimation: HeaderAnimationConfig
}
// Allow only valid CSS color values: hex, rgb(), rgba(), hsl(), hsla(), named colors.
@@ -42,10 +43,25 @@ function colorVars(colors: ThemeColors): string {
return lines.join('\n')
}
-export default function ThemeStyle({ lightMode, darkMode }: Props) {
+// The header wave's colors, so other effects (like the search filters) can match it.
+function waveVars(animation: HeaderAnimationConfig): string {
+ return ([
+ ['--wave-color-1', animation.waveColor1],
+ ['--wave-color-2', animation.waveColor2],
+ ['--wave-color-3', animation.waveColor3],
+ ] as const)
+ .map(([prop, val]) => {
+ const safe = sanitizeCssColor(val)
+ return safe ? ` ${prop}: ${safe};` : null
+ })
+ .filter(Boolean)
+ .join('\n')
+}
+
+export default function ThemeStyle({ lightMode, darkMode, headerAnimation }: Props) {
// Use html:root (higher specificity than :root alone) so this always wins
// over the bare :root block in globals.css regardless of stylesheet load order.
- const css = `html:root {\n${colorVars(lightMode)}\n}\nhtml.dark:root {\n${colorVars(darkMode)}\n}`
+ const css = `html:root {\n${colorVars(lightMode)}\n${waveVars(headerAnimation)}\n}\nhtml.dark:root {\n${colorVars(darkMode)}\n}`
// Values are sanitized above — only valid CSS color syntax passes through.
// eslint-disable-next-line react/no-danger
return