form-fields.stories.js 12 KB

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