form-fields.stories.js 13 KB

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