diff --git a/apps/x/apps/renderer/src/App.css b/apps/x/apps/renderer/src/App.css index 2cb6ac33..bdb1430f 100644 --- a/apps/x/apps/renderer/src/App.css +++ b/apps/x/apps/renderer/src/App.css @@ -82,64 +82,40 @@ background-image: radial-gradient(circle, oklch(0.7 0 0 / 0.06) 1px, transparent 1px); } +/* Inbox surface — mapped onto the app's design tokens so it follows the same + palette, accent, and theme switching as the rest of Rowboat. Light/dark is + handled by the app tokens (:root / .dark), so no separate .light override. */ .gmail-shell { - --gm-bg: #0f0f12; - --gm-bg-card: #131317; - --gm-bg-input: #1c1c20; - --gm-bg-row-hover: #16161a; - --gm-bg-row-selected: #1a1620; - --gm-bg-row-selected-hover: #1d1825; - --gm-bg-iframe: #fafafa; - --gm-bg-pill: #1c1c20; - --gm-bg-pill-hover: #232328; - --gm-text: #e4e4e7; - --gm-text-strong: #fafafa; - --gm-text-muted: #71717a; - --gm-text-faint: #52525b; - --gm-text-body: #d4d4d8; - --gm-border: #1f1f24; - --gm-border-strong: #2e2e35; - --gm-accent: #a78bfa; - --gm-accent-hover: #b9a6ff; - --gm-accent-glow: rgba(167, 139, 250, 0.45); - --gm-accent-fg: #18181b; - --gm-icon-hover-bg: #1f1f24; - --gm-placeholder: #52525b; + --gm-bg: var(--background); + --gm-bg-card: var(--card-surface); + --gm-bg-input: var(--muted); + --gm-bg-row-hover: var(--accent); + --gm-bg-row-selected: var(--rowboat-wash); + --gm-bg-row-selected-hover: color-mix(in oklab, var(--primary) 18%, var(--background)); + --gm-bg-iframe: #ffffff; + --gm-bg-pill: var(--background); + --gm-bg-pill-hover: var(--accent); + --gm-text: var(--foreground); + --gm-text-strong: var(--foreground); + --gm-text-muted: var(--muted-foreground); + --gm-text-faint: color-mix(in oklab, var(--muted-foreground) 70%, var(--background)); + --gm-text-body: color-mix(in oklab, var(--foreground) 88%, var(--background)); + --gm-border: var(--border); + --gm-border-strong: var(--rowboat-hairline); + --gm-accent: var(--primary); + --gm-accent-hover: color-mix(in oklab, var(--primary) 90%, transparent); + --gm-accent-glow: color-mix(in oklab, var(--primary) 40%, transparent); + --gm-accent-fg: var(--primary-foreground); + --gm-icon-hover-bg: var(--accent); + --gm-placeholder: var(--muted-foreground); display: flex; height: 100%; min-height: 0; width: 100%; overflow: hidden; - background: var(--gm-bg); - color: var(--gm-text); - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; - font-feature-settings: "ss01", "cv11"; -} - -.light .gmail-shell { - --gm-bg: #ffffff; - --gm-bg-card: #ffffff; - --gm-bg-input: #f4f4f7; - --gm-bg-row-hover: #f7f7f9; - --gm-bg-row-selected: #f5f0ff; - --gm-bg-row-selected-hover: #ece4ff; - --gm-bg-iframe: #ffffff; - --gm-bg-pill: #ffffff; - --gm-bg-pill-hover: #f4f4f7; - --gm-text: #27272a; - --gm-text-strong: #09090b; - --gm-text-muted: #71717a; - --gm-text-faint: #a1a1aa; - --gm-text-body: #3f3f46; - --gm-border: #e4e4e7; - --gm-border-strong: #d4d4d8; - --gm-accent: #7c3aed; - --gm-accent-hover: #6d28d9; - --gm-accent-glow: rgba(124, 58, 237, 0.3); - --gm-accent-fg: #ffffff; - --gm-icon-hover-bg: #f4f4f7; - --gm-placeholder: #a1a1aa; + background: var(--background); + color: var(--foreground); } .gmail-main { @@ -326,7 +302,7 @@ } .gmail-row-action-danger:hover { - color: #e8453c; + color: var(--destructive); } .gmail-row:hover { @@ -714,714 +690,78 @@ border-color: var(--gm-border-strong); } -/* Standalone "new email" composer — centered modal popup */ -.gmail-compose-overlay { - position: fixed; - inset: 0; - z-index: 50; - display: flex; - align-items: center; - justify-content: center; - padding: 32px; - background: rgba(0, 0, 0, 0.32); -} - -/* Dark defaults (mirrors .gmail-shell); .light overrides below. */ -.gmail-compose-modal, -.gmail-compose-card { - --gm-bg-card: #131317; - --gm-bg-input: #1c1c20; - --gm-bg-elevated: #1c1c20; - --gm-bg-pill: #1c1c20; - --gm-bg-pill-hover: #232328; - --gm-text: #e4e4e7; - --gm-text-strong: #fafafa; - --gm-text-muted: #71717a; - --gm-text-body: #d4d4d8; - --gm-border: #1f1f24; - --gm-border-strong: #2e2e35; - --gm-accent: #a78bfa; - --gm-accent-hover: #b9a6ff; - --gm-accent-fg: #18181b; - --gm-icon-hover-bg: #1f1f24; - --gm-placeholder: #52525b; -} - -.light .gmail-compose-modal, -.light .gmail-compose-card { - --gm-bg-card: #ffffff; - --gm-bg-input: #f4f4f7; - --gm-bg-elevated: #ffffff; - --gm-bg-pill: #ffffff; - --gm-bg-pill-hover: #f4f4f7; - --gm-text: #27272a; - --gm-text-strong: #09090b; - --gm-text-muted: #71717a; - --gm-text-body: #3f3f46; - --gm-border: #e4e4e7; - --gm-border-strong: #d4d4d8; - --gm-accent: #7c3aed; - --gm-accent-hover: #6d28d9; - --gm-accent-fg: #ffffff; - --gm-icon-hover-bg: #f4f4f7; - --gm-placeholder: #a1a1aa; -} - -.gmail-compose-modal { - display: flex; - flex-direction: column; - width: min(840px, 100%); - height: min(720px, calc(100vh - 64px)); - max-height: calc(100vh - 64px); - border: 1px solid var(--gm-border-strong); - border-radius: 10px; - overflow: hidden; - background: var(--gm-bg-card); - box-shadow: 0 16px 48px rgba(0, 0, 0, 0.35); -} - -.gmail-compose-modal-header { - display: flex; - align-items: center; - gap: 10px; - height: 40px; - padding: 0 8px 0 14px; - background: var(--gm-bg-input); - color: var(--gm-text-body); - font-size: 12px; - font-weight: 600; - letter-spacing: 0.01em; - text-transform: uppercase; -} - -.gmail-compose-modal-header > span { - flex: 1; -} - -.gmail-compose-modal .gmail-compose-editor { - flex: 1; - min-height: 160px; - max-height: none; - padding: 0 14px; -} - -.gmail-compose-ai-bar { - display: flex; - align-items: center; - gap: 8px; - padding: 8px 12px; - border-bottom: 1px solid var(--gm-border); -} - -.gmail-compose-ai-input { - flex: 1; - min-width: 0; - height: 30px; - padding: 0 10px; - border: 1px solid var(--gm-border-strong); - border-radius: 6px; - outline: none; - background: var(--gm-bg-input); - color: var(--gm-text); - font: inherit; - font-size: 12px; -} - -.gmail-compose-ai-presets { - display: flex; - flex-wrap: wrap; - gap: 6px; - padding: 0 12px 10px; - border-bottom: 1px solid var(--gm-border); -} - -.gmail-compose-ai-presets button { - height: 24px; - padding: 0 10px; - border: 1px solid var(--gm-border-strong); - border-radius: 999px; - background: var(--gm-bg-pill); - color: var(--gm-text-muted); - font: inherit; - font-size: 11px; - font-weight: 500; - cursor: pointer; - transition: background 120ms ease, color 120ms ease, border-color 120ms ease; -} - -.gmail-compose-ai-presets button:hover:not(:disabled) { - background: var(--gm-bg-pill-hover); - border-color: var(--gm-accent); - color: var(--gm-accent); -} - -.gmail-compose-ai-presets button:disabled, -.gmail-compose-ai-input:disabled { - opacity: 0.5; - cursor: default; -} - -.gmail-compose-card { - max-width: 720px; - margin-left: 40px; - border: 1px solid var(--gm-border-strong); - border-radius: 8px; - overflow: hidden; - background: var(--gm-bg-card); -} - -.gmail-compose-header { - display: flex; - align-items: center; - justify-content: space-between; - height: 32px; - padding: 0 12px; - background: var(--gm-bg-input); - color: var(--gm-text-body); - font-size: 12px; - font-weight: 500; - letter-spacing: 0.01em; - text-transform: uppercase; -} - -.gmail-compose-header button, -.gmail-compose-link { - border: none; - background: transparent; - color: var(--gm-text-muted); - cursor: pointer; -} - -.gmail-compose-line { - display: flex; - align-items: center; - gap: 8px; - min-height: 32px; - padding: 0 12px; - border-bottom: 1px solid var(--gm-border); - color: var(--gm-text-muted); - font-size: 12px; -} - -.gmail-compose-line input { - min-width: 0; - flex: 1; - border: none; - outline: none; - background: transparent; - color: var(--gm-text); - font: inherit; -} - -.gmail-compose-label { - flex: none; - min-width: 28px; - color: var(--gm-text-muted); -} - -.gmail-compose-subject-input { - min-width: 0; - flex: 1; - border: none; - outline: none; - background: transparent; - color: var(--gm-text); - font: inherit; -} - -/* Recipient (To / Cc / Bcc) rows with editable chips */ -.gmail-recipient-row { - display: flex; - align-items: flex-start; - gap: 8px; - min-height: 34px; - padding: 5px 12px; - border-bottom: 1px solid var(--gm-border); - font-size: 13px; -} - -.gmail-recipient-label { - flex: none; - min-width: 28px; - padding-top: 5px; - color: var(--gm-text-muted); -} - -.gmail-recipient-field { - display: flex; - flex-wrap: wrap; - align-items: center; - gap: 4px; - flex: 1; - min-width: 0; - position: relative; -} - -.gmail-recipient-suggestions { - position: absolute; - top: calc(100% + 6px); - left: 0; - z-index: 30; - margin: 0; - padding: 6px; - list-style: none; - width: max-content; - min-width: 280px; - max-width: min(440px, 100%); - background: var(--gm-bg-elevated, #ffffff); - border: 1px solid var(--gm-border); - border-radius: 10px; - box-shadow: - 0 1px 2px rgba(24, 24, 27, 0.08), - 0 12px 32px rgba(24, 24, 27, 0.18); - max-height: 296px; - overflow-y: auto; - overscroll-behavior: contain; - transform-origin: top left; - animation: gmail-recipient-suggestions-in 110ms cubic-bezier(0.2, 0.7, 0.2, 1); -} - -@keyframes gmail-recipient-suggestions-in { - from { - opacity: 0; - transform: translateY(-2px) scale(0.985); - } - to { - opacity: 1; - transform: translateY(0) scale(1); - } -} - -.gmail-recipient-suggestion { - display: flex; - align-items: center; - gap: 10px; - padding: 6px 10px; - border-radius: 6px; - font-size: 13px; - color: var(--gm-text); - cursor: pointer; - transition: background-color 80ms linear; -} - -.gmail-recipient-suggestion:hover { - background: var(--gm-bg-pill-hover); -} - -.gmail-recipient-suggestion.is-active { - background: rgba(99, 142, 255, 0.18); -} - -.gmail-recipient-suggestion-avatar { - flex: none; - display: inline-flex; - align-items: center; - justify-content: center; - width: 26px; - height: 26px; - border-radius: 50%; - color: #fff; - font-size: 12px; - font-weight: 600; - letter-spacing: 0.2px; - text-transform: uppercase; -} - -.gmail-recipient-suggestion-text { - display: flex; - flex-direction: column; - flex: 1 1 auto; - min-width: 0; - line-height: 1.25; -} - -.gmail-recipient-suggestion-name { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-weight: 500; -} - -.gmail-recipient-suggestion-email { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - font-size: 11.5px; - color: var(--gm-text-muted); - margin-top: 1px; -} - -.gmail-recipient-suggestion-match { - background: transparent; - color: inherit; - font-weight: 700; - padding: 0; -} - -.gmail-recipient-chip { - display: inline-flex; - align-items: center; - gap: 4px; - max-width: 100%; - height: 24px; - padding: 0 4px 0 10px; - border-radius: 12px; - background: var(--gm-bg-pill); - color: var(--gm-text); - font-size: 12px; - line-height: 1; -} - -.gmail-recipient-chip-label { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - max-width: 240px; -} - -.gmail-recipient-chip-remove { - display: inline-flex; - align-items: center; - justify-content: center; - width: 16px; - height: 16px; - border: none; - border-radius: 50%; - background: transparent; - color: var(--gm-text-muted); - font-size: 14px; - line-height: 1; - cursor: pointer; -} - -.gmail-recipient-chip-remove:hover { - background: var(--gm-bg-pill-hover); - color: var(--gm-text); -} - -.gmail-recipient-input { - flex: 1 1 80px; - min-width: 80px; - height: 24px; - border: none; - outline: none; - background: transparent; - color: var(--gm-text); - font: inherit; - font-size: 13px; -} - -.gmail-recipient-trailing { - flex: none; - padding-top: 5px; -} - -.gmail-recipient-toggles { - display: flex; - gap: 10px; -} - -.gmail-recipient-toggles button { - border: none; - background: transparent; - color: var(--gm-text-muted); - font: inherit; - font-size: 12px; - cursor: pointer; -} - -.gmail-recipient-toggles button:hover { - color: var(--gm-text); - text-decoration: underline; -} - -.gmail-compose-toolbar { - display: flex; - align-items: center; - gap: 2px; - flex: 1; - min-width: 0; - justify-content: flex-start; - padding-left: 10px; - margin-left: 2px; - border-left: 1px solid var(--gm-border-strong); -} - -.gmail-compose-link-popover { - display: flex; - align-items: center; - gap: 6px; - padding: 8px 12px; - border-top: 1px solid var(--gm-border); - background: var(--gm-bg-input); -} - -.gmail-compose-link-popover input { - flex: 1; - min-width: 0; - height: 28px; - padding: 0 8px; - border: 1px solid var(--gm-border-strong); - border-radius: 4px; - background: var(--gm-bg-card); - color: var(--gm-text); - font: inherit; - font-size: 12px; - outline: none; -} - -.gmail-compose-link-popover input:focus { - border-color: var(--gm-accent); -} - -.gmail-compose-link-popover button { - height: 26px; - padding: 0 10px; - border: 1px solid var(--gm-border-strong); - border-radius: 4px; - background: var(--gm-bg-pill); - color: var(--gm-text); - font: inherit; - font-size: 12px; - cursor: pointer; -} - -.gmail-compose-link-popover button:hover { - background: var(--gm-bg-pill-hover); -} - -.gmail-compose-link-popover-apply { - background: var(--gm-accent) !important; - border-color: var(--gm-accent) !important; - color: var(--gm-accent-fg) !important; - font-weight: 600; -} - -.gmail-compose-link-popover-apply:hover { - background: var(--gm-accent-hover) !important; - border-color: var(--gm-accent-hover) !important; -} - -.gmail-compose-tool { - display: inline-flex; - align-items: center; - justify-content: center; - width: 26px; - height: 26px; - border: none; - border-radius: 4px; - background: transparent; - color: var(--gm-text-muted); - cursor: pointer; - transition: background 120ms ease, color 120ms ease; -} - -.gmail-compose-tool:hover:not(:disabled) { - background: var(--gm-bg-pill-hover); - color: var(--gm-text); -} - -.gmail-compose-tool:disabled { - opacity: 0.4; - cursor: default; -} - -.gmail-compose-tool.is-active { - background: var(--gm-bg-pill-hover); - color: var(--gm-accent); -} - -.gmail-compose-tool-sep { - display: inline-block; - width: 1px; - height: 18px; - margin: 0 6px; - background: var(--gm-border-strong); -} - -.gmail-compose-editor { - display: block; - width: 100%; - max-height: 360px; - overflow-y: auto; -} - -.gmail-compose-content { +/* Email composer body — Tiptap content, styled to the app's design system. */ +.compose-content { outline: none; min-height: 120px; padding: 12px; background: transparent; - color: var(--gm-text); - font: 13px/1.55 inherit; + color: var(--foreground); + font-size: 0.875rem; + line-height: 1.6; } -.gmail-compose-content p { +.compose-content p { margin: 0; } -.gmail-compose-content p + p, -.gmail-compose-content p + ul, -.gmail-compose-content p + ol, -.gmail-compose-content p + blockquote { +.compose-content p + p, +.compose-content p + ul, +.compose-content p + ol, +.compose-content p + blockquote { margin-top: 8px; } -.gmail-compose-content ul, -.gmail-compose-content ol { +.compose-content ul, +.compose-content ol { margin: 0; padding-left: 22px; } -.gmail-compose-content ul { +.compose-content ul { list-style: disc; } -.gmail-compose-content ol { +.compose-content ol { list-style: decimal; } -.gmail-compose-content li { +.compose-content li { margin: 2px 0; } -.gmail-compose-content li > p { +.compose-content li > p { margin: 0; } -.gmail-compose-content blockquote { +.compose-content blockquote { margin: 4px 0; padding-left: 12px; - border-left: 2px solid var(--gm-border-strong); - color: var(--gm-text-muted); + border-left: 2px solid var(--border); + color: var(--muted-foreground); } -.gmail-compose-content a { - color: var(--gm-accent); +.compose-content a { + color: var(--primary); text-decoration: underline; } -.gmail-compose-content code { +.compose-content code { padding: 1px 4px; border-radius: 3px; - background: var(--gm-bg-pill-hover); + background: var(--muted); font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; - font-size: 12px; + font-size: 0.8125rem; } -.gmail-compose-content p.is-editor-empty:first-child::before { +.compose-content p.is-editor-empty:first-child::before { content: attr(data-placeholder); - color: var(--gm-placeholder); + color: var(--muted-foreground); float: left; height: 0; pointer-events: none; } -.gmail-compose-attachments { - display: flex; - flex-wrap: wrap; - gap: 6px; - padding: 8px 12px 0; -} - -.gmail-compose-attachment { - display: inline-flex; - align-items: center; - gap: 6px; - max-width: 240px; - padding: 4px 8px; - border: 1px solid var(--gm-border); - border-radius: 6px; - background: var(--gm-bg-pill); - font-size: 12px; - color: var(--gm-text); -} - -.gmail-compose-attachment-name { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.gmail-compose-attachment-size { - color: var(--gm-text-muted); - flex-shrink: 0; -} - -.gmail-compose-attachment-remove { - border: none; - background: transparent; - color: var(--gm-text-muted); - cursor: pointer; - font-size: 15px; - line-height: 1; - padding: 0 0 0 2px; - flex-shrink: 0; -} - -.gmail-compose-attachment-remove:hover { - color: var(--gm-text); -} - -.gmail-compose-actions { - display: flex; - align-items: center; - gap: 12px; - padding: 10px 12px; - border-top: 1px solid var(--gm-border); -} - -.gmail-compose-actions-primary { - display: flex; - align-items: center; - gap: 8px; - flex-shrink: 0; -} - -.gmail-refine-button { - display: inline-flex; - align-items: center; - gap: 8px; - box-sizing: border-box; - height: 30px; - padding: 0 14px; - border: 1px solid var(--gm-border-strong); - border-radius: 6px; - background: var(--gm-bg-pill); - color: var(--gm-text); - font: inherit; - font-size: 12px; - font-weight: 500; - cursor: pointer; - transition: background 120ms ease, border-color 120ms ease, color 120ms ease; -} - -.gmail-refine-button:hover { - background: var(--gm-bg-pill-hover); - border-color: var(--gm-accent); - color: var(--gm-accent); -} - -.gmail-send-button { - display: inline-flex; - align-items: center; - gap: 8px; - box-sizing: border-box; - height: 30px; - padding: 0 14px; - border: 1px solid transparent; - border-radius: 6px; - background: var(--gm-accent); - color: var(--gm-accent-fg); - font: inherit; - font-size: 12px; - font-weight: 600; - cursor: pointer; -} - -.gmail-send-button:hover { - background: var(--gm-accent-hover); -} - .gmail-empty-state { display: flex; align-items: center; diff --git a/apps/x/apps/renderer/src/components/email-view.tsx b/apps/x/apps/renderer/src/components/email-view.tsx index 5d62898a..266ae93c 100644 --- a/apps/x/apps/renderer/src/components/email-view.tsx +++ b/apps/x/apps/renderer/src/components/email-view.tsx @@ -1,5 +1,5 @@ import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react' -import { Archive, Bold, CheckCheck, Forward, Italic, Link as LinkIcon, List, ListOrdered, LoaderIcon, Mail, Paperclip, Quote, Redo2, RefreshCw, Reply, ReplyAll, Search, Send, Sparkles, SquarePen, Strikethrough, Trash2, Undo2 } from 'lucide-react' +import { Archive, Bold, CheckCheck, Forward, Italic, Link as LinkIcon, List, ListOrdered, LoaderIcon, Mail, Paperclip, Quote, Redo2, RefreshCw, Reply, ReplyAll, Search, Send, Sparkles, SquarePen, Strikethrough, Trash2, Undo2, X } from 'lucide-react' import { useEditor, EditorContent, type Editor } from '@tiptap/react' import StarterKit from '@tiptap/starter-kit' import Link from '@tiptap/extension-link' @@ -9,6 +9,9 @@ import { cn } from '@/lib/utils' import { toast } from '@/lib/toast' import { useTheme } from '@/contexts/theme-context' import { SettingsDialog } from '@/components/settings-dialog' +import { Button } from '@/components/ui/button' +import { Input } from '@/components/ui/input' +import { Dialog, DialogContent, DialogTitle } from '@/components/ui/dialog' type GmailThread = blocks.GmailThread type GmailThreadMessage = blocks.GmailThreadMessage @@ -539,9 +542,11 @@ function ComposeToolbarButton({ children: React.ReactNode }) { return ( - + ) } function ComposeToolbar({ editor, onOpenLink }: { editor: Editor; onOpenLink: () => void }) { return ( -
+