feat(ThemeSwitch): create ThemeSwitch component that uses ThemeMager toggle to switch theme
This commit is contained in:
2
src/features/ChangeAppTheme/index.ts
Normal file
2
src/features/ChangeAppTheme/index.ts
Normal file
@@ -0,0 +1,2 @@
|
||||
export * from './model';
|
||||
export * from './ui';
|
||||
1
src/features/ChangeAppTheme/model/index.ts
Normal file
1
src/features/ChangeAppTheme/model/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { themeManager } from './store/ThemeManager/ThemeManager.svelte';
|
||||
@@ -0,0 +1,59 @@
|
||||
<script module>
|
||||
import { defineMeta } from '@storybook/addon-svelte-csf';
|
||||
import ThemeSwitch from './ThemeSwitch.svelte';
|
||||
|
||||
const { Story } = defineMeta({
|
||||
title: 'Features/ThemeSwitch',
|
||||
component: ThemeSwitch,
|
||||
tags: ['autodocs'],
|
||||
parameters: {
|
||||
docs: {
|
||||
description: {
|
||||
component:
|
||||
'Theme toggle button that switches between light and dark modes. Uses ThemeManager to persist user preference and sync with system preference. Displays sun/moon icon based on current theme.',
|
||||
},
|
||||
story: { inline: false },
|
||||
},
|
||||
},
|
||||
argTypes: {
|
||||
// ThemeSwitch has no explicit props - it uses themeManager internally
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<script lang="ts">
|
||||
import { themeManager } from '$features/ChangeAppTheme';
|
||||
import {
|
||||
onDestroy,
|
||||
onMount,
|
||||
} from 'svelte';
|
||||
|
||||
// Current theme state for display
|
||||
const currentTheme = $derived(themeManager.value);
|
||||
const themeSource = $derived(themeManager.source);
|
||||
const isDark = $derived(themeManager.isDark);
|
||||
|
||||
// Initialize themeManager on mount
|
||||
onMount(() => {
|
||||
themeManager.init();
|
||||
});
|
||||
|
||||
// Clean up themeManager when story unmounts
|
||||
onDestroy(() => {
|
||||
themeManager.destroy();
|
||||
});
|
||||
</script>
|
||||
|
||||
<Story name="Default">
|
||||
<div class="flex items-center justify-center p-8 gap-4">
|
||||
<ThemeSwitch />
|
||||
<div class="text-sm text-muted-foreground">
|
||||
Theme: <span class="font-semibold">{currentTheme}</span>
|
||||
{#if themeSource === 'user'}
|
||||
<span class="text-xs ml-2">(user preference)</span>
|
||||
{:else}
|
||||
<span class="text-xs ml-2">(system preference)</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</Story>
|
||||
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
Component: ThemeSwitch
|
||||
Toggles the theme between light and dark mode.
|
||||
-->
|
||||
<script lang="ts">
|
||||
import type { ResponsiveManager } from '$shared/lib';
|
||||
import { IconButton } from '$shared/ui';
|
||||
import MoonIcon from '@lucide/svelte/icons/moon';
|
||||
import SunIcon from '@lucide/svelte/icons/sun';
|
||||
import { getContext } from 'svelte';
|
||||
import { themeManager } from '../../model';
|
||||
|
||||
const responsive = getContext<ResponsiveManager>('responsive');
|
||||
|
||||
const theme = $derived(themeManager.value);
|
||||
</script>
|
||||
|
||||
<IconButton onclick={() => themeManager.toggle()} size={responsive.isMobile ? 'sm' : 'md'} title="Toggle theme">
|
||||
{#snippet icon()}
|
||||
{#if theme === 'light'}
|
||||
<MoonIcon />
|
||||
{:else}
|
||||
<SunIcon />
|
||||
{/if}
|
||||
{/snippet}
|
||||
</IconButton>
|
||||
1
src/features/ChangeAppTheme/ui/index.ts
Normal file
1
src/features/ChangeAppTheme/ui/index.ts
Normal file
@@ -0,0 +1 @@
|
||||
export { default as ThemeSwitch } from './ThemeSwitch/ThemeSwitch.svelte';
|
||||
Reference in New Issue
Block a user