fix: simplify settings layout
This commit is contained in:
1 parent
62b3c0aa5e
commit
5b41d169c0
3 files changed
+9
-145
No files matched your search
@@ -13,7 +13,7 @@ tags:
|
||||
The settings page applies options to the whole Homarr application.
|
||||
Some changes need a full page reload before they take effect.
|
||||
|
||||
Use the settings navigation to jump to a section. The highlighted entry follows the section currently in view, and all sections remain visible in a single form. Click the **Save changes** button in the save bar at the bottom of the page to apply them. The save bar only appears when you have unsaved changes, and the **Discard** button reverts your changes.
|
||||
All settings sections remain visible in a single form. Click the **Save changes** button in the save bar at the bottom of the page to apply them. The save bar only appears when you have unsaved changes, and the **Discard** button reverts your changes.
|
||||
|
||||
## Analytics
|
||||
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
.layout {
|
||||
align-items: start;
|
||||
display: grid;
|
||||
gap: var(--mantine-spacing-xl);
|
||||
grid-template-columns: minmax(12rem, 15rem) minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.navigation {
|
||||
max-height: calc(100vh - var(--app-shell-header-height) - var(--mantine-spacing-xl));
|
||||
overflow-y: auto;
|
||||
position: sticky;
|
||||
top: calc(var(--app-shell-header-height) + var(--mantine-spacing-md));
|
||||
}
|
||||
|
||||
.tableOfContents {
|
||||
gap: var(--mantine-spacing-xs);
|
||||
}
|
||||
|
||||
.control {
|
||||
text-align: start;
|
||||
}
|
||||
|
||||
.sections {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.section {
|
||||
scroll-margin-top: calc(var(--app-shell-header-height) + var(--mantine-spacing-md));
|
||||
}
|
||||
|
||||
@mixin smaller-than $mantine-breakpoint-sm {
|
||||
.layout {
|
||||
gap: var(--mantine-spacing-lg);
|
||||
grid-template-columns: minmax(0, 1fr);
|
||||
}
|
||||
|
||||
.navigation {
|
||||
max-height: none;
|
||||
overflow: hidden;
|
||||
position: static;
|
||||
}
|
||||
|
||||
.tableOfContents {
|
||||
flex-direction: row;
|
||||
overflow-x: auto;
|
||||
padding-block-end: var(--mantine-spacing-xs);
|
||||
}
|
||||
|
||||
.control {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { Button, Stack, TableOfContents } from "@mantine/core";
|
||||
import { Button, Stack } from "@mantine/core";
|
||||
import { z } from "zod/v4";
|
||||
|
||||
import type { RouterOutputs } from "@homarr/api";
|
||||
@@ -21,7 +21,6 @@ import { BoardSettingsForm } from "./board-settings-form";
|
||||
import { CrawlingAndIndexingSettings } from "./crawling-and-indexing.settings";
|
||||
import { CultureSettingsForm } from "./culture-settings-form";
|
||||
import { SearchSettingsForm } from "./search-settings-form";
|
||||
import classes from "./settings-form.module.css";
|
||||
import { UserSettingsForm } from "./user-settings-form";
|
||||
|
||||
const settingsFormSchema = z.object({
|
||||
@@ -170,98 +169,16 @@ export const SettingsForm = ({ initialData, selectableBoards, selectableSearchEn
|
||||
form.resetDirty();
|
||||
};
|
||||
|
||||
const tableOfContentsData = [
|
||||
{ id: "settings-board", value: tSettings("section.board.title"), depth: 1 },
|
||||
{ id: "settings-user", value: tSettings("section.user.title"), depth: 1 },
|
||||
{ id: "settings-search", value: tSettings("section.search.title"), depth: 1 },
|
||||
{ id: "settings-appearance", value: tSettings("section.appearance.title"), depth: 1 },
|
||||
{ id: "settings-culture", value: tSettings("section.culture.title"), depth: 1 },
|
||||
{ id: "settings-analytics", value: tSettings("section.analytics.title"), depth: 1 },
|
||||
{ id: "settings-crawling", value: tSettings("section.crawlingAndIndexing.title"), depth: 1 },
|
||||
];
|
||||
|
||||
return (
|
||||
<form onSubmit={form.onSubmit((values) => void handleSubmitAsync(values))}>
|
||||
<Stack gap="xl">
|
||||
<div className={classes.layout}>
|
||||
<nav className={classes.navigation} aria-label={tSettings("title")}>
|
||||
<TableOfContents
|
||||
classNames={{ root: classes.tableOfContents, control: classes.control }}
|
||||
initialData={tableOfContentsData}
|
||||
minDepthToOffset={1}
|
||||
scrollSpyOptions={{
|
||||
selector: "[data-settings-section]",
|
||||
getDepth: () => 1,
|
||||
getValue: (element) => element.getAttribute("data-label") ?? "",
|
||||
offset: 80,
|
||||
}}
|
||||
getControlProps={({ data }) => ({
|
||||
onClick: () => data.getNode().scrollIntoView({ block: "start" }),
|
||||
children: data.value,
|
||||
})}
|
||||
variant="light"
|
||||
/>
|
||||
</nav>
|
||||
|
||||
<Stack className={classes.sections} gap="xl">
|
||||
<section
|
||||
id="settings-board"
|
||||
className={classes.section}
|
||||
data-settings-section
|
||||
data-label={tSettings("section.board.title")}
|
||||
>
|
||||
<BoardSettingsForm form={form} selectableBoards={selectableBoards} />
|
||||
</section>
|
||||
<section
|
||||
id="settings-user"
|
||||
className={classes.section}
|
||||
data-settings-section
|
||||
data-label={tSettings("section.user.title")}
|
||||
>
|
||||
<UserSettingsForm form={form} />
|
||||
</section>
|
||||
<section
|
||||
id="settings-search"
|
||||
className={classes.section}
|
||||
data-settings-section
|
||||
data-label={tSettings("section.search.title")}
|
||||
>
|
||||
<SearchSettingsForm form={form} selectableSearchEngines={selectableSearchEngines} />
|
||||
</section>
|
||||
<section
|
||||
id="settings-appearance"
|
||||
className={classes.section}
|
||||
data-settings-section
|
||||
data-label={tSettings("section.appearance.title")}
|
||||
>
|
||||
<AppearanceSettingsForm form={form} />
|
||||
</section>
|
||||
<section
|
||||
id="settings-culture"
|
||||
className={classes.section}
|
||||
data-settings-section
|
||||
data-label={tSettings("section.culture.title")}
|
||||
>
|
||||
<CultureSettingsForm form={form} />
|
||||
</section>
|
||||
<section
|
||||
id="settings-analytics"
|
||||
className={classes.section}
|
||||
data-settings-section
|
||||
data-label={tSettings("section.analytics.title")}
|
||||
>
|
||||
<AnalyticsSettings form={form} />
|
||||
</section>
|
||||
<section
|
||||
id="settings-crawling"
|
||||
className={classes.section}
|
||||
data-settings-section
|
||||
data-label={tSettings("section.crawlingAndIndexing.title")}
|
||||
>
|
||||
<CrawlingAndIndexingSettings form={form} />
|
||||
</section>
|
||||
</Stack>
|
||||
</div>
|
||||
<BoardSettingsForm form={form} selectableBoards={selectableBoards} />
|
||||
<UserSettingsForm form={form} />
|
||||
<SearchSettingsForm form={form} selectableSearchEngines={selectableSearchEngines} />
|
||||
<AppearanceSettingsForm form={form} />
|
||||
<CultureSettingsForm form={form} />
|
||||
<AnalyticsSettings form={form} />
|
||||
<CrawlingAndIndexingSettings form={form} />
|
||||
|
||||
{form.isDirty() && (
|
||||
<UnsavedChangesBar>
|
||||
|
||||
Reference in new issue
Block a user