form-fields.stories.js 12 KB

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