feat(webmail): the new interface - logo, dark and light themes, command menu
A mark (a lambda on an ultramarine tile with the flap of an envelope), the favicon, home-screen icons and an install manifest. Every colour is a variable defined once per theme, and the Tailwind scales the screens already use read them, so dark (the default) and light are a change of values and not of classes. Geist is served by the app itself. Ctrl+K opens a command menu for folders, actions, accounts and appearance, and typing something that matches no command searches the mail; c writes a message and / goes to the search field. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6b97807856
commit
e667843b59
38 files changed
+1161
-316
No files matched your search
@@ -0,0 +1,37 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import { Laptop, Moon, Sun } from "lucide-react";
|
||||
import { useTranslations } from "../i18n/provider";
|
||||
import { useTheme, type ThemeChoice } from "../lib/theme";
|
||||
|
||||
/** Dark, light or follow the system: three buttons, one click each. */
|
||||
export function ThemeToggle({ className = "" }: { className?: string }) {
|
||||
const t = useTranslations();
|
||||
const theme = useTheme();
|
||||
const options: [ThemeChoice, React.ComponentType<{ className?: string }>, string][] = [
|
||||
["dark", Moon, t("appearance.dark")],
|
||||
["light", Sun, t("appearance.light")],
|
||||
["system", Laptop, t("appearance.system")],
|
||||
];
|
||||
return (
|
||||
<div role="radiogroup" aria-label={t("appearance.title")} className={`flex rounded-lg p-0.5 shadow-edge ${className}`}>
|
||||
{options.map(([value, Icon, label]) => (
|
||||
<button
|
||||
key={value}
|
||||
type="button"
|
||||
role="radio"
|
||||
aria-checked={theme.choice === value}
|
||||
aria-label={label}
|
||||
title={label}
|
||||
onClick={() => theme.set(value)}
|
||||
className={`flex h-7 w-8 items-center justify-center rounded-md transition-colors ${
|
||||
theme.choice === value ? "bg-indigo-500/20 text-indigo-300" : "text-slate-400 hover:text-slate-100"
|
||||
}`}
|
||||
>
|
||||
<Icon className="h-3.5 w-3.5" />
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user