Refactor all input components embedded within dropdowns, popovers, and overlay panels to follow a “flush embedded control” visual rule. Inputs inside overlays should appear integrated with their container (no double borders, consistent padding, shared background) rather than looking like standalone fields dropped into a box. This refactor also ensures dark mode parity for all affected components and codifies the rule in agents.md for future development.
Introduction
Overview
When form inputs (TextField, Select, SearchInput) appear inside dropdowns, popovers, command palettes, or slide-out panels, they often display a visible border against the overlay’s bordered container, creating a “border-on-border” visual artifact. This makes the UI feel unpolished and inconsistent. The design system needs a formalized “flush embedded control” pattern that strips the input’s standalone border and adjusts its padding to integrate with the overlay container.
Goals
Define and implement a “flush embedded control” CSS utility class and/or variant that removes standalone input chrome when embedded inside overlays.
Apply this rule consistently across all dropdown, popover, command palette, and slide-out panel components that contain inputs.
Achieve full dark mode parity for all affected components.
Add the “flush embedded control” rule to agents.md so future component development follows it automatically.
Ship visual regression stories capturing before/after states.
Non-Goals
Redesigning the overlay components themselves (shape, shadow, animation).
Changing the standalone appearance of any input component.
Adding new input components; this is purely a visual polish refactor.
Scope
In Scope
Item
Description
Flush embedded control class
A CSS utility (flush-embedded or similar) that strips border, adjusts padding, and sets bg-transparent on inputs inside overlays.
Dropdown family
Apply flush rule to inputs in Dropdown, DropdownMenu, Combobox, and Command Palette search fields.
Popover family
Apply flush rule to inputs inside Popover, DatePicker popover, and filter popovers.
SlideOutPanel
Apply flush rule to search/filter inputs in SlideOutPanel headers.
ListToolbar
Apply flush rule to the search input inside ListToolbar when rendered within an overlay context.
Dark mode audit
Verify all affected components render correctly in dark mode after the refactor.
agents.md update
Add the “flush embedded control” rule to the design system operating rules.
Visual regression stories
Before/after stories for each affected component.
Out of Scope
Item
Reason
Modal dialogs
Inputs in modals are typically in a spacious layout; flush rule is less applicable.
Standalone form pages
No overlay context; standard input chrome is correct.
New component creation
This is a refactor of existing visual behavior.
Users and Pain Points
User
Pain Point
Design system consumers
Inputs inside dropdowns look inconsistent; teams add custom CSS overrides to fix the double-border.
Designers reviewing implementations
Embedded inputs don’t match design specs; visual QA catches these repeatedly.
Dark mode users
Some embedded inputs have mismatched backgrounds in dark mode, making them appear to float.
LLM agents building components
No codified rule exists; agents recreate the double-border issue in new components.
Definitions
Term
Definition
Flush embedded control
An input control rendered without its standalone border and background, visually merging with its parent overlay container.
Double border
The visual artifact where an input’s border renders adjacent to or against an overlay’s border, creating a heavy or doubled line.
Overlay context
Any component that renders as a floating layer: dropdowns, popovers, command palettes, slide-out panels.
Field shell
The styled container (getFieldShellClassName) that provides border, background, and focus ring to form inputs.
Current State
getFieldShellClassName (src/lib/form-control-styles.ts): Generates the border, background, padding, and focus ring classes for all form inputs. Does not have an “embedded” or “flush” variant.
dropdownOverlayPanelClassName (src/components/ui/dropdowns/dropdown-hooks.ts): Shared class for dropdown/popover overlay panels. Applies its own border and background.
DatePicker popover: Contains a calendar but no embedded input currently.
Combobox / Command Palette: Contains a search TextField at the top of the dropdown; currently shows double border.
ListToolbar: Contains a search input; when rendered inside a SlideOutPanel, the input border doubles with the panel border.
Dark mode: Most components technically support dark mode via tokens, but some embedded inputs have subtle background mismatches.
Proposed Solution
Define the flush variant
Add a flush variant to getFieldShellClassName in src/lib/form-control-styles.ts:
// When flush is true: border-transparent, bg-transparent, shadow-none, px-0
This strips the standalone chrome while preserving focus ring behavior (focus ring applies to the overlay container or the input directly, depending on context).
Apply contextually
Each overlay component that embeds an input passes flush to the input (or wraps it in a context provider that signals “you are embedded”). Candidate approach: a FormControlContext with { embedded: boolean } that field shells read automatically. This avoids threading a prop through every component tree.
Component-by-component changes
Combobox search input: Auto-flush via context when inside dropdown panel.
Command Palette search input: Auto-flush; adjust top padding to align with panel padding.
ListToolbar in SlideOutPanel: Detect overlay ancestor via context; flush the search input.
Filter popovers: Any TextField or Select inside a popover reads the embedded context.
Dark mode audit
After applying flush, audit all affected components in dark mode. The overlay’s bg-card or bg-popover token is the source of truth; inputs inherit it via bg-transparent.
Codify in agents.md
Add a rule under the design-system operating rules:
Flush embedded control rule: Any form input rendered inside a dropdown, popover, command palette, or slide-out panel must use the flush field shell variant. The input’s border, background, and padding must integrate with the overlay container rather than rendering standalone chrome. This prevents border-on-border artifacts and ensures dark mode parity.
Requirements
Requirement Priorities
Must Have: Flush variant in field shell, applied to Combobox and Command Palette.
Should Have: FormControlContext for automatic flush detection, applied to all overlay families.
Could Have: Animated border-fade transition when an input moves from standalone to embedded context.
Functional Requirements
ID
Requirement
Priority
FR-01
getFieldShellClassName accepts a flush boolean that removes border, background, and shadow.
Must
FR-02
Combobox search input renders flush inside its dropdown panel.
Must
FR-03
Command Palette search input renders flush inside its overlay.
Must
FR-04
ListToolbar search input renders flush when inside a SlideOutPanel.
Should
FR-05
FormControlContext provides { embedded: boolean } to descendants of overlay components.
Should
FR-06
Field shells automatically apply flush styling when embedded is true in context.
Should
FR-07
Focus ring remains visible on flush inputs (applied to the input element directly, not a border wrapper).
Must
FR-08
All affected components render correctly in dark mode with no background mismatches.
Must
FR-09
agents.md is updated with the flush embedded control rule.
Must
Non-Functional Requirements
ID
Requirement
Target
NFR-01
No visual regression in standalone input appearance.
Zero pixel-level changes to non-embedded inputs.
NFR-02
No bundle size increase from the context provider.
< 200 bytes gzipped.
NFR-03
Dark mode parity
All affected components pass visual inspection in both themes.
API/Interface Requirements
getFieldShellClassName extension
interface FieldShellOptions {
size?:"sm"|"md"|"lg";
disabled?:boolean;
error?:boolean;
flush?:boolean; // NEW — removes standalone chrome
Overlay components (Popover, DropdownPanel, SlideOutPanel) wrap children with <FormControlContext.Provider value={{ embedded: true }}>.
Accessibility Requirements
ID
Requirement
A11Y-01
Focus ring remains visible on flush inputs; it must meet 3:1 contrast ratio against the overlay background.
A11Y-02
No change to ARIA attributes on any affected input.
A11Y-03
Screen reader experience is unchanged; labels and descriptions remain linked.
Content and Documentation Requirements
ID
Requirement
DOC-01
Update agents.md with the “flush embedded control” rule.
DOC-02
Storybook stories showing embedded vs. standalone inputs side by side.
DOC-03
Migration guide for teams that have manually overridden embedded input styling.
Dependencies
Dependency
Type
Risk
src/lib/form-control-styles.ts
Internal
Low — adding a variant to existing utility.
All overlay components
Internal
Medium — multiple files touched, but changes are CSS-only.
src/styles/motion.css
Internal
Low — no motion changes needed.
Risks and Tradeoffs
Risk
Likelihood
Impact
Mitigation
Flush variant accidentally applied in non-overlay contexts
Low
Medium
Context-based detection ensures flush only activates inside overlays; manual flush prop is opt-in only.
Visual regression in existing components
Medium
High
Chromatic or Percy visual regression tests on all affected stories.
FormControlContext overhead in deeply nested trees
Low
Low
Context value is a static object; no re-renders unless overlay mounts/unmounts.
Open Questions
#
Question
Owner
Status
OQ-01
Should flush apply to Modal dialog inputs or only overlay/dropdown contexts?
David Holmes
Open
OQ-02
Should the context provider be named FormControlContext or OverlayContext (broader)?
David Holmes
Open
OQ-03
Should flush inputs have a subtle bottom-border separator instead of fully borderless?
David Holmes
Open
Acceptance Criteria
#
Criterion
AC-01
getFieldShellClassName({ flush: true }) produces classes without border, background, or shadow.
AC-02
Combobox and Command Palette search inputs render without double-border artifacts.
AC-03
All affected components render correctly in dark mode with no background mismatches.
AC-04
Standalone inputs are visually unchanged (zero regression).
AC-05
Focus ring is visible on flush inputs with 3:1+ contrast ratio.
AC-06
agents.md contains the flush embedded control rule.
AC-07
Visual regression stories exist for all affected components.
AC-08
pnpm typecheck and pnpm vitest run --project unit pass with zero errors.
LLM Handoff Instructions
When implementing this FRD:
Start with getFieldShellClassName in src/lib/form-control-styles.ts. Add a flush option that conditionally omits border, background, and shadow classes. Test by rendering a TextField with flush in a Storybook story.
Then add FormControlContext in a new file src/lib/form-control-context.tsx (or add to an existing context file). Provide it from overlay components: Popover, DropdownPanel (in dropdown-hooks.ts), SlideOutPanel.
Then modify the field shell to read from FormControlContext when flush is not explicitly passed — if embedded is true in context, auto-apply flush.
Then audit each overlay component that contains inputs: Combobox, Command Palette, ListToolbar, filter popovers. Verify the flush rule applies. Check dark mode.
Update agents.md with the flush embedded control rule under the design-system operating rules section.
Add visual regression stories showing embedded inputs in each overlay type.