form-fields.stories.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521
  1. import {action} from '@storybook/addon-actions';
  2. import NewBooleanField from 'sentry/components/forms/booleanField';
  3. import CheckboxField from 'sentry/components/forms/checkboxField';
  4. import CompactSelect from 'sentry/components/forms/compactSelect';
  5. import CompositeSelect from 'sentry/components/forms/compositeSelect';
  6. import RadioGroup from 'sentry/components/forms/controls/radioGroup';
  7. import RangeSlider from 'sentry/components/forms/controls/rangeSlider';
  8. import DatePickerField from 'sentry/components/forms/datePickerField';
  9. import FileField from 'sentry/components/forms/fileField';
  10. import Form from 'sentry/components/forms/form';
  11. import FormField from 'sentry/components/forms/formField';
  12. import MultipleCheckboxField from 'sentry/components/forms/MultipleCheckboxField';
  13. import RadioBooleanField from 'sentry/components/forms/radioBooleanField';
  14. import RadioField from 'sentry/components/forms/radioField';
  15. import SelectField from 'sentry/components/forms/selectField';
  16. import TextareaField from 'sentry/components/forms/textareaField';
  17. import TextCopyInput from 'sentry/components/forms/textCopyInput';
  18. import TextField from 'sentry/components/forms/textField';
  19. import {Panel} from 'sentry/components/panels';
  20. import Switch from 'sentry/components/switchButton';
  21. export default {
  22. title: 'Components/Forms/Fields',
  23. };
  24. export const _TextField = () => (
  25. <Panel>
  26. <Form initialData={{context: {location: 'cat'}}}>
  27. <TextField
  28. name="simpletextfieldvalue"
  29. label="Simple Text Field with Value"
  30. placeholder="Simple Text Field"
  31. defaultValue="With a value present"
  32. />
  33. <TextField
  34. name="simpletextfieldplaceholder"
  35. label="Simple Text Field with Placeholder"
  36. placeholder="This is placeholder text"
  37. />
  38. <TextField
  39. name="simpletextfieldvaluedisabled"
  40. label="Disabled - Simple Text Field with Value"
  41. placeholder="Simple Text Field"
  42. defaultValue="With a value present"
  43. disabled
  44. />
  45. <TextField
  46. name="simpletextfieldplaceholderdisabled"
  47. label="Disabled - Simple Text Field with Placeholder"
  48. placeholder="This is placeholder text in a disabled field"
  49. disabled
  50. />
  51. <TextField
  52. name="textfieldwithreturnsubmit"
  53. label="Text Field With Return Submit"
  54. placeholder="Type here to show the return button"
  55. showReturnButton
  56. />
  57. <TextField
  58. name="textfieldflexiblecontrol"
  59. label="Text Field With Flexible Control State Size"
  60. placeholder="Type text and then delete it"
  61. required
  62. flexibleControlStateSize
  63. />
  64. <TextField
  65. name="textfielddisabled"
  66. label="Text field with disabled reason"
  67. placeholder="I am disabled"
  68. disabled
  69. disabledReason="This is the reason this field is disabled"
  70. />
  71. </Form>
  72. </Panel>
  73. );
  74. _TextField.storyName = 'Text';
  75. _TextField.parameters = {
  76. docs: {
  77. description: {
  78. story: 'Simple text field',
  79. },
  80. },
  81. };
  82. export const _TextareaField = ({autosize, rows}) => (
  83. <Panel>
  84. <Form initialData={{context: {location: 'cat'}}}>
  85. <TextareaField
  86. name="simpletextfieldvalue"
  87. label="Simple Textarea Field with Value"
  88. help="Additional help text"
  89. placeholder="Simple Textarea Field"
  90. defaultValue="With a value present"
  91. />
  92. <TextareaField
  93. name="simpletextfieldautosize"
  94. autosize={autosize}
  95. label="Textarea field with autosize"
  96. rows={rows}
  97. placeholder="Use knobs to control rows and autosize setting"
  98. />
  99. <TextareaField
  100. name="simpletextfieldvaluedisabled"
  101. label="Disabled - Simple Textarea Field with Value"
  102. placeholder="Simple Textarea Field"
  103. defaultValue="With a value present"
  104. disabled
  105. />
  106. <TextareaField
  107. name="simpletextfieldplaceholderdisabled"
  108. label="Disabled - Simple Textarea Field with Placeholder"
  109. placeholder="This is placeholder text in a disabled field"
  110. disabled
  111. />
  112. <TextareaField
  113. name="textfieldwithreturnsubmit"
  114. label="Textarea Field With Return Submit"
  115. placeholder="Type here to show the return button"
  116. showReturnButton
  117. />
  118. <TextareaField
  119. name="textfieldflexiblecontrol"
  120. label="Textarea Field With Flexible Control State Size"
  121. placeholder="Type text and then delete it"
  122. required
  123. flexibleControlStateSize
  124. />
  125. <TextareaField
  126. name="textfielddisabled"
  127. label="Textarea Field with disabled reason"
  128. placeholder="I am disabled"
  129. disabled
  130. disabledReason="This is the reason this field is disabled"
  131. />
  132. <TextareaField
  133. name="textareafielderror"
  134. label="Textarea Field with error"
  135. placeholder="I have an error"
  136. error="An error has occurred"
  137. />
  138. </Form>
  139. </Panel>
  140. );
  141. _TextareaField.storyName = 'Textarea';
  142. _TextareaField.args = {
  143. autosize: true,
  144. rows: 1,
  145. };
  146. export const __BooleanField = () => (
  147. <Form>
  148. <NewBooleanField name="field" label="New Boolean Field" />
  149. </Form>
  150. );
  151. __BooleanField.storyName = 'Boolean';
  152. export const _CheckboxField = () => (
  153. <Form>
  154. <CheckboxField key="agree" name="agree" id="agree" label="Do you agree?" />
  155. <CheckboxField
  156. key="compelled"
  157. name="compelled"
  158. id="compelled"
  159. label="You are compelled to agree"
  160. help="More content to help you decide."
  161. required
  162. />
  163. </Form>
  164. );
  165. _CheckboxField.storyName = 'Checkbox';
  166. export const _MultipleCheckboxField = () => (
  167. <Form>
  168. <MultipleCheckboxField
  169. choices={[
  170. {title: 'Checkbox', value: 0},
  171. {title: 'Disabled Checkbox', value: 1},
  172. {title: 'Checked Checkbox', value: 2, checked: true},
  173. {title: 'Intermediate Checkbox', value: 3, intermediate: true},
  174. {title: 'Disabled Checked Checkbox', value: 4, checked: true, disabled: true},
  175. {
  176. title: 'Disabled Intermediate Checkbox',
  177. value: 5,
  178. intermediate: true,
  179. disabled: true,
  180. },
  181. ]}
  182. />
  183. </Form>
  184. );
  185. _MultipleCheckboxField.storyName = 'MultipleCheckbox';
  186. export const _DatePickerField = () => (
  187. <Form>
  188. <DatePickerField name="field" label="Date Picker Field" />
  189. </Form>
  190. );
  191. _DatePickerField.storyName = 'Datepicker';
  192. export const _RadioField = () => (
  193. <Form>
  194. <RadioField
  195. name="radio"
  196. label="Radio Field"
  197. choices={[
  198. ['choice_one', 'Choice One'],
  199. ['choice_two', 'Choice Two'],
  200. ['choice_three', 'Choice Three'],
  201. ]}
  202. />
  203. <RadioField
  204. orientInline
  205. name="inline-radio"
  206. label="Inline Radios"
  207. choices={[
  208. ['choice_one', 'Choice One'],
  209. ['choice_two', 'Choice Two'],
  210. ]}
  211. />
  212. </Form>
  213. );
  214. export const __FileField = () => (
  215. <Form>
  216. <FileField name="field" label="File Field" />
  217. </Form>
  218. );
  219. __FileField.storyName = 'File';
  220. _RadioField.storyName = 'Radio';
  221. export const _RadioBooleanField = ({disabled}) => (
  222. <Form>
  223. <RadioBooleanField
  224. name="subscribe"
  225. yesLabel="Yes, I would like to receive updates via email"
  226. noLabel="No, I'd prefer not to receive these updates"
  227. help="Help text for making an informed decision"
  228. disabled={disabled}
  229. />
  230. </Form>
  231. );
  232. _RadioBooleanField.storyName = 'Radio - Boolean';
  233. _RadioBooleanField.args = {
  234. disabled: false,
  235. };
  236. export const _SelectField = () => (
  237. <Form>
  238. <SelectField
  239. name="select"
  240. label="Select Field"
  241. choices={[
  242. ['choice_one', 'Choice One'],
  243. ['choice_two', 'Choice Two'],
  244. ['choice_three', 'Choice Three'],
  245. ]}
  246. />
  247. </Form>
  248. );
  249. _SelectField.storyName = 'Select';
  250. export const SelectFieldMultiple = () => (
  251. <Form>
  252. <SelectField
  253. name="select"
  254. label="Multi Select"
  255. multiple
  256. choices={[
  257. ['choice_one', 'Choice One'],
  258. ['choice_two', 'Choice Two'],
  259. ['choice_three', 'Choice Three'],
  260. ]}
  261. />
  262. </Form>
  263. );
  264. SelectFieldMultiple.storyName = 'Select - Multiple';
  265. export const SelectFieldGrouped = () => (
  266. <Form>
  267. <SelectField
  268. name="select"
  269. label="Grouped Select"
  270. options={[
  271. {
  272. label: 'Group 1',
  273. options: [
  274. {value: 'choice_one', label: 'Choice One'},
  275. {value: 'choice_two', label: 'Choice Two'},
  276. ],
  277. },
  278. {
  279. label: 'Group 2',
  280. options: [
  281. {value: 'choice_three', label: 'Choice Three'},
  282. {value: 'choice_four', label: 'Choice Four'},
  283. ],
  284. },
  285. ]}
  286. />
  287. </Form>
  288. );
  289. SelectFieldGrouped.storyName = 'Select - Grouped';
  290. export const SelectFieldInFieldLabel = () => (
  291. <Form>
  292. <SelectField
  293. name="select"
  294. label="Select With Label In Field"
  295. inFieldLabel="Label: "
  296. choices={[
  297. ['choice_one', 'Choice One'],
  298. ['choice_two', 'Choice Two'],
  299. ['choice_three', 'Choice Three'],
  300. ]}
  301. />
  302. </Form>
  303. );
  304. SelectFieldInFieldLabel.storyName = 'Select - Label in Field';
  305. SelectFieldInFieldLabel.parameters = {
  306. docs: {
  307. description: {
  308. story: 'Select Control w/ Label In Field',
  309. },
  310. },
  311. };
  312. export const CompactSelectField = props => (
  313. <CompactSelect
  314. defaultValue="opt_one"
  315. options={[
  316. {value: 'opt_one', label: 'Option One'},
  317. {value: 'opt_two', label: 'Option Two'},
  318. ]}
  319. {...props}
  320. />
  321. );
  322. CompactSelectField.storyName = 'Select - Compact';
  323. CompactSelectField.parameters = {
  324. docs: {
  325. description: {
  326. story: 'Compact',
  327. },
  328. },
  329. };
  330. CompactSelectField.args = {
  331. size: 'md',
  332. menuTitle: '',
  333. isSearchable: false,
  334. isDisabled: false,
  335. isClearable: false,
  336. isLoading: false,
  337. multiple: false,
  338. placeholder: 'Search…',
  339. closeOnSelect: true,
  340. shouldCloseOnBlur: true,
  341. isDismissable: true,
  342. offset: 8,
  343. crossOffset: 0,
  344. containerPadding: 8,
  345. placement: 'bottom left',
  346. triggerProps: {
  347. prefix: 'Prefix',
  348. },
  349. };
  350. CompactSelectField.argTypes = {
  351. placement: {
  352. options: [
  353. 'top',
  354. 'bottom',
  355. 'left',
  356. 'right',
  357. 'top left',
  358. 'top right',
  359. 'bottom left',
  360. 'bottom right',
  361. 'left top',
  362. 'left bottom',
  363. 'right top',
  364. 'right bottom',
  365. ],
  366. control: {type: 'radio'},
  367. },
  368. size: {
  369. options: ['md', 'sm', 'xs'],
  370. control: {type: 'radio'},
  371. },
  372. };
  373. export const CompositeSelectField = props => (
  374. <CompositeSelect
  375. sections={[
  376. {
  377. label: 'Group 1',
  378. value: 'group_1',
  379. defaultValue: 'choice_one',
  380. options: [
  381. {value: 'choice_one', label: 'Choice One'},
  382. {value: 'choice_two', label: 'Choice Two'},
  383. ],
  384. },
  385. {
  386. label: 'Group 2',
  387. value: 'group_2',
  388. defaultValue: ['choice_three'],
  389. multiple: true,
  390. options: [
  391. {value: 'choice_three', label: 'Choice Three'},
  392. {value: 'choice_four', label: 'Choice Four'},
  393. ],
  394. },
  395. ]}
  396. {...props}
  397. />
  398. );
  399. CompositeSelectField.storyName = 'Select - Composite';
  400. CompositeSelectField.args = {...CompactSelectField.args};
  401. delete CompositeSelectField.args.multiple;
  402. CompositeSelectField.argTypes = CompactSelectField.argTypes;
  403. export const NonInlineField = () => (
  404. <Form>
  405. <FormField name="radio" label="Radio Field" inline={false}>
  406. {({value, label, onChange}) => (
  407. <RadioGroup
  408. onChange={onChange}
  409. label={label}
  410. value={value}
  411. choices={[
  412. ['choice_one', 'Choice One', 'Description for Choice One'],
  413. ['choice_two', 'Choice Two', 'Description for Choice Two'],
  414. ['choice_three', 'Choice Three'],
  415. ]}
  416. />
  417. )}
  418. </FormField>
  419. </Form>
  420. );
  421. NonInlineField.storyName = 'Non-inline';
  422. NonInlineField.parameters = {
  423. docs: {
  424. description: {
  425. story: 'Radio Group used w/ FormField',
  426. },
  427. },
  428. };
  429. export const _RangeSlider = () => (
  430. <div style={{backgroundColor: '#fff', padding: 20}}>
  431. <RangeSlider
  432. name="rangeField"
  433. min={1}
  434. max={10}
  435. step={1}
  436. value={1}
  437. formatLabel={value => {
  438. return `${value} Toaster Strudle${value > 1 ? 's' : ''}`;
  439. }}
  440. />
  441. </div>
  442. );
  443. _RangeSlider.storyName = 'Range Slider';
  444. export const WithoutAParentForm = ({onChange}) => {
  445. return (
  446. <div>
  447. <TextField
  448. name="simpletextfield"
  449. label="Simple Text Field"
  450. placeholder="Simple Text Field"
  451. onChange={onChange}
  452. />
  453. <NewBooleanField name="field" label="New Boolean Field" onChange={onChange} />
  454. <RadioField
  455. name="radio"
  456. label="Radio Field"
  457. onChange={onChange}
  458. choices={[
  459. ['choice_one', 'Choice One'],
  460. ['choice_two', 'Choice Two'],
  461. ['choice_three', 'Choice Three'],
  462. ]}
  463. />
  464. <Switch id="test" />
  465. </div>
  466. );
  467. };
  468. WithoutAParentForm.storyName = 'Without a Parent Form';
  469. WithoutAParentForm.argTypes = {
  470. onChange: {action: 'onChange'},
  471. };
  472. WithoutAParentForm.parameters = {
  473. docs: {
  474. description: {
  475. story: 'New form fields used without having a parent Form',
  476. },
  477. },
  478. };
  479. export const __TextCopyInput = () => (
  480. <TextCopyInput onCopy={action('Copied!')}>Value to be copied </TextCopyInput>
  481. );
  482. __TextCopyInput.storyName = 'Text Copy';