@recursica/adapter-mui-v7 1.3.1 → 1.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +1 -1
  3. package/dist/adapter-mui-v7.cjs +16 -16
  4. package/dist/adapter-mui-v7.cjs.map +1 -1
  5. package/dist/adapter-mui-v7.css +1 -1
  6. package/dist/adapter-mui-v7.js +902 -880
  7. package/dist/adapter-mui-v7.js.map +1 -1
  8. package/dist/index.d.ts +8 -5
  9. package/docs/PHILOSOPHY.md +4 -0
  10. package/package.json +4 -8
  11. package/src/components/Heading/HEADING_IMPLEMENTATION_NOTES.md +10 -0
  12. package/src/components/Panel/PANEL_IMPLEMENTATION_NOTES.md +8 -0
  13. package/src/components/Panel/Panel.tsx +51 -9
  14. package/src/components/Slider/Slider.module.css +11 -0
  15. package/src/components/Text/TEXT_IMPLEMENTATION_NOTES.md +12 -0
  16. package/src/components/Text/Text.headings.dom.test.tsx +54 -0
  17. package/src/components/Text/Text.tsx +16 -0
  18. package/.storybook/commonArgTypes.ts +0 -148
  19. package/recursica_brand.json +0 -2610
  20. package/recursica_tokens.json +0 -769
  21. package/recursica_ui-kit.json +0 -9049
  22. package/recursica_variables_scoped.css +0 -6178
  23. package/src/Introduction.stories.tsx +0 -178
  24. package/src/components/Accordion/Accordion.stories.tsx +0 -198
  25. package/src/components/AssistiveElement/AssistiveElement.stories.tsx +0 -68
  26. package/src/components/AutoComplete/AutoComplete.stories.tsx +0 -336
  27. package/src/components/Avatar/Avatar.stories.tsx +0 -92
  28. package/src/components/Badge/Badge.stories.tsx +0 -78
  29. package/src/components/Breadcrumb/Breadcrumb.stories.tsx +0 -114
  30. package/src/components/Button/Button.stories.tsx +0 -196
  31. package/src/components/Card/Card.stories.tsx +0 -132
  32. package/src/components/Checkbox/Checkbox.stories.tsx +0 -97
  33. package/src/components/Checkbox/CheckboxGroup.stories.tsx +0 -139
  34. package/src/components/Chip/Chip.stories.tsx +0 -154
  35. package/src/components/Container/Container.stories.tsx +0 -118
  36. package/src/components/DatePicker/DatePicker.stories.tsx +0 -163
  37. package/src/components/Dropdown/Dropdown.stories.tsx +0 -252
  38. package/src/components/FileInput/FileInput.stories.tsx +0 -313
  39. package/src/components/FileUpload/FileUpload.stories.tsx +0 -362
  40. package/src/components/Flex/Flex.stories.tsx +0 -128
  41. package/src/components/FormControlLayout/FormControlLayout.stories.tsx +0 -118
  42. package/src/components/FormControlWrapper/FormControlWrapper.stories.tsx +0 -129
  43. package/src/components/Group/Group.stories.tsx +0 -120
  44. package/src/components/Heading/Heading.stories.tsx +0 -112
  45. package/src/components/HoverCard/HoverCard.stories.tsx +0 -172
  46. package/src/components/Label/Label.stories.tsx +0 -131
  47. package/src/components/LayoutGrid/LayoutGrid.stories.tsx +0 -61
  48. package/src/components/Link/Link.stories.tsx +0 -58
  49. package/src/components/Loader/Loader.stories.tsx +0 -123
  50. package/src/components/Menu/Menu.stories.tsx +0 -402
  51. package/src/components/Modal/Modal.stories.tsx +0 -105
  52. package/src/components/NumberInput/NumberInput.stories.tsx +0 -96
  53. package/src/components/Pagination/Pagination.stories.tsx +0 -48
  54. package/src/components/Panel/Panel.stories.tsx +0 -227
  55. package/src/components/Popover/Popover.stories.tsx +0 -133
  56. package/src/components/Radio/Radio.stories.tsx +0 -93
  57. package/src/components/Radio/RadioGroup.stories.tsx +0 -117
  58. package/src/components/ReadOnlyField/ReadOnlyField.stories.tsx +0 -163
  59. package/src/components/SegmentedControl/SegmentedControl.stories.tsx +0 -106
  60. package/src/components/Slider/Slider.stories.tsx +0 -282
  61. package/src/components/Stack/Stack.stories.tsx +0 -108
  62. package/src/components/Stepper/Stepper.stories.tsx +0 -157
  63. package/src/components/Switch/Switch.stories.tsx +0 -114
  64. package/src/components/Switch/SwitchGroup.stories.tsx +0 -132
  65. package/src/components/Table/Table.stories.tsx +0 -154
  66. package/src/components/Tabs/Tabs.stories.tsx +0 -174
  67. package/src/components/Text/Text.stories.tsx +0 -123
  68. package/src/components/TextArea/TextArea.stories.tsx +0 -94
  69. package/src/components/TextField/TextField.stories.tsx +0 -162
  70. package/src/components/TimePicker/TimePicker.stories.tsx +0 -155
  71. package/src/components/Timeline/Timeline.stories.tsx +0 -128
  72. package/src/components/Toast/Toast.stories.tsx +0 -67
  73. package/src/components/Tooltip/Tooltip.stories.tsx +0 -165
  74. package/src/components/TransferList/TransferList.stories.tsx +0 -121
  75. package/src/components/Tree/Tree.stories.tsx +0 -104
package/dist/index.d.ts CHANGED
@@ -985,18 +985,23 @@ export declare const Panel: PanelComponent;
985
985
  * </Panel>
986
986
  * ```
987
987
  *
988
+ * Always non-modal, with no props to change it: the page behind stays usable
989
+ * (no overlay, focus trap, scroll lock, `aria-modal` or `aria-hidden` on the
990
+ * rest of the page), focus returns to the opener on close, Escape always
991
+ * closes, and outside clicks never do. Implemented with MUI's `persistent`
992
+ * Drawer variant (no Modal) plus an Escape listener and focus restoration.
993
+ *
988
994
  * Mui Drawer sub-components available via dot-notation:
989
995
  * - `Panel.Header` — Top section with title and close button
990
996
  * - `Panel.Title` — Title text within the header
991
997
  * - `Panel.CloseButton` — Close button within the header
992
998
  * - `Panel.Body` — Scrollable body content area
993
999
  * - `Panel.Content` — Outer content container
994
- * - `Panel.Overlay` — Background overlay
995
1000
  * - `Panel.Root` — Root element for advanced composition
996
1001
  * - `Panel.Stack` — Stacked drawer context
997
1002
  */
998
1003
  declare const PanelBase: {
999
- ({ overStyled, placement, keepMounted, wrapHeaderText, opened, title, withOverlay, withCloseButton, onClose, children, ...rest }: PanelProps): JSX.Element;
1004
+ ({ overStyled, placement, keepMounted, wrapHeaderText, opened, title, withCloseButton, onClose, children, ...rest }: PanelProps): JSX.Element;
1000
1005
  displayName: string;
1001
1006
  };
1002
1007
 
@@ -1208,11 +1213,9 @@ export declare interface RecursicaNumberInputProps extends Omit<InputBaseProps,
1208
1213
  /**
1209
1214
  * Recursica Panel root props. Extends Mui Drawer.
1210
1215
  */
1211
- export declare interface RecursicaPanelProps extends Omit<DrawerProps, "classes" | "position" | "style" | "anchor" | "open" | "title">, RecursicaPanelProps_2 {
1216
+ export declare interface RecursicaPanelProps extends Omit<DrawerProps, "classes" | "position" | "style" | "anchor" | "open" | "title" | "variant" | "hideBackdrop" | "ModalProps" | "BackdropComponent" | "BackdropProps" | "disableEscapeKeyDown" | "disableScrollLock" | "disableEnforceFocus" | "disableAutoFocus" | "disableRestoreFocus">, RecursicaPanelProps_2 {
1212
1217
  /** Panel header title label. */
1213
1218
  title?: ReactNode;
1214
- /** Whether to display a background overlay. Default true. */
1215
- withOverlay?: boolean;
1216
1219
  /** Whether to display the close button in the header. Default true. */
1217
1220
  withCloseButton?: boolean;
1218
1221
  }
@@ -4,6 +4,10 @@ Recursica's component architecture isn't just a wrapper; it's a strict enforcing
4
4
 
5
5
  This document serves as the governing framework for why the `adapter-mui-v7` components are built the way they are.
6
6
 
7
+ ## Why an Adapter?
8
+
9
+ Most companies already have an existing component library or use an existing UI kit, and switching to a different kit means painful refactoring. Rather than replace MUI, this adapter adapts to its API surface while enforcing the behaviors and styling Recursica defines for a consistent UX. You don't ship two separate UI kits, and you can migrate to Recursica systematically, over time.
10
+
7
11
  ## 1. Strict Separation of Props (The Unified Recursica Prop Layer)
8
12
 
9
13
  Recursica has a **single universal API surface** internally regardless of whether we use MUI or another underlying UI library.
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "type": "git",
13
13
  "url": "git+https://github.com/borderux/recursica-adapter-mui-v7.git"
14
14
  },
15
- "version": "1.3.1",
15
+ "version": "1.3.3",
16
16
  "publishConfig": {
17
17
  "access": "public"
18
18
  },
@@ -31,18 +31,14 @@
31
31
  "files": [
32
32
  "dist",
33
33
  "src",
34
+ "!src/**/*.stories.tsx",
34
35
  "CHANGELOG.md",
35
- ".storybook/commonArgTypes.ts",
36
36
  "llms.txt",
37
37
  "USAGE.md",
38
38
  "ARCHITECTURE.md",
39
39
  "SETUP.md",
40
40
  "OVERSTYLING.md",
41
- "docs/PHILOSOPHY.md",
42
- "recursica_variables_scoped.css",
43
- "recursica_brand.json",
44
- "recursica_tokens.json",
45
- "recursica_ui-kit.json"
41
+ "docs/PHILOSOPHY.md"
46
42
  ],
47
43
  "keywords": [
48
44
  "react",
@@ -85,7 +81,7 @@
85
81
  "@playwright/test": "^1.62.1",
86
82
  "@recursica/adapter-tester": "^5.3.1",
87
83
  "@recursica/recursica-postcss-vars": "^1.5.0",
88
- "@recursica/storybook-template": "^0.7.15",
84
+ "@recursica/storybook-template": "^0.7.16",
89
85
  "@recursica/token-analyzer": "^1.8.0",
90
86
  "@storybook/addon-a11y": "^10.3.3",
91
87
  "@storybook/addon-docs": "^10.3.3",
@@ -0,0 +1,10 @@
1
+ # Heading – Implementation Notes
2
+
3
+ ## Heading owns semantic `h1`-`h6` (Matt Massey, 2026-10-08)
4
+
5
+ **Decision:** `Heading` is the only component that renders semantic `<h1>`-`<h6>` elements. Each
6
+ `order` maps to a heading level that Recursica and Forge define and style
7
+ (`recursica_brand_typography_h{order}`).
8
+
9
+ **Implementation:** Heading's styles are fixed by the Recursica JSON/CSS. Do not add variants to
10
+ Heading. Any other kind of text belongs in `Text`, which throws if asked to render `h1`-`h6`.
@@ -131,3 +131,11 @@ clips descenders (e.g. the "g" in a long title) whenever `text_line-height` is t
131
131
  font's natural ascent+descent. Switched to `overflow: clip; overflow-clip-margin: 0.35em;` — same
132
132
  truncation, but ink can bleed slightly past the line box before it's actually clipped.
133
133
  Project-wide fix; see Chip's `CHIP_IMPLEMENTATION_NOTES.md` for the original discovery.
134
+
135
+ ---
136
+
137
+ ## 10. Always non-modal (Matt Massey, 2026-10-08)
138
+
139
+ **Decision:** Panel is never modal, and there are no props to change that.
140
+
141
+ **Implementation:** The house rule is that the page behind a panel stays usable. `Panel.tsx` always renders MUI's Drawer with `variant="persistent"` (after the caller's props), which has no Modal: no backdrop, no focus trap, no scroll lock, no `aria-modal`, and no `aria-hidden` on the rest of the page. Because there is no Modal, `Panel.tsx` supplies the rest itself: a document `keydown` listener (while open) calls `onClose` on Escape, and focus returns to the opener (the element focused at open) on close. Escape is independent of outside clicks and always closes the panel; clicking the page behind never does. `withOverlay` and MUI's `variant`, `hideBackdrop`, `ModalProps`, `BackdropProps`/`BackdropComponent` and `disable*` (escape, scroll lock, enforce focus, auto focus, restore focus) props are omitted from `RecursicaPanelProps`. Every adapter must match.
@@ -1,4 +1,4 @@
1
- import { forwardRef, type ReactNode } from "react";
1
+ import { forwardRef, useEffect, useRef, type ReactNode } from "react";
2
2
  import {
3
3
  Drawer as MuiDrawer,
4
4
  type DrawerProps as MuiDrawerProps,
@@ -23,13 +23,26 @@ import { type RecursicaPanelProps as BaseRecursicaPanelProps } from "@recursica/
23
23
  export interface RecursicaPanelProps
24
24
  extends Omit<
25
25
  MuiDrawerProps,
26
- "classes" | "position" | "style" | "anchor" | "open" | "title"
26
+ | "classes"
27
+ | "position"
28
+ | "style"
29
+ | "anchor"
30
+ | "open"
31
+ | "title"
32
+ | "variant"
33
+ | "hideBackdrop"
34
+ | "ModalProps"
35
+ | "BackdropComponent"
36
+ | "BackdropProps"
37
+ | "disableEscapeKeyDown"
38
+ | "disableScrollLock"
39
+ | "disableEnforceFocus"
40
+ | "disableAutoFocus"
41
+ | "disableRestoreFocus"
27
42
  >,
28
43
  BaseRecursicaPanelProps {
29
44
  /** Panel header title label. */
30
45
  title?: ReactNode;
31
- /** Whether to display a background overlay. Default true. */
32
- withOverlay?: boolean;
33
46
  /** Whether to display the close button in the header. Default true. */
34
47
  withCloseButton?: boolean;
35
48
  }
@@ -68,13 +81,18 @@ const CloseIcon = () => (
68
81
  * </Panel>
69
82
  * ```
70
83
  *
84
+ * Always non-modal, with no props to change it: the page behind stays usable
85
+ * (no overlay, focus trap, scroll lock, `aria-modal` or `aria-hidden` on the
86
+ * rest of the page), focus returns to the opener on close, Escape always
87
+ * closes, and outside clicks never do. Implemented with MUI's `persistent`
88
+ * Drawer variant (no Modal) plus an Escape listener and focus restoration.
89
+ *
71
90
  * Mui Drawer sub-components available via dot-notation:
72
91
  * - `Panel.Header` — Top section with title and close button
73
92
  * - `Panel.Title` — Title text within the header
74
93
  * - `Panel.CloseButton` — Close button within the header
75
94
  * - `Panel.Body` — Scrollable body content area
76
95
  * - `Panel.Content` — Outer content container
77
- * - `Panel.Overlay` — Background overlay
78
96
  * - `Panel.Root` — Root element for advanced composition
79
97
  * - `Panel.Stack` — Stacked drawer context
80
98
  */
@@ -85,13 +103,37 @@ const PanelBase = function Panel({
85
103
  wrapHeaderText = true,
86
104
  opened,
87
105
  title,
88
- withOverlay = true,
89
106
  withCloseButton = true,
90
107
  onClose,
91
108
  children,
92
109
  ...rest
93
110
  }: PanelProps) {
94
111
  const sanitizedProps = filterStylingProps(rest, overStyled);
112
+ const isOpen = Boolean(opened);
113
+ const openerRef = useRef<HTMLElement | null>(null);
114
+ const onCloseRef = useRef(onClose);
115
+ onCloseRef.current = onClose;
116
+
117
+ // Non-modal: there is no Modal to handle Escape or focus restoration, so do both here.
118
+ useEffect(() => {
119
+ if (!isOpen) return;
120
+ openerRef.current = document.activeElement as HTMLElement | null;
121
+ const onKeyDown = (e: KeyboardEvent) => {
122
+ if (e.key === "Escape") {
123
+ onCloseRef.current?.(
124
+ e as unknown as React.SyntheticEvent,
125
+ "escapeKeyDown",
126
+ );
127
+ }
128
+ };
129
+ document.addEventListener("keydown", onKeyDown);
130
+ return () => {
131
+ document.removeEventListener("keydown", onKeyDown);
132
+ const opener = openerRef.current;
133
+ if (opener && opener.isConnected) opener.focus();
134
+ openerRef.current = null;
135
+ };
136
+ }, [isOpen]);
95
137
 
96
138
  // MUI Drawer's `classes` prop only recognizes its own slot names (`root`, `paper`,
97
139
  // `docked`, ...) — unlike Mantine's `classNames`, it has no `content`/`header`/`title`/`body`
@@ -113,10 +155,10 @@ const PanelBase = function Panel({
113
155
  <MuiDrawer
114
156
  anchor={placement} /* Recursica default: right; Mui default: left */
115
157
  keepMounted={keepMounted}
116
- open={Boolean(opened)}
117
- onClose={onClose}
118
- hideBackdrop={!withOverlay}
158
+ open={isOpen}
119
159
  {...(sanitizedProps as unknown as MuiDrawerProps)}
160
+ /* Always non-modal: persistent variant has no backdrop, focus trap, scroll lock or aria-modal */
161
+ variant="persistent"
120
162
  classes={mergedClassNames as unknown as MuiDrawerProps["classes"]}
121
163
  >
122
164
  <div
@@ -74,6 +74,8 @@
74
74
 
75
75
  .sliderRoot {
76
76
  width: 100%;
77
+ /* MUI defaults the root to 4px, so the thumb overflows and the block collapses; match the thumb height. */
78
+ height: var(--recursica_ui-kit_components_slider_properties_thumb-size);
77
79
  box-sizing: border-box;
78
80
  color: inherit;
79
81
  font-family: inherit;
@@ -84,6 +86,7 @@
84
86
 
85
87
  .sliderTrack {
86
88
  height: var(--recursica_ui-kit_components_slider_properties_track-height);
89
+ opacity: 1; /* MUI fades the rail to 0.38 by default, which washes out the token color */
87
90
  border-radius: var(
88
91
  --recursica_ui-kit_components_slider_properties_track-border-radius
89
92
  );
@@ -249,6 +252,14 @@
249
252
  display: flex !important;
250
253
  align-items: center !important;
251
254
  justify-content: center !important;
255
+
256
+ /* The transform override above defeats MUI's scale(0) hiding, so hide until MUI marks it open. */
257
+ opacity: 0;
258
+ pointer-events: none;
259
+ }
260
+
261
+ .sliderTooltip:global(.MuiSlider-valueLabelOpen) {
262
+ opacity: 1;
252
263
  }
253
264
 
254
265
  .sliderTooltip * {
@@ -18,3 +18,15 @@ accepts any string since `@recursica/adapter-common` 1.2.0). In development, `Te
18
18
  if absent it logs one `console.error` per name and sets `data-typography-missing`, which
19
19
  `Typography.module.css` hides with `visibility: hidden`. The attribute is never set when
20
20
  `NODE_ENV === "production"`.
21
+
22
+ ## Text must never render `h1`-`h6` (Matt Massey, 2026-10-08)
23
+
24
+ **Decision:** `Text` must never render an `<h1>`-`<h6>` element. It is not allowed. Semantic
25
+ headings use `Heading`.
26
+
27
+ **Implementation:** `Text` covers every other kind of text in the system (body, labels, captions,
28
+ etc.). Its variants can extend what the Recursica JSON and CSS define, so a variant need not
29
+ exist in the Recursica tokens. Heading levels are the one thing `Text` can't be: they have a
30
+ fixed definition and styling from Recursica and Forge, owned by `Heading`. `Text.tsx` throws
31
+ `Text cannot render <hN>. Use <Heading> for semantic h1-h6.` when `component` (or
32
+ `variantMapping.inherit`, which MUI uses to pick the element) is `h1`-`h6`.
@@ -0,0 +1,54 @@
1
+ import React from "react";
2
+ import { describe, it, expect, vi } from "vitest";
3
+ import { createRoot } from "react-dom/client";
4
+ import { flushSync } from "react-dom";
5
+ import { Text } from "./Text";
6
+
7
+ class Boundary extends React.Component<
8
+ { children: React.ReactNode },
9
+ { message: string | null }
10
+ > {
11
+ state = { message: null as string | null };
12
+ static getDerivedStateFromError(error: Error) {
13
+ return { message: error.message };
14
+ }
15
+ render() {
16
+ return this.state.message ?? this.props.children;
17
+ }
18
+ }
19
+
20
+ function render(props: Record<string, unknown>): HTMLElement {
21
+ const container = document.createElement("div");
22
+ document.body.appendChild(container);
23
+ flushSync(() =>
24
+ createRoot(container).render(
25
+ <Boundary>
26
+ <Text {...(props as object)}>Content</Text>
27
+ </Boundary>,
28
+ ),
29
+ );
30
+ return container;
31
+ }
32
+
33
+ describe("Text heading elements", () => {
34
+ it.each(["h1", "h2", "h3", "h4", "h5", "h6"])(
35
+ "throws when component is %s",
36
+ (component) => {
37
+ vi.spyOn(console, "error").mockImplementation(() => {});
38
+ expect(render({ component }).textContent).toContain(
39
+ `Text cannot render <${component}>. Use <Heading> for semantic h1-h6.`,
40
+ );
41
+ },
42
+ );
43
+
44
+ it("throws when variantMapping maps to a heading", () => {
45
+ vi.spyOn(console, "error").mockImplementation(() => {});
46
+ expect(render({ variantMapping: { inherit: "h2" } }).textContent).toContain(
47
+ "Text cannot render <h2>.",
48
+ );
49
+ });
50
+
51
+ it.each(["p", "span", "label"])("renders component=%s", (component) => {
52
+ expect(render({ component }).querySelector(component)).not.toBeNull();
53
+ });
54
+ });
@@ -11,10 +11,26 @@ export type TextProps = RecursicaOverStyled<
11
11
  "color"
12
12
  >;
13
13
 
14
+ const HEADING_ELEMENTS = ["h1", "h2", "h3", "h4", "h5", "h6"];
15
+
14
16
  export const Text = forwardRef<HTMLElement, TextProps>(function Text(
15
17
  { variant = "body", emphasis = "high", color = "default", ...rest },
16
18
  ref,
17
19
  ) {
20
+ // Text never renders semantic h1-h6; those belong to Heading. MUI picks the element from
21
+ // `component`, or (for variant "inherit") from `variantMapping.inherit`, so check both.
22
+ const { component, variantMapping } = rest as {
23
+ component?: unknown;
24
+ variantMapping?: Record<string, unknown>;
25
+ };
26
+ for (const element of [component, variantMapping?.inherit]) {
27
+ if (typeof element === "string" && HEADING_ELEMENTS.includes(element)) {
28
+ throw new Error(
29
+ `Text cannot render <${element}>. Use <Heading> for semantic h1-h6.`,
30
+ );
31
+ }
32
+ }
33
+
18
34
  // Dev only: an unknown variant hides the text (and logs) instead of silently rendering with the
19
35
  // UI kit's default styling.
20
36
  const typographyMissing =
@@ -1,148 +0,0 @@
1
- /**
2
- * commonArgTypes.ts
3
- *
4
- * This file centralizes the standard Storybook Controls (ArgTypes) for all UI Kit
5
- * components that natively wrap or extend the `FormControlWrapper`.
6
- *
7
- * PHILOSOPHY:
8
- * Recursica ensures strict unified design boundaries across all form inputs (TextField,
9
- * CheckboxGroup, Dropdown, etc.). Because they all share the exact same label structures,
10
- * layout variants (stacked vs side-by-side), and assistive text bindings natively supplied
11
- * by the `FormControlWrapper`, their Storybook experiences should be exactly identical.
12
- *
13
- * USAGE:
14
- * Rather than recreating these controls inside every `Component.stories.tsx` file,
15
- * developers must spread this object directly into the `argTypes` of their story default block:
16
- *
17
- * ```tsx
18
- * import { formControlArgTypes } from "../../.storybook/commonArgTypes";
19
- *
20
- * export default {
21
- * component: TextField,
22
- * argTypes: {
23
- * ...formControlArgTypes,
24
- * // Component-specific argTypes below...
25
- * }
26
- * }
27
- * ```
28
- */
29
- import type { ArgTypes } from "@storybook/react";
30
-
31
- export const formControlArgTypes: Partial<ArgTypes> = {
32
- formLayout: {
33
- control: "inline-radio",
34
- options: ["stacked", "side-by-side"],
35
- description:
36
- "Determines the structural flow layout of the Label relative to the Input.",
37
- table: {
38
- category: "Form Layout",
39
- },
40
- },
41
- labelSize: {
42
- control: "inline-radio",
43
- options: ["default", "small"],
44
- description:
45
- "Adjusts the typographical boundaries bounding the Label section.",
46
- table: {
47
- category: "Form Layout",
48
- },
49
- },
50
- labelAlignment: {
51
- control: "inline-radio",
52
- options: ["left", "right"],
53
- description:
54
- "Adjusts the explicit text alignment axis exclusively evaluating side-by-side structures.",
55
- table: {
56
- category: "Form Layout",
57
- },
58
- },
59
- labelOptionalText: {
60
- control: "text",
61
- description:
62
- "Optional secondary stylistic text injected alongside the primary Label node.",
63
- table: {
64
- category: "Form Layout",
65
- },
66
- },
67
- labelWithEditIcon: {
68
- control: "boolean",
69
- description:
70
- "Dynamically toggles interactivity hooks revealing the Edit context icon.",
71
- table: {
72
- category: "Form Layout",
73
- },
74
- },
75
- description: {
76
- table: {
77
- disable: true,
78
- },
79
- },
80
- assistiveText: {
81
- control: "text",
82
- description:
83
- "Helper instructions safely dynamically anchored below the input box natively outperforming description.",
84
- table: {
85
- category: "Form Layout",
86
- },
87
- },
88
- assistiveWithIcon: {
89
- control: "boolean",
90
- description:
91
- "Toggles native Recursica Info-styling rendering universally alongside the assistive block.",
92
- table: {
93
- category: "Form Layout",
94
- },
95
- },
96
- error: {
97
- control: "text",
98
- description:
99
- "Dynamically maps error feedback validation strings rendering explicit error states.",
100
- table: {
101
- category: "Form State",
102
- },
103
- },
104
- required: {
105
- control: "boolean",
106
- description:
107
- "Native DOM compliance flag explicitly marking the field as required natively.",
108
- table: {
109
- category: "Form State",
110
- },
111
- },
112
- disabled: {
113
- control: "boolean",
114
- description:
115
- "Globally disables interactive components bounding all click and focus logic natively.",
116
- table: {
117
- category: "Form State",
118
- },
119
- },
120
- withAsterisk: {
121
- control: "boolean",
122
- description:
123
- "Visually forces the mandatory asterisk presence completely independent of logical 'required' attribute properties.",
124
- table: {
125
- category: "Form State",
126
- },
127
- },
128
- labelActionArea: {
129
- table: {
130
- disable: true,
131
- },
132
- },
133
- onLabelEditClick: {
134
- table: {
135
- disable: true,
136
- },
137
- },
138
- controlMaxWidth: {
139
- table: {
140
- disable: true,
141
- },
142
- },
143
- controlMinWidth: {
144
- table: {
145
- disable: true,
146
- },
147
- },
148
- };