Merge pull request 'update: better color support on wishlists' (#5) from update/wishlist-color-update-updates-background-and-svg-color into master
Reviewed-on: #5
This commit was merged in pull request #5.
This commit is contained in:
@@ -13,6 +13,7 @@
|
||||
}
|
||||
|
||||
:root {
|
||||
color-scheme: light;
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.129 0.042 264.695);
|
||||
@@ -48,6 +49,7 @@
|
||||
}
|
||||
|
||||
.dark {
|
||||
color-scheme: dark;
|
||||
--background: oklch(0.129 0.042 264.695);
|
||||
--foreground: oklch(0.984 0.003 247.858);
|
||||
--card: oklch(0.208 0.042 265.755);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte';
|
||||
import ThemeBackground from '$lib/components/themes/ThemeBackground.svelte';
|
||||
import { hexToRgba } from '$lib/utils/colors';
|
||||
import { themeStore } from '$lib/stores/theme.svelte';
|
||||
|
||||
let {
|
||||
children,
|
||||
@@ -13,9 +15,20 @@
|
||||
theme?: string | null;
|
||||
themeColor?: string | null;
|
||||
} = $props();
|
||||
|
||||
const backgroundStyle = $derived.by(() => {
|
||||
if (!themeColor) return '';
|
||||
|
||||
const isDark = themeStore.getResolvedTheme() === 'dark';
|
||||
const tintedColor = hexToRgba(themeColor, 0.15);
|
||||
|
||||
return isDark
|
||||
? `background: linear-gradient(${tintedColor}, ${tintedColor}), #000000;`
|
||||
: `background-color: ${tintedColor};`;
|
||||
});
|
||||
</script>
|
||||
|
||||
<div class="min-h-screen p-4 md:p-8 relative overflow-hidden">
|
||||
<div class="min-h-screen p-4 md:p-8 relative overflow-hidden" style={backgroundStyle}>
|
||||
<ThemeBackground themeName={theme} color={themeColor} />
|
||||
<div class="max-w-{maxWidth} mx-auto space-y-6 relative z-10">
|
||||
{@render children()}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script lang="ts">
|
||||
import TopPattern from './svgs/TopPattern.svelte';
|
||||
import BottomPattern from './svgs/BottomPattern.svelte';
|
||||
import { getTheme, getPatternColor, PATTERN_OPACITY } from '$lib/utils/themes';
|
||||
import { getTheme, PATTERN_OPACITY } from '$lib/utils/themes';
|
||||
import { themeStore } from '$lib/stores/theme.svelte';
|
||||
|
||||
let {
|
||||
themeName,
|
||||
@@ -16,7 +17,10 @@
|
||||
} = $props();
|
||||
|
||||
const theme = $derived(getTheme(themeName));
|
||||
const patternColor = $derived(getPatternColor(color));
|
||||
const patternColor = $derived.by(() => {
|
||||
const isDark = themeStore.getResolvedTheme() === 'dark';
|
||||
return isDark ? '#FFFFFF' : '#000000';
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if theme.pattern !== 'none'}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import CardPattern from './svgs/CardPattern.svelte';
|
||||
import { getTheme, getPatternColor, PATTERN_OPACITY } from '$lib/utils/themes';
|
||||
import { getTheme, PATTERN_OPACITY } from '$lib/utils/themes';
|
||||
import { themeStore } from '$lib/stores/theme.svelte';
|
||||
|
||||
let {
|
||||
themeName,
|
||||
@@ -11,7 +12,10 @@
|
||||
} = $props();
|
||||
|
||||
const theme = $derived(getTheme(themeName));
|
||||
const patternColor = $derived(getPatternColor(color));
|
||||
const patternColor = $derived.by(() => {
|
||||
const isDark = themeStore.getResolvedTheme() === 'dark';
|
||||
return isDark ? '#FFFFFF' : '#000000';
|
||||
});
|
||||
</script>
|
||||
|
||||
{#if theme.pattern !== 'none'}
|
||||
|
||||
@@ -13,13 +13,15 @@
|
||||
rearranging,
|
||||
onStartEditing,
|
||||
onReorder,
|
||||
theme = null
|
||||
theme = null,
|
||||
wishlistColor = null
|
||||
}: {
|
||||
items: Item[];
|
||||
rearranging: boolean;
|
||||
onStartEditing: (item: Item) => void;
|
||||
onReorder: (items: Item[]) => Promise<void>;
|
||||
theme?: string | null;
|
||||
wishlistColor?: string | null;
|
||||
} = $props();
|
||||
|
||||
const t = $derived(languageStore.t);
|
||||
@@ -30,7 +32,7 @@
|
||||
<div class="space-y-4">
|
||||
{#each items as item (item.id)}
|
||||
<div animate:flip={{ duration: 300 }}>
|
||||
<WishlistItem {item} {theme} showDragHandle={false}>
|
||||
<WishlistItem {item} {theme} {wishlistColor} showDragHandle={false}>
|
||||
<div class="flex gap-2">
|
||||
<Button
|
||||
type="button"
|
||||
|
||||
@@ -4,15 +4,18 @@
|
||||
import { Label } from '$lib/components/ui/label';
|
||||
import { Card, CardContent } from '$lib/components/ui/card';
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
import { getCardStyle } from '$lib/utils/colors';
|
||||
|
||||
interface Props {
|
||||
publicUrl: string;
|
||||
ownerUrl?: string;
|
||||
wishlistColor?: string | null;
|
||||
}
|
||||
|
||||
let { publicUrl, ownerUrl }: Props = $props();
|
||||
let { publicUrl, ownerUrl, wishlistColor = null }: Props = $props();
|
||||
|
||||
const t = $derived(languageStore.t);
|
||||
const cardStyle = $derived(getCardStyle(null, wishlistColor));
|
||||
|
||||
let copiedPublic = $state(false);
|
||||
let copiedOwner = $state(false);
|
||||
@@ -34,7 +37,7 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<Card>
|
||||
<Card style={cardStyle}>
|
||||
<CardContent class="space-y-4 pt-6">
|
||||
<div class="space-y-2">
|
||||
<Label>{t.wishlist.shareViewOnly}</Label>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
import ThemePicker from "$lib/components/ui/theme-picker.svelte";
|
||||
import type { Wishlist } from "$lib/server/schema";
|
||||
import { languageStore } from '$lib/stores/language.svelte';
|
||||
import { getCardStyle } from '$lib/utils/colors';
|
||||
|
||||
let {
|
||||
wishlist,
|
||||
@@ -39,6 +40,8 @@
|
||||
: null,
|
||||
);
|
||||
|
||||
const cardStyle = $derived(getCardStyle(null, wishlistColor));
|
||||
|
||||
async function saveTitle() {
|
||||
if (!wishlistTitle.trim()) {
|
||||
wishlistTitle = wishlist.title;
|
||||
@@ -134,7 +137,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Settings Card -->
|
||||
<Card>
|
||||
<Card style={cardStyle}>
|
||||
<CardContent class="pt-6 space-y-4">
|
||||
<!-- Description -->
|
||||
<div class="space-y-2">
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
children?: any;
|
||||
showDragHandle?: boolean;
|
||||
theme?: string | null;
|
||||
wishlistColor?: string | null;
|
||||
}
|
||||
|
||||
let {
|
||||
@@ -20,7 +21,8 @@
|
||||
showImage = true,
|
||||
children,
|
||||
showDragHandle = false,
|
||||
theme = null
|
||||
theme = null,
|
||||
wishlistColor = null
|
||||
}: Props = $props();
|
||||
|
||||
const t = $derived(languageStore.t);
|
||||
@@ -51,7 +53,7 @@
|
||||
return `${symbol}${amount}`;
|
||||
}
|
||||
|
||||
const cardStyle = $derived(getCardStyle(item.color));
|
||||
const cardStyle = $derived(getCardStyle(item.color, wishlistColor));
|
||||
</script>
|
||||
|
||||
<Card style={cardStyle} class="relative overflow-hidden">
|
||||
|
||||
@@ -5,6 +5,7 @@ type ResolvedTheme = 'light' | 'dark';
|
||||
|
||||
class ThemeStore {
|
||||
current = $state<Theme>('system');
|
||||
resolved = $state<ResolvedTheme>('light');
|
||||
|
||||
constructor() {
|
||||
if (browser) {
|
||||
@@ -27,6 +28,8 @@ class ThemeStore {
|
||||
const isDark = this.current === 'dark' ||
|
||||
(this.current === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||
|
||||
this.resolved = isDark ? 'dark' : 'light';
|
||||
|
||||
if (isDark) {
|
||||
document.documentElement.classList.add('dark');
|
||||
} else {
|
||||
@@ -35,11 +38,7 @@ class ThemeStore {
|
||||
}
|
||||
|
||||
getResolvedTheme(): ResolvedTheme {
|
||||
if (!browser) return 'light';
|
||||
|
||||
const isDark = this.current === 'dark' ||
|
||||
(this.current === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
|
||||
return isDark ? 'dark' : 'light';
|
||||
return this.resolved;
|
||||
}
|
||||
|
||||
toggle() {
|
||||
|
||||
@@ -11,8 +11,10 @@ export function hexToRgba(hex: string, alpha: number): string {
|
||||
/**
|
||||
* Generate card style string with color, transparency, and blur
|
||||
*/
|
||||
export function getCardStyle(color: string | null): string {
|
||||
if (!color) return '';
|
||||
export function getCardStyle(color: string | null, fallbackColor?: string | null): string {
|
||||
const activeColor = color || fallbackColor;
|
||||
if (!activeColor) return '';
|
||||
|
||||
return `background-color: ${hexToRgba(color, 0.2)} !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(10px) !important;`;
|
||||
const opacity = color ? 0.2 : 0.15;
|
||||
return `background-color: ${hexToRgba(activeColor, opacity)} !important; backdrop-filter: blur(10px) !important; -webkit-backdrop-filter: blur(10px) !important;`;
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
<div class="space-y-4">
|
||||
{#if filteredItems.length > 0}
|
||||
{#each filteredItems as item}
|
||||
<WishlistItem {item} theme={data.wishlist.theme}>
|
||||
<WishlistItem {item} theme={data.wishlist.theme} wishlistColor={data.wishlist.color}>
|
||||
<ReservationButton
|
||||
itemId={item.id}
|
||||
isReserved={item.isReserved}
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
let editFormElement = $state<HTMLElement | null>(null);
|
||||
let searchQuery = $state("");
|
||||
let currentTheme = $state(data.wishlist.theme || 'none');
|
||||
let currentColor = $state(data.wishlist.color);
|
||||
|
||||
let items = $state<Item[]>([]);
|
||||
|
||||
@@ -111,9 +112,14 @@
|
||||
currentTheme = theme || 'none';
|
||||
await wishlistUpdates.updateTheme(theme);
|
||||
}
|
||||
|
||||
async function handleColorUpdate(color: string | null) {
|
||||
currentColor = color;
|
||||
await wishlistUpdates.updateColor(color);
|
||||
}
|
||||
</script>
|
||||
|
||||
<PageContainer maxWidth="4xl" theme={currentTheme} themeColor={data.wishlist.color}>
|
||||
<PageContainer maxWidth="4xl" theme={currentTheme} themeColor={currentColor}>
|
||||
<Navigation
|
||||
isAuthenticated={data.isAuthenticated}
|
||||
showDashboardLink={true}
|
||||
@@ -123,7 +129,7 @@
|
||||
wishlist={data.wishlist}
|
||||
onTitleUpdate={wishlistUpdates.updateTitle}
|
||||
onDescriptionUpdate={wishlistUpdates.updateDescription}
|
||||
onColorUpdate={wishlistUpdates.updateColor}
|
||||
onColorUpdate={handleColorUpdate}
|
||||
onEndDateUpdate={wishlistUpdates.updateEndDate}
|
||||
onThemeUpdate={handleThemeUpdate}
|
||||
/>
|
||||
@@ -131,6 +137,7 @@
|
||||
<ShareLinks
|
||||
publicUrl={data.publicUrl}
|
||||
ownerUrl="/wishlist/{data.wishlist.ownerToken}/edit"
|
||||
wishlistColor={currentColor}
|
||||
/>
|
||||
|
||||
<ClaimWishlistSection
|
||||
@@ -176,6 +183,7 @@
|
||||
onStartEditing={startEditing}
|
||||
onReorder={handleReorder}
|
||||
theme={currentTheme}
|
||||
wishlistColor={currentColor}
|
||||
/>
|
||||
|
||||
<DangerZone bind:unlocked={rearranging} />
|
||||
|
||||
Reference in New Issue
Block a user