Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion desktop/src/app/AppShell.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -799,7 +799,7 @@ export function AppShell() {
className="isolate min-h-0 min-w-0 overflow-hidden bg-sidebar"
style={chromeCssVarDefaults}
>
<div className="relative z-10 ml-px mt-px flex min-h-0 flex-1 flex-col overflow-hidden rounded-tl-xl bg-background shadow-[-1px_-1px_0_0_hsl(var(--sidebar-border)/0.45)]">
<div className="relative z-10 mb-2 ml-px mr-2 mt-px flex min-h-0 flex-1 flex-col overflow-hidden rounded-xl bg-background shadow-[-1px_-1px_0_0_hsl(var(--sidebar-border)/0.45)]">
<ConnectionBanner
errorMessage={channelsErrorMessage}
/>
Expand Down
21 changes: 21 additions & 0 deletions desktop/src/app/AppTopChrome.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as React from "react";
import {
ChevronLeft,
ChevronRight,
Expand All @@ -22,6 +23,10 @@ type AppTopChromeProps = {
const TOP_CHROME_ICON_BUTTON_CLASS =
"h-7 w-7 rounded-[4px] text-sidebar-foreground/65 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground [&_svg]:size-4";

function preventTopChromeWheel(event: WheelEvent) {
event.preventDefault();
}

function TopChromeSidebarTrigger() {
const sidebar = useOptionalSidebar();

Expand Down Expand Up @@ -50,6 +55,7 @@ export function AppTopChrome({
onGoBack,
onGoForward,
}: AppTopChromeProps) {
const topChromeRef = React.useRef<HTMLDivElement>(null);
const isFullscreen = useIsFullscreen();
// On macOS the traffic-light buttons overlay the chrome (see
// `trafficLightPosition` in `tauri.conf.json`), so the nav row clears their
Expand All @@ -60,14 +66,29 @@ export function AppTopChrome({
const navRowAlignmentClass =
isMacPlatform() && !isFullscreen ? "translate-y-[3px]" : null;

React.useEffect(() => {
const topChrome = topChromeRef.current;
if (!topChrome) {
return;
}

const options = { capture: true, passive: false };
topChrome.addEventListener("wheel", preventTopChromeWheel, options);
return () => {
topChrome.removeEventListener("wheel", preventTopChromeWheel, options);
};
}, []);

return (
<div
ref={topChromeRef}
className={cn(
"relative z-45 flex shrink-0 cursor-default select-none items-center bg-sidebar pr-3 text-sidebar-foreground",
topChromeBackdrop.height,
navRowPaddingClass,
)}
data-tauri-drag-region
data-testid="app-top-chrome"
>
<div className={cn("flex items-center gap-0.5", navRowAlignmentClass)}>
<TopChromeSidebarTrigger />
Expand Down
4 changes: 2 additions & 2 deletions desktop/src/features/channels/ui/AgentSessionThreadPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { Button } from "@/shared/ui/button";
import type { UserProfileLookup } from "@/features/profile/lib/identity";
import {
OverlayPanelBackdrop,
PANEL_BASE_CLASS,
PANEL_ENTER_BASE_CLASS,
PANEL_OVERLAY_CLASS,
PANEL_SINGLE_COLUMN_HEADER_LAYER_CLASS,
} from "@/shared/ui/OverlayPanelBackdrop";
Expand Down Expand Up @@ -179,7 +179,7 @@ export function AgentSessionThreadPanel({
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
<aside
className={cn(
PANEL_BASE_CLASS,
PANEL_ENTER_BASE_CLASS,
isSinglePanelView && "border-l-0",
isFloatingOverlay && PANEL_OVERLAY_CLASS,
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export function ChannelManagementAuxiliaryPanel({
}: ChannelManagementAuxiliaryPanelProps) {
const panel = (
<ChannelManagementSheet
animateSplitEnter={isSinglePanelView && !useSplitAuxiliaryPane}
channel={activeChannel}
currentPubkey={currentPubkey}
layout={useSplitAuxiliaryPane || isSinglePanelView ? "split" : "overlay"}
Expand Down
7 changes: 6 additions & 1 deletion desktop/src/features/channels/ui/ChannelManagementSheet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import { useScrollBoundaryLock } from "@/shared/hooks/useScrollBoundaryLock";
import {
OverlayPanelBackdrop,
PANEL_BASE_CLASS,
PANEL_ENTER_MOTION_CLASS,
PANEL_OVERLAY_CLASS,
} from "@/shared/ui/OverlayPanelBackdrop";
import { ChannelCanvas } from "./ChannelCanvas";
Expand All @@ -81,6 +82,7 @@ import { ChannelManagementModerationActions } from "./ChannelManagementModeratio

type ChannelManagementSheetProps = {
channel: Channel | null;
animateSplitEnter?: boolean;
currentPubkey?: string;
layout?: "overlay" | "split";
onDeleted?: () => void;
Expand All @@ -91,6 +93,7 @@ type ChannelManagementSheetProps = {
const DEFAULT_EPHEMERAL_TTL_SECONDS = 7 * 24 * 60 * 60;

export function ChannelManagementSheet({
animateSplitEnter = false,
channel,
currentPubkey,
layout = "overlay",
Expand Down Expand Up @@ -315,6 +318,7 @@ export function ChannelManagementSheet({
className={cn(
PANEL_BASE_CLASS,
"h-full w-full cursor-default overflow-hidden border-l-0 p-0",
animateSplitEnter && PANEL_ENTER_MOTION_CLASS,
isDark
? "bg-background/85 backdrop-blur-xl supports-[backdrop-filter]:bg-background/75"
: "bg-background",
Expand Down Expand Up @@ -361,7 +365,8 @@ export function ChannelManagementSheet({
className={cn(
PANEL_BASE_CLASS,
PANEL_OVERLAY_CLASS,
"w-[380px] cursor-default overflow-hidden p-0 transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right",
PANEL_ENTER_MOTION_CLASS,
"w-[380px] cursor-default overflow-hidden p-0 data-[state=closed]:animate-out data-[state=closed]:slide-out-to-right data-[state=closed]:duration-200",
isDark
? "bg-background/85 backdrop-blur-xl supports-[backdrop-filter]:bg-background/75"
: "bg-background",
Expand Down
2 changes: 1 addition & 1 deletion desktop/src/features/channels/ui/ChannelPane.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,7 @@ export const ChannelPane = React.memo(function ChannelPane({
{hasTypingActivity ? (
<TypingIndicatorRow
channel={activeChannel}
className="min-w-0 flex-1 px-0 py-0"
className="min-w-0 flex-1 py-0 pl-[calc(0.75rem+1px)] pr-0 sm:pl-[calc(1rem+1px)]"
currentPubkey={currentPubkey}
profiles={profiles}
typingPubkeys={typingPubkeys}
Expand Down
7 changes: 6 additions & 1 deletion desktop/src/features/channels/ui/RightAuxiliaryPane.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import type * as React from "react";

import { THREAD_PANEL_MIN_WIDTH_PX } from "@/shared/hooks/useThreadPanelWidth";
import { cn } from "@/shared/lib/cn";
import { PANEL_ENTER_MOTION_CLASS } from "@/shared/ui/OverlayPanelBackdrop";

type RightAuxiliaryPaneProps = {
canResetWidth: boolean;
Expand All @@ -23,7 +25,10 @@ export function RightAuxiliaryPane({
}: RightAuxiliaryPaneProps) {
return (
<aside
className="group/right-pane relative flex h-full shrink-0 flex-col overflow-hidden bg-background before:pointer-events-none before:absolute before:bottom-0 before:left-0 before:top-0 before:z-40 before:w-px before:bg-border/80 before:content-['']"
className={cn(
"group/right-pane relative flex h-full shrink-0 flex-col overflow-hidden bg-background before:pointer-events-none before:absolute before:bottom-0 before:left-0 before:top-0 before:z-40 before:w-px before:bg-border/80 before:content-['']",
PANEL_ENTER_MOTION_CLASS,
)}
data-testid={testId}
style={{
maxWidth: constrainToAvailableSpace
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ export const MessageComposerToolbar = React.memo(
editor={editor}
onLinkButton={onLinkButton}
/>
<div className="flex min-h-10 min-w-0 flex-1 items-center gap-1 py-1">
<div className="-ml-2 flex min-h-10 min-w-0 flex-1 items-center gap-1 py-1">
{/*
* AnimatePresence with mode="popLayout" — exiting elements
* are popped out of flow immediately so entering elements
Expand Down
12 changes: 6 additions & 6 deletions desktop/src/features/messages/ui/MessageThreadPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import {
import { Button } from "@/shared/ui/button";
import {
OverlayPanelBackdrop,
PANEL_BASE_CLASS,
PANEL_ENTER_BASE_CLASS,
PANEL_OVERLAY_CLASS,
PANEL_SINGLE_COLUMN_HEADER_LAYER_CLASS,
} from "@/shared/ui/OverlayPanelBackdrop";
Expand Down Expand Up @@ -207,7 +207,7 @@ function ThreadComposerSkeleton() {
</div>
<div
className={cn(
"-mt-1 h-7 bg-background pb-1 pt-0",
"h-7 bg-background pb-1 pt-0",
THREAD_PANEL_COMPOSER_GUTTER_CLASS,
)}
/>
Expand Down Expand Up @@ -304,7 +304,7 @@ export function MessageThreadPanelSkeleton({
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
<aside
className={cn(
PANEL_BASE_CLASS,
PANEL_ENTER_BASE_CLASS,
isSinglePanelView && "border-l-0",
isFloatingOverlay && PANEL_OVERLAY_CLASS,
)}
Expand Down Expand Up @@ -902,7 +902,7 @@ export function MessageThreadPanel({
/>
<div
className={cn(
"-mt-1 h-7 bg-background pb-1 pt-0",
"h-7 bg-background pb-1 pt-0",
THREAD_PANEL_COMPOSER_GUTTER_CLASS,
)}
>
Expand All @@ -913,7 +913,7 @@ export function MessageThreadPanel({
{threadTypingPubkeys.length > 0 ? (
<TypingIndicatorRow
channel={channel}
className="min-w-0 flex-1 px-0 py-0"
className="min-w-0 flex-1 py-0 pl-[calc(0.75rem+1px)] pr-0 sm:pl-[calc(1rem+1px)]"
currentPubkey={currentPubkey}
profiles={profiles}
typingPubkeys={threadTypingPubkeys}
Expand Down Expand Up @@ -974,7 +974,7 @@ export function MessageThreadPanel({
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
<aside
className={cn(
PANEL_BASE_CLASS,
PANEL_ENTER_BASE_CLASS,
isSinglePanelView && "border-l-0",
isFloatingOverlay && PANEL_OVERLAY_CLASS,
)}
Expand Down
14 changes: 7 additions & 7 deletions desktop/src/features/messages/ui/TypingIndicatorRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ export function TypingIndicatorRow({
{labels.length > 0 && (
<div
className={cn(
"flex w-full items-center gap-2",
isActivityVariant && "h-full",
"flex min-w-0 w-full items-center",
isActivityVariant ? "h-full gap-1.5" : "gap-2",
)}
>
<div className="flex shrink-0 items-center">
Expand All @@ -103,7 +103,7 @@ export function TypingIndicatorRow({
key={pubkey}
className={cn(
"relative shrink-0 rounded-lg ring-1 ring-background",
isActivityVariant ? "h-[18px] w-[18px]" : "h-5 w-5",
isActivityVariant ? "h-4 w-4" : "h-5 w-5",
index > 0 && "-ml-1.5",
)}
data-testid="message-typing-avatar"
Expand All @@ -113,7 +113,7 @@ export function TypingIndicatorRow({
label={label}
className={cn(
isActivityVariant
? "h-[18px] w-[18px] text-3xs"
? "h-4 w-4 text-3xs"
: "h-5 w-5 text-3xs",
)}
iconClassName={
Expand All @@ -126,10 +126,10 @@ export function TypingIndicatorRow({
</div>
<p
className={cn(
"truncate text-muted-foreground",
"min-w-0 translate-y-px truncate text-muted-foreground",
isActivityVariant
? "text-xs font-semibold leading-none"
: "text-sm",
? "text-2xs font-medium leading-3"
: "text-xs font-medium leading-4",
)}
data-testid="message-typing-indicator-label"
>
Expand Down
4 changes: 2 additions & 2 deletions desktop/src/features/profile/ui/UserProfilePanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ import type { Channel, ManagedAgent, RelayAgent } from "@/shared/api/types";
import { Button } from "@/shared/ui/button";
import {
OverlayPanelBackdrop,
PANEL_BASE_CLASS,
PANEL_ENTER_BASE_CLASS,
PANEL_OVERLAY_CLASS,
PANEL_SINGLE_COLUMN_HEADER_LAYER_CLASS,
} from "@/shared/ui/OverlayPanelBackdrop";
Expand Down Expand Up @@ -461,7 +461,7 @@ export function UserProfilePanel({
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
<aside
className={cn(
PANEL_BASE_CLASS,
PANEL_ENTER_BASE_CLASS,
isSinglePanelView && "border-l-0",
isFloatingOverlay && PANEL_OVERLAY_CLASS,
)}
Expand Down
23 changes: 23 additions & 0 deletions desktop/src/shared/styles/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -1496,7 +1496,25 @@
}
}

@keyframes buzz-side-panel-enter {
from {
opacity: 0;
transform: translate3d(24px, 0, 0);
}

to {
opacity: 1;
transform: translate3d(0, 0, 0);
}
}

@layer components {
.buzz-side-panel-enter {
animation: buzz-side-panel-enter 260ms cubic-bezier(0.32, 0.72, 0, 1) both;
transform-origin: right center;
will-change: transform, opacity;
}

.buzz-huddle-shell {
--buzz-huddle-drawer-height: 5rem;
--buzz-huddle-drawer-radius: 24px;
Expand Down Expand Up @@ -1634,6 +1652,11 @@
}

@media (prefers-reduced-motion: reduce) {
.buzz-side-panel-enter {
animation: none;
will-change: auto;
}

.buzz-huddle-app-surface {
transition: none;
}
Expand Down
4 changes: 4 additions & 0 deletions desktop/src/shared/ui/OverlayPanelBackdrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export const PANEL_BASE_CLASS =
export const PANEL_OVERLAY_CLASS =
"fixed bottom-0 right-0 top-11 z-40 h-auto shadow-xl max-w-[calc(100vw-2rem)]";

export const PANEL_ENTER_MOTION_CLASS = "buzz-side-panel-enter";

export const PANEL_ENTER_BASE_CLASS = `${PANEL_BASE_CLASS} ${PANEL_ENTER_MOTION_CLASS}`;

/**
* Single-column panel headers should render above the local panel backdrop
* (z-40) but stay below global top chrome controls (z-[45]).
Expand Down
Loading