mirror of
https://github.com/block/buzz.git
synced 2026-11-07 18:01:06 +00:00
## Summary Project workspace sheets now slide in from the right as an independent layer over an open conversation thread instead of replacing the thread or rendering inside its panel. Closing the sheet restores the unchanged thread, Escape applies only to the topmost surface, and the covered thread's resize divider no longer leaks through the overlay. ### Related issue Related: #6602. No matching issue found. ### Testing - `pnpm --dir desktop exec biome check src/features/channels/ui/RightAuxiliaryPane.tsx tests/e2e/project-commit-detail.spec.ts` - `pnpm exec playwright test tests/e2e/project-commit-detail.spec.ts --project=smoke --grep "project workspace sheet stays independent from an open thread"` - Pre-push desktop formatting, file-size, typecheck, and unit-test checks --------- Signed-off-by: Thomas Petersen <thomasp@squareup.com>
67 lines
1.8 KiB
TypeScript
67 lines
1.8 KiB
TypeScript
import * as React from "react";
|
|
|
|
import { FocusThreadDrawer } from "@/features/channels/ui/FocusThreadDrawer";
|
|
import { usePresenceCoverage } from "@/features/channels/ui/useFocusDrawerPresence";
|
|
|
|
type ThreadPanelSurfaceProps = {
|
|
channelName: string;
|
|
children: React.ReactNode;
|
|
covered: boolean;
|
|
hasActiveEdit: boolean;
|
|
isFocusDrawer: boolean;
|
|
onClose: () => void;
|
|
};
|
|
|
|
/** Keeps a thread mounted while controlling its focus-drawer presentation. */
|
|
export const ThreadPanelSurface = React.forwardRef<
|
|
HTMLDivElement,
|
|
ThreadPanelSurfaceProps
|
|
>(function ThreadPanelSurface(
|
|
{ channelName, children, covered, hasActiveEdit, isFocusDrawer, onClose },
|
|
ref,
|
|
) {
|
|
return (
|
|
<div
|
|
aria-hidden={covered ? true : undefined}
|
|
className="contents"
|
|
data-testid="thread-surface"
|
|
inert={covered ? true : undefined}
|
|
ref={ref}
|
|
>
|
|
{isFocusDrawer ? (
|
|
<FocusThreadDrawer
|
|
channelName={channelName}
|
|
escapeEnabled={!covered}
|
|
hasActiveEdit={hasActiveEdit}
|
|
onClose={onClose}
|
|
>
|
|
{children}
|
|
</FocusThreadDrawer>
|
|
) : (
|
|
children
|
|
)}
|
|
</div>
|
|
);
|
|
});
|
|
|
|
/** Supplies covered-thread lifecycle and focus ownership for an overlay drawer. */
|
|
export function useThreadPanelSurface(
|
|
open: boolean,
|
|
onExitComplete: () => void,
|
|
) {
|
|
const ref = React.useRef<HTMLDivElement>(null);
|
|
const coverage = usePresenceCoverage(open);
|
|
const markExitComplete = React.useCallback(() => {
|
|
coverage.markExitComplete();
|
|
onExitComplete();
|
|
}, [coverage.markExitComplete, onExitComplete]);
|
|
const restoreFocusTarget = React.useCallback(
|
|
() =>
|
|
ref.current?.querySelector<HTMLElement>(
|
|
'[data-testid="auxiliary-panel-close"]',
|
|
) ?? null,
|
|
[],
|
|
);
|
|
return { ...coverage, markExitComplete, ref, restoreFocusTarget };
|
|
}
|