Skip to content

Commit e83beb4

Browse files
committed
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>
1 parent e2a727d commit e83beb4

3 files changed

Lines changed: 42 additions & 16 deletions

File tree

apps/webapp/app/components/primitives/SheetV3.tsx

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ interface SheetContentProps
5454
showCloseButton?: boolean;
5555
}
5656

57+
const SheetCloseButtonContext = React.createContext(false);
58+
59+
/**
60+
* True when an enclosing sheet renders its own floating close button, so a header
61+
* rendered inside it has to leave room for it. False outside a sheet, which is why
62+
* components used both in a sheet and as a full page can rely on it.
63+
*/
64+
export function useSheetHasCloseButton() {
65+
return React.useContext(SheetCloseButtonContext);
66+
}
67+
5768
const SheetContent = React.forwardRef<
5869
React.ElementRef<typeof SheetPrimitive.Content>,
5970
SheetContentProps
@@ -72,7 +83,9 @@ const SheetContent = React.forwardRef<
7283
</SheetPrimitive.Close>
7384
</div>
7485
)}
75-
{children}
86+
<SheetCloseButtonContext.Provider value={showCloseButton}>
87+
{children}
88+
</SheetCloseButtonContext.Provider>
7689
</SheetPrimitive.Content>
7790
</SheetPortal>
7891
));
@@ -94,18 +107,23 @@ SheetFooter.displayName = "SheetFooter";
94107
const SheetTitle = React.forwardRef<
95108
React.ElementRef<typeof SheetPrimitive.Title>,
96109
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
97-
>(({ className, children, ...props }, ref) => (
98-
<SheetPrimitive.Title
99-
ref={ref}
100-
className={cn(
101-
"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",
102-
className
103-
)}
104-
{...props}
105-
>
106-
{children}
107-
</SheetPrimitive.Title>
108-
));
110+
>(({ className, children, ...props }, ref) => {
111+
const hasCloseButton = useSheetHasCloseButton();
112+
113+
return (
114+
<SheetPrimitive.Title
115+
ref={ref}
116+
className={cn(
117+
"sticky top-0 flex items-center justify-between border-b border-grid-bright bg-background-dimmed pb-1.5 pl-3 pt-2",
118+
hasCloseButton ? "pr-16" : "pr-1.5",
119+
className
120+
)}
121+
{...props}
122+
>
123+
{children}
124+
</SheetPrimitive.Title>
125+
);
126+
});
109127
SheetTitle.displayName = SheetPrimitive.Title.displayName;
110128

111129
const SheetDescription = React.forwardRef<

apps/webapp/app/components/schedules/ScheduleInspector.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { Header2, Header3 } from "~/components/primitives/Headers";
2323
import { InfoPanel } from "~/components/primitives/InfoPanel";
2424
import { Paragraph } from "~/components/primitives/Paragraph";
2525
import * as Property from "~/components/primitives/PropertyTable";
26+
import { useSheetHasCloseButton } from "~/components/primitives/SheetV3";
2627
import {
2728
Table,
2829
TableBlankRow,
@@ -96,6 +97,7 @@ export function ScheduleInspector({
9697
const organization = useOrganization();
9798
const project = useProject();
9899
const environment = useEnvironment();
100+
const hasSheetCloseButton = useSheetHasCloseButton();
99101

100102
const isUtc = schedule.timezone === "UTC";
101103
const isImperative = schedule.type === "IMPERATIVE";
@@ -110,8 +112,7 @@ export function ScheduleInspector({
110112
<div
111113
className={cn(
112114
"mx-3 flex items-center justify-between gap-2 border-b border-grid-dimmed",
113-
// Without header actions the sheet's own floating close button sits here.
114-
!headerActions && "pr-14"
115+
hasSheetCloseButton && "pr-14"
115116
)}
116117
>
117118
<Header2 className="truncate">{schedule.friendlyId}</Header2>

apps/webapp/app/routes/resources.orgs.$organizationSlug.projects.$projectParam.env.$envParam.schedules.new/route.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ import {
4040
TableRow,
4141
} from "~/components/primitives/Table";
4242
import { TextLink } from "~/components/primitives/TextLink";
43+
import { useSheetHasCloseButton } from "~/components/primitives/SheetV3";
4344
import { TimezoneList } from "~/components/scheduled/timezones";
4445
import { prisma } from "~/db.server";
4546
import { useEnvironment } from "~/hooks/useEnvironment";
@@ -156,6 +157,7 @@ export function UpsertScheduleForm({
156157
/** Submits via this fetcher with `_format=json` so the host can toast/close itself. */
157158
submitFetcher?: FetcherWithComponents<unknown>;
158159
}) {
160+
const hasSheetCloseButton = useSheetHasCloseButton();
159161
const actionData = useActionData();
160162
// Only feed conform-shaped data (`status`) to `useForm` — `{ ok, message }`
161163
// envelopes lack it and crash conform.
@@ -231,7 +233,12 @@ export function UpsertScheduleForm({
231233
{...getFormProps(form)}
232234
className="grid h-full max-h-full grid-rows-[2.5rem_1fr_auto] overflow-hidden bg-background-bright"
233235
>
234-
<div className="mx-3 flex min-w-0 items-center justify-between gap-2 overflow-hidden border-b border-grid-dimmed pr-14">
236+
<div
237+
className={cn(
238+
"mx-3 flex min-w-0 items-center justify-between gap-2 overflow-hidden border-b border-grid-dimmed",
239+
hasSheetCloseButton && "pr-14"
240+
)}
241+
>
235242
<Header2 className="truncate">
236243
{schedule?.friendlyId
237244
? "Edit schedule"

0 commit comments

Comments
 (0)