Thanks to visit codestin.com
Credit goes to github.com

Skip to content
12 changes: 11 additions & 1 deletion site/src/components/DropdownMenu/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,17 @@ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
import { Check } from "lucide-react";
import { cn } from "utils/cn";

export const DropdownMenu = DropdownMenuPrimitive.Root;
export const DropdownMenu = ({
children,
modal = false,
Comment thread
jakehwll marked this conversation as resolved.
...props
}: React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Root>) => {
return (
<DropdownMenuPrimitive.Root modal={modal} {...props}>
{children}
</DropdownMenuPrimitive.Root>
);
};

export const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;

Expand Down
30 changes: 17 additions & 13 deletions site/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -108,22 +108,26 @@
@apply border-border;
}

/*
By default, Radix adds a margin to the `body` element when a dropdown is displayed,
causing some shifting when the dropdown has a full-width size, as is the case with the mobile menu.
To prevent this, we need to apply the styles below.

/* Prevent layout shift when modals open by maintaining scrollbar width.
scrollbar-gutter: stable reserves space for the scrollbar so Radix's
scroll-bar compensation (margin-right/padding-right) is unnecessary
and causes double spacing. We zero it out with !important to win
over Radix's injected !important styles. The @supports guard ensures
we only do this on browsers that actually support scrollbar-gutter.

There’s a related issue on GitHub: Radix UI Primitives Issue #3251
https://github.com/radix-ui/primitives/issues/3251
*/
html body[data-scroll-locked] {
--removed-body-scroll-bar-size: 0;
margin-right: 0;
}
*/
@supports (scrollbar-gutter: stable) {
html {
scrollbar-gutter: stable;
}

/* Prevent layout shift when modals open by maintaining scrollbar width */
html {
scrollbar-gutter: stable;
html body[data-scroll-locked] {
--removed-body-scroll-bar-size: 0 !important;
margin-right: 0 !important;
overflow-y: scroll !important;
}
}

/*
Expand Down
2 changes: 1 addition & 1 deletion site/src/modules/dashboard/Navbar/MobileMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export const MobileMenu: FC<MobileMenuProps> = ({
const hasSomePermission = Object.values(permissions).some((p) => p);

return (
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenu modal open={open} onOpenChange={setOpen}>
{open && (
<div className="fixed inset-0 top-[72px] z-10 bg-surface-primary" />
)}
Expand Down
28 changes: 20 additions & 8 deletions site/src/modules/tasks/TaskPrompt/TaskPrompt.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ export const ChangeTemplate: Story = {
await step("Change template", async () => {
const templateSelect = await canvas.findByLabelText(/select template/i);
await userEvent.click(templateSelect);
const templateOption = await body.findByRole("option", {
const templateOption = await body.findByRole("menuitemradio", {
name: /codex/i,
});
await userEvent.click(templateOption);
Expand Down Expand Up @@ -277,7 +277,7 @@ export const SelectTemplateVersion: Story = {
const body = within(canvasElement.ownerDocument.body);
const versionSelect = await canvas.findByLabelText(/template version/i);
await userEvent.click(versionSelect);
const versionOption = await body.findByRole("option", {
const versionOption = await body.findByRole("menuitemradio", {
name: /v2.0.0/i,
});
await userEvent.click(versionOption);
Expand Down Expand Up @@ -459,7 +459,7 @@ export const CheckExternalAuthOnChangingVersions: Story = {
const body = within(canvasElement.ownerDocument.body);
const versionSelect = await canvas.findByLabelText(/template version/i);
await userEvent.click(versionSelect);
const versionOption = await body.findByRole("option", {
const versionOption = await body.findByRole("menuitemradio", {
name: /no external/i,
});
await userEvent.click(versionOption);
Expand Down Expand Up @@ -566,7 +566,7 @@ export const CheckPresetsWhenChangingTemplate: Story = {
const presetSelect = await canvas.findByLabelText(/preset/i);
await userEvent.click(presetSelect);

const options = await body.findAllByRole("option");
const options = await body.findAllByRole("menuitemradio");
expect(options).toHaveLength(1);
expect(options[0]).toContainHTML("Claude Code Dev");

Expand All @@ -577,17 +577,23 @@ export const CheckPresetsWhenChangingTemplate: Story = {
const templateSelect = await canvas.findByLabelText(/select template/i);
await userEvent.click(templateSelect);

const codexTemplateOption = await body.findByRole("option", {
const codexTemplateOption = await body.findByRole("menuitemradio", {
name: /codex/i,
});
await userEvent.click(codexTemplateOption);
});

await step("Presets are present in new template", async () => {
// Wait for the template dropdown's close animation to finish
// so its menuitemradio items are removed from the DOM.
await waitFor(() => {
expect(body.queryAllByRole("menuitemradio")).toHaveLength(0);
});

const presetSelect = await canvas.findByLabelText(/preset/i);
await userEvent.click(presetSelect);

const options = await body.findAllByRole("option");
const options = await body.findAllByRole("menuitemradio");
expect(options).toHaveLength(1);
expect(options[0]).toContainHTML("Codex Dev");

Expand All @@ -598,17 +604,23 @@ export const CheckPresetsWhenChangingTemplate: Story = {
const templateSelect = await canvas.findByLabelText(/select template/i);
await userEvent.click(templateSelect);

const codexTemplateOption = await body.findByRole("option", {
const codexTemplateOption = await body.findByRole("menuitemradio", {
name: /claude code/i,
});
await userEvent.click(codexTemplateOption);
});

await step("Presets are present in original template", async () => {
// Wait for the template dropdown's close animation to finish
// so its menuitemradio items are removed from the DOM.
await waitFor(() => {
expect(body.queryAllByRole("menuitemradio")).toHaveLength(0);
});

const presetSelect = await canvas.findByLabelText(/preset/i);
await userEvent.click(presetSelect);

const options = await body.findAllByRole("option");
const options = await body.findAllByRole("menuitemradio");
expect(options).toHaveLength(1);
expect(options[0]).toContainHTML("Claude Code Dev");
});
Expand Down
Loading
Loading