|
7 | 7 | /** @type import('./public.d.ts').ResolvedConfig */ |
8 | 8 | config |
9 | 9 | } = $props(); |
10 | | - let open = $state(true); // todo change this to false |
| 10 | + let open = $state(false); // Default to closed |
11 | 11 |
|
12 | 12 | /** @type {SvelteMap<string, Record<string, any>>} */ |
13 | 13 | let active_tools = $state(new SvelteMap()); |
|
20 | 20 | let dragOffsetY = 0; |
21 | 21 |
|
22 | 22 | onMount(() => { |
| 23 | + toolbar.style.right = '20px'; |
| 24 | + toolbar.style.bottom = '20px'; |
23 | 25 | recalculate_toolbar_panel_position(); |
24 | 26 | }); |
25 | 27 |
|
|
33 | 35 | if (tool.component) mounted_component = mountTool(tool.component, tool.name, { tool }); |
34 | 36 |
|
35 | 37 | active_tools.set(tool.name, mounted_component); |
36 | | - tool.activate(); |
| 38 | + if (tool.activate) tool.activate(); |
37 | 39 | } else { |
38 | 40 | const mounted_component = active_tools.get(tool.name); |
39 | 41 | if (tool.component && mounted_component) unmountTool(mounted_component, tool.name); |
40 | 42 |
|
41 | | - tool.deactivate(); |
| 43 | + if (tool.deactivate) tool.deactivate(); |
42 | 44 | active_tools.delete(tool.name); |
43 | 45 | } |
| 46 | +
|
| 47 | + if (active_tools.size === 0) toolbarPanels.style.display = 'none'; |
| 48 | + else toolbarPanels.style.display = 'block'; |
44 | 49 | } |
45 | 50 |
|
46 | 51 | /** |
|
99 | 104 |
|
100 | 105 | async function toggle_toolbar() { |
101 | 106 | open = !open; |
102 | | -
|
103 | | - // need to wait here, so that the toolbar can close first |
104 | 107 | await tick(); |
105 | | -
|
106 | 108 | recalculate_toolbar_panel_position(); |
107 | 109 | } |
108 | 110 |
|
109 | 111 | function recalculate_toolbar_panel_position() { |
110 | 112 | const rect = toolbar.getBoundingClientRect(); |
111 | 113 | toolbarPanels.style.right = toolbar.style.right; |
112 | | - toolbarPanels.style.bottom = parseFloat(toolbar.style.bottom ?? 0) + rect.height + 'px'; |
| 114 | + toolbarPanels.style.bottom = parseFloat(toolbar.style.bottom ?? 0) + rect.height + 10 + 'px'; // Add a small gap |
113 | 115 | } |
114 | 116 | </script> |
115 | 117 |
|
116 | 118 | <svelte:window onresize={recalculate_toolbar_panel_position} /> |
117 | 119 |
|
118 | 120 | <div |
119 | | - class="toolbar" |
| 121 | + class="svelte-toolbar" |
120 | 122 | bind:this={toolbar} |
121 | 123 | draggable="true" |
122 | 124 | ondrag={drag} |
|
125 | 127 | tabindex="-1" |
126 | 128 | > |
127 | 129 | {#if open} |
128 | | - <ul class="tools"> |
| 130 | + <ul class="svelte-toolbar-tools"> |
129 | 131 | {#each config.tools as tool} |
130 | 132 | <li class:active={active_tools.has(tool.name)}> |
131 | 133 | <button onclick={() => toggle_tool(tool)} aria-label={tool.name}>{@html tool.icon}</button |
|
134 | 136 | {/each} |
135 | 137 | </ul> |
136 | 138 | {/if} |
137 | | - <button type="button" class="toolbar-selector" onclick={toggle_toolbar}> |
| 139 | + <button type="button" class="svelte-toolbar-selector" onclick={toggle_toolbar}> |
138 | 140 | <Icon /> |
139 | 141 | </button> |
140 | 142 | </div> |
141 | | -<div class="toolbar-panels" bind:this={toolbarPanels}></div> |
| 143 | +<div class="svelte-toolbar-panels" bind:this={toolbarPanels}></div> |
142 | 144 |
|
143 | 145 | <style> |
144 | | - .toolbar-selector { |
| 146 | + .svelte-toolbar { |
| 147 | + display: inline-flex; |
| 148 | + background-color: var(--toolbar-background); |
| 149 | + color: var(--toolbar-color); |
| 150 | + position: fixed; |
| 151 | + z-index: 1000; |
| 152 | + border-radius: 8px; |
| 153 | + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15); |
| 154 | + padding: 8px; |
| 155 | + } |
| 156 | +
|
| 157 | + .svelte-toolbar-selector { |
145 | 158 | cursor: pointer; |
| 159 | + background: none; |
| 160 | + border: none; |
| 161 | + padding: 8px; |
| 162 | + border-radius: 6px; |
| 163 | + transition: background-color 0.2s ease-in-out; |
146 | 164 | } |
147 | 165 |
|
148 | | - .toolbar-selector :global(svg) { |
149 | | - width: 50px; |
150 | | - height: 50px; |
| 166 | + .svelte-toolbar-selector:hover { |
| 167 | + background-color: var(--toolbar-selector-hover-background); |
151 | 168 | } |
152 | 169 |
|
153 | | - .tools { |
| 170 | + .svelte-toolbar-selector :global(svg) { |
| 171 | + width: 24px; |
| 172 | + height: 24px; |
| 173 | + fill: var(--toolbar-icon-color); |
| 174 | + } |
| 175 | +
|
| 176 | + .svelte-toolbar-tools { |
154 | 177 | list-style: none; |
155 | 178 | margin: 0; |
156 | 179 | padding: 0; |
157 | 180 | display: flex; |
158 | 181 | align-items: center; |
159 | 182 | } |
160 | 183 |
|
161 | | - .tools li { |
| 184 | + .svelte-toolbar-tools li { |
162 | 185 | display: inline-block; |
163 | | - background-color: #444; |
164 | | - border: #111 1px solid; |
165 | | - border-radius: 50%; |
166 | | - margin: 0 10px; |
167 | | - height: 50px; |
168 | | - width: 50px; |
169 | | - } |
170 | | -
|
171 | | - .tools li.active { |
172 | | - border-color: #ff3e00; |
| 186 | + margin: 0 4px; |
173 | 187 | } |
174 | 188 |
|
175 | | - .tools li button { |
176 | | - padding: 0; |
| 189 | + .svelte-toolbar-tools li button { |
| 190 | + padding: 8px; |
177 | 191 | display: flex; |
178 | 192 | align-items: center; |
179 | 193 | justify-content: center; |
180 | | - width: 100%; |
181 | | - height: 100%; |
| 194 | + width: 36px; |
| 195 | + height: 36px; |
| 196 | + border-radius: 50%; |
| 197 | + border: none; |
| 198 | + background-color: var(--tool-button-background); |
| 199 | + color: var(--tool-button-color); |
| 200 | + cursor: pointer; |
| 201 | + transition: |
| 202 | + background-color 0.2s ease-in-out, |
| 203 | + border-color 0.2s ease-in-out; |
182 | 204 | } |
183 | 205 |
|
184 | | - .tools li button :global(svg) { |
185 | | - height: 30px; |
186 | | - width: 30px; |
| 206 | + .svelte-toolbar-tools li button:hover { |
| 207 | + background-color: var(--tool-button-hover-background); |
187 | 208 | } |
188 | 209 |
|
189 | | - .toolbar { |
190 | | - display: inline-flex; |
191 | | - background-color: #666; /* TODO: consider dark / light mode */ |
192 | | - color: white; |
193 | | - position: fixed; |
194 | | - right: 0; |
195 | | - bottom: 0; |
| 210 | + .svelte-toolbar-tools li.active button { |
| 211 | + border: 2px solid var(--accent-color); |
| 212 | + } |
| 213 | +
|
| 214 | + .svelte-toolbar-tools li :global(svg) { |
| 215 | + filter: grayscale(100%); |
| 216 | + } |
| 217 | +
|
| 218 | + .svelte-toolbar-tools li.active :global(svg) { |
| 219 | + filter: unset; |
| 220 | + } |
| 221 | +
|
| 222 | + .svelte-toolbar-tools li button :global(svg) { |
| 223 | + height: 20px; |
| 224 | + width: 20px; |
| 225 | + fill: var(--tool-icon-color); |
196 | 226 | } |
197 | 227 |
|
198 | | - .toolbar-panels { |
| 228 | + .svelte-toolbar-panels { |
199 | 229 | position: fixed; |
200 | | - background-color: #999; |
201 | | - right: 0; |
202 | | - bottom: 0; |
203 | | - display: flex; |
| 230 | + z-index: 999; |
| 231 | + background-color: var(--panel-background); |
| 232 | + border-radius: 8px; |
| 233 | + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); |
| 234 | + padding: 16px; |
| 235 | + display: none; |
| 236 | + flex-direction: column; |
| 237 | + gap: 8px; |
| 238 | + color: var(--toolbar-color); |
| 239 | + } |
| 240 | +
|
| 241 | + :root { |
| 242 | + --toolbar-background: #f0f0f0; |
| 243 | + --toolbar-color: #222; |
| 244 | + --toolbar-selector-hover-background: #e0e0e0; |
| 245 | + --toolbar-icon-color: #333; |
| 246 | + --tool-button-background: #fff; |
| 247 | + --tool-button-color: #333; |
| 248 | + --tool-button-hover-background: #eee; |
| 249 | + --tool-icon-color: #333; |
| 250 | + --accent-color: #ff3e00; |
| 251 | + --panel-background: #fff; |
| 252 | + } |
| 253 | +
|
| 254 | + @media (prefers-color-scheme: dark) { |
| 255 | + :root { |
| 256 | + --toolbar-background: #1e1e27; |
| 257 | + --toolbar-color: white; |
| 258 | + --toolbar-selector-hover-background: #333344; |
| 259 | + --toolbar-icon-color: #d4d4d8; |
| 260 | + --tool-button-background: #333344; |
| 261 | + --tool-button-color: #d4d4d8; |
| 262 | + --tool-button-hover-background: #444; |
| 263 | + --tool-icon-color: #d4d4d8; |
| 264 | + --accent-color: #ff3e00; |
| 265 | + --panel-background: #252531; |
| 266 | + } |
204 | 267 | } |
205 | 268 | </style> |
0 commit comments