mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
Polish side panel motion and composer alignment (#1294)
Signed-off-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Wes <wesbillman@users.noreply.github.com> Co-authored-by: Pinky <44b8e82baa6e0e254e0208d68f335c283c94e7b78dd1fa10d5a49d3f13dd0435@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
@@ -801,7 +801,7 @@ export function AppShell() {
|
|||||||
className="isolate min-h-0 min-w-0 overflow-hidden bg-sidebar"
|
className="isolate min-h-0 min-w-0 overflow-hidden bg-sidebar"
|
||||||
style={chromeCssVarDefaults}
|
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
|
<ConnectionBanner
|
||||||
errorMessage={channelsErrorMessage}
|
errorMessage={channelsErrorMessage}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import * as React from "react";
|
||||||
import {
|
import {
|
||||||
ChevronLeft,
|
ChevronLeft,
|
||||||
ChevronRight,
|
ChevronRight,
|
||||||
@@ -22,6 +23,10 @@ type AppTopChromeProps = {
|
|||||||
const TOP_CHROME_ICON_BUTTON_CLASS =
|
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";
|
"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() {
|
function TopChromeSidebarTrigger() {
|
||||||
const sidebar = useOptionalSidebar();
|
const sidebar = useOptionalSidebar();
|
||||||
|
|
||||||
@@ -50,6 +55,7 @@ export function AppTopChrome({
|
|||||||
onGoBack,
|
onGoBack,
|
||||||
onGoForward,
|
onGoForward,
|
||||||
}: AppTopChromeProps) {
|
}: AppTopChromeProps) {
|
||||||
|
const topChromeRef = React.useRef<HTMLDivElement>(null);
|
||||||
const isFullscreen = useIsFullscreen();
|
const isFullscreen = useIsFullscreen();
|
||||||
// On macOS the traffic-light buttons overlay the chrome (see
|
// On macOS the traffic-light buttons overlay the chrome (see
|
||||||
// `trafficLightPosition` in `tauri.conf.json`), so the nav row clears their
|
// `trafficLightPosition` in `tauri.conf.json`), so the nav row clears their
|
||||||
@@ -60,14 +66,29 @@ export function AppTopChrome({
|
|||||||
const navRowAlignmentClass =
|
const navRowAlignmentClass =
|
||||||
isMacPlatform() && !isFullscreen ? "translate-y-[3px]" : null;
|
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 (
|
return (
|
||||||
<div
|
<div
|
||||||
|
ref={topChromeRef}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative z-45 flex shrink-0 cursor-default select-none items-center bg-sidebar pr-3 text-sidebar-foreground",
|
"relative z-45 flex shrink-0 cursor-default select-none items-center bg-sidebar pr-3 text-sidebar-foreground",
|
||||||
topChromeBackdrop.height,
|
topChromeBackdrop.height,
|
||||||
navRowPaddingClass,
|
navRowPaddingClass,
|
||||||
)}
|
)}
|
||||||
data-tauri-drag-region
|
data-tauri-drag-region
|
||||||
|
data-testid="app-top-chrome"
|
||||||
>
|
>
|
||||||
<div className={cn("flex items-center gap-0.5", navRowAlignmentClass)}>
|
<div className={cn("flex items-center gap-0.5", navRowAlignmentClass)}>
|
||||||
<TopChromeSidebarTrigger />
|
<TopChromeSidebarTrigger />
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import { Button } from "@/shared/ui/button";
|
|||||||
import type { UserProfileLookup } from "@/features/profile/lib/identity";
|
import type { UserProfileLookup } from "@/features/profile/lib/identity";
|
||||||
import {
|
import {
|
||||||
OverlayPanelBackdrop,
|
OverlayPanelBackdrop,
|
||||||
PANEL_BASE_CLASS,
|
PANEL_ENTER_BASE_CLASS,
|
||||||
PANEL_OVERLAY_CLASS,
|
PANEL_OVERLAY_CLASS,
|
||||||
PANEL_SINGLE_COLUMN_HEADER_LAYER_CLASS,
|
PANEL_SINGLE_COLUMN_HEADER_LAYER_CLASS,
|
||||||
} from "@/shared/ui/OverlayPanelBackdrop";
|
} from "@/shared/ui/OverlayPanelBackdrop";
|
||||||
@@ -179,7 +179,7 @@ export function AgentSessionThreadPanel({
|
|||||||
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
|
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
|
||||||
<aside
|
<aside
|
||||||
className={cn(
|
className={cn(
|
||||||
PANEL_BASE_CLASS,
|
PANEL_ENTER_BASE_CLASS,
|
||||||
isSinglePanelView && "border-l-0",
|
isSinglePanelView && "border-l-0",
|
||||||
isFloatingOverlay && PANEL_OVERLAY_CLASS,
|
isFloatingOverlay && PANEL_OVERLAY_CLASS,
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export function ChannelManagementAuxiliaryPanel({
|
|||||||
}: ChannelManagementAuxiliaryPanelProps) {
|
}: ChannelManagementAuxiliaryPanelProps) {
|
||||||
const panel = (
|
const panel = (
|
||||||
<ChannelManagementSheet
|
<ChannelManagementSheet
|
||||||
|
animateSplitEnter={isSinglePanelView && !useSplitAuxiliaryPane}
|
||||||
channel={activeChannel}
|
channel={activeChannel}
|
||||||
currentPubkey={currentPubkey}
|
currentPubkey={currentPubkey}
|
||||||
layout={useSplitAuxiliaryPane || isSinglePanelView ? "split" : "overlay"}
|
layout={useSplitAuxiliaryPane || isSinglePanelView ? "split" : "overlay"}
|
||||||
|
|||||||
@@ -62,6 +62,7 @@ import { useScrollBoundaryLock } from "@/shared/hooks/useScrollBoundaryLock";
|
|||||||
import {
|
import {
|
||||||
OverlayPanelBackdrop,
|
OverlayPanelBackdrop,
|
||||||
PANEL_BASE_CLASS,
|
PANEL_BASE_CLASS,
|
||||||
|
PANEL_ENTER_MOTION_CLASS,
|
||||||
PANEL_OVERLAY_CLASS,
|
PANEL_OVERLAY_CLASS,
|
||||||
} from "@/shared/ui/OverlayPanelBackdrop";
|
} from "@/shared/ui/OverlayPanelBackdrop";
|
||||||
import { ChannelCanvas } from "./ChannelCanvas";
|
import { ChannelCanvas } from "./ChannelCanvas";
|
||||||
@@ -81,6 +82,7 @@ import { ChannelManagementModerationActions } from "./ChannelManagementModeratio
|
|||||||
|
|
||||||
type ChannelManagementSheetProps = {
|
type ChannelManagementSheetProps = {
|
||||||
channel: Channel | null;
|
channel: Channel | null;
|
||||||
|
animateSplitEnter?: boolean;
|
||||||
currentPubkey?: string;
|
currentPubkey?: string;
|
||||||
layout?: "overlay" | "split";
|
layout?: "overlay" | "split";
|
||||||
onDeleted?: () => void;
|
onDeleted?: () => void;
|
||||||
@@ -91,6 +93,7 @@ type ChannelManagementSheetProps = {
|
|||||||
const DEFAULT_EPHEMERAL_TTL_SECONDS = 7 * 24 * 60 * 60;
|
const DEFAULT_EPHEMERAL_TTL_SECONDS = 7 * 24 * 60 * 60;
|
||||||
|
|
||||||
export function ChannelManagementSheet({
|
export function ChannelManagementSheet({
|
||||||
|
animateSplitEnter = false,
|
||||||
channel,
|
channel,
|
||||||
currentPubkey,
|
currentPubkey,
|
||||||
layout = "overlay",
|
layout = "overlay",
|
||||||
@@ -315,6 +318,7 @@ export function ChannelManagementSheet({
|
|||||||
className={cn(
|
className={cn(
|
||||||
PANEL_BASE_CLASS,
|
PANEL_BASE_CLASS,
|
||||||
"h-full w-full cursor-default overflow-hidden border-l-0 p-0",
|
"h-full w-full cursor-default overflow-hidden border-l-0 p-0",
|
||||||
|
animateSplitEnter && PANEL_ENTER_MOTION_CLASS,
|
||||||
isDark
|
isDark
|
||||||
? "bg-background/85 backdrop-blur-xl supports-[backdrop-filter]:bg-background/75"
|
? "bg-background/85 backdrop-blur-xl supports-[backdrop-filter]:bg-background/75"
|
||||||
: "bg-background",
|
: "bg-background",
|
||||||
@@ -361,7 +365,8 @@ export function ChannelManagementSheet({
|
|||||||
className={cn(
|
className={cn(
|
||||||
PANEL_BASE_CLASS,
|
PANEL_BASE_CLASS,
|
||||||
PANEL_OVERLAY_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
|
isDark
|
||||||
? "bg-background/85 backdrop-blur-xl supports-[backdrop-filter]:bg-background/75"
|
? "bg-background/85 backdrop-blur-xl supports-[backdrop-filter]:bg-background/75"
|
||||||
: "bg-background",
|
: "bg-background",
|
||||||
|
|||||||
@@ -794,7 +794,7 @@ export const ChannelPane = React.memo(function ChannelPane({
|
|||||||
{hasTypingActivity ? (
|
{hasTypingActivity ? (
|
||||||
<TypingIndicatorRow
|
<TypingIndicatorRow
|
||||||
channel={activeChannel}
|
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}
|
currentPubkey={currentPubkey}
|
||||||
profiles={profiles}
|
profiles={profiles}
|
||||||
typingPubkeys={typingPubkeys}
|
typingPubkeys={typingPubkeys}
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import type * as React from "react";
|
import type * as React from "react";
|
||||||
|
|
||||||
import { THREAD_PANEL_MIN_WIDTH_PX } from "@/shared/hooks/useThreadPanelWidth";
|
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 = {
|
type RightAuxiliaryPaneProps = {
|
||||||
canResetWidth: boolean;
|
canResetWidth: boolean;
|
||||||
@@ -23,7 +25,10 @@ export function RightAuxiliaryPane({
|
|||||||
}: RightAuxiliaryPaneProps) {
|
}: RightAuxiliaryPaneProps) {
|
||||||
return (
|
return (
|
||||||
<aside
|
<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}
|
data-testid={testId}
|
||||||
style={{
|
style={{
|
||||||
maxWidth: constrainToAvailableSpace
|
maxWidth: constrainToAvailableSpace
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ export const MessageComposerToolbar = React.memo(
|
|||||||
editor={editor}
|
editor={editor}
|
||||||
onLinkButton={onLinkButton}
|
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
|
* AnimatePresence with mode="popLayout" — exiting elements
|
||||||
* are popped out of flow immediately so entering elements
|
* are popped out of flow immediately so entering elements
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ import {
|
|||||||
import { Button } from "@/shared/ui/button";
|
import { Button } from "@/shared/ui/button";
|
||||||
import {
|
import {
|
||||||
OverlayPanelBackdrop,
|
OverlayPanelBackdrop,
|
||||||
PANEL_BASE_CLASS,
|
PANEL_ENTER_BASE_CLASS,
|
||||||
PANEL_OVERLAY_CLASS,
|
PANEL_OVERLAY_CLASS,
|
||||||
PANEL_SINGLE_COLUMN_HEADER_LAYER_CLASS,
|
PANEL_SINGLE_COLUMN_HEADER_LAYER_CLASS,
|
||||||
} from "@/shared/ui/OverlayPanelBackdrop";
|
} from "@/shared/ui/OverlayPanelBackdrop";
|
||||||
@@ -207,7 +207,7 @@ function ThreadComposerSkeleton() {
|
|||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
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,
|
THREAD_PANEL_COMPOSER_GUTTER_CLASS,
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
@@ -304,7 +304,7 @@ export function MessageThreadPanelSkeleton({
|
|||||||
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
|
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
|
||||||
<aside
|
<aside
|
||||||
className={cn(
|
className={cn(
|
||||||
PANEL_BASE_CLASS,
|
PANEL_ENTER_BASE_CLASS,
|
||||||
isSinglePanelView && "border-l-0",
|
isSinglePanelView && "border-l-0",
|
||||||
isFloatingOverlay && PANEL_OVERLAY_CLASS,
|
isFloatingOverlay && PANEL_OVERLAY_CLASS,
|
||||||
)}
|
)}
|
||||||
@@ -902,7 +902,7 @@ export function MessageThreadPanel({
|
|||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
className={cn(
|
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,
|
THREAD_PANEL_COMPOSER_GUTTER_CLASS,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
@@ -913,7 +913,7 @@ export function MessageThreadPanel({
|
|||||||
{threadTypingPubkeys.length > 0 ? (
|
{threadTypingPubkeys.length > 0 ? (
|
||||||
<TypingIndicatorRow
|
<TypingIndicatorRow
|
||||||
channel={channel}
|
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}
|
currentPubkey={currentPubkey}
|
||||||
profiles={profiles}
|
profiles={profiles}
|
||||||
typingPubkeys={threadTypingPubkeys}
|
typingPubkeys={threadTypingPubkeys}
|
||||||
@@ -974,7 +974,7 @@ export function MessageThreadPanel({
|
|||||||
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
|
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
|
||||||
<aside
|
<aside
|
||||||
className={cn(
|
className={cn(
|
||||||
PANEL_BASE_CLASS,
|
PANEL_ENTER_BASE_CLASS,
|
||||||
isSinglePanelView && "border-l-0",
|
isSinglePanelView && "border-l-0",
|
||||||
isFloatingOverlay && PANEL_OVERLAY_CLASS,
|
isFloatingOverlay && PANEL_OVERLAY_CLASS,
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -90,8 +90,8 @@ export function TypingIndicatorRow({
|
|||||||
{labels.length > 0 && (
|
{labels.length > 0 && (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex w-full items-center gap-2",
|
"flex min-w-0 w-full items-center",
|
||||||
isActivityVariant && "h-full",
|
isActivityVariant ? "h-full gap-1.5" : "gap-2",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="flex shrink-0 items-center">
|
<div className="flex shrink-0 items-center">
|
||||||
@@ -103,7 +103,7 @@ export function TypingIndicatorRow({
|
|||||||
key={pubkey}
|
key={pubkey}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative shrink-0 rounded-lg ring-1 ring-background",
|
"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",
|
index > 0 && "-ml-1.5",
|
||||||
)}
|
)}
|
||||||
data-testid="message-typing-avatar"
|
data-testid="message-typing-avatar"
|
||||||
@@ -113,7 +113,7 @@ export function TypingIndicatorRow({
|
|||||||
label={label}
|
label={label}
|
||||||
className={cn(
|
className={cn(
|
||||||
isActivityVariant
|
isActivityVariant
|
||||||
? "h-[18px] w-[18px] text-3xs"
|
? "h-4 w-4 text-3xs"
|
||||||
: "h-5 w-5 text-3xs",
|
: "h-5 w-5 text-3xs",
|
||||||
)}
|
)}
|
||||||
iconClassName={
|
iconClassName={
|
||||||
@@ -126,10 +126,10 @@ export function TypingIndicatorRow({
|
|||||||
</div>
|
</div>
|
||||||
<p
|
<p
|
||||||
className={cn(
|
className={cn(
|
||||||
"truncate text-muted-foreground",
|
"min-w-0 translate-y-px truncate text-muted-foreground",
|
||||||
isActivityVariant
|
isActivityVariant
|
||||||
? "text-xs font-semibold leading-none"
|
? "text-2xs font-medium leading-3"
|
||||||
: "text-sm",
|
: "text-xs font-medium leading-4",
|
||||||
)}
|
)}
|
||||||
data-testid="message-typing-indicator-label"
|
data-testid="message-typing-indicator-label"
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ import type { Channel, ManagedAgent, RelayAgent } from "@/shared/api/types";
|
|||||||
import { Button } from "@/shared/ui/button";
|
import { Button } from "@/shared/ui/button";
|
||||||
import {
|
import {
|
||||||
OverlayPanelBackdrop,
|
OverlayPanelBackdrop,
|
||||||
PANEL_BASE_CLASS,
|
PANEL_ENTER_BASE_CLASS,
|
||||||
PANEL_OVERLAY_CLASS,
|
PANEL_OVERLAY_CLASS,
|
||||||
PANEL_SINGLE_COLUMN_HEADER_LAYER_CLASS,
|
PANEL_SINGLE_COLUMN_HEADER_LAYER_CLASS,
|
||||||
} from "@/shared/ui/OverlayPanelBackdrop";
|
} from "@/shared/ui/OverlayPanelBackdrop";
|
||||||
@@ -469,7 +469,7 @@ export function UserProfilePanel({
|
|||||||
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
|
{isFloatingOverlay && <OverlayPanelBackdrop onClose={onClose} />}
|
||||||
<aside
|
<aside
|
||||||
className={cn(
|
className={cn(
|
||||||
PANEL_BASE_CLASS,
|
PANEL_ENTER_BASE_CLASS,
|
||||||
isSinglePanelView && "border-l-0",
|
isSinglePanelView && "border-l-0",
|
||||||
isFloatingOverlay && PANEL_OVERLAY_CLASS,
|
isFloatingOverlay && PANEL_OVERLAY_CLASS,
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -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 {
|
@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-shell {
|
||||||
--buzz-huddle-drawer-height: 5rem;
|
--buzz-huddle-drawer-height: 5rem;
|
||||||
--buzz-huddle-drawer-radius: 24px;
|
--buzz-huddle-drawer-radius: 24px;
|
||||||
@@ -1634,6 +1652,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.buzz-side-panel-enter {
|
||||||
|
animation: none;
|
||||||
|
will-change: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.buzz-huddle-app-surface {
|
.buzz-huddle-app-surface {
|
||||||
transition: none;
|
transition: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,10 @@ export const PANEL_BASE_CLASS =
|
|||||||
export const PANEL_OVERLAY_CLASS =
|
export const PANEL_OVERLAY_CLASS =
|
||||||
"fixed bottom-0 right-0 top-11 z-40 h-auto shadow-xl max-w-[calc(100vw-2rem)]";
|
"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
|
* Single-column panel headers should render above the local panel backdrop
|
||||||
* (z-40) but stay below global top chrome controls (z-[45]).
|
* (z-40) but stay below global top chrome controls (z-[45]).
|
||||||
|
|||||||
Reference in New Issue
Block a user