handoff minor fixes

This commit is contained in:
debu-2 2026-10-06 23:31:49 +05:30
parent d4bb4df40d
commit 48eea5d201
8 changed files with 99 additions and 28 deletions

View file

@ -132,6 +132,37 @@ function selectionInside(editor) {
return { selection, range }; return { selection, range };
} }
const ALIGN_BY_COMMAND = {
justifyLeft: "left",
justifyCenter: "center",
justifyRight: "right",
};
function alignmentBlock(editor, range) {
if (!editor || !range) return null;
let node = range.startContainer;
if (node.nodeType !== Node.ELEMENT_NODE) node = node.parentElement;
const block = node?.closest?.("li, p, div, blockquote, h1, h2, h3, h4");
if (!block || !editor.contains(block)) return null;
return block;
}
function explicitAlignment(block) {
if (!block) return "";
const value = (block.style?.textAlign || block.getAttribute?.("align") || "").toLowerCase();
if (value === "center") return "center";
if (value === "right" || value === "end") return "right";
if (value === "left" || value === "start") return "left";
return "";
}
function clearAlignment(block) {
if (!block) return;
block.style.textAlign = "";
if (!block.getAttribute("style")) block.removeAttribute("style");
block.removeAttribute("align");
}
function FormatButton({ title, active, onClick, children }) { function FormatButton({ title, active, onClick, children }) {
return ( return (
<button <button
@ -389,14 +420,17 @@ export default function ComposeModal({
function updateFormatState() { function updateFormatState() {
try { try {
const editor = editorRef.current;
const current = selectionInside(editor);
const align = explicitAlignment(alignmentBlock(editor, current?.range));
setFormatState({ setFormatState({
bold: document.queryCommandState("bold"), bold: document.queryCommandState("bold"),
italic: document.queryCommandState("italic"), italic: document.queryCommandState("italic"),
underline: document.queryCommandState("underline"), underline: document.queryCommandState("underline"),
strikeThrough: document.queryCommandState("strikeThrough"), strikeThrough: document.queryCommandState("strikeThrough"),
justifyLeft: document.queryCommandState("justifyLeft"), justifyLeft: align === "left",
justifyCenter: document.queryCommandState("justifyCenter"), justifyCenter: align === "center",
justifyRight: document.queryCommandState("justifyRight"), justifyRight: align === "right",
insertUnorderedList: document.queryCommandState("insertUnorderedList"), insertUnorderedList: document.queryCommandState("insertUnorderedList"),
insertOrderedList: document.queryCommandState("insertOrderedList"), insertOrderedList: document.queryCommandState("insertOrderedList"),
}); });
@ -408,7 +442,16 @@ export default function ComposeModal({
function execFormat(command, value = null) { function execFormat(command, value = null) {
restoreSelection(); restoreSelection();
document.execCommand("defaultParagraphSeparator", false, "div"); document.execCommand("defaultParagraphSeparator", false, "div");
const align = ALIGN_BY_COMMAND[command];
if (align) {
const editor = editorRef.current;
const current = selectionInside(editor);
const block = alignmentBlock(editor, current?.range);
if (explicitAlignment(block) === align) clearAlignment(block);
else document.execCommand(command, false, value);
} else {
document.execCommand(command, false, value); document.execCommand(command, false, value);
}
saveSelection(); saveSelection();
syncBodyFromEditor(); syncBodyFromEditor();
updateFormatState(); updateFormatState();
@ -678,12 +721,14 @@ export default function ComposeModal({
orgDomain={orgDomain} orgDomain={orgDomain}
inline inline
autoFocus autoFocus
/> trailing={(!showCc || !showBcc) ? (
</div>
<div className="compose-recipient-toggles"> <div className="compose-recipient-toggles">
{!showCc && <button type="button" onClick={() => setShowCc(true)}>Cc</button>} {!showCc && <button type="button" onClick={() => setShowCc(true)}>Cc</button>}
{!showBcc && <button type="button" onClick={() => setShowBcc(true)}>Bcc</button>} {!showBcc && <button type="button" onClick={() => setShowBcc(true)}>Bcc</button>}
</div> </div>
) : null}
/>
</div>
</div> </div>
{showCc && ( {showCc && (

View file

@ -175,7 +175,7 @@ export default function DashboardPage() {
} }
function closeMobileMenu() { function closeMobileMenu() {
if (window.matchMedia("(max-width: 767px)").matches) { if (window.matchMedia("(max-width: 767.98px)").matches) {
setMenuOpen(false); setMenuOpen(false);
} }
} }
@ -219,7 +219,7 @@ export default function DashboardPage() {
setLens("all"); setLens("all");
setAgentNav(actionKey); setAgentNav(actionKey);
closeMobileMenu(); closeMobileMenu();
const compact = window.matchMedia("(max-width: 1199px)").matches; const compact = window.matchMedia("(max-width: 1199.98px)").matches;
setSheet(actionKey === "handoff" || !compact ? null : "agent"); setSheet(actionKey === "handoff" || !compact ? null : "agent");
} }

View file

@ -10,7 +10,7 @@ import {
} from "../api"; } from "../api";
import AgentSpark from "./AgentSpark"; import AgentSpark from "./AgentSpark";
import HumanHandoffDrawer from "./HumanHandoffDrawer"; import HumanHandoffDrawer from "./HumanHandoffDrawer";
import { buildRuleCardChips } from "../utils/handoffUtils"; import { buildRuleCardChips, typeLabel } from "../utils/handoffUtils";
function ruleScope(rule) { function ruleScope(rule) {
return buildRuleCardChips(rule).filter((chip) => chip !== rule.name).join(" · "); return buildRuleCardChips(rule).filter((chip) => chip !== rule.name).join(" · ");

View file

@ -128,7 +128,9 @@ export default function HumanHandoffDrawer({
<div className="handoff-drawer-body"> <div className="handoff-drawer-body">
<section className="handoff-form-section"> <section className="handoff-form-section">
<h3>Rule</h3> <h3>Rule</h3>
<label className="handoff-field-label" htmlFor="handoff-rule-name">Rule name</label> <label className="handoff-field-label" htmlFor="handoff-rule-name">
Rule name <span className="handoff-required" aria-hidden="true">*</span>
</label>
<input <input
id="handoff-rule-name" id="handoff-rule-name"
className="handoff-text-input" className="handoff-text-input"
@ -152,7 +154,9 @@ export default function HumanHandoffDrawer({
<section className="handoff-form-section"> <section className="handoff-form-section">
<h3>Human owner</h3> <h3>Human owner</h3>
<label className="handoff-field-label" htmlFor="handoff-owner-email">Owner email address</label> <label className="handoff-field-label" htmlFor="handoff-owner-email">
Owner email address <span className="handoff-required" aria-hidden="true">*</span>
</label>
<div className="handoff-email-input"> <div className="handoff-email-input">
<Mail size={16} strokeWidth={1.75} /> <Mail size={16} strokeWidth={1.75} />
<input <input
@ -178,7 +182,7 @@ export default function HumanHandoffDrawer({
</section> </section>
<section className="handoff-form-section"> <section className="handoff-form-section">
<h3>Hand off emails with these labels</h3> <h3>Hand off emails with these labels <span className="handoff-required" aria-hidden="true">*</span></h3>
<p className="handoff-helper"> <p className="handoff-helper">
These are content-based handoff categories, not inbox tabs. Gentic infers them from These are content-based handoff categories, not inbox tabs. Gentic infers them from
subject and body text. Choose <strong>All mail</strong> to hand off every incoming email. subject and body text. Choose <strong>All mail</strong> to hand off every incoming email.
@ -213,7 +217,7 @@ export default function HumanHandoffDrawer({
</section> </section>
<section className="handoff-form-section"> <section className="handoff-form-section">
<h3>Hand off these types of email</h3> <h3>Hand off these types of email <span className="handoff-required" aria-hidden="true">*</span></h3>
<p className="handoff-helper"> <p className="handoff-helper">
Types are also inferred from email content. Choose <strong>All types</strong> if you Types are also inferred from email content. Choose <strong>All types</strong> if you
do not want to restrict by category. do not want to restrict by category.
@ -234,7 +238,7 @@ export default function HumanHandoffDrawer({
</section> </section>
<section className="handoff-form-section"> <section className="handoff-form-section">
<h3>When should the agent hand off?</h3> <h3>When should the agent hand off? <span className="handoff-required" aria-hidden="true">*</span></h3>
<p className="handoff-helper">Write this naturally, just as you would instruct your agent.</p> <p className="handoff-helper">Write this naturally, just as you would instruct your agent.</p>
<textarea <textarea
className="handoff-instructions" className="handoff-instructions"
@ -298,7 +302,14 @@ export default function HumanHandoffDrawer({
<button <button
type="button" type="button"
className="handoff-btn primary" className="handoff-btn primary"
disabled={saving || !ruleName.trim() || !ownerEmail.trim()} disabled={
saving
|| !ruleName.trim()
|| !ownerEmail.trim()
|| !labels.length
|| !emailTypes.length
|| !instructions.trim()
}
onClick={() => onSave({ onClick={() => onSave({
name: ruleName.trim(), name: ruleName.trim(),
priority, priority,

View file

@ -35,6 +35,7 @@ export default function RecipientField({
onFocus, onFocus,
autoFocus = false, autoFocus = false,
inline = false, inline = false,
trailing = null,
}) { }) {
const [input, setInput] = useState(""); const [input, setInput] = useState("");
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
@ -138,6 +139,7 @@ export default function RecipientField({
<div className={`compose-recipient-field${inline ? " inline" : ""}`} ref={wrapRef}> <div className={`compose-recipient-field${inline ? " inline" : ""}`} ref={wrapRef}>
{label ? <span className="compose-recipient-label">{label}</span> : null} {label ? <span className="compose-recipient-label">{label}</span> : null}
<div className="compose-recipient-chips" onClick={() => inputRef.current?.focus()}> <div className="compose-recipient-chips" onClick={() => inputRef.current?.focus()}>
{trailing}
{recipients.map((recipient, index) => ( {recipients.map((recipient, index) => (
<span <span
key={`${recipientKey(recipient)}-${index}`} key={`${recipientKey(recipient)}-${index}`}

View file

@ -6,7 +6,7 @@
.shell-sheet-bar, .shell-sheet-bar,
.mobile-more-layer { display:none; } .mobile-more-layer { display:none; }
@media (min-width:768px) and (max-width:1199px) { @media (min-width:768px) and (max-width:1199.98px) {
html,body { overflow-x:clip; } html,body { overflow-x:clip; }
.dashboard { display:grid; grid-template-columns:72px minmax(0,1fr); overflow-x:clip; } .dashboard { display:grid; grid-template-columns:72px minmax(0,1fr); overflow-x:clip; }
.dashboard-mobile-header { display:none; } .dashboard-mobile-header { display:none; }
@ -157,7 +157,7 @@
.dashboard-sidebar.open .dashboard-profile > button { display:grid; } .dashboard-sidebar.open .dashboard-profile > button { display:grid; }
} }
@media (max-width:767px) { @media (max-width:767.98px) {
html,body { overflow-x:clip; } html,body { overflow-x:clip; }
.dashboard { display:block; min-height:100vh; overflow-x:clip; } .dashboard { display:block; min-height:100vh; overflow-x:clip; }
.dashboard-mobile-header { .dashboard-mobile-header {
@ -501,7 +501,7 @@
.dashboard-notice { left:16px; right:16px; bottom:calc(76px + env(safe-area-inset-bottom)); } .dashboard-notice { left:16px; right:16px; bottom:calc(76px + env(safe-area-inset-bottom)); }
} }
@media (max-width:1199px) { @media (max-width:1199.98px) {
.mailbox-rail.shell-calendar .agent-panel-hello, .mailbox-rail.shell-calendar .agent-panel-hello,
.mailbox-rail.shell-calendar .agent-stat-grid, .mailbox-rail.shell-calendar .agent-stat-grid,
.mailbox-rail.shell-calendar .agent-quick, .mailbox-rail.shell-calendar .agent-quick,

View file

@ -1,4 +1,4 @@
@import url("https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=Manrope:wght@400;500;600;700&display=swap"); @import url("https://fonts.googleapis.com/css2?family=DM+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Manrope:wght@400;500;600;700&display=swap");
:root { font-family:"DM Sans",sans-serif; color:#080821; background:#fffdfb; font-synthesis:none; --ink:#080821; --muted:#67677a; --coral:#ff6a52; --blush:#fff3ef; --line:#eee9e5; --canvas:#F5F4F2; --workspace:#f0eeeb; --surface:#ffffff; --agent:#7656e8; --agent-soft:#f6f2ff; --agent-border:#ddd4ff; --info:#4d74c4; --info-soft:#eef4ff; --success:#3d8a5d; --success-soft:#eef8f2; --attention:#b7892d; --attention-soft:#fff8ea; --navy:#171329; --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px; --space-5:20px; --space-6:24px; --space-7:32px; --text-content:14px; --text-meta:12px; --text-control:13px; --text-micro:11px; --line-content:1.45; --line-meta:1.4; --radius-xs:6px; --radius-sm:8px; --radius-md:10px; --radius-lg:12px; --radius-xl:16px; --radius-float:20px; --radius-pill:999px; --border-subtle:rgba(20,20,30,0.05); --border-normal:rgba(20,20,30,0.08); --border-strong:rgba(20,20,30,0.12); --shadow-surface:0 1px 2px rgba(20,20,30,0.04),0 12px 32px rgba(20,20,30,0.06); --shadow-float:0 8px 30px rgba(0,0,0,0.08); --shadow-accent:0 5px 14px rgba(255,95,80,0.16); --icon-stroke:1.75; --motion-fast:140ms; --motion-base:180ms; --motion-slow:200ms; --ease-standard:cubic-bezier(.2,.8,.2,1); } :root { font-family:"DM Sans",sans-serif; color:#080821; background:#fffdfb; font-synthesis:none; --ink:#080821; --muted:#67677a; --coral:#ff6a52; --blush:#fff3ef; --line:#eee9e5; --canvas:#F5F4F2; --workspace:#f0eeeb; --surface:#ffffff; --agent:#7656e8; --agent-soft:#f6f2ff; --agent-border:#ddd4ff; --info:#4d74c4; --info-soft:#eef4ff; --success:#3d8a5d; --success-soft:#eef8f2; --attention:#b7892d; --attention-soft:#fff8ea; --navy:#171329; --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px; --space-5:20px; --space-6:24px; --space-7:32px; --text-content:14px; --text-meta:12px; --text-control:13px; --text-micro:11px; --line-content:1.45; --line-meta:1.4; --radius-xs:6px; --radius-sm:8px; --radius-md:10px; --radius-lg:12px; --radius-xl:16px; --radius-float:20px; --radius-pill:999px; --border-subtle:rgba(20,20,30,0.05); --border-normal:rgba(20,20,30,0.08); --border-strong:rgba(20,20,30,0.12); --shadow-surface:0 1px 2px rgba(20,20,30,0.04),0 12px 32px rgba(20,20,30,0.06); --shadow-float:0 8px 30px rgba(0,0,0,0.08); --shadow-accent:0 5px 14px rgba(255,95,80,0.16); --icon-stroke:1.75; --motion-fast:140ms; --motion-base:180ms; --motion-slow:200ms; --ease-standard:cubic-bezier(.2,.8,.2,1); }
* { box-sizing:border-box; } * { box-sizing:border-box; }
@ -774,9 +774,14 @@ h1 em { color:var(--coral); font-style:normal; font-weight:500; }
.handoff-drawer-foot { padding:14px 22px 18px; display:flex; justify-content:flex-end; gap:8px; border-top:1px solid #f0eef2; background:#fcfbfd; } .handoff-drawer-foot { padding:14px 22px 18px; display:flex; justify-content:flex-end; gap:8px; border-top:1px solid #f0eef2; background:#fcfbfd; }
.handoff-form-section h3 { margin:0 0 8px; font:700 13px/1.3 "DM Sans"; color:#171424; text-transform:none; letter-spacing:0; } .handoff-form-section h3 { margin:0 0 8px; font:700 13px/1.3 "DM Sans"; color:#171424; text-transform:none; letter-spacing:0; }
.handoff-field-label { display:block; margin-bottom:6px; font-size:11px; font-weight:600; color:#5a5562; } .handoff-field-label { display:block; margin-bottom:6px; font-size:11px; font-weight:600; color:#5a5562; }
.handoff-required { color:#e15b45; font-weight:700; }
.handoff-helper { margin:8px 0 0; color:#77758a; font-size:11px; line-height:1.5; } .handoff-helper { margin:8px 0 0; color:#77758a; font-size:11px; line-height:1.5; }
.handoff-email-input,.handoff-text-input { width:100%; min-height:42px; padding:0 12px; display:flex; align-items:center; gap:8px; border:1px solid #e4e1e8; border-radius:10px; background:#fff; } .handoff-email-input,.handoff-text-input { width:100%; min-height:42px; padding:0 12px; display:flex; align-items:center; gap:8px; border:1px solid #e4e1e8; border-radius:10px; background:#fff; }
.handoff-email-input input,.handoff-text-input { width:100%; border:0; outline:0; background:transparent; font-size:13px; color:#171424; } .handoff-email-input input,.handoff-text-input { width:100%; border:0; outline:0; background:transparent; font-size:13px; color:#171424; }
.handoff-email-input input::placeholder,
.handoff-text-input::placeholder,
.handoff-label-toolbar input::placeholder,
.handoff-instructions::placeholder { color:#c4bfc8; }
.handoff-owner-preview { margin-top:10px; padding:10px 12px; display:flex; align-items:center; gap:10px; border:1px solid #ece9f2; border-radius:10px; background:#faf9fc; } .handoff-owner-preview { margin-top:10px; padding:10px 12px; display:flex; align-items:center; gap:10px; border:1px solid #ece9f2; border-radius:10px; background:#faf9fc; }
.handoff-owner-avatar { width:34px; height:34px; display:grid; place-items:center; border-radius:50%; background:#f6f2ff; color:#7357f6; } .handoff-owner-avatar { width:34px; height:34px; display:grid; place-items:center; border-radius:50%; background:#f6f2ff; color:#7357f6; }
.handoff-owner-preview strong { display:block; font-size:13px; } .handoff-owner-preview strong { display:block; font-size:13px; }
@ -1094,16 +1099,19 @@ h1 em { color:var(--coral); font-style:normal; font-weight:500; }
.compose-row { height:44px; padding:0 var(--compose-pad); display:grid; grid-template-columns:var(--compose-label) minmax(0,1fr) auto; align-items:center; gap:12px; border-bottom:1px solid #ECE9EE; flex-shrink:0; } .compose-row { height:44px; padding:0 var(--compose-pad); display:grid; grid-template-columns:var(--compose-label) minmax(0,1fr) auto; align-items:center; gap:12px; border-bottom:1px solid #ECE9EE; flex-shrink:0; }
.compose-row-label { color:#77717a; font-size:11px; font-weight:700; } .compose-row-label { color:#77717a; font-size:11px; font-weight:700; }
.compose-row-main { min-width:0; } .compose-row-main { min-width:0; }
.compose-recipient-row .compose-row-main { display:flex; align-items:center; min-height:28px; } .compose-recipient-row { height:auto; min-height:44px; padding-top:8px; padding-bottom:8px; align-items:start; grid-template-columns:var(--compose-label) minmax(0,1fr); }
.compose-recipient-toggles { display:flex; align-items:center; gap:12px; align-self:center; } .compose-recipient-row .compose-row-label { line-height:28px; }
.compose-recipient-row .compose-row-main { display:block; min-height:28px; }
.compose-recipient-toggles { float:right; height:28px; margin-left:10px; display:flex; align-items:center; gap:12px; }
.compose-recipient-toggles button { padding:0; border:0; background:transparent; color:#847e87; font-size:10px; font-weight:700; line-height:1; } .compose-recipient-toggles button { padding:0; border:0; background:transparent; color:#847e87; font-size:10px; font-weight:700; line-height:1; }
.compose-recipient-toggles button:hover { color:#bc5948; } .compose-recipient-toggles button:hover { color:#bc5948; }
.compose-recipient-field { position:relative; width:100%; } .compose-recipient-field { position:relative; width:100%; }
.compose-recipient-field.inline { display:block; } .compose-recipient-field.inline { display:block; }
.compose-recipient-chips { min-height:28px; display:flex; flex-wrap:wrap; align-items:center; gap:6px; } .compose-recipient-chips { min-height:28px; display:block; }
.compose-recipient-input { flex:1; min-width:80px; height:28px; border:0; border-radius:0; outline:none; background:transparent; color:var(--ink); font:500 12px/28px "DM Sans"; box-shadow:none; } .compose-recipient-input { width:40px; min-width:40px; max-width:100%; height:28px; margin:0; border:0; border-radius:0; outline:none; background:transparent; color:var(--ink); font:500 12px/28px "DM Sans"; box-shadow:none; vertical-align:middle; }
.compose-recipient-chips:not(:has(.compose-chip)) .compose-recipient-input { width:160px; }
.compose-recipient-input:focus { outline:none; box-shadow:none; } .compose-recipient-input:focus { outline:none; box-shadow:none; }
.compose-chip { max-width:100%; height:24px; padding:0 4px 0 8px; display:inline-flex; align-items:center; gap:4px; border-radius:6px; background:#f3efec; color:var(--ink); font-size:11px; font-weight:600; } .compose-chip { max-width:100%; height:24px; margin:2px 6px 2px 0; padding:0 4px 0 8px; display:inline-flex; align-items:center; vertical-align:middle; gap:4px; border-radius:6px; background:#f3efec; color:var(--ink); font-size:11px; font-weight:600; }
.compose-chip.external { background:#fff4ea; color:#9a5b28; } .compose-chip.external { background:#fff4ea; color:#9a5b28; }
.compose-chip.invalid { background:#fdeeed; color:#b54f3d; } .compose-chip.invalid { background:#fdeeed; color:#b54f3d; }
.compose-chip.group { background:#eef4ff; color:#4d74c4; } .compose-chip.group { background:#eef4ff; color:#4d74c4; }
@ -1131,6 +1139,7 @@ h1 em { color:var(--coral); font-style:normal; font-weight:500; }
.compose-attachment-actions button { padding:3px 4px; border:0; border-radius:4px; background:transparent; color:#8a848d; font-size:8px; font-weight:700; } .compose-attachment-actions button { padding:3px 4px; border:0; border-radius:4px; background:transparent; color:#8a848d; font-size:8px; font-weight:700; }
.compose-attachment-actions button:hover { background:#f3efec; color:var(--ink); } .compose-attachment-actions button:hover { background:#f3efec; color:var(--ink); }
.compose-editor { min-height:160px; flex:1; padding:16px; overflow:auto; outline:none; color:var(--ink); font:400 13px/1.6 "DM Sans"; background:#fff; } .compose-editor { min-height:160px; flex:1; padding:16px; overflow:auto; outline:none; color:var(--ink); font:400 13px/1.6 "DM Sans"; background:#fff; }
.compose-editor i,.compose-editor em,.compose-editor span[style*="italic"] { font-style:italic; }
.compose-editor:focus { outline:none; box-shadow:none; } .compose-editor:focus { outline:none; box-shadow:none; }
.compose-editor:empty:before { content:attr(data-placeholder); color:#aaa4ac; pointer-events:none; } .compose-editor:empty:before { content:attr(data-placeholder); color:#aaa4ac; pointer-events:none; }
.compose-editor blockquote { margin:8px 0; padding-left:12px; border-left:3px solid #e5dfd9; color:#67677a; } .compose-editor blockquote { margin:8px 0; padding-left:12px; border-left:3px solid #e5dfd9; color:#67677a; }
@ -1297,7 +1306,7 @@ body.compose-blank-open .mailbox-empty-cta { opacity:.42; filter:saturate(.55);
.dns-copy { width:28px; height:28px; flex:0 0 auto; display:grid; place-items:center; border:1px solid #ece7e3; border-radius:8px; background:white; color:#67677a; } .dns-copy { width:28px; height:28px; flex:0 0 auto; display:grid; place-items:center; border:1px solid #ece7e3; border-radius:8px; background:white; color:#67677a; }
.link-button { border:0; background:transparent; color:var(--coral); font:inherit; font-weight:600; cursor:pointer; padding:0; } .link-button { border:0; background:transparent; color:var(--coral); font:inherit; font-weight:600; cursor:pointer; padding:0; }
.dashboard { grid-template-columns:228px minmax(0,1fr); background:var(--canvas); } .dashboard { grid-template-columns:228px minmax(0,1fr); background:var(--canvas); }
.dashboard-sidebar { width:228px; min-height:100vh; max-height:100vh; padding:var(--space-4) var(--space-3) var(--space-3); display:flex; flex-direction:column; overflow:hidden; border-right:0; color:#d7d3e2; background:linear-gradient(180deg,#171329 0%,#120f24 55%,#100d20 100%); box-shadow:inset -1px 0 0 #ffffff08; position:sticky; top:0; } .dashboard-sidebar { width:228px; min-height:100vh; max-height:100vh; padding:var(--space-4) var(--space-3) var(--space-3); display:flex; flex-direction:column; overflow:hidden; border-right:0; color:#d7d3e2; background:linear-gradient(180deg,#171329 0%,#120f24 55%,#100d20 100%); box-shadow:inset -1px 0 0 #ffffff08; position:sticky; top:0; transform:none; }
.dashboard-brand-row { flex-shrink:0; padding:0 6px 2px; } .dashboard-brand-row { flex-shrink:0; padding:0 6px 2px; }
.dashboard-sidebar-scroll { flex:1 1 auto; min-height:0; overflow-y:auto; overscroll-behavior:contain; } .dashboard-sidebar-scroll { flex:1 1 auto; min-height:0; overflow-y:auto; overscroll-behavior:contain; }
.dashboard-brand-row>button { color:#c8c3d4; } .dashboard-brand-row>button { color:#c8c3d4; }

View file

@ -52,8 +52,12 @@ function joinOrNone(items, fallback = "any email") {
return `${items.slice(0, -1).join(", ")} or ${items.at(-1)}`; return `${items.slice(0, -1).join(", ")} or ${items.at(-1)}`;
} }
export function typeLabel(id) {
return EMAIL_TYPE_OPTIONS.find((item) => item.id === id)?.title || id;
}
function typeTitles(types) { function typeTitles(types) {
return types.map((id) => EMAIL_TYPE_OPTIONS.find((item) => item.id === id)?.title || id); return types.map(typeLabel);
} }
export function buildHandoffSummary({ export function buildHandoffSummary({