Skip to content
194 changes: 114 additions & 80 deletions apps/vr-tests-react-components/src/stories/Field.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
CheckboxField,
ComboboxField,
InputField,
InputFieldProps,
ProgressField,
RadioGroupField,
SelectField,
Expand All @@ -16,85 +15,120 @@ import {
TextareaField,
} from '@fluentui/react-field';
import { SparkleFilled } from '@fluentui/react-icons';
import { FieldComponent, FieldPropsWithOptionalComponentProps } from '@fluentui/react-field/src/Field';

const AllFields = (
props: Pick<
InputFieldProps,
'orientation' | 'required' | 'label' | 'validationState' | 'validationMessage' | 'validationMessageIcon' | 'hint'
>,
) => {
return (
<div style={{ display: 'grid', rowGap: '12px' }}>
<CheckboxField label="Checkbox" {...props} />
<ComboboxField label="Combo box field" {...props} />
<InputField label="Input field" {...props} />
<ProgressField label="Progress field" value={0.5} {...props} />
<RadioGroupField label="Radio group field" {...props}>
<Radio label="Option one" />
<Radio label="Option two" />
<Radio label="Option three" />
</RadioGroupField>
<SelectField label="Select field" {...props}>
<option>Option</option>
</SelectField>
<SliderField label="Slider field" {...props} />
<SpinButtonField label="Spin button field" {...props} />
<SwitchField label="Switch field" {...props} />
<TextareaField label="Textarea field" {...props} />
</div>
);
};
type FieldComponentProps = Pick<
FieldPropsWithOptionalComponentProps<FieldComponent>,
'orientation' | 'required' | 'label' | 'validationState' | 'validationMessage' | 'validationMessageIcon' | 'hint'
>;

storiesOf('Field Converged', module)
.addDecorator(story => (
<div style={{ display: 'flex' }}>
<div className="testWrapper" style={{ padding: '10px', width: '480px' }}>
<Screener steps={new Steps().snapshot('default', { cropTo: '.testWrapper' }).end()}>{story()}</Screener>
/**
* Common VR tests for all field components. Pass the given Field component (or a wrapper around it).
*/
const storiesOfField = (name: string, Field: React.VoidFunctionComponent<FieldComponentProps>) =>
storiesOf(name, module)
.addDecorator(story => <Screener steps={new Steps().snapshot('default').end()}>{story()}</Screener>)
.addDecorator(story => (
<div style={{ display: 'flex' }}>
<div className="testWrapper" style={{ padding: '10px', width: '480px' }}>
<Screener steps={new Steps().snapshot('default', { cropTo: '.testWrapper' }).end()}>{story()}</Screener>
</div>
</div>
</div>
))
.addStory('base', () => <AllFields />)
.addStory('required', () => <AllFields required />)
.addStory('validation:error', () => <AllFields validationState="error" validationMessage="Error message" />)
.addStory('validation:warning', () => <AllFields validationState="warning" validationMessage="Warning message" />)
.addStory('validation:success', () => <AllFields validationState="success" validationMessage="Success message" />)
.addStory('validation:custom', () => (
<AllFields validationMessageIcon={<SparkleFilled />} validationMessage="Custom message" />
))
.addStory('hint', () => <AllFields hint="Hint message" />)
.addStory('horizontal', () => <AllFields orientation="horizontal" />)
.addStory('horizontal+label:multiline', () => (
<AllFields
orientation="horizontal"
label="This is a very long label that should wrap around to be multiple lines in height"
/>
))
.addStory('horizontal+validation:error+hint', () => (
<AllFields orientation="horizontal" validationState="error" validationMessage="Error message" hint="Hint text" />
))
.addStory('size:small', () => (
<div style={{ display: 'grid', rowGap: '12px' }}>
<ComboboxField label="Combo box field" size="small" />
<InputField label="Input field" size="small" />
<SelectField label="Select field" size="small">
<option>Option</option>
</SelectField>
<SliderField label="Slider field" size="small" />
<SpinButtonField label="Spin button field" size="small" />
<TextareaField label="Textarea field" size="small" />
</div>
))
.addStory('size:large', () => (
<div style={{ display: 'grid', rowGap: '12px' }}>
<CheckboxField label="Checkbox" size="large" />
<ComboboxField label="Combo box field" size="large" />
<InputField label="Input field" size="large" />
<SelectField label="Select field" size="large">
<option>Option</option>
</SelectField>
<TextareaField label="Textarea field" size="large" />
</div>
))
.addStory('CheckboxField+fieldLabel', () => (
<CheckboxField label="Label for the checkbox" fieldLabel="Field label" required />
));
))
.addStory('base', () => <Field label="Example field" />)
.addStory('required', () => <Field label="Example field" required />)
.addStory('validation', () => (
<div style={{ display: 'grid', rowGap: '10px' }}>
<Field label="Validation error" validationState="error" validationMessage="Error message" />
<Field label="Validation warning" validationState="warning" validationMessage="Warning message" />
<Field label="Validation success" validationState="success" validationMessage="Success message" />
<Field
label="Custom validation state"
validationMessageIcon={<SparkleFilled />}
validationMessage="Custom message"
/>
</div>
))
.addStory('hint', () => <Field label="Example field" hint="Hint message" />)
.addStory('horizontal', () => (
<Field
label="This is a very long label that should wrap around to be multiple lines in height"
orientation="horizontal"
validationState="error"
validationMessage="Error message"
hint="Hint text"
/>
));

/**
* Same as storiesOfField, but with extra stories for Field components that support the size prop.
*/
const storiesOfFieldWithSize = (
name: string,
Field: React.VoidFunctionComponent<FieldComponentProps & { size?: 'small' | 'medium' | 'large' }>,
) =>
storiesOfField(name, Field)
.addStory('size:small', () => <Field label="Example field" size="small" />)
.addStory('size:large', () => <Field label="Example field" size="large" />);

//
// CheckboxField
//
storiesOfField('CheckboxField converged', CheckboxField)
.addStory('size:large', () => <CheckboxField label="Example field" size="large" />)
.addStory('fieldLabel', () => <CheckboxField label="Label for the checkbox" fieldLabel="Field label" required />);

//
// ComboboxField
//
storiesOfFieldWithSize('ComboboxField converged', ComboboxField);

//
// InputField
//
storiesOfFieldWithSize('InputField converged', InputField);

//
// ProgressField
//
storiesOfField('ProgressField converged', props => <ProgressField value={0.5} {...props} />);

//
// RadioGroupField
//
storiesOfField('RadioGroupField converged', props => (
<RadioGroupField {...props}>
<Radio label="Option one" />
<Radio label="Option two" />
<Radio label="Option three" />
</RadioGroupField>
));

//
// SelectField
//
storiesOfFieldWithSize('SelectField converged', props => (
<SelectField {...props}>
<option>Option one</option>
</SelectField>
));

//
// SliderField
//
storiesOfField('SliderField converged', SliderField);

//
// SpinButtonField
//
storiesOfField('SpinButtonField converged', SpinButtonField);

//
// SwitchField
//
storiesOfField('SwitchField converged', SwitchField);

//
// TextareaField
//
storiesOfFieldWithSize('TextareaField converged', TextareaField);