fix(webapp): reserve sheet close-button space only inside a sheet
UpsertScheduleForm and ScheduleInspector each render both inside a sheet and as a standalone page. Reserving room for the sheet's floating close button unconditionally left an empty gap on the standalone edit route. SheetContent now publishes whether it rendered the button via context and the headers that sit under it read that, which also replaces the "has header actions" stand-in for "am I in a sheet". Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,17 @@ interface SheetContentProps
|
||||
showCloseButton?: boolean;
|
||||
}
|
||||
|
||||
const SheetCloseButtonContext = React.createContext(false);
|
||||
|
||||
/**
|
||||
* True when an enclosing sheet renders its own floating close button, so a header
|
||||
* rendered inside it has to leave room for it. False outside a sheet, which is why
|
||||
* components used both in a sheet and as a full page can rely on it.
|
||||
*/
|
||||
export function useSheetHasCloseButton() {
|
||||
return React.useContext(SheetCloseButtonContext);
|
||||
}
|
||||
|
||||
const SheetContent = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Content>,
|
||||
SheetContentProps
|
||||
@@ -72,7 +83,9 @@ const SheetContent = React.forwardRef<
|
||||
</SheetPrimitive.Close>
|
||||
</div>
|
||||
)}
|
||||
{children}
|
||||
<SheetCloseButtonContext.Provider value={showCloseButton}>
|
||||
{children}
|
||||
</SheetCloseButtonContext.Provider>
|
||||
</SheetPrimitive.Content>
|
||||
</SheetPortal>
|
||||
));
|
||||
@@ -94,18 +107,23 @@ SheetFooter.displayName = "SheetFooter";
|
||||
const SheetTitle = React.forwardRef<
|
||||
React.ElementRef<typeof SheetPrimitive.Title>,
|
||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
||||
>(({ className, children, ...props }, ref) => (
|
||||
<SheetPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"sticky top-0 flex items-center justify-between border-b border-grid-bright bg-background-dimmed pb-1.5 pl-3 pr-16 pt-2",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</SheetPrimitive.Title>
|
||||
));
|
||||
>(({ className, children, ...props }, ref) => {
|
||||
const hasCloseButton = useSheetHasCloseButton();
|
||||
|
||||
return (
|
||||
<SheetPrimitive.Title
|
||||
ref={ref}
|
||||
className={cn(
|
||||
"sticky top-0 flex items-center justify-between border-b border-grid-bright bg-background-dimmed pb-1.5 pl-3 pt-2",
|
||||
hasCloseButton ? "pr-16" : "pr-1.5",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</SheetPrimitive.Title>
|
||||
);
|
||||
});
|
||||
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
||||
|
||||
const SheetDescription = React.forwardRef<
|
||||
|
||||
@@ -23,6 +23,7 @@ import { Header2, Header3 } from "~/components/primitives/Headers";
|
||||
import { InfoPanel } from "~/components/primitives/InfoPanel";
|
||||
import { Paragraph } from "~/components/primitives/Paragraph";
|
||||
import * as Property from "~/components/primitives/PropertyTable";
|
||||
import { useSheetHasCloseButton } from "~/components/primitives/SheetV3";
|
||||
import {
|
||||
Table,
|
||||
TableBlankRow,
|
||||
@@ -96,6 +97,7 @@ export function ScheduleInspector({
|
||||
const organization = useOrganization();
|
||||
const project = useProject();
|
||||
const environment = useEnvironment();
|
||||
const hasSheetCloseButton = useSheetHasCloseButton();
|
||||
|
||||
const isUtc = schedule.timezone === "UTC";
|
||||
const isImperative = schedule.type === "IMPERATIVE";
|
||||
@@ -110,8 +112,7 @@ export function ScheduleInspector({
|
||||
<div
|
||||
className={cn(
|
||||
"mx-3 flex items-center justify-between gap-2 border-b border-grid-dimmed",
|
||||
// Without header actions the sheet's own floating close button sits here.
|
||||
!headerActions && "pr-14"
|
||||
hasSheetCloseButton && "pr-14"
|
||||
)}
|
||||
>
|
||||
<Header2 className="truncate">{schedule.friendlyId}</Header2>
|
||||
|
||||
+8
-1
@@ -40,6 +40,7 @@ import {
|
||||
TableRow,
|
||||
} from "~/components/primitives/Table";
|
||||
import { TextLink } from "~/components/primitives/TextLink";
|
||||
import { useSheetHasCloseButton } from "~/components/primitives/SheetV3";
|
||||
import { TimezoneList } from "~/components/scheduled/timezones";
|
||||
import { prisma } from "~/db.server";
|
||||
import { useEnvironment } from "~/hooks/useEnvironment";
|
||||
@@ -156,6 +157,7 @@ export function UpsertScheduleForm({
|
||||
/** Submits via this fetcher with `_format=json` so the host can toast/close itself. */
|
||||
submitFetcher?: FetcherWithComponents<unknown>;
|
||||
}) {
|
||||
const hasSheetCloseButton = useSheetHasCloseButton();
|
||||
const actionData = useActionData();
|
||||
// Only feed conform-shaped data (`status`) to `useForm` — `{ ok, message }`
|
||||
// envelopes lack it and crash conform.
|
||||
@@ -231,7 +233,12 @@ export function UpsertScheduleForm({
|
||||
{...getFormProps(form)}
|
||||
className="grid h-full max-h-full grid-rows-[2.5rem_1fr_auto] overflow-hidden bg-background-bright"
|
||||
>
|
||||
<div className="mx-3 flex min-w-0 items-center justify-between gap-2 overflow-hidden border-b border-grid-dimmed pr-14">
|
||||
<div
|
||||
className={cn(
|
||||
"mx-3 flex min-w-0 items-center justify-between gap-2 overflow-hidden border-b border-grid-dimmed",
|
||||
hasSheetCloseButton && "pr-14"
|
||||
)}
|
||||
>
|
||||
<Header2 className="truncate">
|
||||
{schedule?.friendlyId
|
||||
? "Edit schedule"
|
||||
|
||||
Reference in New Issue
Block a user