From 8f6306da3c79828857a1f45197759d0747dc4d10 Mon Sep 17 00:00:00 2001 From: komalSharma225 Date: Thu, 4 Jun 2026 21:12:50 +0530 Subject: [PATCH 1/4] BAH-4747 | Add autodocs and metadata wiring to composite control stories - Wire metadata (description + argTypes) to ObsControl, AbnormalObsControl, Section, MultiSelect, Forms stories - Add tags: ['autodocs'] for auto-generated professional documentation (Carbon Design System style) - Refactor StoryWrapper with optional showDebug prop (default false) for clean views - Add MDX support to Storybook config - Create _meta/*.js files with reusable control metadata and prop descriptions - Remove unused React import in Section.stories.js AC met: #2 (descriptions), #3 (argTypes), #4 (autodocs), #5 (clean default), #7 (all 5 controls) Note: AC #1 (sidebar rename to "Composite Controls") skipped per user direction to keep "Complex Controls" Co-Authored-By: Claude Sonnet 4.6 --- .storybook/main.js | 2 +- stories/AbnormalObsControl.stories.js | 9 +- stories/Forms.stories.js | 19 +--- stories/MultiSelect.stories.js | 9 +- stories/ObsControl.stories.js | 30 +----- stories/Section.stories.js | 35 +------ stories/StoryWrapper.js | 19 +++- stories/_meta/abnormalObsControlMeta.js | 81 ++++++++++++++++ stories/_meta/formsMeta.js | 102 ++++++++++++++++++++ stories/_meta/multiSelectMeta.js | 63 ++++++++++++ stories/_meta/obsControlMeta.js | 122 ++++++++++++++++++++++++ stories/_meta/sectionMeta.js | 90 +++++++++++++++++ 12 files changed, 499 insertions(+), 82 deletions(-) create mode 100644 stories/_meta/abnormalObsControlMeta.js create mode 100644 stories/_meta/formsMeta.js create mode 100644 stories/_meta/multiSelectMeta.js create mode 100644 stories/_meta/obsControlMeta.js create mode 100644 stories/_meta/sectionMeta.js diff --git a/.storybook/main.js b/.storybook/main.js index fae84149..74e7d277 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -1,7 +1,7 @@ const path = require('path'); module.exports = { - stories: ['../stories/**/*.stories.js'], + stories: ['../stories/**/*.stories.js', '../stories/**/*.mdx'], addons: [ '@storybook/addon-essentials', '@storybook/addon-interactions', diff --git a/stories/AbnormalObsControl.stories.js b/stories/AbnormalObsControl.stories.js index 316b043a..36e75fbb 100644 --- a/stories/AbnormalObsControl.stories.js +++ b/stories/AbnormalObsControl.stories.js @@ -6,18 +6,19 @@ import { List } from 'immutable'; import StoryWrapper from './StoryWrapper'; import { registerCoreComponents } from './componentRegistry'; import { pulseDataMetadata } from './mockData'; +import { description, argTypes } from './_meta/abnormalObsControlMeta'; registerCoreComponents(); export default { title: 'Complex Controls/AbnormalObsControl', + component: ObsGroupControl, + tags: ['autodocs'], + argTypes, parameters: { docs: { description: { - component: - 'AbnormalObsControl demonstrates an ObsGroup that pairs a numeric observation with a ' + - 'Boolean "Abnormal" toggle button. The toggle is rendered inline using the Button display ' + - 'type and lets clinicians flag an out-of-range reading without leaving the field.', + component: description, }, }, }, diff --git a/stories/Forms.stories.js b/stories/Forms.stories.js index fa28e19a..60969b37 100644 --- a/stories/Forms.stories.js +++ b/stories/Forms.stories.js @@ -3,6 +3,7 @@ import StoryWrapper from './StoryWrapper'; import { Container } from 'src/components/Container.jsx'; import { runEventScript } from 'src/helpers/runEventScript'; import { SYSTOLIC_UUID, DIASTOLIC_UUID } from './mockData'; +import { description, argTypes } from './_meta/formsMeta'; const form = { id: 1, @@ -163,23 +164,13 @@ const obsList = [ export default { title: 'Example Forms/Lifecycle & Events', + component: Container, + tags: ['autodocs'], + argTypes, parameters: { docs: { description: { - component: ` -A guided tour of the form lifecycle. Each story documents one event or method exposed -by the form engine and shows it working on a real form. - -**Stories on this page:** - -- **Basic Data Binding** — foundation: how the Container renders pre-populated observations. -- **Form Lifecycle Demo** — all six lifecycle events on one interactive form with a live - Event Log: onFormInit, onValueChange, onValueUpdated, getValue(), onFormSave, Submit/Reset. -- **Event Flow Diagram** — the complete init → change → submit → post-save timeline. -- **Handler Templates** — copy-pasteable handler snippets for the most common patterns. -- **Accessibility for Events** — keyboard and assistive-technology considerations when - events update the form dynamically. - `, + component: description, }, }, }, diff --git a/stories/MultiSelect.stories.js b/stories/MultiSelect.stories.js index 47d345dc..f45f50c3 100644 --- a/stories/MultiSelect.stories.js +++ b/stories/MultiSelect.stories.js @@ -1,6 +1,7 @@ import React from 'react'; import StoryWrapper from './StoryWrapper'; import { Container } from 'src/components/Container.jsx'; +import { description, argTypes } from './_meta/multiSelectMeta'; const form = { id: 1, @@ -321,13 +322,13 @@ const obsList = [ export default { title: 'Atomic Controls/MultiSelect', + component: Container, + tags: ['autodocs'], + argTypes, parameters: { docs: { description: { - component: - 'Demonstrates a form containing a multi-select coded observation (Tuberculosis Comorbidity). ' + - 'Multi-select obs allow clinicians to choose multiple answers for a single concept and store ' + - 'each answer as a separate observation record.', + component: description, }, }, }, diff --git a/stories/ObsControl.stories.js b/stories/ObsControl.stories.js index 1666cd32..26d3cbea 100644 --- a/stories/ObsControl.stories.js +++ b/stories/ObsControl.stories.js @@ -3,6 +3,7 @@ import { ObsControlWithIntl as ObsControl } from 'src/components/ObsControl.jsx' import StoryWrapper from './StoryWrapper'; import '../styles/styles.scss'; import { SYSTOLIC_UUID, DIASTOLIC_UUID } from './mockData'; +import { description, argTypes } from './_meta/obsControlMeta'; const form = { controls: [ @@ -106,35 +107,12 @@ const emptyValue = { value: undefined, comment: undefined, interpretation: undef export default { title: 'Complex Controls/ObsControl', component: ObsControl, - argTypes: { - validate: { control: 'boolean', description: 'Trigger field-level validation' }, - validateForm: { control: 'boolean', description: 'Trigger form-level validation' }, - onValueChanged: { action: 'onValueChanged' }, - showNotification: { action: 'showNotification' }, - onControlAdd: { action: 'onControlAdd' }, - onControlRemove: { action: 'onControlRemove' }, - }, + tags: ['autodocs'], + argTypes, parameters: { docs: { description: { - component: - 'ObsControl is the primary observation control that binds a single concept to a form field. ' + - 'It wraps the underlying input widget (NumericBox, TextBox, BooleanControl, CodedControl, etc.) ' + - 'based on the concept datatype resolved at render time via componentStore.\n\n' + - '**Concept binding**: The `metadata.concept` object identifies which OpenMRS concept is being ' + - 'captured. The `concept.datatype` drives which widget renders (Numeric → NumericBox, ' + - 'Text → TextBox, Boolean → BooleanControl / Button, Coded → AutoComplete or DropDown).\n\n' + - '**Value wrapping**: ObsControl receives and emits values as `{ value, comment, interpretation }` ' + - 'objects. When a user changes the input the `onValueChanged(formFieldPath, value, errors)` ' + - 'callback is fired with the updated wrapped value so the parent Container can update its ' + - 'ControlRecordTree.\n\n' + - '**Add More**: When `properties.addMore` is true, the control renders Add / Remove buttons ' + - 'via AddMoreDecorator, allowing the clinician to capture repeated observations for the same ' + - 'concept within a single encounter.\n\n' + - 'Accessibility (WCAG 2.1 AA): Each input is associated with a `