feat: implement theme changing
quick settings are now properly implemented
This commit is contained in:
parent
e40518d68f
commit
a29d11f385
@ -101,6 +101,8 @@
|
|||||||
text-transform: lowercase;
|
text-transform: lowercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.top { height: 18px; }
|
||||||
|
|
||||||
.channel.local {
|
.channel.local {
|
||||||
background-color: var(--cyan);
|
background-color: var(--cyan);
|
||||||
}
|
}
|
||||||
|
146
src/lib/QuickSetting.svelte
Normal file
146
src/lib/QuickSetting.svelte
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/svelte-fontawesome';
|
||||||
|
import type { IconDefinition } from '@fortawesome/free-solid-svg-icons'
|
||||||
|
|
||||||
|
import { crossfade, fade } from 'svelte/transition';
|
||||||
|
import { expoInOut } from 'svelte/easing';
|
||||||
|
|
||||||
|
const [send, receive] = crossfade({
|
||||||
|
duration: 350,
|
||||||
|
easing: expoInOut
|
||||||
|
});
|
||||||
|
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
|
export let enabled: boolean = false;
|
||||||
|
export let icon: IconDefinition | undefined = undefined;
|
||||||
|
export let chevron: IconDefinition | undefined = undefined;
|
||||||
|
export let title: string;
|
||||||
|
export let subtitle: string = "";
|
||||||
|
|
||||||
|
export let showMenu: boolean = false;
|
||||||
|
export let menu: {
|
||||||
|
title: string,
|
||||||
|
items?: {
|
||||||
|
value: string,
|
||||||
|
enabled?: boolean,
|
||||||
|
}[]
|
||||||
|
} = { title: "Menu" };
|
||||||
|
|
||||||
|
export let column: number | undefined = undefined, row: number | undefined = undefined;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if showMenu}
|
||||||
|
<div class="modal-background clickable" transition:fade="{{easing: expoInOut}}"
|
||||||
|
on:click={() => showMenu = false} />
|
||||||
|
<div class="menu" in:send="{{key: 0}}" out:receive="{{key: 0}}">
|
||||||
|
<h1 class="no-select">{menu.title}</h1>
|
||||||
|
<div class="items d-flex col">
|
||||||
|
{#each menu.items || [] as item}
|
||||||
|
<button class="item mb-8 radius-24 border-0 px-24 py-24"
|
||||||
|
class:enabled="{item.enabled}"
|
||||||
|
on:click={() => dispatch("menu:click", item.value)}
|
||||||
|
>{item.value}</button>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<button in:send="{{key: 0}}" out:receive="{{key: 0}}"
|
||||||
|
style:grid-row-start="{row}"
|
||||||
|
style:grid-column-start="{column}"
|
||||||
|
class:enabled="{enabled}"
|
||||||
|
class="border-0 ma-8 radius-32 d-flex pa-8 no-select"
|
||||||
|
on:click>
|
||||||
|
<div class="button-icon px-8">
|
||||||
|
{#if icon}
|
||||||
|
<FontAwesomeIcon icon="{icon}" />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
<div class="button-text d-flex col grow-1">
|
||||||
|
<div class="title mb-2">
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
<div class="subtitle overflow-hidden">
|
||||||
|
{subtitle}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="button-icon px-8">
|
||||||
|
{#if chevron}
|
||||||
|
<FontAwesomeIcon icon="{chevron}" />
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.hide {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
height: auto;
|
||||||
|
align-items: center;
|
||||||
|
text-align: start;
|
||||||
|
/* padding-left: 24px; */
|
||||||
|
font-size: 1.2em;
|
||||||
|
transition: background-color;
|
||||||
|
transition-duration: 250ms;
|
||||||
|
font-size: calc(15px + 0.390625vw);
|
||||||
|
}
|
||||||
|
|
||||||
|
button.enabled {
|
||||||
|
background: var(--base-600);
|
||||||
|
color: var(--base-700);
|
||||||
|
}
|
||||||
|
button:not(.enabled) {
|
||||||
|
background: var(--base-800);
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-text {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
button .title {
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: .9em;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
button .subtitle {
|
||||||
|
font-size: .85em;
|
||||||
|
font-weight: 300;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.menu {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
width: calc(100vw - 4em);
|
||||||
|
max-width: 32em;
|
||||||
|
max-height: calc(100vh - 4em);
|
||||||
|
overflow: auto;
|
||||||
|
transform: translate(-50%,-50%);
|
||||||
|
padding: 1em;
|
||||||
|
border-radius: 12px;
|
||||||
|
background: var(--base-700);
|
||||||
|
z-index: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-background {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0,0,0,0.3);
|
||||||
|
z-index: 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
.items {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
79
src/lib/QuickSettings.svelte
Normal file
79
src/lib/QuickSettings.svelte
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import QuickSetting from "./QuickSetting.svelte";
|
||||||
|
import { globalMode, themes, theme, type Theme } from "./settings";
|
||||||
|
import { faEarthEurope, faPaintRoller, faChevronRight } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import type { ComponentProps } from "svelte";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
|
||||||
|
export let rows = 2;
|
||||||
|
export let cols = 2;
|
||||||
|
|
||||||
|
let showMenus = writable(Array.from(Array(rows*cols).keys()).map(() => false));
|
||||||
|
|
||||||
|
// TODO: figure out how deep object reactivity works, this doesn't feel clean
|
||||||
|
let settings: (ComponentProps<QuickSetting> & Record<string, any>)[];
|
||||||
|
$: {
|
||||||
|
settings = [
|
||||||
|
{
|
||||||
|
title: "Global Mode",
|
||||||
|
subtitle: $globalMode ? 'Enabled' : 'Disabled',
|
||||||
|
enabled: $globalMode,
|
||||||
|
icon: faEarthEurope,
|
||||||
|
click: () => $globalMode = !$globalMode,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Theme",
|
||||||
|
subtitle: $theme,
|
||||||
|
enabled: true,
|
||||||
|
icon: faPaintRoller,
|
||||||
|
chevron: faChevronRight,
|
||||||
|
showMenu: $showMenus[1],
|
||||||
|
click: () => $showMenus[1] = !$showMenus[1],
|
||||||
|
menu: {
|
||||||
|
title: "Theme",
|
||||||
|
items: themes.map(t => ({
|
||||||
|
value: t,
|
||||||
|
enabled: $theme === t,
|
||||||
|
}))
|
||||||
|
},
|
||||||
|
menuClick: (theme: CustomEvent<Theme>) => $theme = theme.detail
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
subtitle: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "",
|
||||||
|
subtitle: '',
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="quick-settings h-100 w-100"
|
||||||
|
style:--rows="{rows}"
|
||||||
|
style:--cols="{cols}">
|
||||||
|
{#each settings as setting, i}
|
||||||
|
<QuickSetting
|
||||||
|
row="{Math.floor(i / rows) + 1}"
|
||||||
|
column="{(i % rows) + 1}"
|
||||||
|
enabled="{setting.enabled}"
|
||||||
|
icon="{setting.icon}"
|
||||||
|
chevron="{setting.chevron}"
|
||||||
|
title="{setting.title}"
|
||||||
|
bind:showMenu="{$showMenus[i]}"
|
||||||
|
menu="{setting.menu}"
|
||||||
|
subtitle="{setting.subtitle}"
|
||||||
|
on:click="{setting.click}"
|
||||||
|
on:menu:click="{setting.menuClick}" />
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.quick-settings {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: repeat(var(--rows), calc(100% / var(--rows)));
|
||||||
|
grid-template-columns: repeat(var(--cols), calc(100% / var(--cols)));
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,5 +1,6 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Header from './Header.svelte';
|
import Header from './Header.svelte';
|
||||||
|
import QuickSettings from './QuickSettings.svelte';
|
||||||
import { globalMode, theme } from './settings';
|
import { globalMode, theme } from './settings';
|
||||||
import { mentions } from './chat';
|
import { mentions } from './chat';
|
||||||
import MessageView from './MessageView.svelte';
|
import MessageView from './MessageView.svelte';
|
||||||
@ -63,42 +64,11 @@
|
|||||||
<div class="contents">
|
<div class="contents">
|
||||||
<div class="settings">
|
<div class="settings">
|
||||||
<div class="quick-settings">
|
<div class="quick-settings">
|
||||||
<div class="button" on:click="{globalModeClick}"
|
<QuickSettings />
|
||||||
class:enabled="{$globalMode}">
|
|
||||||
<div class="button-icon">
|
|
||||||
<FontAwesomeIcon icon="{faEarthEurope}" />
|
|
||||||
</div>
|
|
||||||
<div class="button-text">
|
|
||||||
<div class="title">
|
|
||||||
Global Mode
|
|
||||||
</div>
|
|
||||||
<div class="subtitle">
|
|
||||||
{$globalMode ? 'Enabled' : 'Disabled'}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="button">
|
|
||||||
<div class="button-icon">
|
|
||||||
<FontAwesomeIcon icon="{faPaintRoller}" />
|
|
||||||
</div>
|
|
||||||
<div class="button-text">
|
|
||||||
<div class="title">
|
|
||||||
Theme
|
|
||||||
</div>
|
|
||||||
<div class="subtitle">
|
|
||||||
{$theme}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="button-icon">
|
|
||||||
<FontAwesomeIcon icon="{faChevronRight}" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="button" />
|
|
||||||
<div class="button" />
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="spacer"/>
|
<div class="spacer"/>
|
||||||
|
|
||||||
<div class="options-bar">
|
<div class="options-bar">
|
||||||
<div class="button enabled">Edit</div>
|
<div class="button enabled">Edit</div>
|
||||||
<div class="button enabled">Theme</div>
|
<div class="button enabled">Theme</div>
|
||||||
@ -178,9 +148,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.quick-settings {
|
.quick-settings {
|
||||||
display: grid;
|
/* display: grid; */
|
||||||
grid-template-rows: repeat(2, 1fr);
|
/* grid-template-rows: repeat(2, 1fr); */
|
||||||
grid-template-columns: repeat(2, 50%);
|
/* grid-template-columns: repeat(2, 50%); */
|
||||||
height: 35%;
|
height: 35%;
|
||||||
|
|
||||||
:global(.container:not(.mobile)) & {
|
:global(.container:not(.mobile)) & {
|
||||||
|
@ -2,6 +2,7 @@ import { writable } from 'svelte/store';
|
|||||||
|
|
||||||
export const globalMode = writable(true);
|
export const globalMode = writable(true);
|
||||||
|
|
||||||
export type Theme = 'solarized-light' | 'solarized-dark';
|
export const themes = ['solarized-light', 'solarized-dark'] as const;
|
||||||
|
export type Theme = (typeof themes)[number];
|
||||||
|
|
||||||
export const theme = writable<Theme>('solarized-light');
|
export const theme = writable<Theme>('solarized-light');
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
|
|
||||||
import { clickOutside } from "$lib/ui/clickOutside";
|
import { clickOutside } from "$lib/ui/clickOutside";
|
||||||
|
|
||||||
|
import { theme } from "$lib/settings";
|
||||||
|
|
||||||
import { offset, flip, shift } from "@floating-ui/dom";
|
import { offset, flip, shift } from "@floating-ui/dom";
|
||||||
import { createFloatingActions } from "svelte-floating-ui";
|
import { createFloatingActions } from "svelte-floating-ui";
|
||||||
import UserSettings from "$lib/UserSettings.svelte";
|
import UserSettings from "$lib/UserSettings.svelte";
|
||||||
@ -140,8 +142,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateTheme(node, theme) {
|
||||||
|
node.className = theme;
|
||||||
|
return {
|
||||||
|
update: (theme) => {
|
||||||
|
node.className = theme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<svelte:body use:updateTheme="{$theme}" />
|
||||||
|
|
||||||
<div class="container hide-scrollbar snap-y h-100vh"
|
<div class="container hide-scrollbar snap-y h-100vh"
|
||||||
class:mobile="{mobile}"
|
class:mobile="{mobile}"
|
||||||
bind:this="{container}" on:scroll="{onScroll}"
|
bind:this="{container}" on:scroll="{onScroll}"
|
||||||
|
Loading…
Reference in New Issue
Block a user