improve ui
This commit is contained in:
1 parent
da9b803bdb
commit
f1e2aeec1b
5 files changed
+42
-6
No files matched your search
@@ -11,6 +11,8 @@ import {
|
||||
Users,
|
||||
Route,
|
||||
Webhook,
|
||||
KeyRound,
|
||||
Bot,
|
||||
} from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { NavItem } from "./components-nav";
|
||||
@@ -36,9 +38,11 @@ const sections = [
|
||||
{
|
||||
label: "Administration",
|
||||
links: [
|
||||
{ href: "/agent", label: "Agent", icon: Bot },
|
||||
{ href: "/accounts", label: "Accounts", icon: Users },
|
||||
{ href: "/activity", label: "Activity", icon: Activity },
|
||||
{ href: "/backups", label: "Backups", icon: DatabaseBackup },
|
||||
{ href: "/api-keys", label: "API keys", icon: KeyRound },
|
||||
],
|
||||
},
|
||||
{
|
||||
@@ -46,7 +50,6 @@ const sections = [
|
||||
links: [
|
||||
{ href: "/branding", label: "Branding", icon: Palette },
|
||||
{ href: "/licenses", label: "Licenses", icon: BadgeDollarSign },
|
||||
// { href: "/api-keys", label: "API Keys", icon: KeyRound },
|
||||
],
|
||||
},
|
||||
];
|
||||
@@ -58,8 +61,8 @@ export function AdminNav({ className }: { className?: string }) {
|
||||
return (
|
||||
<nav className={cn("flex min-h-full flex-col gap-1", className)}>
|
||||
<SidebarHeader href="/inbox" label="Admin" />
|
||||
<div className={cn("space-y-4", minimal && "space-y-2")}>
|
||||
{sections.map((section) => {
|
||||
<div className={cn("space-y-4", minimal && "space-y-2 pl-1")}>
|
||||
{sections.map((section, sectionIndex) => {
|
||||
const links = section.links.filter(
|
||||
(link) =>
|
||||
link.href !== "/branding" || branding.canCustomizeBranding,
|
||||
@@ -69,6 +72,7 @@ export function AdminNav({ className }: { className?: string }) {
|
||||
return (
|
||||
// The first section has no label, so fall back to its first href for a stable key.
|
||||
<section key={section.label ?? links[0].href}>
|
||||
{minimal && sectionIndex > 0 && <hr className="mx-3 mb-3 border-neutral-200/70" />}
|
||||
{!minimal && section.label && (
|
||||
<p className="mb-1 px-3 text-[11px] font-semibold uppercase tracking-wider text-neutral-400">
|
||||
{section.label}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import type { FormEvent } from "react";
|
||||
import { Fragment } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import {
|
||||
Archive,
|
||||
@@ -173,8 +174,12 @@ export function DashboardNav({ className }: { className?: string }) {
|
||||
<nav className={cn("flex min-h-full flex-col gap-1", className)}>
|
||||
<SidebarHeader href="/inbox" />
|
||||
{linksWithCounts.map((link, i) => (
|
||||
<NavItem link={link} key={`nav-${link.href || i}`} />
|
||||
<Fragment key={`nav-${link.href || i}`}>
|
||||
<NavItem link={link} />
|
||||
{minimal && i === 0 && <hr className="mx-3 my-2 border-neutral-200/70" />}
|
||||
</Fragment>
|
||||
))}
|
||||
{minimal && <hr className="mx-3 my-2 border-neutral-200/70" />}
|
||||
{!minimal && (
|
||||
<div className="mt-2 flex h-8 items-center justify-between px-3">
|
||||
<span className="text-xs font-medium uppercase tracking-wide text-neutral-400">
|
||||
|
||||
@@ -71,6 +71,7 @@ export function getEmailPageTitleCount(total: number, unread: number): number {
|
||||
}
|
||||
|
||||
export function formatEmailPageTitle({ location, total, unread, emailAddress }: EmailPageTitleInput): string {
|
||||
if (location === "Inbox") return unread > 0 ? `Inbox (${unread})` : "Inbox";
|
||||
const count = getEmailPageTitleCount(total, unread);
|
||||
const suffix = emailAddress ? ` - ${emailAddress}` : "";
|
||||
return `${location} (${count})${suffix}`;
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
const SIDEBAR_MINIMAL_STORAGE_KEY = "mailflare-sidebar-minimal";
|
||||
|
||||
export function readInitialSidebarMinimal(): boolean {
|
||||
if (typeof window === "undefined") return false;
|
||||
try {
|
||||
const saved = localStorage.getItem(SIDEBAR_MINIMAL_STORAGE_KEY);
|
||||
if (saved !== null) return saved === "true";
|
||||
const userKeys = Object.keys(localStorage).filter((key) => key.startsWith(`${SIDEBAR_MINIMAL_STORAGE_KEY}:`));
|
||||
return userKeys.length === 1 && localStorage.getItem(userKeys[0]) === "true";
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function saveInitialSidebarMinimal(minimal: boolean): void {
|
||||
try {
|
||||
localStorage.setItem(SIDEBAR_MINIMAL_STORAGE_KEY, String(minimal));
|
||||
} catch {
|
||||
// Storage can be unavailable in private windows.
|
||||
}
|
||||
}
|
||||
@@ -2,12 +2,13 @@
|
||||
|
||||
import { createContext, useContext, useEffect, useState } from "react";
|
||||
import { readColumnWidth } from "./column-width-preferences";
|
||||
import { readInitialSidebarMinimal, saveInitialSidebarMinimal } from "./sidebar-state-utils";
|
||||
import type { SidebarProviderProps, SidebarState } from "./sidebar-state-types";
|
||||
|
||||
const SidebarContext = createContext<SidebarState>({ minimal: false, width: 260, userId: null, toggle: () => undefined, setWidth: () => undefined, setForcedMinimal: () => undefined });
|
||||
|
||||
export function SidebarProvider({ children, expandedWidth = 260 }: SidebarProviderProps) {
|
||||
const [minimal, setMinimal] = useState(false);
|
||||
const [minimal, setMinimal] = useState(readInitialSidebarMinimal);
|
||||
const [forcedMinimal, setForcedMinimal] = useState(false);
|
||||
const [width, setWidth] = useState(expandedWidth);
|
||||
const [userId, setUserId] = useState<string | null>(null);
|
||||
@@ -29,7 +30,9 @@ export function SidebarProvider({ children, expandedWidth = 260 }: SidebarProvid
|
||||
const key = `mailflare-sidebar-minimal:${userId}`;
|
||||
setStorageKey(key);
|
||||
try {
|
||||
setMinimal(localStorage.getItem(key) === "true");
|
||||
const savedMinimal = localStorage.getItem(key) === "true";
|
||||
setMinimal(savedMinimal);
|
||||
saveInitialSidebarMinimal(savedMinimal);
|
||||
setWidth(readColumnWidth(userId, "sidebar", expandedWidth, 200, 480));
|
||||
} catch {
|
||||
// Storage can be unavailable in private windows; keep the default.
|
||||
@@ -42,11 +45,13 @@ export function SidebarProvider({ children, expandedWidth = 260 }: SidebarProvid
|
||||
if (forcedMinimal) {
|
||||
setForcedMinimal(false);
|
||||
setMinimal(false);
|
||||
saveInitialSidebarMinimal(false);
|
||||
if (storageKey) localStorage.setItem(storageKey, "false");
|
||||
return;
|
||||
}
|
||||
setMinimal((current) => {
|
||||
const next = !current;
|
||||
saveInitialSidebarMinimal(next);
|
||||
if (storageKey) localStorage.setItem(storageKey, String(next));
|
||||
return next;
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user