From 7a7c2b49202e8fa3c0b66f0beb5f7d84cbcbe1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Grimm?= Date: Thu, 14 May 2026 20:29:27 -0500 Subject: [PATCH 01/18] feat: add ControlPresentation primitive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A presentational layout shell for input-like controls. Provides border chrome, focus/hover/disabled/readonly/invalid styling, and two slots (startSlot, endSlot) flanking an arbitrary focusable control passed as children. Forwards a ref to the wrapper and forwards click events to the inner control (toggleable via forwardClickToControl). State-driven styling fires from :has() selectors that match three signaling conventions — native HTML, ARIA, and data-attr — on the inner control. The single source of truth is the a11y attributes the control needs anyway. :invalid is deliberately omitted (fires pre-interaction). Spacing is explicit conditional padding: 10px outer on each side by default; left shrinks to 6px when startSlot is present (with 6px gap to control); right shrinks to 4px when endSlot is present (with 6px gap). ControlActionButton ships alongside as a compact 24x24 button variant sized to fit the chrome alongside a 16px icon glyph. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../control-action-button.tsx | 48 +++ .../control-presentation.module.css | 136 +++++++++ .../control-presentation.stories.tsx | 286 ++++++++++++++++++ .../control-presentation.tsx | 108 +++++++ src/control-presentation/index.ts | 2 + src/index.ts | 1 + src/styles/design-tokens.css | 9 +- 7 files changed, 589 insertions(+), 1 deletion(-) create mode 100644 src/control-presentation/control-action-button.tsx create mode 100644 src/control-presentation/control-presentation.module.css create mode 100644 src/control-presentation/control-presentation.stories.tsx create mode 100644 src/control-presentation/control-presentation.tsx create mode 100644 src/control-presentation/index.ts diff --git a/src/control-presentation/control-action-button.tsx b/src/control-presentation/control-action-button.tsx new file mode 100644 index 00000000..25c6b0b3 --- /dev/null +++ b/src/control-presentation/control-action-button.tsx @@ -0,0 +1,48 @@ +import * as React from 'react' + +import classNames from 'classnames' + +import { Button, IconButton } from '../button' + +import styles from './control-presentation.module.css' + +import type { ComponentProps } from 'react' + +export type ControlActionButtonProps = + | ({ + children: React.ReactElement + } & Omit, 'variant' | 'size'>) + | ({ + icon?: React.ReactElement + } & Omit, 'variant' | 'size'>) + +/** + * A compact action button intended for `ControlPresentation`'s `endSlot`. Wraps + * Reactist's `Button` / `IconButton` with a 24×24, 3px-radius variant sized to fit + * the field chrome alongside a 16px icon glyph. + */ +export const ControlActionButton = React.forwardRef( + function ControlActionButton({ exceptionallySetClassName, ...props }, ref) { + return 'children' in props ? ( +