mirror of
https://github.com/BetterSEQTA/BetterSEQTA-Plus.git
synced 2026-08-28 17:21:05 +00:00
feat: sidebar customisaitons and settings fixes
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { onDestroy } from "svelte";
|
||||
import Sortable from "sortablejs";
|
||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||
import {
|
||||
restoreCustomMenuActive,
|
||||
@@ -16,8 +18,10 @@
|
||||
|
||||
let { menuEl }: Props = $props();
|
||||
|
||||
let dragKey = $state<string | null>(null);
|
||||
let listEl = $state<HTMLElement | null>(null);
|
||||
let coverEl: HTMLElement | null = null;
|
||||
let sortable: Sortable | null = null;
|
||||
let dragging = $state(false);
|
||||
|
||||
const BACK_SVG = `<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><g style="fill: currentcolor;"><path d="M15.422 16.078l-1.406 1.406-6-6 6-6 1.406 1.406-4.594 4.594z"></path></g></svg>`;
|
||||
|
||||
@@ -50,17 +54,80 @@
|
||||
sidebarState.setItemVisibility(key, visible);
|
||||
}
|
||||
|
||||
function onDragStart(key: string) {
|
||||
dragKey = key;
|
||||
function destroySortable() {
|
||||
sortable?.destroy();
|
||||
sortable = null;
|
||||
dragging = false;
|
||||
document.documentElement.style.removeProperty("--bsplus-drag-width");
|
||||
}
|
||||
|
||||
function onDrop(key: string) {
|
||||
if (dragKey && sidebarState.editMode) {
|
||||
sidebarState.reorderRoot(dragKey, key);
|
||||
}
|
||||
dragKey = null;
|
||||
function syncSortableFromState() {
|
||||
if (!sortable || dragging) return;
|
||||
const order = sidebarState.editRootItems.map((item) => item.key);
|
||||
sortable.sort(order, true);
|
||||
}
|
||||
|
||||
function restoreDefault() {
|
||||
sidebarState.restoreDefaultOrder();
|
||||
queueMicrotask(syncSortableFromState);
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
const editing = sidebarState.editMode;
|
||||
const list = listEl;
|
||||
|
||||
destroySortable();
|
||||
if (!editing || !list) return;
|
||||
|
||||
sortable = Sortable.create(list, {
|
||||
animation: 220,
|
||||
easing: "cubic-bezier(0.22, 1, 0.36, 1)",
|
||||
draggable: ".bsplus-sidebar-item.draggable",
|
||||
filter: ".toggle, .toggle input, .bsplus-sidebar-edit-header, .bsplus-sidebar-edit-actions",
|
||||
preventOnFilter: false,
|
||||
dataIdAttr: "data-key",
|
||||
ghostClass: "bsplus-sortable-ghost",
|
||||
chosenClass: "bsplus-sortable-chosen",
|
||||
dragClass: "bsplus-sortable-drag",
|
||||
forceFallback: true,
|
||||
fallbackOnBody: true,
|
||||
fallbackTolerance: 3,
|
||||
swapThreshold: 0.65,
|
||||
direction: "vertical",
|
||||
onStart: (evt) => {
|
||||
dragging = true;
|
||||
const width = evt.item.getBoundingClientRect().width;
|
||||
document.documentElement.style.setProperty(
|
||||
"--bsplus-drag-width",
|
||||
`${Math.round(width)}px`,
|
||||
);
|
||||
// Fallback clone is created just after onStart; pin size + drop
|
||||
// `.active` so theme/active rules don't expand it to full width.
|
||||
requestAnimationFrame(() => {
|
||||
const dragEl = document.querySelector(
|
||||
".bsplus-sortable-drag",
|
||||
) as HTMLElement | null;
|
||||
if (!dragEl) return;
|
||||
dragEl.style.width = `${Math.round(width)}px`;
|
||||
dragEl.style.maxWidth = `${Math.round(width)}px`;
|
||||
dragEl.classList.remove("active");
|
||||
});
|
||||
},
|
||||
onEnd: (evt) => {
|
||||
dragging = false;
|
||||
document.documentElement.style.removeProperty("--bsplus-drag-width");
|
||||
if (evt.from !== evt.to) return;
|
||||
if (evt.oldIndex == null || evt.newIndex == null) return;
|
||||
if (evt.oldIndex === evt.newIndex) return;
|
||||
sidebarState.applyMenuOrder(sortable?.toArray() ?? []);
|
||||
},
|
||||
});
|
||||
|
||||
return () => {
|
||||
destroySortable();
|
||||
};
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
const editing = sidebarState.editMode;
|
||||
const container = document.getElementById("container");
|
||||
@@ -111,6 +178,12 @@
|
||||
root.scrollTop = 0;
|
||||
});
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
destroySortable();
|
||||
coverEl?.remove();
|
||||
coverEl = null;
|
||||
});
|
||||
</script>
|
||||
|
||||
<!--
|
||||
@@ -124,32 +197,28 @@
|
||||
class:drilling={sidebarState.isDrilling}
|
||||
class:compact={sidebarState.compact}
|
||||
class:edit-mode={sidebarState.editMode}
|
||||
class:is-sorting={dragging}
|
||||
aria-label="Main"
|
||||
bind:this={listEl}
|
||||
>
|
||||
{#if sidebarState.editMode}
|
||||
<li class="item bsplus-sidebar-edit-header" aria-hidden="true">
|
||||
<!-- svelte-ignore a11y_label_has_associated_control -->
|
||||
<label><span class="label">Edit Sidebar</span></label>
|
||||
</li>
|
||||
{#each sidebarState.items as item (item.key)}
|
||||
{#each sidebarState.editRootItems as item (item.key)}
|
||||
<SidebarItem
|
||||
{item}
|
||||
active={sidebarState.activeKey === item.key}
|
||||
compact={sidebarState.compact}
|
||||
compact={false}
|
||||
editMode={true}
|
||||
visible={itemVisible(item.key)}
|
||||
{onActivate}
|
||||
{onToggleVisible}
|
||||
{onDragStart}
|
||||
{onDrop}
|
||||
/>
|
||||
{/each}
|
||||
<li class="item bsplus-sidebar-edit-actions">
|
||||
<button
|
||||
type="button"
|
||||
class="edit-btn"
|
||||
onclick={() => sidebarState.restoreDefaultOrder()}
|
||||
>
|
||||
<button type="button" class="edit-btn" onclick={restoreDefault}>
|
||||
Restore Default
|
||||
</button>
|
||||
<button type="button" class="edit-btn primary" onclick={closeEdit}>
|
||||
@@ -306,6 +375,11 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.bsplus-sidebar-list.is-sorting {
|
||||
cursor: grabbing;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.bsplus-sidebar-edit-header {
|
||||
pointer-events: none;
|
||||
width: 85%;
|
||||
@@ -361,4 +435,30 @@
|
||||
.edit-btn.primary {
|
||||
background: rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
/* SortableJS classes (applied to our items; must be :global). */
|
||||
.bsplus-sidebar-list :global(.bsplus-sortable-ghost) {
|
||||
opacity: 0.35 !important;
|
||||
background: rgba(255, 255, 255, 0.08) !important;
|
||||
box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.18);
|
||||
}
|
||||
|
||||
.bsplus-sidebar-list :global(.bsplus-sortable-chosen) {
|
||||
background: rgba(0, 0, 0, 0.28) !important;
|
||||
}
|
||||
|
||||
.bsplus-sidebar-list :global(.bsplus-sortable-drag),
|
||||
:global(.bsplus-sortable-drag) {
|
||||
opacity: 1 !important;
|
||||
cursor: grabbing !important;
|
||||
z-index: 10000 !important;
|
||||
width: var(--bsplus-drag-width, 240px) !important;
|
||||
max-width: var(--bsplus-drag-width, 240px) !important;
|
||||
box-sizing: border-box !important;
|
||||
box-shadow:
|
||||
0 14px 32px rgba(0, 0, 0, 0.35),
|
||||
0 0 0 1px rgba(255, 255, 255, 0.12) !important;
|
||||
transform: scale(1.03);
|
||||
background: rgba(0, 0, 0, 0.45) !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -12,8 +12,6 @@
|
||||
drillEnter?: boolean;
|
||||
onActivate: (item: SidebarItem) => void;
|
||||
onToggleVisible?: (key: string, visible: boolean) => void;
|
||||
onDragStart?: (key: string) => void;
|
||||
onDrop?: (key: string) => void;
|
||||
};
|
||||
|
||||
let {
|
||||
@@ -25,11 +23,10 @@
|
||||
drillEnter = false,
|
||||
onActivate,
|
||||
onToggleVisible,
|
||||
onDragStart,
|
||||
onDrop,
|
||||
}: Props = $props();
|
||||
|
||||
const CHEVRON_SVG = `<svg width="24" height="24" viewBox="0 0 24 24" aria-hidden="true"><g style="fill: currentcolor;"><path d="M8.578 16.359l4.594-4.594-4.594-4.594 1.406-1.406 6 6-6 6z"></path></g></svg>`;
|
||||
const GRIP_SVG = `<svg width="16" height="16" viewBox="0 0 16 16" aria-hidden="true"><circle cx="5" cy="3" r="1.35" fill="currentColor"/><circle cx="11" cy="3" r="1.35" fill="currentColor"/><circle cx="5" cy="8" r="1.35" fill="currentColor"/><circle cx="11" cy="8" r="1.35" fill="currentColor"/><circle cx="5" cy="13" r="1.35" fill="currentColor"/><circle cx="11" cy="13" r="1.35" fill="currentColor"/></svg>`;
|
||||
</script>
|
||||
|
||||
<!-- SEQTA class names (item / hasChildren / active) so theme CSS keeps matching. -->
|
||||
@@ -51,11 +48,7 @@
|
||||
tabindex={editMode ? -1 : 0}
|
||||
aria-label={item.label}
|
||||
aria-current={active ? "page" : undefined}
|
||||
draggable={editMode}
|
||||
in:fly={{ x: drillEnter ? 24 : 0, duration: drillEnter ? 180 : 0 }}
|
||||
ondragstart={() => onDragStart?.(item.key)}
|
||||
ondragover={(e) => e.preventDefault()}
|
||||
ondrop={() => onDrop?.(item.key)}
|
||||
onclick={(e) => {
|
||||
// Keep SEQTA's #menu handlers from seeing custom-list clicks — that fights
|
||||
// our drill UI and can freeze the tab (Goals / Folios / etc.).
|
||||
@@ -72,6 +65,9 @@
|
||||
}
|
||||
}}
|
||||
>
|
||||
{#if editMode}
|
||||
<span class="drag-grip" aria-hidden="true">{@html GRIP_SVG}</span>
|
||||
{/if}
|
||||
<!-- svelte-ignore a11y_label_has_associated_control -->
|
||||
<label>
|
||||
{#if item.iconHtml}
|
||||
@@ -118,7 +114,7 @@
|
||||
box-sizing: border-box;
|
||||
transition:
|
||||
background-color 0.2s ease,
|
||||
transform 0.2s ease,
|
||||
box-shadow 0.2s ease,
|
||||
opacity 0.2s ease;
|
||||
user-select: none;
|
||||
}
|
||||
@@ -165,18 +161,36 @@
|
||||
|
||||
.bsplus-sidebar-item.edit-mode {
|
||||
cursor: grab;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
gap: 4px;
|
||||
padding-right: 4px;
|
||||
box-sizing: border-box;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.bsplus-sidebar-item.edit-mode:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
|
||||
/* Keep the same label padding/size as normal items; only reserve toggle space. */
|
||||
.bsplus-sidebar-item.edit-mode > label:not(.toggle) {
|
||||
flex: 1 1 0;
|
||||
width: 0;
|
||||
flex: 1 1 auto;
|
||||
width: auto;
|
||||
min-width: 0;
|
||||
padding-right: 4px;
|
||||
padding: 12px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.drag-grip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 0 0 auto;
|
||||
width: 20px;
|
||||
margin-left: 10px;
|
||||
opacity: 0.45;
|
||||
color: inherit;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.bsplus-sidebar-item.edit-mode:hover .drag-grip {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.bsplus-sidebar-item :global(label > svg) {
|
||||
|
||||
@@ -9,6 +9,11 @@ import {
|
||||
clearNativeDrillActive,
|
||||
sidebarState,
|
||||
} from "./sidebarState.svelte";
|
||||
import {
|
||||
applySidebarLook,
|
||||
applySidebarStyleClass,
|
||||
clearSidebarAppearance,
|
||||
} from "./sidebarStyles";
|
||||
|
||||
const ROOT_ID = "bsplus-sidebar-root";
|
||||
const MENU_CLASS = "bsplus-custom-sidebar";
|
||||
@@ -166,6 +171,8 @@ export function prepareCustomSidebarEarly() {
|
||||
|
||||
earlyPrepareStarted = true;
|
||||
document.documentElement.classList.add(PENDING_CLASS);
|
||||
// Width/blur vars before mount so layout doesn't jump.
|
||||
applySidebarLook(document.getElementById("menu"));
|
||||
void mountCustomSidebar();
|
||||
}
|
||||
|
||||
@@ -183,6 +190,8 @@ export async function mountCustomSidebar(): Promise<boolean> {
|
||||
// Already mounted — re-sync after Home/News/Analytics injections.
|
||||
if (app && menuEl) {
|
||||
ensureDefaultMenuOrder(menuEl);
|
||||
applySidebarStyleClass(menuEl, settingsState.sidebarStyle);
|
||||
applySidebarLook(menuEl);
|
||||
sidebarState.syncSettings();
|
||||
syncFromMenu();
|
||||
startCatchupSync();
|
||||
@@ -214,6 +223,8 @@ export async function mountCustomSidebar(): Promise<boolean> {
|
||||
}
|
||||
|
||||
menu.classList.add(MENU_CLASS);
|
||||
applySidebarStyleClass(menu, settingsState.sidebarStyle);
|
||||
applySidebarLook(menu);
|
||||
document.getElementById(ROOT_ID)?.remove();
|
||||
|
||||
app = mount(Sidebar, {
|
||||
@@ -265,6 +276,18 @@ export async function mountCustomSidebar(): Promise<boolean> {
|
||||
|
||||
clearSettingListeners();
|
||||
registerSetting("iconOnlySidebar", () => sidebarState.syncSettings());
|
||||
registerSetting("sidebarStyle", () =>
|
||||
applySidebarStyleClass(menuEl, settingsState.sidebarStyle),
|
||||
);
|
||||
for (const key of [
|
||||
"sidebarDensity",
|
||||
"sidebarCornerRadius",
|
||||
"sidebarActiveIndicator",
|
||||
"sidebarWidth",
|
||||
"sidebarBlur",
|
||||
] as const) {
|
||||
registerSetting(key, () => applySidebarLook(menuEl));
|
||||
}
|
||||
const resync = () => syncFromMenu();
|
||||
registerSetting("menuorder", resync);
|
||||
registerSetting("menuitems", resync);
|
||||
@@ -305,7 +328,10 @@ export function unmountCustomSidebar() {
|
||||
}
|
||||
|
||||
document.getElementById(ROOT_ID)?.remove();
|
||||
menuEl?.classList.remove(MENU_CLASS, "bsplus-sidebar-edit-mode");
|
||||
if (menuEl) {
|
||||
menuEl.classList.remove(MENU_CLASS, "bsplus-sidebar-edit-mode");
|
||||
clearSidebarAppearance(menuEl);
|
||||
}
|
||||
menuEl = null;
|
||||
sidebarState.resetDrill();
|
||||
sidebarState.setEditMode(false);
|
||||
|
||||
@@ -191,6 +191,11 @@ class SidebarState {
|
||||
filterVisible(orderItems(this.items, settingsState.menuorder ?? [])),
|
||||
);
|
||||
|
||||
/** Full ordered root list for edit mode (includes hidden items). */
|
||||
editRootItems = $derived(
|
||||
orderItems(this.items, settingsState.menuorder ?? []),
|
||||
);
|
||||
|
||||
isDrilling = $derived(this.drillStack.length > 0);
|
||||
|
||||
compact = $derived(this.iconOnly && !this.isDrilling && !this.editMode);
|
||||
@@ -305,9 +310,14 @@ class SidebarState {
|
||||
if (enabled) this.resetDrill();
|
||||
}
|
||||
|
||||
applyMenuOrder(keys: string[]) {
|
||||
if (!keys.length) return;
|
||||
settingsState.menuorder = [...keys];
|
||||
}
|
||||
|
||||
reorderRoot(fromKey: string, toKey: string) {
|
||||
if (fromKey === toKey) return;
|
||||
const keys = this.visibleRootItems.map((item) => item.key);
|
||||
const keys = this.editRootItems.map((item) => item.key);
|
||||
const from = keys.indexOf(fromKey);
|
||||
const to = keys.indexOf(toKey);
|
||||
if (from < 0 || to < 0) return;
|
||||
@@ -315,7 +325,7 @@ class SidebarState {
|
||||
const next = [...keys];
|
||||
const [moved] = next.splice(from, 1);
|
||||
next.splice(to, 0, moved);
|
||||
settingsState.menuorder = next;
|
||||
this.applyMenuOrder(next);
|
||||
}
|
||||
|
||||
setItemVisibility(key: string, visible: boolean) {
|
||||
|
||||
@@ -0,0 +1,158 @@
|
||||
import { settingsState } from "@/seqta/utils/listeners/SettingsState";
|
||||
|
||||
export type SidebarStyleId =
|
||||
| "classic"
|
||||
| "soft"
|
||||
| "pill"
|
||||
| "glass"
|
||||
| "sharp"
|
||||
| "strip"
|
||||
| "neon";
|
||||
|
||||
export type SidebarDensity = "compact" | "comfortable" | "large";
|
||||
export type SidebarActiveIndicator = "fill" | "bar" | "outline" | "underline";
|
||||
export type SidebarWidth = "narrow" | "default" | "wide";
|
||||
|
||||
export type SidebarStyleDef = {
|
||||
id: SidebarStyleId;
|
||||
label: string;
|
||||
description: string;
|
||||
};
|
||||
|
||||
export const SIDEBAR_STYLES: readonly SidebarStyleDef[] = [
|
||||
{ id: "classic", label: "Classic", description: "Default BetterSEQTA look" },
|
||||
{ id: "soft", label: "Soft", description: "Roomier spacing with gentle shadows" },
|
||||
{ id: "pill", label: "Pill", description: "Fully rounded capsule items" },
|
||||
{ id: "glass", label: "Glass", description: "Frosted translucent rows" },
|
||||
{ id: "sharp", label: "Sharp", description: "Compact, squared edges" },
|
||||
{ id: "strip", label: "Strip", description: "Flat rows with a strong active accent" },
|
||||
{ id: "neon", label: "Neon", description: "Glowing active highlight" },
|
||||
] as const;
|
||||
|
||||
const STYLE_IDS = SIDEBAR_STYLES.map((s) => s.id);
|
||||
|
||||
/** Defaults match the current custom sidebar (no visual change). */
|
||||
export const DEFAULT_SIDEBAR_STYLE: SidebarStyleId = "classic";
|
||||
export const DEFAULT_SIDEBAR_DENSITY: SidebarDensity = "comfortable";
|
||||
export const DEFAULT_SIDEBAR_INDICATOR: SidebarActiveIndicator = "fill";
|
||||
export const DEFAULT_SIDEBAR_WIDTH: SidebarWidth = "default";
|
||||
export const DEFAULT_SIDEBAR_RADIUS = 12;
|
||||
export const DEFAULT_SIDEBAR_BLUR = 50;
|
||||
|
||||
export const SIDEBAR_WIDTH_PX = {
|
||||
narrow: 220,
|
||||
default: 270,
|
||||
wide: 320,
|
||||
} as const;
|
||||
|
||||
export const STYLE_CLASS_PREFIX = "bsplus-sidebar-style-";
|
||||
export const DENSITY_CLASS_PREFIX = "bsplus-sidebar-density-";
|
||||
export const INDICATOR_CLASS_PREFIX = "bsplus-sidebar-indicator-";
|
||||
|
||||
function oneOf<T extends string>(value: unknown, allowed: readonly T[], fallback: T): T {
|
||||
return typeof value === "string" && (allowed as readonly string[]).includes(value)
|
||||
? (value as T)
|
||||
: fallback;
|
||||
}
|
||||
|
||||
function clampInt(value: unknown, min: number, max: number, fallback: number): number {
|
||||
const n = typeof value === "number" ? value : Number(value);
|
||||
if (!Number.isFinite(n)) return fallback;
|
||||
return Math.min(max, Math.max(min, Math.round(n)));
|
||||
}
|
||||
|
||||
export const normalizeSidebarStyleId = (v: unknown) =>
|
||||
oneOf(v, STYLE_IDS, DEFAULT_SIDEBAR_STYLE);
|
||||
|
||||
export const normalizeSidebarDensity = (v: unknown) =>
|
||||
oneOf(v, ["compact", "comfortable", "large"] as const, DEFAULT_SIDEBAR_DENSITY);
|
||||
|
||||
export const normalizeSidebarIndicator = (v: unknown) =>
|
||||
oneOf(
|
||||
v,
|
||||
["fill", "bar", "outline", "underline"] as const,
|
||||
DEFAULT_SIDEBAR_INDICATOR,
|
||||
);
|
||||
|
||||
export const normalizeSidebarWidth = (v: unknown) =>
|
||||
oneOf(v, ["narrow", "default", "wide"] as const, DEFAULT_SIDEBAR_WIDTH);
|
||||
|
||||
export const normalizeSidebarRadius = (v: unknown) =>
|
||||
clampInt(v, 0, 24, DEFAULT_SIDEBAR_RADIUS);
|
||||
|
||||
export const normalizeSidebarBlur = (v: unknown) =>
|
||||
clampInt(v, 0, 80, DEFAULT_SIDEBAR_BLUR);
|
||||
|
||||
export function getSidebarStyle(id: unknown): SidebarStyleDef {
|
||||
const normalized = normalizeSidebarStyleId(id);
|
||||
return SIDEBAR_STYLES.find((s) => s.id === normalized) ?? SIDEBAR_STYLES[0];
|
||||
}
|
||||
|
||||
function clearPrefixed(el: HTMLElement, prefix: string) {
|
||||
for (const cls of [...el.classList]) {
|
||||
if (cls.startsWith(prefix)) el.classList.remove(cls);
|
||||
}
|
||||
}
|
||||
|
||||
function setExclusiveClass(
|
||||
el: HTMLElement,
|
||||
prefix: string,
|
||||
value: string,
|
||||
skipDefault?: string,
|
||||
) {
|
||||
clearPrefixed(el, prefix);
|
||||
if (value !== skipDefault) el.classList.add(`${prefix}${value}`);
|
||||
}
|
||||
|
||||
/** Apply style preset class on `#menu` (classic = no class). */
|
||||
export function applySidebarStyleClass(
|
||||
menu: HTMLElement | null | undefined,
|
||||
styleId: unknown,
|
||||
) {
|
||||
if (!menu) return;
|
||||
setExclusiveClass(
|
||||
menu,
|
||||
STYLE_CLASS_PREFIX,
|
||||
normalizeSidebarStyleId(styleId),
|
||||
DEFAULT_SIDEBAR_STYLE,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply Look CSS variables + non-default density/indicator classes.
|
||||
* Safe to call with no menu (still sets width/blur/radius on `:root`).
|
||||
*/
|
||||
export function applySidebarLook(
|
||||
menu: HTMLElement | null | undefined = document.getElementById("menu"),
|
||||
) {
|
||||
const density = normalizeSidebarDensity(settingsState.sidebarDensity);
|
||||
const indicator = normalizeSidebarIndicator(settingsState.sidebarActiveIndicator);
|
||||
const width = normalizeSidebarWidth(settingsState.sidebarWidth);
|
||||
const radius = normalizeSidebarRadius(settingsState.sidebarCornerRadius);
|
||||
const blur = normalizeSidebarBlur(settingsState.sidebarBlur);
|
||||
|
||||
const root = document.documentElement;
|
||||
root.style.setProperty("--bsplus-sidebar-width", `${SIDEBAR_WIDTH_PX[width]}px`);
|
||||
root.style.setProperty("--bsplus-sidebar-radius", `${radius}px`);
|
||||
root.style.setProperty("--bsplus-sidebar-blur", `${blur}px`);
|
||||
|
||||
if (!menu) return;
|
||||
setExclusiveClass(menu, DENSITY_CLASS_PREFIX, density, DEFAULT_SIDEBAR_DENSITY);
|
||||
setExclusiveClass(
|
||||
menu,
|
||||
INDICATOR_CLASS_PREFIX,
|
||||
indicator,
|
||||
DEFAULT_SIDEBAR_INDICATOR,
|
||||
);
|
||||
}
|
||||
|
||||
export function clearSidebarAppearance(menu: HTMLElement | null | undefined) {
|
||||
const root = document.documentElement;
|
||||
root.style.removeProperty("--bsplus-sidebar-width");
|
||||
root.style.removeProperty("--bsplus-sidebar-radius");
|
||||
root.style.removeProperty("--bsplus-sidebar-blur");
|
||||
if (!menu) return;
|
||||
clearPrefixed(menu, STYLE_CLASS_PREFIX);
|
||||
clearPrefixed(menu, DENSITY_CLASS_PREFIX);
|
||||
clearPrefixed(menu, INDICATOR_CLASS_PREFIX);
|
||||
}
|
||||
@@ -63,6 +63,12 @@ export function getDefaultSettingsState(): SettingsState {
|
||||
notificationCollector: false,
|
||||
newsSource: "australia",
|
||||
iconOnlySidebar: false,
|
||||
sidebarStyle: "classic",
|
||||
sidebarDensity: "comfortable",
|
||||
sidebarCornerRadius: 12,
|
||||
sidebarActiveIndicator: "fill",
|
||||
sidebarWidth: "default",
|
||||
sidebarBlur: 50,
|
||||
adaptiveThemeColour: false,
|
||||
adaptiveThemeGradient: false,
|
||||
adaptiveThemeColourTransition: true,
|
||||
|
||||
Reference in New Issue
Block a user