Skip to content

Enhance/settings layout#89

Open
kzamanbd wants to merge 8 commits intomainfrom
enhance/settings-layout
Open

Enhance/settings layout#89
kzamanbd wants to merge 8 commits intomainfrom
enhance/settings-layout

Conversation

@kzamanbd
Copy link
Copy Markdown
Contributor

@kzamanbd kzamanbd commented Apr 28, 2026

Summary by CodeRabbit

  • New Features

    • Collapsible settings sections with keyboard accessibility.
    • Settings exports expanded (provider, field renderer) and new save-button props.
    • Sidebar search placeholder customizable and search can be disabled.
    • Admin notice component now exported.
  • Bug Fixes

    • Save button visibility respects tab-level hide settings.
  • Style

    • Pointer cursor for interactive controls; spacing tweaks for sidebar, layout, pagination, and media upload UI.
  • Chores

    • Added WordPress API fetch dependency and updated ignore rules.

kzamanbd and others added 4 commits April 25, 2026 19:50
Enable collapsible settings sections and allow customizing the sidebar search placeholder. Updates include: new SettingsProps.searchPlaceholder, pass-through from Settings -> SettingsSidebar, and placeholder on the search input. SettingsSection now supports collapsible/collapsed in types, manages open state, toggles via header button with aria attributes, renders a ChevronDown icon, and prevents tooltip/doc link clicks from toggling collapse. Also import useState where needed and add .vscode to .gitignore.
Co-authored-by: Copilot <copilot@github.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 28, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 26fe4b51-fc68-492d-be79-68bbdc1bb035

📥 Commits

Reviewing files that changed from the base of the PR and between 58b5b4e and 0616328.

📒 Files selected for processing (1)
  • src/components/settings/settings-sidebar.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/settings/settings-sidebar.tsx

📝 Walkthrough

Walkthrough

Adds configurable sidebar search and collapsible sections to Settings, migrates notice network calls to @wordpress/api-fetch, expands re-exports (AdminNotice, SettingsProvider, FieldRenderer, SaveButtonRenderProps), tightens notice typing, updates externals/package, and includes minor styling and story tweaks.

Changes

Settings core & UI

Layer / File(s) Summary
Data Shape / Types
src/components/settings/settings-types.ts
Adds collapsible?/collapsed? to section type; relaxes default to accept objects; makes is_danger optional; adds searchPlaceholder? and searchable? to SettingsProps.
Component API / Props
src/components/settings/index.tsx, src/components/settings/settings-sidebar.tsx
Settings and SettingsSidebar now accept searchPlaceholder?: string and searchable?: boolean (default true); Settings forwards these into inner components.
Core UI Behavior
src/components/settings/settings-content.tsx
Implements collapsible section behavior (open state, init from collapsed, click/keyboard handlers, ARIA, Chevron rotation) and hides save button when active tab has hide_save.
Wiring / Styling
src/components/ui/sidebar.tsx, src/components/wordpress/layout-menu.tsx, src/components/wordpress/WpMediaUpload*.tsx, src/styles.css, src/components/wordpress/style.css
Minor class/tailwind adjustments: sidebar/layout-menu padding, media upload CSS hooks, pointer-cursor rule, pagination select margin override.
Stories / Top-level mapping
src/components/settings/Settings.stories.tsx, src/components/top-bar.tsx
Story data normalized (null'', removed description); top-bar map items wrapped in keyed fragments.
Exports
src/index.ts
Re-exports SettingsProvider, FieldRenderer, and SaveButtonRenderProps related to settings surface.

Notices & WordPress integration

Layer / File(s) Summary
Dependency / Build
package.json, webpack.config.js
Adds @wordpress/api-fetch dependency and marks it external in webpack.
Data/Types
src/components/wordpress/AdminNotice.tsx
Tightens NoticeAction.ajax_data and Notice.ajax_data index signatures from anyunknown; removes unused modal imports; adjusts wrapper spacing classes.
Core Logic
src/hooks/use-notices.ts
Replaces raw fetch with @wordpress/api-fetch calls (typed); memoizes fetch callback with useCallback; clears error before requests; uses apiFetch for POST actions (with parse: false) while preserving success/error handling.
Exports
src/index.ts
Exports AdminNotice from UI components for public use.

Repo & editor config

Layer / File(s) Summary
Repository Ignores
.gitignore
Adds debug-storybook.log ensure and adds .vscode to ignored entries.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SettingsRoot as Settings (root)
    participant Sidebar as SettingsSidebar
    participant Content as SettingsContent

    User->>Sidebar: type search (uses searchPlaceholder)
    Sidebar->>SettingsRoot: emit search query / update filter state
    SettingsRoot->>Content: forward search/filter state
    User->>Content: click or press Enter/Space on section header
    Content->>Content: toggle open state (collapsible/collapsed)
    Content-->>User: show/hide section body (aria-expanded updated)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐇 I hopped through props and class-name trails,

Sections fold like soft, wind-driven sails,
Search peeks out where placeholders glow,
Notices fetch from places they know,
New exports stitched — a tiny rabbit hail!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Enhance/settings layout' is overly broad and generic. It refers to a real aspect of the changes but does not clearly communicate the main feature or purpose of the pull request to someone scanning the history. Consider using a more specific title that highlights the primary feature, such as 'Add collapsible sections and search controls to settings component' or 'Enhance settings layout with collapsible sections and customizable search'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch enhance/settings-layout

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 (2)
src/components/settings/settings-content.tsx (1)

273-283: ⚠️ Potential issue | 🟠 Major

Add keyboard event propagation stop to the tooltip trigger.

The stopPropagation() on the span's onClick only prevents mouse clicks from bubbling; it doesn't handle keyboard events. When the button is focused and activated via Enter/Space, the keydown event bubbles to the parent heading and triggers onHeadingKeyDown, which calls preventDefault() and breaks the button's keyboard behavior. Add onKeyDown={(e) => e.stopPropagation()} to the span to prevent keyboard event bubbling to the parent.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/settings/settings-content.tsx` around lines 273 - 283, The
tooltip trigger only stops click propagation, so keyboard activations still
bubble to the parent and break behavior; update the TooltipTrigger span (the
inline-flex span inside TooltipTrigger used with <Info />) to also stop keyboard
events by adding an onKeyDown handler that calls e.stopPropagation(), ensuring
keyboard events do not reach parent handlers such as onHeadingKeyDown and
preserving expected keyboard activation for the tooltip trigger.
src/components/wordpress/AdminNotice.tsx (1)

214-220: ⚠️ Potential issue | 🟡 Minor

Preserve a minimum height for the notice card.

Removing min-h-40 makes the carousel collapse to each notice’s content height, which will cause the notice/navigation area to jump as users move between short and tall notices.

♻️ Restore the minimum-height guard
-                <div
-                    className={cn(
-                        'overflow-hidden rounded-md flex border-l-4 bg-white p-2 transition-all items-start duration-300 ease-in-out md:p-4',
-                        noticeAccentClass[activeNotice.type]
-                    )}>
+                <div
+                    className={cn(
+                        'overflow-hidden rounded-md flex min-h-40 border-l-4 bg-white p-2 transition-all items-start duration-300 ease-in-out md:p-4',
+                        noticeAccentClass[activeNotice.type]
+                    )}>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/wordpress/AdminNotice.tsx` around lines 214 - 220, The notice
card is collapsing between carousel items because the min-height Tailwind
utility was removed; restore a minimum height by re-adding the min-h-40 (or
equivalent) utility to the notice container class list where the className is
built (the div using cn(..., noticeAccentClass[activeNotice.type])) so the
carousel and navigation area remain stable; this change touches the same element
that has onMouseEnter={pauseAutoSlide} and onMouseLeave={resumeAutoSlide}.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@package.json`:
- Line 70: The `@wordpress/`* packages listed in dependencies (e.g.,
"@wordpress/api-fetch", "@wordpress/components", "@wordpress/dataviews",
"@wordpress/hooks") should be moved to peerDependencies so consumers provide
them at runtime; update package.json by removing these entries from
"dependencies" and adding equivalent semver entries under "peerDependencies"
(and optionally add them to "devDependencies" to keep them available for local
development/testing), ensuring version ranges match the previous values.

In `@src/styles.css`:
- Around line 256-257: Update the role-based selector so elements with
aria-disabled="true" are treated as disabled: change the selector that currently
reads button:not(:disabled), [role="button"]:not(:disabled) to also exclude
[aria-disabled="true"] (i.e. add :not([aria-disabled="true"]) to the
[role="button"] clause) so pseudo-buttons with aria-disabled do not receive
enabled styles like pointer cursor.

---

Outside diff comments:
In `@src/components/settings/settings-content.tsx`:
- Around line 273-283: The tooltip trigger only stops click propagation, so
keyboard activations still bubble to the parent and break behavior; update the
TooltipTrigger span (the inline-flex span inside TooltipTrigger used with <Info
/>) to also stop keyboard events by adding an onKeyDown handler that calls
e.stopPropagation(), ensuring keyboard events do not reach parent handlers such
as onHeadingKeyDown and preserving expected keyboard activation for the tooltip
trigger.

In `@src/components/wordpress/AdminNotice.tsx`:
- Around line 214-220: The notice card is collapsing between carousel items
because the min-height Tailwind utility was removed; restore a minimum height by
re-adding the min-h-40 (or equivalent) utility to the notice container class
list where the className is built (the div using cn(...,
noticeAccentClass[activeNotice.type])) so the carousel and navigation area
remain stable; this change touches the same element that has
onMouseEnter={pauseAutoSlide} and onMouseLeave={resumeAutoSlide}.
🪄 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: 7e3d0f5a-91fe-4cb6-9197-f5af3372e2e5

📥 Commits

Reviewing files that changed from the base of the PR and between 65d48db and 981ae33.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (13)
  • .gitignore
  • package.json
  • src/components/settings/index.tsx
  • src/components/settings/settings-content.tsx
  • src/components/settings/settings-sidebar.tsx
  • src/components/settings/settings-types.ts
  • src/components/top-bar.tsx
  • src/components/wordpress/AdminNotice.tsx
  • src/components/wordpress/style.css
  • src/hooks/use-notices.ts
  • src/index.ts
  • src/styles.css
  • webpack.config.js

Comment thread package.json
Comment thread src/styles.css
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/settings/settings-sidebar.tsx`:
- Around line 163-178: When `searchable` flips to false the hidden `search`
state must be cleared so the menu isn't silently filtered; add logic in the
SettingsSidebar component to reset `search` (call setSearch('')) whenever
`searchable` becomes false (e.g. useEffect(() => { if (!searchable)
setSearch('') }, [searchable])), or alternatively ignore the stored search by
passing an empty string when rendering the Input if `!searchable`; update
references to `search`, `setSearch`, and the `Input` render so the menu always
shows unfiltered items when `searchable` is disabled.
🪄 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: cbfdd02c-a4b2-45b6-a2d8-113aafdff8d0

📥 Commits

Reviewing files that changed from the base of the PR and between 981ae33 and 9b6c0fd.

📒 Files selected for processing (6)
  • src/components/settings/Settings.stories.tsx
  • src/components/settings/index.tsx
  • src/components/settings/settings-sidebar.tsx
  • src/components/settings/settings-types.ts
  • src/components/ui/sidebar.tsx
  • src/components/wordpress/layout-menu.tsx
✅ Files skipped from review due to trivial changes (2)
  • src/components/wordpress/layout-menu.tsx
  • src/components/ui/sidebar.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/components/settings/settings-types.ts

Comment on lines +163 to +178
{searchable && (
<div className="shrink-0 p-2 px-4">
<div className="relative">
<Search className="text-muted-foreground pointer-events-none absolute left-2.5 top-1/2 size-4 -translate-y-1/2" />
<Input
type="search"
value={search}
onChange={(e) => setSearch(e.target.value)}
className="h-8 pl-8"
placeholder={searchPlaceholder}
aria-label="Search settings"
data-testid="settings-search"
/>
</div>
</div>
</div>
)}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Clear hidden search state when searchable is turned off.

If a query exists and searchable later becomes false, the menu stays filtered while the input is hidden, so users can’t clear it. Reset or ignore search when search is disabled.

💡 Suggested fix
-import { useMemo, useState } from 'react';
+import { useEffect, useMemo, useState } from 'react';
@@
     const [search, setSearch] = useState('');
+
+    useEffect(() => {
+        if (!searchable) {
+            setSearch('');
+        }
+    }, [searchable]);
@@
-        const q = search.trim().toLowerCase();
+        const q = searchable ? search.trim().toLowerCase() : '';
         if (!q) return items;
@@
-    }, [items, search, searchIndex]);
+    }, [items, search, searchIndex, searchable]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/settings/settings-sidebar.tsx` around lines 163 - 178, When
`searchable` flips to false the hidden `search` state must be cleared so the
menu isn't silently filtered; add logic in the SettingsSidebar component to
reset `search` (call setSearch('')) whenever `searchable` becomes false (e.g.
useEffect(() => { if (!searchable) setSearch('') }, [searchable])), or
alternatively ignore the stored search by passing an empty string when rendering
the Input if `!searchable`; update references to `search`, `setSearch`, and the
`Input` render so the menu always shows unfiltered items when `searchable` is
disabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant