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:
Lucas RayanandClaude Sonnet 5.5 committed 2026-10-22 22:33:15 -03:00
1 parent 6b97807856
commit e667843b59
38 files changed
+1161 -316

No files matched your search

@@ -510,7 +510,7 @@ export default function UserSettingsPage() {
type="button"
onClick={() => void revokeAppPassword(ap.id)}
aria-label={t("common.delete")}
className="flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg text-slate-400 transition-colors hover:bg-white/[0.07] hover:text-rose-400"
className="flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg text-slate-400 transition-colors hover:bg-ink/[0.07] hover:text-rose-400"
>
<Trash2 className="h-[15px] w-[15px]" />
</button>
@@ -551,7 +551,7 @@ export default function UserSettingsPage() {
type="button"
onClick={() => void revokeSession(session.id)}
aria-label={t("common.delete")}
className="flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg text-slate-400 transition-colors hover:bg-white/[0.07] hover:text-rose-400"
className="flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg text-slate-400 transition-colors hover:bg-ink/[0.07] hover:text-rose-400"
>
<Trash2 className="h-[15px] w-[15px]" />
</button>
@@ -769,7 +769,7 @@ export default function UserSettingsPage() {
disabled={index === 0}
aria-label={t("settings.ruleMoveUp")}
title={t("settings.ruleMoveUp")}
className="flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg text-slate-400 transition-colors hover:bg-white/[0.07] hover:text-slate-100 disabled:opacity-30"
className="flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg text-slate-400 transition-colors hover:bg-ink/[0.07] hover:text-slate-100 disabled:opacity-30"
>
<ChevronUp className="h-[15px] w-[15px]" />
</button>
@@ -779,7 +779,7 @@ export default function UserSettingsPage() {
disabled={index === rules.length - 1}
aria-label={t("settings.ruleMoveDown")}
title={t("settings.ruleMoveDown")}
className="flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg text-slate-400 transition-colors hover:bg-white/[0.07] hover:text-slate-100 disabled:opacity-30"
className="flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg text-slate-400 transition-colors hover:bg-ink/[0.07] hover:text-slate-100 disabled:opacity-30"
>
<ChevronDown className="h-[15px] w-[15px]" />
</button>
@@ -787,7 +787,7 @@ export default function UserSettingsPage() {
type="button"
onClick={() => removeSieveRule(r.id)}
aria-label={t("common.delete")}
className="flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg text-slate-400 transition-colors hover:bg-white/[0.07] hover:text-rose-400"
className="flex h-[30px] w-[30px] flex-none items-center justify-center rounded-lg text-slate-400 transition-colors hover:bg-ink/[0.07] hover:text-rose-400"
>
<Trash2 className="h-[15px] w-[15px]" />
</button>
@@ -914,12 +914,12 @@ export default function UserSettingsPage() {
aria-label={b.title}
onMouseDown={(e) => e.preventDefault()}
onClick={() => applySignatureCommand(b.cmd)}
className={`h-7 w-7 rounded-md text-[13px] text-slate-300 transition-colors hover:bg-white/[0.09] hover:text-slate-100 ${b.cls}`}
className={`h-7 w-7 rounded-md text-[13px] text-slate-300 transition-colors hover:bg-ink/[0.09] hover:text-slate-100 ${b.cls}`}
>
{b.label}
</button>
))}
<span className="mx-1 h-4 w-px bg-white/10" />
<span className="mx-1 h-4 w-px bg-ink/10" />
<button
type="button"
title={t("ui.insertLink")}
@@ -929,7 +929,7 @@ export default function UserSettingsPage() {
const url = window.prompt(t("ui.insertLink"), "https://");
if (url) applySignatureCommand("createLink", url);
}}
className="h-7 rounded-md px-2 text-[12px] text-slate-300 transition-colors hover:bg-white/[0.09] hover:text-slate-100"
className="h-7 rounded-md px-2 text-[12px] text-slate-300 transition-colors hover:bg-ink/[0.09] hover:text-slate-100"
>
{t("ui.insertLink")}
</button>
@@ -942,7 +942,7 @@ export default function UserSettingsPage() {
const url = window.prompt(t("ui.insertImage"), "https://");
if (url) applySignatureCommand("insertImage", url);
}}
className="h-7 rounded-md px-2 text-[12px] text-slate-300 transition-colors hover:bg-white/[0.09] hover:text-slate-100"
className="h-7 rounded-md px-2 text-[12px] text-slate-300 transition-colors hover:bg-ink/[0.09] hover:text-slate-100"
>
{t("ui.insertImage")}
</button>