form-fields.stories.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516
  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. menuTitle: '',
  332. isSearchable: false,
  333. isDisabled: false,
  334. isClearable: false,
  335. isLoading: false,
  336. multiple: false,
  337. placeholder: 'Search…',
  338. closeOnSelect: true,
  339. shouldCloseOnBlur: true,
  340. isDismissable: true,
  341. offset: 8,
  342. crossOffset: 0,
  343. containerPadding: 8,
  344. placement: 'bottom left',
  345. triggerProps: {
  346. prefix: 'Prefix',
  347. },
  348. };
  349. CompactSelectField.argTypes = {
  350. placement: {
  351. options: [
  352. 'top',
  353. 'bottom',
  354. 'left',
  355. 'right',
  356. 'top left',
  357. 'top right',
  358. 'bottom left',
  359. 'bottom right',
  360. 'left top',
  361. 'left bottom',
  362. 'right top',
  363. 'right bottom',
  364. ],
  365. control: {type: 'radio'},
  366. },
  367. };
  368. export const CompositeSelectField = props => (
  369. <CompositeSelect
  370. sections={[
  371. {
  372. label: 'Group 1',
  373. value: 'group_1',
  374. defaultValue: 'choice_one',
  375. options: [
  376. {value: 'choice_one', label: 'Choice One'},
  377. {value: 'choice_two', label: 'Choice Two'},
  378. ],
  379. },
  380. {
  381. label: 'Group 2',
  382. value: 'group_2',
  383. defaultValue: ['choice_three'],
  384. multiple: true,
  385. options: [
  386. {value: 'choice_three', label: 'Choice Three'},
  387. {value: 'choice_four', label: 'Choice Four'},
  388. ],
  389. },
  390. ]}
  391. {...props}
  392. />
  393. );
  394. CompositeSelectField.storyName = 'Select - Composite';
  395. CompositeSelectField.args = {...CompactSelectField.args};
  396. delete CompositeSelectField.args.multiple;
  397. CompositeSelectField.argTypes = CompactSelectField.argTypes;
  398. export const NonInlineField = () => (
  399. <Form>
  400. <FormField name="radio" label="Radio Field" inline={false}>
  401. {({value, label, onChange}) => (
  402. <RadioGroup
  403. onChange={onChange}
  404. label={label}
  405. value={value}
  406. choices={[
  407. ['choice_one', 'Choice One', 'Description for Choice One'],
  408. ['choice_two', 'Choice Two', 'Description for Choice Two'],
  409. ['choice_three', 'Choice Three'],
  410. ]}
  411. />
  412. )}
  413. </FormField>
  414. </Form>
  415. );
  416. NonInlineField.storyName = 'Non-inline';
  417. NonInlineField.parameters = {
  418. docs: {
  419. description: {
  420. story: 'Radio Group used w/ FormField',
  421. },
  422. },
  423. };
  424. export const _RangeSlider = () => (
  425. <div style={{backgroundColor: '#fff', padding: 20}}>
  426. <RangeSlider
  427. name="rangeField"
  428. min={1}
  429. max={10}
  430. step={1}
  431. value={1}
  432. formatLabel={value => {
  433. return `${value} Toaster Strudle${value > 1 ? 's' : ''}`;
  434. }}
  435. />
  436. </div>
  437. );
  438. _RangeSlider.storyName = 'Range Slider';
  439. export const WithoutAParentForm = ({onChange}) => {
  440. return (
  441. <div>
  442. <TextField
  443. name="simpletextfield"
  444. label="Simple Text Field"
  445. placeholder="Simple Text Field"
  446. onChange={onChange}
  447. />
  448. <NewBooleanField name="field" label="New Boolean Field" onChange={onChange} />
  449. <RadioField
  450. name="radio"
  451. label="Radio Field"
  452. onChange={onChange}
  453. choices={[
  454. ['choice_one', 'Choice One'],
  455. ['choice_two', 'Choice Two'],
  456. ['choice_three', 'Choice Three'],
  457. ]}
  458. />
  459. <Switch id="test" />
  460. </div>
  461. );
  462. };
  463. WithoutAParentForm.storyName = 'Without a Parent Form';
  464. WithoutAParentForm.argTypes = {
  465. onChange: {action: 'onChange'},
  466. };
  467. WithoutAParentForm.parameters = {
  468. docs: {
  469. description: {
  470. story: 'New form fields used without having a parent Form',
  471. },
  472. },
  473. };
  474. export const __TextCopyInput = () => (
  475. <TextCopyInput onCopy={action('Copied!')}>Value to be copied </TextCopyInput>
  476. );
  477. __TextCopyInput.storyName = 'Text Copy';