From bc8cd7cfe429f796b75f8c82fe6cc74a00fd40be Mon Sep 17 00:00:00 2001 From: Kamruzzaman Date: Sat, 25 Apr 2026 19:50:55 +0600 Subject: [PATCH 1/8] Add collapsible sections & search placeholder 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. --- .gitignore | 3 +- src/components/settings/index.tsx | 9 +- src/components/settings/settings-content.tsx | 102 ++++++++++++++----- src/components/settings/settings-sidebar.tsx | 9 +- src/components/settings/settings-types.ts | 7 ++ src/components/top-bar.tsx | 14 +-- src/styles.css | 5 + 7 files changed, 117 insertions(+), 32 deletions(-) diff --git a/.gitignore b/.gitignore index 22a8969..6aea623 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /node_modules /dist storybook-static -debug-storybook.log \ No newline at end of file +debug-storybook.log +.vscode \ No newline at end of file diff --git a/src/components/settings/index.tsx b/src/components/settings/index.tsx index 179c7e2..5e6da51 100644 --- a/src/components/settings/index.tsx +++ b/src/components/settings/index.tsx @@ -27,6 +27,7 @@ export function Settings({ applyFilters, initialPage, onNavigate, + searchPlaceholder, }: SettingsProps) { return ( ); @@ -56,9 +58,11 @@ export function Settings({ function SettingsInner({ title, className, + searchPlaceholder, }: { title?: string; className?: string; + searchPlaceholder?: string; }) { const { loading, activeSubpage, isSidebarVisible } = useSettings(); const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false); @@ -133,7 +137,10 @@ function SettingsInner({ )} - + )} diff --git a/src/components/settings/settings-content.tsx b/src/components/settings/settings-content.tsx index 38a69f0..1bd92ef 100644 --- a/src/components/settings/settings-content.tsx +++ b/src/components/settings/settings-content.tsx @@ -1,8 +1,9 @@ +import { useState } from 'react'; import type { SettingsElement as SettingsElementType } from './settings-types'; import { useSettings } from './settings-context'; import { FieldRenderer } from './field-renderer'; import { cn } from '@/lib/utils'; -import { FileText, Info } from "lucide-react"; +import { ChevronDown, FileText, Info } from "lucide-react"; import { ScrollArea, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui"; import { Button } from "@/components/ui/button"; import { RawHTML } from "@wordpress/element"; @@ -43,8 +44,12 @@ export function SettingsContent({ className }: { className?: string }) { }; // Determine whether to show a save area - // Hidden when the active page/subpage sets hide_save: true (e.g. License page) - const showSaveArea = Boolean(save) && !contentSource?.hide_save; + // Hidden when the active page/subpage — or the currently-active tab — sets + // hide_save: true. Tab-level hide_save lets a single tab under a shared + // scope (e.g. an action-only tab) opt out without affecting siblings. + const activeTabElement = tabs.find((t) => t.id === activeTab); + const showSaveArea = + Boolean(save) && !contentSource?.hide_save && !activeTabElement?.hide_save; if (!contentSource) { return ( @@ -209,6 +214,8 @@ function ContentBlock({ element }: { element: SettingsElementType }) { function SettingsSection({ section }: { section: SettingsElementType }) { const { shouldDisplay } = useSettings(); + const collapsible = section.collapsible === true; + const [open, setOpen] = useState(!section.collapsed); if (!shouldDisplay(section)) { return null; @@ -217,11 +224,44 @@ function SettingsSection({ section }: { section: SettingsElementType }) { const sectionLabel = section.label || section.title || ''; const hasHeading = Boolean(sectionLabel || section.description); const tooltip = section?.tooltip || ''; + const hasChildren = (section.children?.length ?? 0) > 0; + const contentId = `settings-section-content-${section.id}`; + const bodyVisible = !collapsible || open; + + const toggle = () => setOpen((o) => !o); + const onHeadingKeyDown = (e: React.KeyboardEvent) => { + if (!collapsible) return; + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + toggle(); + } + }; + + // Always a
so nested interactive children (doc links, tooltip triggers, + // field controls) keep their native behavior — a +

{tooltip}

@@ -252,25 +295,38 @@ function SettingsSection({ section }: { section: SettingsElementType }) {

)}
- {section.doc_link && ( - - - { section.doc_link_text ?? '' } - - )} - +
+ {section.doc_link && ( + e.stopPropagation()} + className="text-muted-foreground flex gap-1 items-center text-sm hover:text-foreground transition-colors" + > + + { section.doc_link_text ?? '' } + + )} + {collapsible && ( + + )} +
+ )} -
- {section.children?.map((child) => ( - - ))} -
+ {hasChildren && bodyVisible && ( +
+ {section.children?.map((child) => ( + + ))} +
+ )} ); } diff --git a/src/components/settings/settings-sidebar.tsx b/src/components/settings/settings-sidebar.tsx index 4206ab7..3a1dbf2 100644 --- a/src/components/settings/settings-sidebar.tsx +++ b/src/components/settings/settings-sidebar.tsx @@ -53,7 +53,13 @@ function collectSearchableText(element: SettingsElement): string { return texts.join(' ').toLowerCase(); } -export function SettingsSidebar({ className }: { className?: string }) { +export function SettingsSidebar({ + className, + searchPlaceholder, +}: { + className?: string; + searchPlaceholder?: string; +}) { const { schema, activePage, @@ -160,6 +166,7 @@ export function SettingsSidebar({ className }: { className?: string }) { value={search} onChange={(e) => setSearch(e.target.value)} className="h-8 pl-8" + placeholder={searchPlaceholder} aria-label="Search settings" data-testid="settings-search" /> diff --git a/src/components/settings/settings-types.ts b/src/components/settings/settings-types.ts index 831720d..8645567 100644 --- a/src/components/settings/settings-types.ts +++ b/src/components/settings/settings-types.ts @@ -108,6 +108,11 @@ export type SettingsElement = { field_group_id?: string; priority?: number; + /** Section-only: render the card with a collapse toggle in its header. */ + collapsible?: boolean; + /** Section-only: initial collapsed state when `collapsible` is true. */ + collapsed?: boolean; + // Validation error (runtime) validationError?: string; @@ -178,6 +183,8 @@ export interface SettingsProps { initialPage?: string; /** Called whenever the active page changes. Use to sync a URL query param. */ onNavigate?: (pageId: string) => void; + /** Placeholder text for the sidebar search input. */ + searchPlaceholder?: string; } export interface FieldComponentProps { diff --git a/src/components/top-bar.tsx b/src/components/top-bar.tsx index e00df70..9914610 100644 --- a/src/components/top-bar.tsx +++ b/src/components/top-bar.tsx @@ -51,12 +51,14 @@ function TopBar({className, logo, versions = [], rightSideComponents = <>}: T ); } - return <> - { Component } - { - versions.length - 1 !== index && - } - + return ( + + { Component } + { + versions.length - 1 !== index && + } + + ); }) } diff --git a/src/styles.css b/src/styles.css index 71ff9c1..b6b57b9 100644 --- a/src/styles.css +++ b/src/styles.css @@ -252,6 +252,11 @@ background-color: transparent; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; + + button:not(:disabled), + [role="button"]:not(:disabled) { + cursor: pointer; + } } /* ============================================ From e30c64c13c740e2dead716a0d7c25d0987f86aef Mon Sep 17 00:00:00 2001 From: Kamruzzaman Date: Sat, 25 Apr 2026 20:23:16 +0600 Subject: [PATCH 2/8] Export SettingsProvider and FieldRenderer --- src/components/settings/index.tsx | 3 ++- src/index.ts | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/components/settings/index.tsx b/src/components/settings/index.tsx index 5e6da51..ead5d12 100644 --- a/src/components/settings/index.tsx +++ b/src/components/settings/index.tsx @@ -191,7 +191,8 @@ function usePrevious(value: T): T | undefined { // Re-exports // ============================================ -export { useSettings } from './settings-context'; +export { SettingsProvider, useSettings } from './settings-context'; export type { ApplyFiltersFunction } from './settings-context'; +export { FieldRenderer } from './field-renderer'; export { formatSettingsData, extractValues } from './settings-formatter'; export type { SettingsElement, SettingsProps, FieldComponentProps, SaveButtonRenderProps } from './settings-types'; diff --git a/src/index.ts b/src/index.ts index 4306d4b..e923ea1 100644 --- a/src/index.ts +++ b/src/index.ts @@ -354,13 +354,16 @@ export { License, type LicenseProps, type LicenseLabels, type LicenseStatus, typ // Settings (schema-driven settings page) export { Settings, + SettingsProvider, useSettings, + FieldRenderer, formatSettingsData, extractValues, type ApplyFiltersFunction, type SettingsProps, type SettingsElement, type FieldComponentProps, + type SaveButtonRenderProps, } from './components/settings'; export { SettingsSkeleton } from './components/settings/settings-skeleton'; From 36135f4347b0ebeaa2d75ff38af2407dd567dd0f Mon Sep 17 00:00:00 2001 From: Kamruzzaman Date: Sun, 26 Apr 2026 14:42:07 +0600 Subject: [PATCH 3/8] Use @wordpress/api-fetch for notices --- package-lock.json | 42 ++++++++++++++++++++---- package.json | 1 + src/components/wordpress/AdminNotice.tsx | 10 +++--- src/hooks/use-notices.ts | 30 ++++++++--------- src/index.ts | 2 ++ webpack.config.js | 1 + 6 files changed, 57 insertions(+), 29 deletions(-) diff --git a/package-lock.json b/package-lock.json index 70e5a6a..09e382c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@dnd-kit/react": "^0.3.0", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", + "@wordpress/api-fetch": "^7.43.0", "@wordpress/components": "^32.5.0", "@wordpress/dataviews": "^14.0.0", "@wordpress/hooks": "^4.43.0", @@ -8251,6 +8252,20 @@ "npm": ">=8.19.2" } }, + "node_modules/@wordpress/api-fetch": { + "version": "7.44.0", + "resolved": "https://registry.npmjs.org/@wordpress/api-fetch/-/api-fetch-7.44.0.tgz", + "integrity": "sha512-KZP5Y0AzUVPRbwCsp2MUNEjIyYPJdaa7ojzYyc/IVlaAlbXVdd0Ofk8UDf4l8PjtXkyyPs9pX9sFy5iNcrF2cQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@wordpress/i18n": "^6.17.0", + "@wordpress/url": "^4.44.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/babel-preset-default": { "version": "8.39.0", "resolved": "https://registry.npmjs.org/@wordpress/babel-preset-default/-/babel-preset-default-8.39.0.tgz", @@ -8875,9 +8890,9 @@ } }, "node_modules/@wordpress/hooks": { - "version": "4.43.0", - "resolved": "https://registry.npmjs.org/@wordpress/hooks/-/hooks-4.43.0.tgz", - "integrity": "sha512-BY7GPjEwhOlgkavVak40E3RtA8Z9ehydqTZckRoesMRjXYfxKSzr1C1FT4wAPS5uXM1pNlWivfofMaJjVNQu5w==", + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@wordpress/hooks/-/hooks-4.44.0.tgz", + "integrity": "sha512-6p2vFvoFaovqnKFnIoy6Kib2XJhTwaJ1VhMXp4tM2PhSLnFMXVm1TpcHeX/kH7E6sWKJACBrDR6FH2nGYMk5dA==", "license": "GPL-2.0-or-later", "engines": { "node": ">=18.12.0", @@ -8895,13 +8910,13 @@ } }, "node_modules/@wordpress/i18n": { - "version": "6.16.0", - "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-6.16.0.tgz", - "integrity": "sha512-D8yiDLzOrs9Aa4Cc1nm7m2OMilZeG9Qd7zHauMIDQujwHOe9xrOyH9ppDDko6AAWb+GeUYsf5zf2Efu5saLq0w==", + "version": "6.17.0", + "resolved": "https://registry.npmjs.org/@wordpress/i18n/-/i18n-6.17.0.tgz", + "integrity": "sha512-v1SLBweg7CRzQ+5+WSC1U93i8h9d3AoB0YBvMsd6gWI5vO8Zh4YKlEMexvrHQC++WN83egwqux84fWEdeU0MUA==", "license": "GPL-2.0-or-later", "dependencies": { "@tannin/sprintf": "^1.3.2", - "@wordpress/hooks": "^4.43.0", + "@wordpress/hooks": "^4.44.0", "gettext-parser": "^1.3.1", "memize": "^2.1.0", "tannin": "^1.2.0" @@ -9468,6 +9483,19 @@ "npm": ">=8.19.2" } }, + "node_modules/@wordpress/url": { + "version": "4.44.0", + "resolved": "https://registry.npmjs.org/@wordpress/url/-/url-4.44.0.tgz", + "integrity": "sha512-kWalXttgtRwFy4szBPX9dJcqHErRC0V9JuZ7uxdrxxdXl6WNv+lx8SYpLx12q3Zk6zNIw73M8E5wHON7eyXZZw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "remove-accents": "^0.5.0" + }, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + } + }, "node_modules/@wordpress/warning": { "version": "3.43.0", "resolved": "https://registry.npmjs.org/@wordpress/warning/-/warning-3.43.0.tgz", diff --git a/package.json b/package.json index bde37bb..fdfd6cb 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "@dnd-kit/react": "^0.3.0", "@dnd-kit/sortable": "^10.0.0", "@dnd-kit/utilities": "^3.2.2", + "@wordpress/api-fetch": "^7.43.0", "@wordpress/components": "^32.5.0", "@wordpress/dataviews": "^14.0.0", "@wordpress/hooks": "^4.43.0", diff --git a/src/components/wordpress/AdminNotice.tsx b/src/components/wordpress/AdminNotice.tsx index bf00dad..7301f73 100644 --- a/src/components/wordpress/AdminNotice.tsx +++ b/src/components/wordpress/AdminNotice.tsx @@ -2,7 +2,7 @@ import { RawHTML, useState } from '@wordpress/element'; import { ShieldAlert, ChevronLeft, ChevronRight } from 'lucide-react'; import { useNotices } from '@/hooks/use-notices'; import { cn } from '@/lib/utils'; -import { Modal, ModalDescription, ModalFooter, ModalHeader, ModalTitle } from '../ui/modal'; +import { Modal, ModalDescription, ModalFooter } from '../ui/modal'; import { Button } from '../ui/button'; export interface NoticeAction { @@ -12,7 +12,7 @@ export interface NoticeAction { ajax_data?: { action: string; nonce: string; - [key: string]: any; + [key: string]: unknown; }; target?: '_self' | '_blank'; class?: string; @@ -33,7 +33,7 @@ export interface Notice { ajax_data?: { action: string; nonce: string; - [key: string]: any; + [key: string]: unknown; }; priority?: number; } @@ -211,8 +211,8 @@ const AdminNotice = ({ interval = 5000, notices: initialNotices = [], noticesUrl }; return ( -
-
+
+
({}); - const fetchNotices = async () => { + const fetchNotices = useCallback(async () => { setIsLoading(true); + setError(null); try { const url = new URL(noticesUrl as string, window.location.href); @@ -39,13 +41,10 @@ export const useNotices = ({ }); } - const res = await fetch(url.toString()); + const data = await apiFetch({ + url: url.toString() + }); - if (!res.ok) { - throw new Error(`Failed to fetch notices: ${res.status}`); - } - - const data: Notice[] | { success: boolean; data: Notice[] } = await res.json(); const fetched = Array.isArray(data) ? data : data.data; setNotices(fetched); } catch (err) { @@ -53,7 +52,7 @@ export const useNotices = ({ } finally { setIsLoading(false); } - }; + }, [noticesUrl, noticesUrlArgs]); useEffect(() => { if (!noticesUrl) { @@ -61,7 +60,7 @@ export const useNotices = ({ } fetchNotices(); - }, [noticesUrl, noticesUrlArgs]); + }, [noticesUrl, noticesUrlArgs, fetchNotices]); useEffect(() => { if (!isAutoSliding || notices.length <= 1) { @@ -122,16 +121,13 @@ export const useNotices = ({ body.append(key, String(value)); }); - const response = await fetch(actionUrl, { + await apiFetch({ + url: actionUrl, method: 'POST', - headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, - body + body, + parse: false }); - if (!response.ok) { - throw new Error(`Request failed: ${response.status}`); - } - removeNoticeAt(noticeIndex); } else { removeNoticeAt(noticeIndex); diff --git a/src/index.ts b/src/index.ts index e923ea1..3c9e06d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -148,6 +148,8 @@ export { ModalFooter, ModalHeader, ModalOverlay, ModalTitle, // Notice Notice, NoticeAction, NoticeTitle, + // AdminNotice (WP-style admin notice card) + AdminNotice, // Popover Popover, PopoverContent, diff --git a/webpack.config.js b/webpack.config.js index ae69f63..2c7371f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -21,6 +21,7 @@ module.exports = { 'react-dom': 'react-dom', 'react/jsx-runtime': 'react/jsx-runtime', '@wordpress/element': '@wordpress/element', + '@wordpress/api-fetch': '@wordpress/api-fetch', '@wordpress/components': '@wordpress/components', '@wordpress/block-editor': '@wordpress/block-editor', '@wordpress/date': '@wordpress/date', From 981ae336bbbeb2425e76596364d8faf7afbf151a Mon Sep 17 00:00:00 2001 From: Kamruzzaman Date: Sun, 26 Apr 2026 22:03:33 +0600 Subject: [PATCH 4/8] fix: adjust margin for pagination select control in dataviews Co-authored-by: Copilot --- src/components/wordpress/style.css | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/wordpress/style.css b/src/components/wordpress/style.css index d228592..c937b81 100644 --- a/src/components/wordpress/style.css +++ b/src/components/wordpress/style.css @@ -85,6 +85,9 @@ border-bottom-left-radius: var(--dokan-dataviews-radius); border-bottom-right-radius: var(--dokan-dataviews-radius); } +.pui-root-dataviews .dataviews-pagination .components-select-control { + margin: 0 !important; +} .pui-root-dataviews .dataviews-wrapper .dataviews-view-table tr td:first-child, .pui-root-dataviews .dataviews-wrapper .dataviews-view-table tr th:first-child { padding-left: 20px !important; From 34b97a70a45d09b8a921da7135584b6adc91def9 Mon Sep 17 00:00:00 2001 From: Kamruzzaman Date: Wed, 29 Apr 2026 14:35:56 +0600 Subject: [PATCH 5/8] fix: update padding for sidebar and layout menu components; adjust default values in settings schema --- src/components/settings/Settings.stories.tsx | 5 ++--- src/components/settings/settings-sidebar.tsx | 2 +- src/components/settings/settings-types.ts | 4 ++-- src/components/ui/sidebar.tsx | 2 +- src/components/wordpress/layout-menu.tsx | 2 +- 5 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/components/settings/Settings.stories.tsx b/src/components/settings/Settings.stories.tsx index 81006e5..05b66ba 100644 --- a/src/components/settings/Settings.stories.tsx +++ b/src/components/settings/Settings.stories.tsx @@ -3576,7 +3576,7 @@ const dokanSettingsSchema: SettingsElement[] = [ "dependencies": [], "validations": [], "variant": "notice", - "value": null, + "value": '', "notice_type": "warning", "notice_icon": "Info", "notice_title": "", @@ -3600,7 +3600,7 @@ const dokanSettingsSchema: SettingsElement[] = [ "dependencies": [], "validations": [], "variant": "notice", - "value": null, + "value": '', "notice_type": "warning", "notice_icon": "Info", "notice_title": "Size Guide Title", @@ -5121,7 +5121,6 @@ const dokanSettingsSchema: SettingsElement[] = [ "doc_link": "" } ], - "description": "Set up AI to elevate your platform with enhanced capabilities.", "dependency_key": "product_generation", "dependencies": [], "validations": [], diff --git a/src/components/settings/settings-sidebar.tsx b/src/components/settings/settings-sidebar.tsx index 3a1dbf2..38e1b28 100644 --- a/src/components/settings/settings-sidebar.tsx +++ b/src/components/settings/settings-sidebar.tsx @@ -158,7 +158,7 @@ export function SettingsSidebar({ return (
{/* Deep-search input */} -
+
| Record; - default?: string | number | boolean | Array; + default?: string | number | boolean | Array | Record; options?: SettingsElementOption[]; readonly?: boolean; disabled?: boolean; diff --git a/src/components/ui/sidebar.tsx b/src/components/ui/sidebar.tsx index 764a37d..c2f0d6c 100644 --- a/src/components/ui/sidebar.tsx +++ b/src/components/ui/sidebar.tsx @@ -432,7 +432,7 @@ function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) { data-slot="sidebar-group" data-sidebar="group" className={cn( - "p-2 relative flex w-full min-w-0 flex-col", + "p-2 px-4 relative flex w-full min-w-0 flex-col", className )} {...props} diff --git a/src/components/wordpress/layout-menu.tsx b/src/components/wordpress/layout-menu.tsx index 8a45560..5223ead 100644 --- a/src/components/wordpress/layout-menu.tsx +++ b/src/components/wordpress/layout-menu.tsx @@ -150,7 +150,7 @@ export const LayoutMenuSearch = forwardRef<
From 9b6c0fdc2d53c70c49fc665cbd1fbfb7faa10294 Mon Sep 17 00:00:00 2001 From: Kamruzzaman Date: Wed, 29 Apr 2026 14:42:19 +0600 Subject: [PATCH 6/8] feat: add searchable prop to Settings and SettingsSidebar components Co-authored-by: Copilot --- src/components/settings/index.tsx | 7 ++++- src/components/settings/settings-sidebar.tsx | 31 +++++++++++--------- src/components/settings/settings-types.ts | 2 ++ 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/components/settings/index.tsx b/src/components/settings/index.tsx index ead5d12..fc1dc8a 100644 --- a/src/components/settings/index.tsx +++ b/src/components/settings/index.tsx @@ -28,6 +28,7 @@ export function Settings({ initialPage, onNavigate, searchPlaceholder, + searchable = true, }: SettingsProps) { return ( ); @@ -59,10 +61,12 @@ function SettingsInner({ title, className, searchPlaceholder, + searchable, }: { title?: string; className?: string; searchPlaceholder?: string; + searchable?: boolean; }) { const { loading, activeSubpage, isSidebarVisible } = useSettings(); const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false); @@ -82,7 +86,7 @@ function SettingsInner({ return (
)} diff --git a/src/components/settings/settings-sidebar.tsx b/src/components/settings/settings-sidebar.tsx index 38e1b28..76ed276 100644 --- a/src/components/settings/settings-sidebar.tsx +++ b/src/components/settings/settings-sidebar.tsx @@ -56,9 +56,11 @@ function collectSearchableText(element: SettingsElement): string { export function SettingsSidebar({ className, searchPlaceholder, + searchable = true, }: { className?: string; searchPlaceholder?: string; + searchable?: boolean; }) { const { schema, @@ -158,24 +160,25 @@ export function SettingsSidebar({ return (
{/* Deep-search input */} -
-
- - setSearch(e.target.value)} - className="h-8 pl-8" - placeholder={searchPlaceholder} - aria-label="Search settings" - data-testid="settings-search" - /> + {searchable && ( +
+
+ + setSearch(e.target.value)} + className="h-8 pl-8" + placeholder={searchPlaceholder} + aria-label="Search settings" + data-testid="settings-search" + /> +
-
+ )} { const isPage = schema.some((p) => p.id === item.id); diff --git a/src/components/settings/settings-types.ts b/src/components/settings/settings-types.ts index 3df199b..07b67e8 100644 --- a/src/components/settings/settings-types.ts +++ b/src/components/settings/settings-types.ts @@ -185,6 +185,8 @@ export interface SettingsProps { onNavigate?: (pageId: string) => void; /** Placeholder text for the sidebar search input. */ searchPlaceholder?: string; + /** Show the sidebar search input. Default: true. */ + searchable?: boolean; } export interface FieldComponentProps { From 58b5b4ed96919bed022413ac44857663f303c843 Mon Sep 17 00:00:00 2001 From: Kamruzzaman Date: Thu, 30 Apr 2026 15:19:39 +0600 Subject: [PATCH 7/8] fix: add specific class names to media upload components for styling consistency --- src/components/wordpress/WpMediaUpload.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/wordpress/WpMediaUpload.tsx b/src/components/wordpress/WpMediaUpload.tsx index 2e7caca..5b1d186 100644 --- a/src/components/wordpress/WpMediaUpload.tsx +++ b/src/components/wordpress/WpMediaUpload.tsx @@ -29,7 +29,7 @@ export function WpMediaUpload( { }; return ( -
+
{ value && (
+
{ value.length > 0 && (
{ value.map( ( url, i ) => ( From 0616328c84dafcda2dd8ba4aef7adc45f34e9af8 Mon Sep 17 00:00:00 2001 From: Kamruzzaman Date: Tue, 5 May 2026 16:49:00 +0600 Subject: [PATCH 8/8] Update settings-sidebar.tsx --- src/components/settings/settings-sidebar.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/settings/settings-sidebar.tsx b/src/components/settings/settings-sidebar.tsx index 76ed276..c42b345 100644 --- a/src/components/settings/settings-sidebar.tsx +++ b/src/components/settings/settings-sidebar.tsx @@ -161,7 +161,7 @@ export function SettingsSidebar({
{/* Deep-search input */} {searchable && ( -
+