Implement dark theme

This commit is contained in:
ninjadev64 committed 2024-05-28 10:50:10 +01:00
1 parent 23538d2004
commit 03807b09ff
21 files changed
+114 -64

No files matched your search

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

After

Width:  |  Height:  |  Size: 84 KiB

+1
View File
@@ -27,6 +27,7 @@ OpenDeck supports ProntoKey and Elgato Stream Deck hardware on all three major d
## Showcase
![Dark mode](.github/readme/darkmode.png)
![Main menu](.github/readme/mainmenu.png)
![Multi action](.github/readme/multiaction.png)
![Plugins](.github/readme/plugins.png)
+2
View File
@@ -54,6 +54,7 @@ where
pub struct Settings {
pub language: String,
pub autolaunch: bool,
pub darktheme: bool
}
impl Default for Settings {
@@ -61,6 +62,7 @@ impl Default for Settings {
Self {
language: "en".to_owned(),
autolaunch: false,
darktheme: false
}
}
}
+22
View File
@@ -1,3 +1,25 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
select {
@apply
appearance-none
px-2 py-1
text-sm text-neutral-700 dark:text-neutral-300
bg-neutral-100 dark:bg-neutral-700
border-2 dark:border-neutral-900 outline-none
cursor-pointer
}
.select-wrapper {
@apply relative
}
.select-wrapper::after {
@apply
absolute right-4 top-[47.5%] -translate-y-1/2
w-2 h-2 rotate-45
border-r-2 border-b-2
pointer-events-none content-['_']
}
+1 -1
View File
@@ -25,7 +25,7 @@
<div class="grow mt-1 overflow-auto">
{#each Object.entries(categories) as [ name, actions ]}
<h3 class="text-xl font-semibold"> {name} </h3>
<h3 class="text-xl font-semibold dark:text-neutral-300"> {name} </h3>
{#each actions as action}
{#if action.visible_in_action_list}
<ListedAction {action} localisation={localiseAction(action, $localisations)} />
+8 -6
View File
@@ -28,10 +28,12 @@
listen("devices", ({ payload }: { payload: { [id: string]: DeviceInfo }}) => devices = payload);
</script>
<select bind:value class="w-full">
<option value="" disabled selected> Choose a device... </option>
<div class="select-wrapper">
<select bind:value class="w-full">
<option value="" disabled selected> Choose a device... </option>
{#each Object.entries(devices).sort() as [ id, device ]}
<option value={id}> {device.name} </option>
{/each}
</select>
{#each Object.entries(devices).sort() as [ id, device ]}
<option value={id}> {device.name} </option>
{/each}
</select>
</div>
+1 -1
View File
@@ -90,7 +90,7 @@
</script>
<div
class="relative m-2 border-2 rounded-md select-none"
class="relative m-2 border-2 dark:border-neutral-700 rounded-md select-none"
style="width: calc(8rem * {scale}); height: calc(8rem * {scale});"
on:dragover on:drop
draggable on:dragstart
+1 -1
View File
@@ -17,5 +17,5 @@
draggable
on:dragstart={handleDragStart}
/>
<span> {localisation.name} </span>
<span class="dark:text-neutral-400"> {localisation.name} </span>
</div>
+5 -5
View File
@@ -44,16 +44,16 @@
context = null!;
</script>
<div class="px-6 pt-6 pb-4">
<div class="px-6 pt-6 pb-4 dark:text-neutral-300">
<button class="float-right text-xl" on:click={() => $inspectedMultiAction = null}> ✕ </button>
<h1 class="font-semibold text-2xl"> Multi Action </h1>
</div>
<div class="flex flex-col h-80 overflow-scroll">
{#each slot as instance, index}
<div class="flex flex-row items-center mx-4 my-1 bg-gray-100 rounded-md">
<div class="flex flex-row items-center mx-4 my-1 bg-neutral-100 dark:bg-neutral-900 rounded-md">
<Key slot={[instance]} {context} active={false} scale={3/4} />
<p class="ml-4 text-xl"> {instance.action.name} </p>
<p class="ml-4 text-xl dark:text-neutral-400"> {instance.action.name} </p>
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<img
src="/rubbish.png"
@@ -64,11 +64,11 @@
</div>
{/each}
<div
class="flex flex-row items-center mx-4 mt-1 mb-4 bg-gray-100 border-2 border-dashed rounded-md"
class="flex flex-row items-center mx-4 mt-1 mb-4 bg-neutral-100 dark:bg-neutral-900 border-2 border-dashed dark:border-neutral-700 rounded-md"
on:dragover={handleDragOver} on:drop={handleDrop}
role="cell" tabindex="-1"
>
<img src="/cube.png" class="m-2 w-24 rounded-xl" alt="Add new action" />
<p class="ml-4 text-xl text-gray-500"> Drop actions here </p>
<p class="ml-4 text-xl text-neutral-500"> Drop actions here </p>
</div>
</div>
+11 -11
View File
@@ -40,22 +40,22 @@
</script>
<button
class="mt-2 p-1 w-1/2 text-sm text-gray-700 bg-gray-100 border rounded-lg"
class="mt-2 p-1 w-1/2 text-sm text-neutral-700 dark:text-neutral-300 bg-neutral-100 dark:bg-neutral-700 border dark:border-neutral-600 rounded-lg"
on:click={() => showPopup = true}
>
Plugins
</button>
<Popup show={showPopup}>
<button class="mr-2 my-1 float-right text-xl" on:click={() => showPopup = false}> ✕ </button>
<h2 class="m-2 font-semibold text-xl"> Manage plugins </h2>
<button class="mr-2 my-1 float-right text-xl dark:text-neutral-300" on:click={() => showPopup = false}> ✕ </button>
<h2 class="m-2 font-semibold text-xl dark:text-neutral-300"> Manage plugins </h2>
<h2 class="mx-2 mt-6 mb-2 text-lg"> Installed plugins </h2>
<h2 class="mx-2 mt-6 mb-2 text-lg dark:text-neutral-400"> Installed plugins </h2>
<div class="grid grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{#each plugins as plugin}
<div class="flex flex-row items-center m-2 p-2 bg-gray-200 rounded-md">
<div class="flex flex-row items-center m-2 p-2 bg-neutral-200 dark:bg-neutral-700 rounded-md">
<img src={"http://localhost:57118/" + plugin.icon} class="w-24 rounded-md" alt={plugin.name} />
<div class="ml-4 mr-2">
<div class="ml-4 mr-2 dark:text-neutral-300">
<p>
<span class="font-semibold">
{($localisations && $localisations[plugin.id] && $localisations[plugin.id].Name) ? $localisations[plugin.id].Name : plugin.name}
@@ -77,14 +77,14 @@
</div>
{#await fetch("https://plugins.amansprojects.com/catalogue.json")}
<h2 class="mx-2 mt-6 mb-2 text-md"> Loading plugin list... </h2>
<h2 class="mx-2 mt-6 mb-2 text-md dark:text-neutral-400"> Loading plugin list... </h2>
{:then res}
{#await res.json() then entries}
<h2 class="mx-2 mt-6 mb-2 text-lg"> Plugin store </h2>
<h2 class="mx-2 mt-6 mb-2 text-lg dark:text-neutral-400"> Plugin store </h2>
<div class="flex flex-row m-2">
<input
bind:value={search}
class="grow p-2 rounded-md outline-none"
class="grow p-2 dark:text-neutral-300 dark:bg-neutral-700 rounded-md outline-none"
placeholder="Search plugins"
type="search"
spellcheck="false"
@@ -93,11 +93,11 @@
<div class="grid grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
{#each entries as plugin}
<div
class="flex flex-row items-center m-2 p-2 bg-gray-200 rounded-md"
class="flex flex-row items-center m-2 p-2 bg-neutral-200 dark:bg-neutral-700 rounded-md"
class:hidden={!plugin.name.toUpperCase().includes(search.toUpperCase())}
>
<img src="https://plugins.amansprojects.com/icons/{plugin.id}.png" class="w-24 rounded-md" alt={plugin.name} />
<div class="ml-4 mr-2">
<div class="ml-4 mr-2 dark:text-neutral-300">
<p class="font-semibold"> {plugin.name} </p>
{plugin.author}
</div>
+1 -1
View File
@@ -3,7 +3,7 @@
</script>
{#if show}
<div class="absolute top-0 left-0 m-2 p-4 w-[calc(100%-1rem)] h-[calc(100%-1rem)] bg-gray-100 border-2 rounded-lg overflow-scroll">
<div class="absolute top-0 left-0 m-2 p-4 w-[calc(100%-1rem)] h-[calc(100%-1rem)] bg-neutral-100 dark:bg-neutral-800 border-2 dark:border-neutral-700 rounded-lg overflow-scroll z-30">
<slot />
</div>
{/if}
+14 -12
View File
@@ -55,20 +55,22 @@
});
</script>
<select bind:value class="mt-1 w-full">
{#each profiles as profile}
<option value={profile}> {profile} </option>
{/each}
<option value="opendeck_edit_profiles"> Edit... </option>
</select>
<div class="select-wrapper">
<select bind:value class="mt-1 w-full">
{#each profiles as profile}
<option value={profile}> {profile} </option>
{/each}
<option value="opendeck_edit_profiles"> Edit... </option>
</select>
</div>
<Popup show={showPopup}>
<button class="mr-1 float-right text-xl" on:click={() => showPopup = false}> ✕ </button>
<h2 class="text-xl font-semibold"> {device.name} </h2>
<button class="mr-1 float-right text-xl dark:text-neutral-300" on:click={() => showPopup = false}> ✕ </button>
<h2 class="text-xl font-semibold dark:text-neutral-300"> {device.name} </h2>
<div class="flex flex-row mt-2 mb-1">
<input class="grow p-2 rounded-l-md outline-none" placeholder="Profile name" bind:value={nameInput} />
<button class="px-4 bg-gray-200 rounded-r-md" on:click={async () => {
<input class="grow p-2 dark:text-neutral-300 dark:bg-neutral-700 rounded-l-md outline-none" placeholder="Profile name" bind:value={nameInput} />
<button class="px-4 dark:text-neutral-300 bg-neutral-200 dark:bg-neutral-900 rounded-r-md" on:click={async () => {
await setProfile(nameInput);
value = nameInput;
nameInput = "";
@@ -77,10 +79,10 @@
</div>
<div class="space-y-2 divide-y">
{#each profiles as profile, i}
{#each profiles as profile}
<div class="pt-2">
<input type="radio" bind:group={value} value={profile} />
{profile}
<span class="dark:text-neutral-400"> {profile} </span>
{#if profile != value}
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
<img
+2 -2
View File
@@ -98,11 +98,11 @@
$: instances = profile.keys.reduce((prev, current) => prev.concat(current), []).concat(profile.sliders.reduce((prev, current) => prev.concat(current), []));
</script>
<div class="grow overflow-scroll bg-white border-t" bind:this={iframeContainer}>
<div class="grow overflow-scroll bg-white dark:bg-neutral-900 border-t dark:border-neutral-700 z-20" bind:this={iframeContainer}>
<button
bind:this={iframeClosePopup}
on:click={() => closePopup(iframePopupsOpen[iframePopupsOpen.length - 1])}
class="absolute top-2 right-2 text-2xl font-bold hidden"
class="absolute top-2 right-2 text-2xl dark:text-neutral-300 font-bold hidden"
>
✕
</button>
+34 -15
View File
@@ -6,30 +6,44 @@
import Tooltip from "./Tooltip.svelte";
let showPopup = false;
settings.subscribe((settings) => {
if (settings) updateTheme(settings.darktheme);
});
function updateTheme(darktheme: boolean) {
if (darktheme) {
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
}
}
</script>
<button
class="ml-2 mt-2 p-1 w-1/2 text-sm text-gray-700 bg-gray-100 border rounded-lg"
class="ml-2 mt-2 p-1 w-1/2 text-sm text-neutral-700 dark:text-neutral-300 bg-neutral-100 dark:bg-neutral-700 border dark:border-neutral-600 rounded-lg"
on:click={() => showPopup = true}
>
Settings
</button>
<Popup show={showPopup}>
<button class="mr-2 my-1 float-right text-xl" on:click={() => showPopup = false}> ✕ </button>
<h2 class="m-2 font-semibold text-xl"> Settings </h2>
<button class="mr-2 my-1 float-right text-xl dark:text-neutral-300" on:click={() => showPopup = false}> ✕ </button>
<h2 class="m-2 font-semibold text-xl dark:text-neutral-300"> Settings </h2>
{#if $settings}
<div class="flex flex-row items-center m-2 space-x-2">
<span> Language: </span>
<select bind:value={$settings.language}>
<option value="en"> English </option>
<option value="es"> Español </option>
<option value="zh_CN"> 中文 </option>
<option value="fr"> Français </option>
<option value="de"> Deutsch </option>
<option value="ja"> 日本語 </option>
<option value="ko"> 韓国語 </option>
</select>
<span class="dark:text-neutral-400"> Language: </span>
<div class="select-wrapper">
<select bind:value={$settings.language} class="w-32">
<option value="en"> English </option>
<option value="es"> Español </option>
<option value="zh_CN"> 中文 </option>
<option value="fr"> Français </option>
<option value="de"> Deutsch </option>
<option value="ja"> 日本語 </option>
<option value="ko"> 韓国語 </option>
</select>
</div>
<Tooltip>
OpenDeck itself is not yet translated.
Changing this setting will translate the text from installed plugins into your language for those that support it.
@@ -37,13 +51,18 @@
</div>
<div class="flex flex-row items-center m-2 space-x-2">
<span> Autolaunch: </span>
<span class="dark:text-neutral-400"> Autolaunch: </span>
<input type="checkbox" bind:checked={$settings.autolaunch} />
<Tooltip> If this option is enabled, OpenDeck will automatically start at login. </Tooltip>
</div>
<div class="flex flex-row items-center m-2 space-x-2">
<span class="dark:text-neutral-400"> Dark theme: </span>
<input type="checkbox" bind:checked={$settings.darktheme} />
</div>
{/if}
<button
class="ml-2 mt-2 px-2 py-1 text-sm text-gray-700 bg-gray-100 border rounded-lg"
class="ml-2 mt-2 px-2 py-1 text-sm text-neutral-700 dark:text-neutral-300 bg-neutral-100 dark:bg-neutral-700 border dark:border-neutral-600 rounded-lg"
on:click={() => invoke("open_config_directory")}
>
Open config directory
+3 -3
View File
@@ -58,7 +58,7 @@
</script>
<div
class="relative flex items-center m-2 w-20 h-144 border-2 rounded-md select-none"
class="relative flex items-center m-2 w-20 h-144 border-2 dark:border-neutral-700 rounded-md select-none"
on:dragover on:drop
draggable on:dragstart
role="cell" tabindex="-1"
@@ -94,7 +94,7 @@
<img
src="/alert.png"
alt="Alert"
class="absolute top-0 left-0 p-1 w-full aspect-square top-[50%] -translate-y-1/2 transition-opacity duration-1000"
class="absolute left-0 p-1 w-full aspect-square top-[50%] -translate-y-1/2 transition-opacity duration-1000"
class:opacity-0={showAlert == 2}
/>
{/if}
@@ -102,7 +102,7 @@
<img
src="/ok.png"
alt="OK"
class="absolute top-0 left-0 p-1 w-full aspect-square top-[50%] -translate-y-1/2 transition-opacity duration-1000"
class="absolute left-0 p-1 w-full aspect-square top-[50%] -translate-y-1/2 transition-opacity duration-1000"
class:opacity-0={showOk == 2}
/>
{/if}
+1 -1
View File
@@ -10,7 +10,7 @@
>
<img src="/question.png" class="w-6" alt="Help" />
{#if show}
<div class="absolute mt-2 p-2 w-96 text-xs bg-gray-100 border-2 rounded-lg">
<div class="absolute mt-2 p-2 w-96 text-xs dark:text-neutral-300 bg-neutral-100 dark:bg-neutral-700 border-2 dark:border-neutral-600 rounded-lg">
<slot />
</div>
{/if}
+2 -1
View File
@@ -1,6 +1,7 @@
export type Settings = {
language: string,
autolaunch: boolean
autolaunch: boolean,
darktheme: boolean
};
import { invoke } from "@tauri-apps/api";
+1 -1
View File
@@ -2,6 +2,6 @@
import "../app.css";
</script>
<div class="flex flex-row h-screen">
<div class="flex flex-row h-screen dark:bg-neutral-900">
<slot />
</div>
+2 -2
View File
@@ -34,7 +34,7 @@
{/if}
</div>
<div class="flex flex-col p-2 grow max-w-[18rem] h-full border-l">
<div class="flex flex-col p-2 grow max-w-[18rem] h-full border-l dark:border-neutral-700">
{#if !$inspectedMultiAction}
<DeviceSelector bind:device={selectedDevice} />
{#if selectedDevice}
@@ -42,7 +42,7 @@
{/if}
{/if}
<ActionList bind:this={actionList} />
<hr class="mt-2 border" />
<hr class="mt-2 border dark:border-neutral-700" />
<div class="flex flex-row">
<PluginManager {actionList} />
<SettingsView />
+2 -1
View File
@@ -4,5 +4,6 @@ export default {
theme: {
extend: {}
},
plugins: []
plugins: [],
darkMode: "selector"
}