Move the theme settings onto the content settings page
This commit is contained in:
parent
227834e947
commit
028ae1bedb
6 changed files with 88 additions and 107 deletions
|
|
@ -1410,8 +1410,8 @@ Acceptance:
|
|||
- Selecting "Dark" applies the dark theme to the document immediately, and
|
||||
"System" follows the OS color-scheme preference.
|
||||
- Choosing a different app theme applies it and persists after a reload.
|
||||
- Dragging the font-size slider updates the displayed percentage and saves
|
||||
without a separate save button.
|
||||
- Dragging the font-size slider updates the displayed percentage, and saving the
|
||||
page applies it and persists it across a reload.
|
||||
|
||||
### US-091 — Set up how people zap you
|
||||
|
||||
|
|
|
|||
|
|
@ -155,8 +155,7 @@ test("US-088 adjust send delay and media servers", async ({seed, as}) => {
|
|||
|
||||
const page = await as(users.alice, "/settings/content")
|
||||
|
||||
// The send delay is the only slider on this page.
|
||||
await page.locator('input[type="range"]').fill("3000")
|
||||
await page.getByLabel("Send delay").fill("3000")
|
||||
|
||||
await page.getByRole("button", {name: "Add Server"}).click()
|
||||
await page.getByRole("listitem").first().locator("input").fill("https://media.test/")
|
||||
|
|
@ -168,7 +167,7 @@ test("US-088 adjust send delay and media servers", async ({seed, as}) => {
|
|||
await waitForToastToClear(page)
|
||||
await page.reload()
|
||||
|
||||
await expect(page.locator('input[type="range"]')).toHaveValue("3000")
|
||||
await expect(page.getByLabel("Send delay")).toHaveValue("3000")
|
||||
})
|
||||
|
||||
test("US-089 configure privacy preferences", async ({seed, as}) => {
|
||||
|
|
@ -235,7 +234,7 @@ test("US-090 change the app's appearance", async ({seed, as}) => {
|
|||
space.relayList(user.alice)
|
||||
})
|
||||
|
||||
const page = await as(users.alice, "/settings/theme", {context: {colorScheme: "light"}})
|
||||
const page = await as(users.alice, "/settings/content", {context: {colorScheme: "light"}})
|
||||
const body = page.locator("body")
|
||||
|
||||
await page.getByRole("button", {name: "Dark", exact: true}).click()
|
||||
|
|
@ -259,11 +258,14 @@ test("US-090 change the app's appearance", async ({seed, as}) => {
|
|||
|
||||
await expect(body).toHaveAttribute("data-fl-theme", "navy")
|
||||
|
||||
// Font size is the only slider on this page, and moving it is the save.
|
||||
await page.locator('input[type="range"]').fill("1.25")
|
||||
// Font size is a setting, so it goes out with the rest of the page.
|
||||
await page.getByLabel("Font size").fill("1.25")
|
||||
await page.getByRole("button", {name: "Save Changes"}).click()
|
||||
|
||||
await expect(page.getByRole("alert")).toContainText("Your settings have been saved!")
|
||||
await expect(page.locator("html")).toHaveAttribute("style", /font-size:\s*1\.25rem/)
|
||||
|
||||
await waitForToastToClear(page)
|
||||
await page.reload()
|
||||
|
||||
await expect(page.locator("html")).toHaveAttribute("style", /font-size:\s*1\.25rem/)
|
||||
|
|
|
|||
|
|
@ -67,8 +67,6 @@
|
|||
</Link>
|
||||
</div>
|
||||
<div class="flex gap-3 items-center opacity-75 text-sm">
|
||||
<Link href="/settings/theme">Theme</Link>
|
||||
/
|
||||
<Link href="/settings/about">About</Link>
|
||||
/
|
||||
<Button onclick={logout}>Log Out</Button>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
import UserCircle from "@assets/icons/user-circle.svg?dataurl"
|
||||
import Wallet from "@assets/icons/wallet.svg?dataurl"
|
||||
import ServerPath from "@assets/icons/server-path.svg?dataurl"
|
||||
import Moon from "@assets/icons/moon.svg?dataurl"
|
||||
import Code2 from "@assets/icons/code-2.svg?dataurl"
|
||||
import Exit from "@assets/icons/logout-3.svg?dataurl"
|
||||
import GalleryMinimalistic from "@assets/icons/gallery-minimalistic.svg?dataurl"
|
||||
|
|
@ -55,9 +54,6 @@
|
|||
<SecondaryNavItem href="/settings/privacy">
|
||||
<Icon icon={Shield} /> Privacy
|
||||
</SecondaryNavItem>
|
||||
<SecondaryNavItem href="/settings/theme">
|
||||
<Icon icon={Moon} /> Theme
|
||||
</SecondaryNavItem>
|
||||
<SecondaryNavItem href="/settings/about">
|
||||
<Icon icon={Code2} /> About
|
||||
</SecondaryNavItem>
|
||||
|
|
|
|||
|
|
@ -1,8 +1,14 @@
|
|||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import {BlossomServerLists, MuteLists, publish} from "@welshman/app"
|
||||
import NotesMinimalistic from "@assets/icons/notes-minimalistic.svg?dataurl"
|
||||
import Accessibility from "@assets/icons/accessibility.svg?dataurl"
|
||||
import AddCircle from "@assets/icons/add-circle.svg?dataurl"
|
||||
import Microphone from "@assets/icons/microphone.svg?dataurl"
|
||||
import Monitor from "@assets/icons/monitor.svg?dataurl"
|
||||
import Moon from "@assets/icons/moon.svg?dataurl"
|
||||
import Palette from "@assets/icons/palette.svg?dataurl"
|
||||
import Sun from "@assets/icons/sun.svg?dataurl"
|
||||
import {preventDefault} from "@lib/html"
|
||||
import Field from "@lib/components/Field.svelte"
|
||||
import FieldInline from "@lib/components/FieldInline.svelte"
|
||||
|
|
@ -18,6 +24,7 @@
|
|||
import {blossomServerLists, deriveUserItem, muteLists} from "@app/core"
|
||||
import {pushToast} from "@app/toast"
|
||||
import {PLATFORM_NAME} from "@app/env"
|
||||
import {flTheme, flThemes, theme} from "@app/theme"
|
||||
import {userSettingsValues, publishSettings, createSettingsForm} from "@app/settings"
|
||||
|
||||
const userMuteList = deriveUserItem(MuteLists)
|
||||
|
|
@ -74,6 +81,16 @@
|
|||
})
|
||||
</script>
|
||||
|
||||
{#snippet colorScheme(value: string, label: string, icon: string)}
|
||||
<Button
|
||||
type="button"
|
||||
class={cx("join-item button button-xs", $theme === value ? "button-primary" : "button-neutral")}
|
||||
onclick={() => theme.set(value)}>
|
||||
<Icon {icon} size={4} />
|
||||
{label}
|
||||
</Button>
|
||||
{/snippet}
|
||||
|
||||
<form {onsubmit}>
|
||||
<PageContent>
|
||||
<Card class="flex flex-col gap-4">
|
||||
|
|
@ -116,6 +133,66 @@
|
|||
{/snippet}
|
||||
</Field>
|
||||
</Card>
|
||||
<Card class="flex flex-col gap-4">
|
||||
<strong class="flex items-center gap-3 text-lg">
|
||||
<Icon icon={Palette} />
|
||||
Theme Settings
|
||||
</strong>
|
||||
<FieldInline>
|
||||
{#snippet label()}
|
||||
<p>Color scheme</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<div class="join">
|
||||
{@render colorScheme("system", "System", Monitor)}
|
||||
{@render colorScheme("light", "Light", Sun)}
|
||||
{@render colorScheme("dark", "Dark", Moon)}
|
||||
</div>
|
||||
{/snippet}
|
||||
{#snippet info()}
|
||||
<p>System follows whatever your device is set to.</p>
|
||||
{/snippet}
|
||||
</FieldInline>
|
||||
<FieldInline>
|
||||
{#snippet label()}
|
||||
<p>App theme</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<select class="select input capitalize" bind:value={$flTheme} aria-label="Style">
|
||||
{#each flThemes as option (option)}
|
||||
<option value={option}>{option}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{/snippet}
|
||||
{#snippet info()}
|
||||
<p>Changes the shape and texture of everything, not just its colors.</p>
|
||||
{/snippet}
|
||||
</FieldInline>
|
||||
</Card>
|
||||
<Card class="flex flex-col gap-4">
|
||||
<strong class="flex items-center gap-3 text-lg">
|
||||
<Icon icon={Accessibility} />
|
||||
Accessibility
|
||||
</strong>
|
||||
<Field>
|
||||
{#snippet label()}
|
||||
<p>Font size</p>
|
||||
{/snippet}
|
||||
{#snippet secondary()}
|
||||
<p>{Math.round($settings.font_size * 100)}%</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<input
|
||||
class="range w-full"
|
||||
type="range"
|
||||
min="0.8"
|
||||
max="1.3"
|
||||
step="0.05"
|
||||
aria-label="Font size"
|
||||
bind:value={$settings.font_size} />
|
||||
{/snippet}
|
||||
</Field>
|
||||
</Card>
|
||||
<Card class="flex flex-col gap-4 shadow-md">
|
||||
<strong class="text-lg">Editor Settings</strong>
|
||||
<Field>
|
||||
|
|
@ -129,6 +206,7 @@
|
|||
min="0"
|
||||
max="10000"
|
||||
step="1000"
|
||||
aria-label="Send delay"
|
||||
bind:value={$settings.send_delay} />
|
||||
{/snippet}
|
||||
{#snippet info()}
|
||||
|
|
|
|||
|
|
@ -1,93 +0,0 @@
|
|||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import Accessibility from "@assets/icons/accessibility.svg?dataurl"
|
||||
import Monitor from "@assets/icons/monitor.svg?dataurl"
|
||||
import Moon from "@assets/icons/moon.svg?dataurl"
|
||||
import Palette from "@assets/icons/palette.svg?dataurl"
|
||||
import Sun from "@assets/icons/sun.svg?dataurl"
|
||||
import Button from "@lib/components/Button.svelte"
|
||||
import Icon from "@lib/components/Icon.svelte"
|
||||
import Card from "@lib/components/Card.svelte"
|
||||
import Field from "@lib/components/Field.svelte"
|
||||
import FieldInline from "@lib/components/FieldInline.svelte"
|
||||
import PageContent from "@lib/components/PageContent.svelte"
|
||||
import {publishSettings, userSettingsValues} from "@app/settings"
|
||||
import {flTheme, flThemes, theme} from "@app/theme"
|
||||
|
||||
const saveFontSize = () => publishSettings({font_size: fontSize})
|
||||
|
||||
let fontSize = $state($userSettingsValues.font_size)
|
||||
</script>
|
||||
|
||||
{#snippet colorScheme(value: string, label: string, icon: string)}
|
||||
<Button
|
||||
type="button"
|
||||
class={cx("join-item button button-xs", $theme === value ? "button-primary" : "button-neutral")}
|
||||
onclick={() => theme.set(value)}>
|
||||
<Icon {icon} size={4} />
|
||||
{label}
|
||||
</Button>
|
||||
{/snippet}
|
||||
|
||||
<PageContent>
|
||||
<Card class="flex flex-col gap-4">
|
||||
<strong class="flex items-center gap-3 text-lg">
|
||||
<Icon icon={Palette} />
|
||||
Theme Settings
|
||||
</strong>
|
||||
<FieldInline>
|
||||
{#snippet label()}
|
||||
<p>Color scheme</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<div class="join">
|
||||
{@render colorScheme("system", "System", Monitor)}
|
||||
{@render colorScheme("light", "Light", Sun)}
|
||||
{@render colorScheme("dark", "Dark", Moon)}
|
||||
</div>
|
||||
{/snippet}
|
||||
{#snippet info()}
|
||||
<p>System follows whatever your device is set to.</p>
|
||||
{/snippet}
|
||||
</FieldInline>
|
||||
<FieldInline>
|
||||
{#snippet label()}
|
||||
<p>App theme</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<select class="select input capitalize" bind:value={$flTheme} aria-label="Style">
|
||||
{#each flThemes as option (option)}
|
||||
<option value={option}>{option}</option>
|
||||
{/each}
|
||||
</select>
|
||||
{/snippet}
|
||||
{#snippet info()}
|
||||
<p>Changes the shape and texture of everything, not just its colors.</p>
|
||||
{/snippet}
|
||||
</FieldInline>
|
||||
</Card>
|
||||
<Card class="flex flex-col gap-4">
|
||||
<strong class="flex items-center gap-3 text-lg">
|
||||
<Icon icon={Accessibility} />
|
||||
Accessibility
|
||||
</strong>
|
||||
<Field>
|
||||
{#snippet label()}
|
||||
<p>Font size</p>
|
||||
{/snippet}
|
||||
{#snippet secondary()}
|
||||
<p>{Math.round(fontSize * 100)}%</p>
|
||||
{/snippet}
|
||||
{#snippet input()}
|
||||
<input
|
||||
class="range w-full"
|
||||
type="range"
|
||||
min="0.8"
|
||||
max="1.3"
|
||||
step="0.05"
|
||||
bind:value={fontSize}
|
||||
onchange={saveFontSize} />
|
||||
{/snippet}
|
||||
</Field>
|
||||
</Card>
|
||||
</PageContent>
|
||||
Loading…
Reference in a new issue