| ... | @@ -568,7 +568,6 @@ function SidebarSectionPlaceholder(props: { | ... | @@ -568,7 +568,6 @@ function SidebarSectionPlaceholder(props: { |
| 568 | function SidebarDragBoundary(props: { | 568 | function SidebarDragBoundary(props: { |
| 569 | marker: "pinned-header" | "pinned-divider"; | 569 | marker: "pinned-header" | "pinned-divider"; |
| 570 | label: string; | 570 | label: string; |
| 571 | hint: string | null; | | |
| 572 | visible: boolean; | 571 | visible: boolean; |
| 573 | isDropTarget: boolean; | 572 | isDropTarget: boolean; |
| 574 | }) { | 573 | }) { |
| ... | @@ -587,7 +586,6 @@ function SidebarDragBoundary(props: { | ... | @@ -587,7 +586,6 @@ function SidebarDragBoundary(props: { |
| 587 | )} | 586 | )} |
| 588 | > | 587 | > |
| 589 | {props.label} | 588 | {props.label} |
| 590 | {props.hint ? <span className="font-normal">{props.hint}</span> : null} | | |
| 591 | </span> | 589 | </span> |
| 592 | <span | 590 | <span |
| 593 | aria-hidden | 591 | aria-hidden |
| ... | @@ -603,7 +601,6 @@ function SidebarDragBoundary(props: { | ... | @@ -603,7 +601,6 @@ function SidebarDragBoundary(props: { |
| 603 | function SidebarSectionHeader(props: { | 601 | function SidebarSectionHeader(props: { |
| 604 | marker: "snoozed-header" | "settled-header"; | 602 | marker: "snoozed-header" | "settled-header"; |
| 605 | label: string; | 603 | label: string; |
| 606 | hint?: string | null; | | |
| 607 | isDropTarget?: boolean; | 604 | isDropTarget?: boolean; |
| 608 | toggle: { expanded: boolean; onToggle: () => void }; | 605 | toggle: { expanded: boolean; onToggle: () => void }; |
| 609 | }) { | 606 | }) { |
| ... | @@ -624,7 +621,6 @@ function SidebarSectionHeader(props: { | ... | @@ -624,7 +621,6 @@ function SidebarSectionHeader(props: { |
| 624 | props.isDropTarget && "bg-primary/30", | 621 | props.isDropTarget && "bg-primary/30", |
| 625 | )} | 622 | )} |
| 626 | /> | 623 | /> |
| 627 | {props.hint ? <span className="truncate text-[11px] font-normal">{props.hint}</span> : null} | | |
| 628 | <ChevronDownIcon | 624 | <ChevronDownIcon |
| 629 | aria-hidden | 625 | aria-hidden |
| 630 | className={cn( | 626 | className={cn( |
| ... | @@ -910,7 +906,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { | ... | @@ -910,7 +906,7 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 910 | // sortable bag applied to the row root so the whole row drags (the | 906 | // sortable bag applied to the row root so the whole row drags (the |
| 911 | // pointer sensor's distance constraint keeps plain clicks working). | 907 | // pointer sensor's distance constraint keeps plain clicks working). |
| 912 | sortable?: SortableThreadRowBag | undefined; | 908 | sortable?: SortableThreadRowBag | undefined; |
| 913 | dropSection: SidebarSection | null; | 909 | dropSection: Exclude<SidebarSection, "snoozed"> | null; |
| 914 | // Compact wake countdown ("2h") for rows in the snoozed shelf. | 910 | // Compact wake countdown ("2h") for rows in the snoozed shelf. |
| 915 | snoozeWakeLabelText: string | null; | 911 | snoozeWakeLabelText: string | null; |
| 916 | // When a snooze ended (timer or early wake); drives the Woke pill until | 912 | // When a snooze ended (timer or early wake); drives the Woke pill until |
| ... | @@ -1331,14 +1327,13 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { | ... | @@ -1331,14 +1327,13 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1331 | role="status" | 1327 | role="status" |
| 1332 | className="pointer-events-none ml-auto inline-flex h-5 shrink-0 items-center gap-1 rounded-sm border border-primary/30 bg-sidebar px-1.5 text-[11px] font-medium text-primary" | 1328 | className="pointer-events-none ml-auto inline-flex h-5 shrink-0 items-center gap-1 rounded-sm border border-primary/30 bg-sidebar px-1.5 text-[11px] font-medium text-primary" |
| 1333 | > | 1329 | > |
| | 1330 | <span className="sr-only">Move to </span> |
| 1334 | <span aria-hidden>→</span> | 1331 | <span aria-hidden>→</span> |
| 1335 | {props.dropSection === "pinned" | 1332 | {props.dropSection === "pinned" |
| 1336 | ? "Pinned" | 1333 | ? "Pinned" |
| 1337 | : props.dropSection === "active" | 1334 | : props.dropSection === "active" |
| 1338 | ? "Active" | 1335 | ? "Active" |
| 1339 | : props.dropSection === "settled" | 1336 | : "Settled"} |
| 1340 | ? "Settled" | | |
| 1341 | : "Snoozed"} | | |
| 1342 | </span> | 1337 | </span> |
| 1343 | ) : null; | 1338 | ) : null; |
| 1344 | | 1339 | |
| ... | @@ -1442,31 +1437,32 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { | ... | @@ -1442,31 +1437,32 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1442 | <TooltipPopup side="top">Unsent draft</TooltipPopup> | 1437 | <TooltipPopup side="top">Unsent draft</TooltipPopup> |
| 1443 | </Tooltip> | 1438 | </Tooltip> |
| 1444 | ) : null; | 1439 | ) : null; |
| 1445 | const pinIndicator = props.isPinned ? ( | 1440 | const pinIndicator = |
| 1446 | props.pinningSupported ? ( | 1441 | props.isPinned && !sortable?.isDragging ? ( |
| 1447 | <Tooltip> | 1442 | props.pinningSupported ? ( |
| 1448 | <TooltipTrigger | 1443 | <Tooltip> |
| 1449 | render={ | 1444 | <TooltipTrigger |
| 1450 | <button | 1445 | render={ |
| 1451 | type="button" | 1446 | <button |
| 1452 | aria-label="Unpin thread" | 1447 | type="button" |
| 1453 | onClick={handleUnpinClick} | 1448 | aria-label="Unpin thread" |
| 1454 | className="inline-flex cursor-pointer items-center rounded-sm text-muted-foreground/65 outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring" | 1449 | onClick={handleUnpinClick} |
| 1455 | /> | 1450 | className="inline-flex cursor-pointer items-center rounded-sm text-muted-foreground/65 outline-none transition-colors hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring" |
| 1456 | } | 1451 | /> |
| 1457 | > | 1452 | } |
| 1458 | <PinIcon aria-hidden className="size-3 shrink-0" /> | 1453 | > |
| 1459 | </TooltipTrigger> | 1454 | <PinIcon aria-hidden className="size-3 shrink-0" /> |
| 1460 | <TooltipPopup>Unpin thread</TooltipPopup> | 1455 | </TooltipTrigger> |
| 1461 | </Tooltip> | 1456 | <TooltipPopup>Unpin thread</TooltipPopup> |
| 1462 | ) : ( | 1457 | </Tooltip> |
| 1463 | <PinIcon | 1458 | ) : ( |
| 1464 | aria-label="Pinned" | 1459 | <PinIcon |
| 1465 | role="img" | 1460 | aria-label="Pinned" |
| 1466 | className="size-3 shrink-0 text-muted-foreground/65" | 1461 | role="img" |
| 1467 | /> | 1462 | className="size-3 shrink-0 text-muted-foreground/65" |
| 1468 | ) | 1463 | /> |
| 1469 | ) : null; | 1464 | ) |
| | 1465 | ) : null; |
| 1470 | | 1466 | |
| 1471 | if (variant === "slim") { | 1467 | if (variant === "slim") { |
| 1472 | return ( | 1468 | return ( |
| ... | @@ -1526,7 +1522,9 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { | ... | @@ -1526,7 +1522,9 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1526 | remain visible AND clickable while the row is hovered. Only | 1522 | remain visible AND clickable while the row is hovered. Only |
| 1527 | the time/jump label yields to the settle affordance. */} | 1523 | the time/jump label yields to the settle affordance. */} |
| 1528 | {prBadge} | 1524 | {prBadge} |
| 1529 | {dragDestination ?? ( | 1525 | {sortable?.isDragging ? ( |
| | 1526 | dragDestination |
| | 1527 | ) : ( |
| 1530 | <span className="relative ml-auto flex h-6 min-w-8 shrink-0 items-center justify-end"> | 1528 | <span className="relative ml-auto flex h-6 min-w-8 shrink-0 items-center justify-end"> |
| 1531 | <span | 1529 | <span |
| 1532 | className={cn( | 1530 | className={cn( |
| ... | @@ -1679,7 +1677,9 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { | ... | @@ -1679,7 +1677,9 @@ const SidebarThreadRow = memo(function SidebarThreadRow(props: { |
| 1679 | actions on hover/keyboard focus or while the popover is open. Keeping | 1677 | actions on hover/keyboard focus or while the popover is open. Keeping |
| 1680 | the hidden state out of flow lets the project label reclaim | 1678 | the hidden state out of flow lets the project label reclaim |
| 1681 | space without either state overlapping it. */} | 1679 | space without either state overlapping it. */} |
| 1682 | {dragDestination ?? ( | 1680 | {sortable?.isDragging ? ( |
| | 1681 | dragDestination |
| | 1682 | ) : ( |
| 1683 | <span className="group/sidebar-status-slot relative ml-auto flex h-5 min-w-8 shrink-0 items-stretch justify-end text-xs"> | 1683 | <span className="group/sidebar-status-slot relative ml-auto flex h-5 min-w-8 shrink-0 items-stretch justify-end text-xs"> |
| 1684 | {/* Read-only status labels yield to the hover actions. Woke is | 1684 | {/* Read-only status labels yield to the hover actions. Woke is |
| 1685 | itself an action, so it stays pointer-enabled and visible | 1685 | itself an action, so it stays pointer-enabled and visible |
| ... | @@ -4534,7 +4534,11 @@ export default function Sidebar() { | ... | @@ -4534,7 +4534,11 @@ export default function Sidebar() { |
| 4534 | isPinned={thread.pinnedAt != null} | 4534 | isPinned={thread.pinnedAt != null} |
| 4535 | sortable={sortable} | 4535 | sortable={sortable} |
| 4536 | dropSection={ | 4536 | dropSection={ |
| 4537 | dragState?.activeKey === threadKey ? dragTargetSection : null | 4537 | dragState?.activeKey === threadKey && |
| | 4538 | dragTargetSection !== dragState.activeSection && |
| | 4539 | dragTargetSection !== "snoozed" |
| | 4540 | ? dragTargetSection |
| | 4541 | : null |
| 4538 | } | 4542 | } |
| 4539 | snoozeWakeLabelText={ | 4543 | snoozeWakeLabelText={ |
| 4540 | section === "snoozed" && thread.snoozedUntil != null | 4544 | section === "snoozed" && thread.snoozedUntil != null |
| ... | @@ -4634,14 +4638,6 @@ export default function Sidebar() { | ... | @@ -4634,14 +4638,6 @@ export default function Sidebar() { |
| 4634 | dragTargetSection !== "pinned" | 4638 | dragTargetSection !== "pinned" |
| 4635 | ? 1 | 4639 | ? 1 |
| 4636 | : 0); | 4640 | : 0); |
| 4637 | const activeHint = | | |
| 4638 | from === "pinned" | | |
| 4639 | ? "Drop to unpin" | | |
| 4640 | : from === "settled" | | |
| 4641 | ? "Drop to un-settle" | | |
| 4642 | : from === "snoozed" | | |
| 4643 | ? "Drop to wake" | | |
| 4644 | : null; | | |
| 4645 | const items: ReactNode[] = [ | 4641 | const items: ReactNode[] = [ |
| 4646 | <SidebarDraftBlock | 4642 | <SidebarDraftBlock |
| 4647 | key="draft-sessions" | 4643 | key="draft-sessions" |
| ... | @@ -4667,7 +4663,6 @@ export default function Sidebar() { | ... | @@ -4667,7 +4663,6 @@ export default function Sidebar() { |
| 4667 | key="pinned-header" | 4663 | key="pinned-header" |
| 4668 | marker="pinned-header" | 4664 | marker="pinned-header" |
| 4669 | label="Pinned" | 4665 | label="Pinned" |
| 4670 | hint={from !== null && from !== "pinned" ? "Drop to pin" : null} | | |
| 4671 | isDropTarget={dragTargetSection === "pinned"} | 4666 | isDropTarget={dragTargetSection === "pinned"} |
| 4672 | visible={from !== null} | 4667 | visible={from !== null} |
| 4673 | />, | 4668 | />, |
| ... | @@ -4679,7 +4674,6 @@ export default function Sidebar() { | ... | @@ -4679,7 +4674,6 @@ export default function Sidebar() { |
| 4679 | key="pinned-divider" | 4674 | key="pinned-divider" |
| 4680 | marker="pinned-divider" | 4675 | marker="pinned-divider" |
| 4681 | label="Active" | 4676 | label="Active" |
| 4682 | hint={dragTargetSection === "active" ? activeHint : null} | | |
| 4683 | isDropTarget={dragTargetSection === "active"} | 4677 | isDropTarget={dragTargetSection === "active"} |
| 4684 | visible={from !== null && previewPinnedCount > 0} | 4678 | visible={from !== null && previewPinnedCount > 0} |
| 4685 | />, | 4679 | />, |
| ... | @@ -4690,7 +4684,7 @@ export default function Sidebar() { | ... | @@ -4690,7 +4684,7 @@ export default function Sidebar() { |
| 4690 | <SidebarSectionPlaceholder | 4684 | <SidebarSectionPlaceholder |
| 4691 | key="active-placeholder" | 4685 | key="active-placeholder" |
| 4692 | marker="active-placeholder" | 4686 | marker="active-placeholder" |
| 4693 | label={activeHint ?? "Drop here"} | 4687 | label="Active" |
| 4694 | showHint={from !== null} | 4688 | showHint={from !== null} |
| 4695 | isDropTarget={dragTargetSection === "active"} | 4689 | isDropTarget={dragTargetSection === "active"} |
| 4696 | />, | 4690 | />, |
| ... | @@ -4723,11 +4717,6 @@ export default function Sidebar() { | ... | @@ -4723,11 +4717,6 @@ export default function Sidebar() { |
| 4723 | ? "Settled" | 4717 | ? "Settled" |
| 4724 | : `Settled (${settledThreads.length})` | 4718 | : `Settled (${settledThreads.length})` |
| 4725 | } | 4719 | } |
| 4726 | hint={ | | |
| 4727 | dragTargetSection === "settled" && from !== "settled" | | |
| 4728 | ? "Drop to settle" | | |
| 4729 | : null | | |
| 4730 | } | | |
| 4731 | isDropTarget={dragTargetSection === "settled"} | 4720 | isDropTarget={dragTargetSection === "settled"} |
| 4732 | toggle={{ | 4721 | toggle={{ |
| 4733 | expanded: settledShelfExpanded, | 4722 | expanded: settledShelfExpanded, |
| ... | @@ -4741,7 +4730,7 @@ export default function Sidebar() { | ... | @@ -4741,7 +4730,7 @@ export default function Sidebar() { |
| 4741 | <SidebarSectionPlaceholder | 4730 | <SidebarSectionPlaceholder |
| 4742 | key="settled-placeholder" | 4731 | key="settled-placeholder" |
| 4743 | marker="settled-placeholder" | 4732 | marker="settled-placeholder" |
| 4744 | label="Drop to settle" | 4733 | label="Settled" |
| 4745 | showHint={from !== null && from !== "settled"} | 4734 | showHint={from !== null && from !== "settled"} |
| 4746 | isDropTarget={dragTargetSection === "settled"} | 4735 | isDropTarget={dragTargetSection === "settled"} |
| 4747 | />, | 4736 | />, |