summaryrefslogtreecommitdiffstats
path: root/apps/web-shared/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web-shared/src/components')
-rw-r--r--apps/web-shared/src/components/theme-switcher.svelte425
1 files changed, 425 insertions, 0 deletions
diff --git a/apps/web-shared/src/components/theme-switcher.svelte b/apps/web-shared/src/components/theme-switcher.svelte
new file mode 100644
index 0000000..26ae507
--- /dev/null
+++ b/apps/web-shared/src/components/theme-switcher.svelte
@@ -0,0 +1,425 @@
+<script lang="ts">
+ import {base_domain, CookieNames} from "$shared/lib/configuration";
+ import {get_cookie, set_cookie} from "$shared/lib/helpers";
+ import {onMount} from "svelte";
+
+ type theme = "system"|"dark"|"light";
+
+ export let show = false;
+ export let selection: theme = "system";
+ export let size;
+ let prefers = window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
+ onMount(() => {
+ selection = get_cookie(CookieNames.theme) as theme;
+ document.addEventListener("keydown", (e) => {
+ if (e.code === "Esc") show = false;
+ });
+ document.addEventListener("click", (e: any) => {
+ if (e.target.closest("[data-theme-switcher-element]") === null) show = false;
+ });
+ });
+ let html = document.querySelector("html");
+
+ window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", (event) => {
+ prefers = event.matches ? "dark" : "light";
+ });
+
+ $: switch (selection || prefers) {
+ case "system":
+ html.dataset.theme = prefers;
+ break;
+ case "light":
+ html.dataset.theme = "light";
+ break;
+ case "dark":
+ html.dataset.theme = "dark";
+ break;
+ }
+
+ function change(to: theme) {
+ selection = to;
+ set_cookie(CookieNames.theme, selection, base_domain());
+ }
+</script>
+
+<div class="ld-switch" data-theme-switcher-element>
+ <button class="reset ld-switch-btn"
+ on:click={() => show =!show}>
+ <span class="sr-only">{selection}</span>
+ <div class="ld-switch-btn__icon-wrapper ld-switch-btn__icon-wrapper--in"
+ aria-hidden="true">
+ {#if selection === "dark"}
+ <svg class="icon ld-switch-btn__icon"
+ viewBox="0 0 20 20">
+ <title>dark</title>
+ <g fill="currentColor">
+ <path d="M11.964 3.284c.021.237.036.474.036.716a8 8 0 0 1-8 8c-.242 0-.479-.015-.716-.036a7 7 0 1 0 8.68-8.68z"
+ fill-opacity=".2"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"></path>
+ <path d="M7 4a.979.979 0 0 1-1-1 1 1 0 0 0-2 0 .979.979 0 0 1-1 1 1 1 0 0 0 0 2 .979.979 0 0 1 1 1 1 1 0 0 0 2 0 .979.979 0 0 1 1-1 1 1 0 0 0 0-2z"></path>
+ </g>
+ </svg>
+ {:else if selection === "light"}
+ <svg class="icon ld-switch-btn__icon"
+ viewBox="0 0 20 20">
+ <title>light-auto</title>
+ <g fill="currentColor">
+ <path d="M10 14a4 4 0 1 1 3.465-6"
+ fill-opacity=".2"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M12 18l2.5-7h1l2.5 7"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M12.714 16h4.572"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M10 1v1.5"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M16.364 3.636l-1.061 1.061"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M3.636 16.364l1.061-1.061"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M1 10h1.5"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M3.636 3.636l1.061 1.061"></path>
+ </g>
+ </svg>
+ {:else }
+ <svg class="icon ld-switch-btn__icon"
+ viewBox="0 0 20 20">
+ <title>dark-auto</title>
+ <g fill="currentColor">
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M12 18l2.5-7h1l2.5 7"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M12.714 16h4.572"></path>
+ <path d="M12.146 10.159A2.5 2.5 0 0 1 14.5 8.5h1a2.5 2.5 0 0 1 1.412.441 7 7 0 0 0-4.948-5.657c.021.237.036.474.036.716a8 8 0 0 1-8 8c-.242 0-.479-.015-.716-.036a6.99 6.99 0 0 0 6.427 5.012z"
+ fill-opacity=".2"></path>
+ <path d="M16.71 8a7.015 7.015 0 0 0-4.746-4.716c.021.237.036.474.036.716a8 8 0 0 1-8 8c-.242 0-.479-.015-.716-.036A7.006 7.006 0 0 0 9 16.929"
+ fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"></path>
+ <path d="M7 4a.979.979 0 0 1-1-1 1 1 0 0 0-2 0 .979.979 0 0 1-1 1 1 1 0 0 0 0 2 .979.979 0 0 1 1 1 1 1 0 0 0 2 0 .979.979 0 0 1 1-1 1 1 0 0 0 0-2z"></path>
+ </g>
+ </svg>
+ {/if}
+ </div>
+
+ <div class="ld-switch-btn__icon-wrapper js-ld-switch-icon"
+ aria-hidden="true">
+ {#if selection === "dark"}
+ <svg class="icon ld-switch-btn__icon"
+ viewBox="0 0 20 20">
+ <title>dark</title>
+ <g fill="currentColor">
+ <path d="M11.964 3.284c.021.237.036.474.036.716a8 8 0 0 1-8 8c-.242 0-.479-.015-.716-.036a7 7 0 1 0 8.68-8.68z"
+ fill-opacity=".2"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"></path>
+ <path d="M7 4a.979.979 0 0 1-1-1 1 1 0 0 0-2 0 .979.979 0 0 1-1 1 1 1 0 0 0 0 2 .979.979 0 0 1 1 1 1 1 0 0 0 2 0 .979.979 0 0 1 1-1 1 1 0 0 0 0-2z"></path>
+ </g>
+ </svg>
+ {:else if selection === "light"}
+ <svg class="icon ld-switch-btn__icon"
+ viewBox="0 0 20 20">
+ <title>light-auto</title>
+ <g fill="currentColor">
+ <path d="M10 14a4 4 0 1 1 3.465-6"
+ fill-opacity=".2"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M12 18l2.5-7h1l2.5 7"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M12.714 16h4.572"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M10 1v1.5"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M16.364 3.636l-1.061 1.061"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M3.636 16.364l1.061-1.061"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M1 10h1.5"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M3.636 3.636l1.061 1.061"></path>
+ </g>
+ </svg>
+ {:else }
+ <svg class="icon ld-switch-btn__icon"
+ viewBox="0 0 20 20">
+ <title>dark-auto</title>
+ <g fill="currentColor">
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M12 18l2.5-7h1l2.5 7"></path>
+ <path fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"
+ d="M12.714 16h4.572"></path>
+ <path d="M12.146 10.159A2.5 2.5 0 0 1 14.5 8.5h1a2.5 2.5 0 0 1 1.412.441 7 7 0 0 0-4.948-5.657c.021.237.036.474.036.716a8 8 0 0 1-8 8c-.242 0-.479-.015-.716-.036a6.99 6.99 0 0 0 6.427 5.012z"
+ fill-opacity=".2"></path>
+ <path d="M16.71 8a7.015 7.015 0 0 0-4.746-4.716c.021.237.036.474.036.716a8 8 0 0 1-8 8c-.242 0-.479-.015-.716-.036A7.006 7.006 0 0 0 9 16.929"
+ fill="none"
+ stroke="currentColor"
+ stroke-linecap="round"
+ stroke-linejoin="round"
+ stroke-width="2"></path>
+ <path d="M7 4a.979.979 0 0 1-1-1 1 1 0 0 0-2 0 .979.979 0 0 1-1 1 1 1 0 0 0 0 2 .979.979 0 0 1 1 1 1 1 0 0 0 2 0 .979.979 0 0 1 1-1 1 1 0 0 0 0-2z"></path>
+ </g>
+ </svg>
+ {/if}
+ </div>
+ </button>
+</div>
+
+<div class="bg-light position-fixed margin-top-xxs padding-x-xs padding-bottom-xs padding-top-xxxs radius-md inner-glow shadow-xs"
+ class:is-hidden={!show}
+ style="right: 15px"
+ data-theme-switcher-element
+ role="listbox">
+ <div class="flex flex-wrap flex-column"
+ role="group">
+ <div class="margin-bottom-xs flex-grow">
+ <span class="text-xs color-contrast-medium">Appearance</span>
+ </div>
+ <div class="flex gap-xs flex-row">
+ <div class="ld-switch-popover__option"
+ aria-selected="{selection === 'dark' ? 'true' : 'false'}"
+ role="option">
+ <figure class="radius-md inner-glow"
+ on:click={() => change("dark")}>
+ <svg id="Layer_1"
+ class="block radius-inherit"
+ data-name="Layer 1"
+ xmlns="http://www.w3.org/2000/svg"
+ width="70"
+ height="50"
+ viewBox="0 0 70 50">
+ <rect width="70"
+ height="50"
+ fill="#22232a"/>
+ <path d="M14,10H70V50H10V14A4,4,0,0,1,14,10Z"
+ fill="#5a5c63"/>
+ <circle cx="18"
+ cy="18"
+ r="3"
+ fill="#22232a"/>
+ <circle cx="27"
+ cy="18"
+ r="3"
+ fill="#22232a"/>
+ <circle cx="36"
+ cy="18"
+ r="3"
+ fill="#22232a"/>
+ <rect x="17"
+ y="28"
+ width="46"
+ height="3"
+ rx="1"
+ fill="#fafaff"/>
+ <rect x="17"
+ y="34"
+ width="46"
+ height="3"
+ rx="1"
+ fill="#fafaff"/>
+ <rect x="17"
+ y="40"
+ width="30"
+ height="3"
+ rx="1"
+ fill="#fafaff"/>
+ </svg>
+ </figure>
+ <div class="text-xs margin-top-xxxs padding-x-xxxxs">Dark</div>
+ </div>
+ <div class="ld-switch-popover__option"
+ aria-selected="{selection === 'light' ? 'true' : 'false'}"
+ role="option">
+ <figure class="radius-md inner-glow"
+ on:click={() => change("light")}>
+ <svg id="Layer_1"
+ class="block radius-inherit"
+ data-name="Layer 1"
+ xmlns="http://www.w3.org/2000/svg"
+ width="70"
+ height="50"
+ viewBox="0 0 70 50">
+ <rect width="70"
+ height="50"
+ fill="#e5e5e6"/>
+ <path d="M14,10H70a0,0,0,0,1,0,0V50a0,0,0,0,1,0,0H10a0,0,0,0,1,0,0V14A4,4,0,0,1,14,10Z"
+ fill="#fff"/>
+ <circle cx="18"
+ cy="18"
+ r="3"
+ fill="#e5e5e6"/>
+ <circle cx="27"
+ cy="18"
+ r="3"
+ fill="#e5e5e6"/>
+ <circle cx="36"
+ cy="18"
+ r="3"
+ fill="#e5e5e6"/>
+ <rect x="17"
+ y="28"
+ width="46"
+ height="3"
+ rx="1"
+ fill="#38393e"/>
+ <rect x="17"
+ y="34"
+ width="46"
+ height="3"
+ rx="1"
+ fill="#38393e"/>
+ <rect x="17"
+ y="40"
+ width="30"
+ height="3"
+ rx="1"
+ fill="#38393e"/>
+ </svg>
+ </figure>
+ <div class="text-xs margin-top-xxxs padding-x-xxxxs">Light</div>
+ </div>
+ <div class="ld-switch-popover__option"
+ aria-selected="{selection === 'system' ? 'true' : 'false'}"
+ role="option">
+ <figure class="radius-md inner-glow"
+ on:click={() => change("system")}>
+ <svg id="Layer_1"
+ class="block radius-inherit"
+ data-name="Layer 1"
+ xmlns="http://www.w3.org/2000/svg"
+ width="70"
+ height="50"
+ viewBox="0 0 70 50">
+ <rect width="35"
+ height="50"
+ fill="#e5e5e6"/>
+ <path d="M14,10H35a0,0,0,0,1,0,0V50a0,0,0,0,1,0,0H10a0,0,0,0,1,0,0V14A4,4,0,0,1,14,10Z"
+ fill="#fff"/>
+ <circle cx="18"
+ cy="18"
+ r="3"
+ fill="#e5e5e6"/>
+ <circle cx="27"
+ cy="18"
+ r="3"
+ fill="#e5e5e6"/>
+ <path d="M18,28H35a0,0,0,0,1,0,0v3a0,0,0,0,1,0,0H18a1,1,0,0,1-1-1V29A1,1,0,0,1,18,28Z"
+ fill="#38393e"/>
+ <path d="M18,34H35a0,0,0,0,1,0,0v3a0,0,0,0,1,0,0H18a1,1,0,0,1-1-1V35A1,1,0,0,1,18,34Z"
+ fill="#38393e"/>
+ <path d="M18,40H35a0,0,0,0,1,0,0v3a0,0,0,0,1,0,0H18a1,1,0,0,1-1-1V41A1,1,0,0,1,18,40Z"
+ fill="#38393e"/>
+ <rect x="35"
+ width="35"
+ height="50"
+ fill="#22232a"/>
+ <path d="M49,10H70V50H45V14A4,4,0,0,1,49,10Z"
+ fill="#5a5c63"/>
+ <circle cx="53"
+ cy="18"
+ r="3"
+ fill="#22232a"/>
+ <circle cx="62"
+ cy="18"
+ r="3"
+ fill="#22232a"/>
+ <path d="M53,28H70a0,0,0,0,1,0,0v3a0,0,0,0,1,0,0H53a1,1,0,0,1-1-1V29A1,1,0,0,1,53,28Z"
+ fill="#fafaff"/>
+ <path d="M53,34H70a0,0,0,0,1,0,0v3a0,0,0,0,1,0,0H53a1,1,0,0,1-1-1V35A1,1,0,0,1,53,34Z"
+ fill="#fafaff"/>
+ <path d="M53,40H70a0,0,0,0,1,0,0v3a0,0,0,0,1,0,0H53a1,1,0,0,1-1-1V41A1,1,0,0,1,53,40Z"
+ fill="#fafaff"/>
+ </svg>
+ </figure>
+ <div class="text-xs margin-top-xxxs padding-x-xxxxs">System</div>
+ </div>
+ </div>
+ </div>
+</div>