@placeholderco/placeholder-ui 1.0.3 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +26 -26
- package/README.md +179 -179
- package/dist/display/Alert.svelte +179 -179
- package/dist/display/Avatar.svelte +166 -166
- package/dist/display/LinkCollection.svelte +161 -161
- package/dist/display/Paper.svelte +118 -118
- package/dist/form/Autocomplete.svelte +223 -191
- package/dist/form/Autocomplete.svelte.d.ts +3 -1
- package/dist/form/AutocompleteMulti.svelte +356 -0
- package/dist/form/AutocompleteMulti.svelte.d.ts +28 -0
- package/dist/form/Checkbox.svelte +201 -201
- package/dist/form/Chips.svelte +128 -128
- package/dist/form/ComboBox.svelte +158 -158
- package/dist/form/ComboBox.svelte.d.ts +1 -1
- package/dist/form/ComboBoxItemBuilder.svelte +460 -460
- package/dist/form/ComboBoxMulti.svelte +197 -197
- package/dist/form/ComboBoxMulti.svelte.d.ts +1 -1
- package/dist/form/CronBuilder.svelte +693 -693
- package/dist/form/DatePicker.svelte +672 -672
- package/dist/form/DateTimePicker.svelte +712 -712
- package/dist/form/FileInput.svelte +235 -235
- package/dist/form/FormGroup.svelte +68 -68
- package/dist/form/Number.svelte +238 -238
- package/dist/form/PasswordInput.svelte +252 -252
- package/dist/form/RadioGroup.svelte +210 -210
- package/dist/form/Rating.svelte +235 -235
- package/dist/form/SegmentedControl.svelte +149 -149
- package/dist/form/Select.svelte +590 -590
- package/dist/form/Select.svelte.d.ts +1 -1
- package/dist/form/SelectMulti.svelte +613 -613
- package/dist/form/SelectMulti.svelte.d.ts +1 -1
- package/dist/form/Slider.svelte +358 -358
- package/dist/form/Switch.svelte +147 -147
- package/dist/form/TextArea.svelte +148 -148
- package/dist/form/Textbox.svelte +228 -228
- package/dist/form/TimePicker.svelte +267 -267
- package/dist/icon/Icon.svelte +52 -52
- package/dist/icon/alert-octagon.svg +5 -5
- package/dist/icon/alert-triangle.svg +5 -5
- package/dist/icon/archive.svg +1 -1
- package/dist/icon/arrow-down.svg +1 -1
- package/dist/icon/arrow-left.svg +1 -1
- package/dist/icon/arrow-right.svg +1 -1
- package/dist/icon/arrow-up.svg +1 -1
- package/dist/icon/at.svg +1 -1
- package/dist/icon/bell.svg +1 -1
- package/dist/icon/bookmark.svg +1 -1
- package/dist/icon/calendar.svg +1 -1
- package/dist/icon/camera.svg +1 -1
- package/dist/icon/chart-bar.svg +1 -1
- package/dist/icon/chart-line.svg +1 -1
- package/dist/icon/chart-pie.svg +1 -1
- package/dist/icon/checkbox.svg +1 -1
- package/dist/icon/checklist.svg +1 -1
- package/dist/icon/circle-check.svg +1 -1
- package/dist/icon/circle-x.svg +1 -1
- package/dist/icon/clock.svg +1 -1
- package/dist/icon/credit-card.svg +1 -1
- package/dist/icon/dots-vertical.svg +1 -1
- package/dist/icon/dots.svg +1 -1
- package/dist/icon/external-link.svg +1 -1
- package/dist/icon/eye-off.svg +1 -1
- package/dist/icon/eye.svg +1 -1
- package/dist/icon/filter.svg +1 -1
- package/dist/icon/fingerprint.svg +1 -1
- package/dist/icon/flag.svg +1 -1
- package/dist/icon/heart.svg +1 -1
- package/dist/icon/home.svg +1 -1
- package/dist/icon/key.svg +1 -1
- package/dist/icon/list-check.svg +1 -1
- package/dist/icon/login.svg +1 -1
- package/dist/icon/logout.svg +1 -1
- package/dist/icon/map-pin.svg +1 -1
- package/dist/icon/maximize.svg +1 -1
- package/dist/icon/microphone.svg +1 -1
- package/dist/icon/minimize.svg +1 -1
- package/dist/icon/note.svg +1 -1
- package/dist/icon/player-pause.svg +1 -1
- package/dist/icon/printer.svg +1 -1
- package/dist/icon/qrcode.svg +1 -1
- package/dist/icon/send.svg +1 -1
- package/dist/icon/settings.svg +1 -1
- package/dist/icon/share.svg +1 -1
- package/dist/icon/shopping-cart.svg +1 -1
- package/dist/icon/sort-ascending.svg +1 -1
- package/dist/icon/sort-descending.svg +1 -1
- package/dist/icon/star.svg +1 -1
- package/dist/icon/tag.svg +1 -1
- package/dist/icon/trending-down.svg +1 -1
- package/dist/icon/trending-up.svg +1 -1
- package/dist/icon/upload.svg +1 -1
- package/dist/icon/volume-off.svg +1 -1
- package/dist/icon/volume.svg +1 -1
- package/dist/icon/world.svg +1 -1
- package/dist/icon/zoom-in.svg +1 -1
- package/dist/icon/zoom-out.svg +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/layout/AppShell.svelte +169 -169
- package/dist/layout/CustomNavbar.svelte +61 -61
- package/dist/layout/Navbar.svelte +206 -206
- package/dist/layout/NavbarItemDisplay.svelte +29 -29
- package/dist/layout/Sidenav.svelte +712 -712
- package/dist/styles/components.css +199 -199
- package/dist/styles/dark.css +146 -146
- package/dist/styles/index.css +116 -116
- package/dist/styles/reset.css +110 -110
- package/dist/styles/semantic.css +86 -86
- package/dist/styles/tokens.css +197 -197
- package/dist/styles/utilities.css +523 -523
- package/dist/ui/Accordion.svelte +289 -289
- package/dist/ui/ActionIcon.svelte +76 -76
- package/dist/ui/Badge.svelte +279 -279
- package/dist/ui/Breadcrumbs.svelte +131 -131
- package/dist/ui/Button.svelte +370 -370
- package/dist/ui/Dialog.svelte +307 -307
- package/dist/ui/Drawer.svelte +524 -524
- package/dist/ui/Dropdown.svelte +97 -97
- package/dist/ui/Dropzone.svelte +122 -122
- package/dist/ui/Link.svelte +32 -32
- package/dist/ui/Loader.svelte +70 -70
- package/dist/ui/LoadingOverlay.svelte +53 -53
- package/dist/ui/Pagination.svelte +135 -135
- package/dist/ui/Popover.svelte +225 -225
- package/dist/ui/Progress.svelte +191 -191
- package/dist/ui/RingProgress.svelte +141 -141
- package/dist/ui/Skeleton.svelte +85 -85
- package/dist/ui/Stepper.svelte +355 -355
- package/dist/ui/Table.svelte +345 -345
- package/dist/ui/Tabs.svelte +146 -146
- package/dist/ui/ThemeSwitcher.svelte +39 -39
- package/dist/ui/Timeline.svelte +225 -225
- package/dist/ui/Toaster.svelte +6 -6
- package/dist/ui/Tooltip.svelte +434 -434
- package/package.json +14 -14
package/dist/ui/Tabs.svelte
CHANGED
|
@@ -1,146 +1,146 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import type { ComboBoxItem } from '../models/ComboBoxItem.js';
|
|
3
|
-
import { onMount } from 'svelte';
|
|
4
|
-
|
|
5
|
-
interface Props {
|
|
6
|
-
tabOptions: ComboBoxItem[];
|
|
7
|
-
activeTab?: string;
|
|
8
|
-
solidBg?: boolean;
|
|
9
|
-
onchange?: (newValue: string) => void;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
let { tabOptions, activeTab = $bindable(''), solidBg = false, onchange }: Props = $props();
|
|
13
|
-
let containerRef: HTMLDivElement;
|
|
14
|
-
let buttonElements = $state<HTMLButtonElement[]>([]);
|
|
15
|
-
let underlineStyle = $state('');
|
|
16
|
-
|
|
17
|
-
// Initialize activeTab if empty and tabs are available
|
|
18
|
-
$effect(() => {
|
|
19
|
-
if (!activeTab && tabOptions && tabOptions.length > 0) {
|
|
20
|
-
activeTab = tabOptions[0].value;
|
|
21
|
-
}
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
// Calculate selected index for background positioning using derived state
|
|
25
|
-
const selectedIndex = $derived(
|
|
26
|
-
tabOptions.findIndex((tabOptions) => tabOptions.value === activeTab)
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
onMount(() => {
|
|
30
|
-
// recalculate 10 times on startup to ensure underline is positioned correctly
|
|
31
|
-
for (let i = 0; i < 10; i++) {
|
|
32
|
-
setTimeout(() => {
|
|
33
|
-
if (selectedIndex >= 0 && buttonElements[selectedIndex]) {
|
|
34
|
-
recalculateUnderline();
|
|
35
|
-
}
|
|
36
|
-
}, 100 * i);
|
|
37
|
-
}
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
// Update underline position and size based on selected element
|
|
41
|
-
$effect(() => {
|
|
42
|
-
if (selectedIndex >= 0 && buttonElements[selectedIndex] && containerRef) {
|
|
43
|
-
recalculateUnderline();
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
function recalculateUnderline() {
|
|
48
|
-
const selectedButton = buttonElements[selectedIndex];
|
|
49
|
-
const containerRect = containerRef.getBoundingClientRect();
|
|
50
|
-
const buttonRect = selectedButton.getBoundingClientRect();
|
|
51
|
-
|
|
52
|
-
const offsetLeft = buttonRect.left - containerRect.left;
|
|
53
|
-
const width = buttonRect.width;
|
|
54
|
-
|
|
55
|
-
underlineStyle = `left: ${offsetLeft}px; width: ${width}px;`;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
function setValue(newValue: any) {
|
|
59
|
-
activeTab = newValue;
|
|
60
|
-
onchange?.(newValue);
|
|
61
|
-
}
|
|
62
|
-
</script>
|
|
63
|
-
|
|
64
|
-
<div class="tabs" bind:this={containerRef}>
|
|
65
|
-
{#each tabOptions as option, index}
|
|
66
|
-
{@const isSelected = option.value === activeTab}
|
|
67
|
-
|
|
68
|
-
<button
|
|
69
|
-
bind:this={buttonElements[index]}
|
|
70
|
-
class="tab-item {isSelected ? 'selected' : ''} {solidBg ? 'solid' : ''}"
|
|
71
|
-
onclick={() => setValue(option.value)}
|
|
72
|
-
>
|
|
73
|
-
{option.label}
|
|
74
|
-
</button>
|
|
75
|
-
{/each}
|
|
76
|
-
<div class="tab-underline" style={underlineStyle}></div>
|
|
77
|
-
</div>
|
|
78
|
-
|
|
79
|
-
<style>
|
|
80
|
-
.tabs {
|
|
81
|
-
position: relative;
|
|
82
|
-
display: inline-flex;
|
|
83
|
-
border-bottom: 1px solid var(--pui-border-default);
|
|
84
|
-
user-select: none;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
.tab-item {
|
|
88
|
-
position: relative;
|
|
89
|
-
display: flex;
|
|
90
|
-
align-items: center;
|
|
91
|
-
justify-content: center;
|
|
92
|
-
padding: var(--pui-spacing-3) var(--pui-spacing-6);
|
|
93
|
-
cursor: pointer;
|
|
94
|
-
user-select: none;
|
|
95
|
-
border: none;
|
|
96
|
-
background: transparent;
|
|
97
|
-
font-size: var(--pui-font-size-base);
|
|
98
|
-
font-weight: var(--pui-font-weight-medium);
|
|
99
|
-
color: var(--pui-color-gray-500);
|
|
100
|
-
transition: color var(--pui-transition-fast) var(--pui-ease-in-out);
|
|
101
|
-
z-index: 1;
|
|
102
|
-
border-bottom: 2px solid transparent;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
.tab-item:hover {
|
|
106
|
-
color: var(--pui-color-gray-700);
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
.tab-item.selected {
|
|
110
|
-
color: var(--pui-color-primary);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
.tab-underline {
|
|
114
|
-
position: absolute;
|
|
115
|
-
bottom: -1px;
|
|
116
|
-
height: 2px;
|
|
117
|
-
background-color: var(--pui-color-primary);
|
|
118
|
-
transition: all var(--pui-transition-fast) var(--pui-ease-in-out);
|
|
119
|
-
z-index: 2;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
.solid {
|
|
123
|
-
background: var(--pui-paper-body-bg);
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
/* Dark mode styles */
|
|
127
|
-
:global(.dark) .tabs {
|
|
128
|
-
border-bottom-color: var(--pui-color-gray-700);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
:global(.dark) .tab-item {
|
|
132
|
-
color: var(--pui-color-gray-400);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
:global(.dark) .tab-item:hover {
|
|
136
|
-
color: var(--pui-color-gray-300);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
:global(.dark) .tab-item.selected {
|
|
140
|
-
color: var(--pui-color-secondary);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
:global(.dark) .tab-underline {
|
|
144
|
-
background-color: var(--pui-color-secondary);
|
|
145
|
-
}
|
|
146
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { ComboBoxItem } from '../models/ComboBoxItem.js';
|
|
3
|
+
import { onMount } from 'svelte';
|
|
4
|
+
|
|
5
|
+
interface Props {
|
|
6
|
+
tabOptions: ComboBoxItem[];
|
|
7
|
+
activeTab?: string;
|
|
8
|
+
solidBg?: boolean;
|
|
9
|
+
onchange?: (newValue: string) => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
let { tabOptions, activeTab = $bindable(''), solidBg = false, onchange }: Props = $props();
|
|
13
|
+
let containerRef: HTMLDivElement;
|
|
14
|
+
let buttonElements = $state<HTMLButtonElement[]>([]);
|
|
15
|
+
let underlineStyle = $state('');
|
|
16
|
+
|
|
17
|
+
// Initialize activeTab if empty and tabs are available
|
|
18
|
+
$effect(() => {
|
|
19
|
+
if (!activeTab && tabOptions && tabOptions.length > 0) {
|
|
20
|
+
activeTab = tabOptions[0].value;
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
// Calculate selected index for background positioning using derived state
|
|
25
|
+
const selectedIndex = $derived(
|
|
26
|
+
tabOptions.findIndex((tabOptions) => tabOptions.value === activeTab)
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
onMount(() => {
|
|
30
|
+
// recalculate 10 times on startup to ensure underline is positioned correctly
|
|
31
|
+
for (let i = 0; i < 10; i++) {
|
|
32
|
+
setTimeout(() => {
|
|
33
|
+
if (selectedIndex >= 0 && buttonElements[selectedIndex]) {
|
|
34
|
+
recalculateUnderline();
|
|
35
|
+
}
|
|
36
|
+
}, 100 * i);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Update underline position and size based on selected element
|
|
41
|
+
$effect(() => {
|
|
42
|
+
if (selectedIndex >= 0 && buttonElements[selectedIndex] && containerRef) {
|
|
43
|
+
recalculateUnderline();
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
function recalculateUnderline() {
|
|
48
|
+
const selectedButton = buttonElements[selectedIndex];
|
|
49
|
+
const containerRect = containerRef.getBoundingClientRect();
|
|
50
|
+
const buttonRect = selectedButton.getBoundingClientRect();
|
|
51
|
+
|
|
52
|
+
const offsetLeft = buttonRect.left - containerRect.left;
|
|
53
|
+
const width = buttonRect.width;
|
|
54
|
+
|
|
55
|
+
underlineStyle = `left: ${offsetLeft}px; width: ${width}px;`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function setValue(newValue: any) {
|
|
59
|
+
activeTab = newValue;
|
|
60
|
+
onchange?.(newValue);
|
|
61
|
+
}
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<div class="tabs" bind:this={containerRef}>
|
|
65
|
+
{#each tabOptions as option, index}
|
|
66
|
+
{@const isSelected = option.value === activeTab}
|
|
67
|
+
|
|
68
|
+
<button
|
|
69
|
+
bind:this={buttonElements[index]}
|
|
70
|
+
class="tab-item {isSelected ? 'selected' : ''} {solidBg ? 'solid' : ''}"
|
|
71
|
+
onclick={() => setValue(option.value)}
|
|
72
|
+
>
|
|
73
|
+
{option.label}
|
|
74
|
+
</button>
|
|
75
|
+
{/each}
|
|
76
|
+
<div class="tab-underline" style={underlineStyle}></div>
|
|
77
|
+
</div>
|
|
78
|
+
|
|
79
|
+
<style>
|
|
80
|
+
.tabs {
|
|
81
|
+
position: relative;
|
|
82
|
+
display: inline-flex;
|
|
83
|
+
border-bottom: 1px solid var(--pui-border-default);
|
|
84
|
+
user-select: none;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.tab-item {
|
|
88
|
+
position: relative;
|
|
89
|
+
display: flex;
|
|
90
|
+
align-items: center;
|
|
91
|
+
justify-content: center;
|
|
92
|
+
padding: var(--pui-spacing-3) var(--pui-spacing-6);
|
|
93
|
+
cursor: pointer;
|
|
94
|
+
user-select: none;
|
|
95
|
+
border: none;
|
|
96
|
+
background: transparent;
|
|
97
|
+
font-size: var(--pui-font-size-base);
|
|
98
|
+
font-weight: var(--pui-font-weight-medium);
|
|
99
|
+
color: var(--pui-color-gray-500);
|
|
100
|
+
transition: color var(--pui-transition-fast) var(--pui-ease-in-out);
|
|
101
|
+
z-index: 1;
|
|
102
|
+
border-bottom: 2px solid transparent;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.tab-item:hover {
|
|
106
|
+
color: var(--pui-color-gray-700);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.tab-item.selected {
|
|
110
|
+
color: var(--pui-color-primary);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.tab-underline {
|
|
114
|
+
position: absolute;
|
|
115
|
+
bottom: -1px;
|
|
116
|
+
height: 2px;
|
|
117
|
+
background-color: var(--pui-color-primary);
|
|
118
|
+
transition: all var(--pui-transition-fast) var(--pui-ease-in-out);
|
|
119
|
+
z-index: 2;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.solid {
|
|
123
|
+
background: var(--pui-paper-body-bg);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* Dark mode styles */
|
|
127
|
+
:global(.dark) .tabs {
|
|
128
|
+
border-bottom-color: var(--pui-color-gray-700);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
:global(.dark) .tab-item {
|
|
132
|
+
color: var(--pui-color-gray-400);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
:global(.dark) .tab-item:hover {
|
|
136
|
+
color: var(--pui-color-gray-300);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
:global(.dark) .tab-item.selected {
|
|
140
|
+
color: var(--pui-color-secondary);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
:global(.dark) .tab-underline {
|
|
144
|
+
background-color: var(--pui-color-secondary);
|
|
145
|
+
}
|
|
146
|
+
</style>
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
<script lang="ts">
|
|
2
|
-
import { setTheme, themeState } from '../theme.svelte.js';
|
|
3
|
-
|
|
4
|
-
import sunSvg from '../icon/sun.svg?raw';
|
|
5
|
-
import moonSvg from '../icon/moon.svg?raw';
|
|
6
|
-
import ActionIcon from './ActionIcon.svelte';
|
|
7
|
-
import type { ButtonVariant } from './ButtonVariant.js';
|
|
8
|
-
|
|
9
|
-
interface Props {
|
|
10
|
-
lightVariant?: ButtonVariant;
|
|
11
|
-
darkVariant?: ButtonVariant;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
let { lightVariant = 'primary-subtle', darkVariant = 'secondary-subtle' }: Props = $props();
|
|
15
|
-
|
|
16
|
-
function toggleDarkMode() {
|
|
17
|
-
setTheme(themeState.isDarkMode ? 'light' : 'dark');
|
|
18
|
-
}
|
|
19
|
-
</script>
|
|
20
|
-
|
|
21
|
-
<div class="theme-switcher">
|
|
22
|
-
{#key themeState.isDarkMode}
|
|
23
|
-
<ActionIcon
|
|
24
|
-
variant={themeState.isDarkMode ? darkVariant : lightVariant}
|
|
25
|
-
svg={themeState.isDarkMode ? moonSvg : sunSvg}
|
|
26
|
-
class="action-icon"
|
|
27
|
-
size="1.6em"
|
|
28
|
-
onclick={toggleDarkMode}
|
|
29
|
-
/>
|
|
30
|
-
{/key}
|
|
31
|
-
</div>
|
|
32
|
-
|
|
33
|
-
<style>
|
|
34
|
-
.theme-switcher {
|
|
35
|
-
display: flex;
|
|
36
|
-
justify-content: flex-end;
|
|
37
|
-
align-items: center;
|
|
38
|
-
}
|
|
39
|
-
</style>
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { setTheme, themeState } from '../theme.svelte.js';
|
|
3
|
+
|
|
4
|
+
import sunSvg from '../icon/sun.svg?raw';
|
|
5
|
+
import moonSvg from '../icon/moon.svg?raw';
|
|
6
|
+
import ActionIcon from './ActionIcon.svelte';
|
|
7
|
+
import type { ButtonVariant } from './ButtonVariant.js';
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
lightVariant?: ButtonVariant;
|
|
11
|
+
darkVariant?: ButtonVariant;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let { lightVariant = 'primary-subtle', darkVariant = 'secondary-subtle' }: Props = $props();
|
|
15
|
+
|
|
16
|
+
function toggleDarkMode() {
|
|
17
|
+
setTheme(themeState.isDarkMode ? 'light' : 'dark');
|
|
18
|
+
}
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<div class="theme-switcher">
|
|
22
|
+
{#key themeState.isDarkMode}
|
|
23
|
+
<ActionIcon
|
|
24
|
+
variant={themeState.isDarkMode ? darkVariant : lightVariant}
|
|
25
|
+
svg={themeState.isDarkMode ? moonSvg : sunSvg}
|
|
26
|
+
class="action-icon"
|
|
27
|
+
size="1.6em"
|
|
28
|
+
onclick={toggleDarkMode}
|
|
29
|
+
/>
|
|
30
|
+
{/key}
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
.theme-switcher {
|
|
35
|
+
display: flex;
|
|
36
|
+
justify-content: flex-end;
|
|
37
|
+
align-items: center;
|
|
38
|
+
}
|
|
39
|
+
</style>
|