feat(seasonal): tone down overlays and add visual preview grid in Settings
- New Year: replace flashing animBurst rays with gentle falling confetti - Lunar New Year: reduce 9 lanterns to 4, halve sizes, dim silk/shimmer - April Fools: remove all glitch/scanline/watermark effects; replace with a subtle rainbow stripe and falling punctuation symbols - Add SeasonalPreview export (position:absolute, reduced-motion) for use inside contained card elements - Replace SettingsSelect dropdown for Seasonal Theme with SeasonalBgGrid, a visual card grid (matches ChatBgGrid pattern) showing ambient previews Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -42,8 +42,13 @@ import {
|
||||
DateFormat,
|
||||
MessageLayout,
|
||||
MessageSpacing,
|
||||
Settings,
|
||||
settingsAtom,
|
||||
} from '../../../state/settings';
|
||||
import {
|
||||
SeasonalPreview,
|
||||
SeasonTheme,
|
||||
} from '../../../components/seasonal/SeasonalEffect';
|
||||
import { SettingTile } from '../../../components/setting-tile';
|
||||
import { KeySymbol } from '../../../utils/key-symbol';
|
||||
import { isMacOS } from '../../../utils/user-agent';
|
||||
@@ -488,32 +493,22 @@ function Appearance() {
|
||||
/>
|
||||
</SequenceCard>
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
<SequenceCard
|
||||
className={SequenceCardStyle}
|
||||
variant="SurfaceVariant"
|
||||
direction="Column"
|
||||
gap="200"
|
||||
>
|
||||
<SettingTile
|
||||
title="Seasonal Theme"
|
||||
description="Decorative overlays that activate automatically on holidays and events, or choose one manually."
|
||||
after={
|
||||
<SettingsSelect
|
||||
value={seasonalThemeOverride ?? 'auto'}
|
||||
onChange={(v) => setSeasonalThemeOverride(v as typeof seasonalThemeOverride)}
|
||||
options={[
|
||||
{ value: 'auto', label: '🗓 Auto (date-based)' },
|
||||
{ value: 'off', label: 'Off' },
|
||||
{ value: 'newyear', label: '🎆 New Year' },
|
||||
{ value: 'lunar', label: '🏮 Lunar New Year' },
|
||||
{ value: 'valentines', label: '💖 Valentine\'s Day' },
|
||||
{ value: 'stpatricks', label: '🍀 St. Patrick\'s Day' },
|
||||
{ value: 'aprilfools', label: '🃏 April Fool\'s Day' },
|
||||
{ value: 'earthday', label: '🌱 Earth Day' },
|
||||
{ value: 'autumn', label: '🍂 Autumn' },
|
||||
{ value: 'halloween', label: '🎃 Halloween' },
|
||||
{ value: 'christmas', label: '❄️ Christmas' },
|
||||
{ value: 'arcade', label: '👾 Retro Arcade Day' },
|
||||
{ value: 'deepspace', label: '🚀 Deep Space Week' },
|
||||
]}
|
||||
/>
|
||||
}
|
||||
description="Decorative overlays for holidays and events. Preview below — click to select."
|
||||
/>
|
||||
<Box style={{ padding: `0 ${config.space.S400} ${config.space.S300}` }}>
|
||||
<SeasonalBgGrid
|
||||
value={seasonalThemeOverride ?? 'auto'}
|
||||
onChange={(v) => setSeasonalThemeOverride(v)}
|
||||
/>
|
||||
</Box>
|
||||
</SequenceCard>
|
||||
|
||||
<SequenceCard className={SequenceCardStyle} variant="SurfaceVariant" direction="Column">
|
||||
@@ -1351,6 +1346,89 @@ function Calls() {
|
||||
);
|
||||
}
|
||||
|
||||
const SEASONAL_OPTIONS: { value: Settings['seasonalThemeOverride']; label: string; emoji: string }[] =
|
||||
[
|
||||
{ value: 'auto', label: 'Auto', emoji: '🗓' },
|
||||
{ value: 'off', label: 'Off', emoji: '×' },
|
||||
{ value: 'newyear', label: 'New Year', emoji: '🎆' },
|
||||
{ value: 'lunar', label: 'Lunar New Year', emoji: '🏮' },
|
||||
{ value: 'valentines', label: "Valentine's", emoji: '💖' },
|
||||
{ value: 'stpatricks', label: "St. Patrick's", emoji: '🍀' },
|
||||
{ value: 'aprilfools', label: 'April Fools', emoji: '?' },
|
||||
{ value: 'earthday', label: 'Earth Day', emoji: '🌱' },
|
||||
{ value: 'autumn', label: 'Autumn', emoji: '🍂' },
|
||||
{ value: 'halloween', label: 'Halloween', emoji: '🎃' },
|
||||
{ value: 'christmas', label: 'Christmas', emoji: '❄️' },
|
||||
{ value: 'arcade', label: 'Arcade Day', emoji: '👾' },
|
||||
{ value: 'deepspace', label: 'Deep Space', emoji: '🚀' },
|
||||
];
|
||||
|
||||
function SeasonalBgGrid({
|
||||
value,
|
||||
onChange,
|
||||
}: {
|
||||
value: Settings['seasonalThemeOverride'];
|
||||
onChange: (v: Settings['seasonalThemeOverride']) => void;
|
||||
}) {
|
||||
return (
|
||||
<Box wrap="Wrap" gap="200">
|
||||
{SEASONAL_OPTIONS.map((opt) => {
|
||||
const selected = value === opt.value;
|
||||
const isSpecial = opt.value === 'auto' || opt.value === 'off';
|
||||
return (
|
||||
<Box key={opt.value} direction="Column" gap="100" style={{ alignItems: 'center' }}>
|
||||
<button
|
||||
type="button"
|
||||
aria-label={opt.label}
|
||||
aria-pressed={selected}
|
||||
onClick={() => onChange(opt.value)}
|
||||
style={{
|
||||
position: 'relative',
|
||||
display: 'block',
|
||||
width: toRem(76),
|
||||
height: toRem(56),
|
||||
borderRadius: toRem(8),
|
||||
cursor: 'pointer',
|
||||
border: selected
|
||||
? `2px solid ${color.Critical.Main}`
|
||||
: '2px solid rgba(128,128,128,0.25)',
|
||||
padding: 0,
|
||||
overflow: 'hidden',
|
||||
backgroundColor: '#030508',
|
||||
}}
|
||||
>
|
||||
{!isSpecial && <SeasonalPreview theme={opt.value as SeasonTheme} />}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
inset: 0,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
backgroundImage:
|
||||
opt.value === 'auto'
|
||||
? 'linear-gradient(135deg, rgba(255,100,0,0.2), rgba(255,200,0,0.2), rgba(0,200,100,0.2), rgba(0,100,255,0.2))'
|
||||
: undefined,
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
>
|
||||
{isSpecial && (
|
||||
<span style={{ fontSize: '22px', opacity: opt.value === 'off' ? 0.4 : 1 }}>
|
||||
{opt.emoji}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</button>
|
||||
<Text size="T200" style={selected ? { color: color.Critical.Main } : undefined}>
|
||||
{opt.label}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
function ChatBgGrid() {
|
||||
const [chatBackground, setChatBackground] = useSetting(settingsAtom, 'chatBackground');
|
||||
const [pauseAnimations] = useSetting(settingsAtom, 'pauseAnimations');
|
||||
|
||||
Reference in New Issue
Block a user