Skip to canvas
Proton Design System
/
Introduction
Changelog
Colors
Icons
Layers Management
Responsive
Sass Css Variables
Typography
Alert
Autocomplete
Badge
ButtonGroup
Checkbox
Collapsible
Copy
CountrySelect
DateInput
Details
Dropdown
Dropzone
EllipsisLoader
Errors
Icon
InputButton
InputField
InputFieldStacked
LabelStack
Logo
Meter
MiddleEllipsis
ModalSkip to canvas
Notification
Price
Progress
Promotion Button
QuickSettings
Radio
Scale
Select
Spotlight
Table
Tabs
Toggle
TopBanner
TotpInput
VideoInstructions
Avatar
Banner
Button
Card
CircleLoader
DashboardCard
Donut
Href
InlineLinkButton
Input
Kbd
NotificationDot
Pill
ProtonLoader
Scroll
Slider
Stepper
UserAvatar
VerticalSteps
Vr
Border
Border Radius
Colors
Columns
Cursor
Divide
ExpandClickArea
Gap
HidingDisablingContent
InteractiveFocusHelper
Lists
Margin
Opacity
OpacityOnHover
Padding
Position
Print
Ratio Container
Responsive
Scroll
Shadow
Sizing
Transforms
Typography
  1. Recently opened
  2. Modalcomponents
  3. Back to componentsESC
  4. Clear history
Skip to sidebar
1import { useState } from 'react'; 2 3import { Button } from '@proton/atoms'; 4import type { ModalProps, ModalSize } from '@proton/components'; 5import { 6 BasicModal, 7 Checkbox, 8 Form, 9 Icon, 10 InputFieldTwo, 11 ModalTwo, 12 ModalTwoContent, 13 ModalTwoFooter, 14 ModalTwoHeader, 15 Prompt, 16 RadioGroup, 17 Tooltip, 18 useModalState, 19 useModalStateObject, 20} from '@proton/components'; 21 22import { getTitle } from '../../helpers/title'; 23import mdx from './Modal.mdx'; 24 25export default { 26 component: ModalTwo, 27 subcomponents: { ModalTwoHeader, Prompt }, 28 title: getTitle(__filename, false), 29 parameters: { 30 docs: { 31 page: mdx, 32 }, 33 }, 34}; 35 36export const Example = () => { 37 const [modalProps, handleSetOpen, render] = useModalState(); 38 39 return ( 40 <div className="text-center"> 41 <Button 42 className="mr-2" 43 onClick={() => { 44 handleSetOpen(true); 45 }} 46 > 47 Open modal 48 </Button> 49 {render && ( 50 <ModalTwo {...modalProps}> 51 <ModalTwoHeader title="Example Modal" /> 52 <ModalTwoContent> 53 <p> 54 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 55 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 56 amet qui vero, blanditiis quos? 57 </p> 58 </ModalTwoContent> 59 <ModalTwoFooter> 60 <Button>Secondary action</Button> 61 <Button color="norm">Primary action</Button> 62 </ModalTwoFooter> 63 </ModalTwo> 64 )} 65 </div> 66 ); 67}; 68 69export const Primary = () => { 70 const [size, setSize] = useState<ModalSize>('medium'); 71 const [modalProps, handleSetOpen, render] = useModalState(); 72 73 return ( 74 <div className="text-center"> 75 <Button 76 className="mr-2" 77 onClick={() => { 78 handleSetOpen(true); 79 }} 80 > 81 Open size modal 82 </Button> 83 {render && ( 84 <ModalTwo size={size} {...modalProps}> 85 <ModalTwoHeader title="Size" /> 86 <ModalTwoContent> 87 <p> 88 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 89 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 90 amet qui vero, blanditiis quos? 91 </p> 92 93 <div className="mr-8"> 94 <strong className="block mb-4">Shape</strong> 95 <RadioGroup 96 name="selected-shape" 97 onChange={setSize} 98 value={size} 99 options={(['xsmall', 'small', 'medium', 'large', 'xlarge', 'full'] as const).map( 100 (size) => ({ 101 value: size, 102 label: size, 103 }) 104 )} 105 /> 106 </div> 107 </ModalTwoContent> 108 <ModalTwoFooter> 109 <Button>Secondary action</Button> 110 <Button color="norm">Primary action</Button> 111 </ModalTwoFooter> 112 </ModalTwo> 113 )} 114 </div> 115 ); 116}; 117 118const WrappedFormModal = (props: ModalProps) => { 119 const [name, setName] = useState(''); 120 return ( 121 <ModalTwo {...props}> 122 <ModalTwoHeader title="Title in ModalHeader" subline="Subline in ModalHeader" /> 123 <ModalTwoContent> 124 <p>I will lose any local state of mine after closing.</p> 125 <InputFieldTwo value={name} label="Name" placeholder="e.g. John Fitzgerald..." onValue={setName} /> 126 </ModalTwoContent> 127 <ModalTwoFooter> 128 <Button>Secondary action</Button> 129 <Button color="norm">Primary action</Button> 130 </ModalTwoFooter> 131 </ModalTwo> 132 ); 133}; 134 135export const UsingUseModalState = () => { 136 const [modalProps, handleSetOpen, render] = useModalState(); 137 138 return ( 139 <div className="text-center"> 140 <Button 141 onClick={() => { 142 handleSetOpen(true); 143 }} 144 > 145 Open modal with useModalState 146 </Button> 147 {render && <WrappedFormModal {...modalProps} />} 148 </div> 149 ); 150}; 151 152export const ModalStateObject = () => { 153 const modal = useModalStateObject(); 154 155 return ( 156 <div className="text-center"> 157 <Button 158 className="mr-2" 159 onClick={() => { 160 modal.openModal(true); 161 }} 162 > 163 Open modal 164 </Button> 165 {modal.render && ( 166 <ModalTwo {...modal.modalProps}> 167 <ModalTwoHeader title="Example Modal" /> 168 <ModalTwoContent> 169 <p> 170 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 171 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 172 amet qui vero, blanditiis quos? 173 </p> 174 </ModalTwoContent> 175 <ModalTwoFooter> 176 <Button>Secondary action</Button> 177 <Button color="norm">Primary action</Button> 178 </ModalTwoFooter> 179 </ModalTwo> 180 )} 181 </div> 182 ); 183}; 184 185export const Header = () => { 186 const [modalProps, handleSetOpen, render] = useModalState(); 187 188 return ( 189 <div className="text-center"> 190 <Button 191 onClick={() => { 192 handleSetOpen(true); 193 }} 194 > 195 Open modal with header extras 196 </Button> 197 {render && ( 198 <ModalTwo {...modalProps}> 199 <ModalTwoHeader title="Title in ModalHeader" subline="Subline in ModalHeader" /> 200 <ModalTwoContent> 201 <p className="m-0"> 202 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 203 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 204 amet qui vero, blanditiis quos? 205 </p> 206 </ModalTwoContent> 207 <ModalTwoFooter> 208 <Button>Secondary action</Button> 209 <Button color="norm">Primary action</Button> 210 </ModalTwoFooter> 211 </ModalTwo> 212 )} 213 </div> 214 ); 215}; 216 217export const HeaderActions = () => { 218 const [modalProps, handleSetOpen, render] = useModalState(); 219 220 return ( 221 <div className="text-center"> 222 <Button 223 onClick={() => { 224 handleSetOpen(true); 225 }} 226 > 227 Open actions modal 228 </Button> 229 {render && ( 230 <ModalTwo {...modalProps}> 231 <ModalTwoHeader 232 actions={[ 233 <Tooltip title="Get help"> 234 <Button icon shape="ghost"> 235 <Icon name="question-circle" /> 236 </Button> 237 </Tooltip>, 238 <Tooltip title="Refresh"> 239 <Button icon shape="ghost"> 240 <Icon name="arrows-rotate" /> 241 </Button> 242 </Tooltip>, 243 ]} 244 /> 245 <ModalTwoContent> 246 <p className="m-0"> 247 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 248 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 249 amet qui vero, blanditiis quos? 250 </p> 251 </ModalTwoContent> 252 <ModalTwoFooter> 253 <Button>Secondary action</Button> 254 <Button color="norm">Primary action</Button> 255 </ModalTwoFooter> 256 </ModalTwo> 257 )} 258 </div> 259 ); 260}; 261
262export const ALotOfContent = () => { 263 const [modalProps, handleSetOpen, render] = useModalState(); 264 265 return ( 266 <div className="text-center"> 267 <Button 268 onClick={() => { 269 handleSetOpen(true); 270 }} 271 > 272 Open modal with a lot of content 273 </Button> 274 {render && ( 275 <ModalTwo {...modalProps}> 276 <ModalTwoHeader title="Title in header" /> 277 <ModalTwoContent> 278 <p> 279 Lorem ipsum dolor sit amet consectetur adipisicing elit. Autem, voluptatum deserunt rem amet 280 consectetur perspiciatis placeat error doloribus vero voluptate quisquam numquam expedita, 281 ex maxime quas, nemo labore necessitatibus accusamus. 282 </p> 283 <p> 284 Delectus blanditiis corporis et est exercitationem odio itaque vero! Fugiat sit eius minus! 285 Architecto quibusdam nisi ullam impedit vel repellat amet, molestias, beatae repudiandae 286 quis fugit, qui ea assumenda maxime. 287 </p> 288 <p> 289 Deserunt rerum aspernatur sint placeat natus nisi quas, facere nesciunt quos obcaecati at 290 suscipit hic modi incidunt numquam necessitatibus labore? Maxime nisi repellendus enim cum 291 nostrum. Officiis porro fuga asperiores? 292 </p> 293 <p> 294 Voluptates minus soluta, ullam maxime labore vitae saepe porro mollitia beatae perferendis 295 velit quasi quidem. Similique numquam repellendus nulla adipisci dolore tempore tenetur 296 laudantium. Sed debitis eos odit beatae soluta? 297 </p> 298 <p> 299 Deleniti, dicta velit. Magnam optio rerum esse est nisi neque unde quos, natus quam aperiam 300 dignissimos porro harum, maxime sed laudantium voluptas cum nam officiis molestiae. Quas 301 iure dicta consectetur. 302 </p> 303 <p> 304 Dolorum ducimus iste asperiores quibusdam laudantium soluta, doloremque minus incidunt 305 distinctio quod dolorem. Nulla nam vitae rerum impedit iste, accusantium veritatis aut, hic 306 animi optio blanditiis, repellat fugit dicta maxime! 307 </p> 308 <p> 309 Quaerat sequi, quis doloribus vel asperiores unde nam excepturi facere consequuntur delectus 310 officia dolorem et itaque sunt iste, suscipit maiores fugiat minus cum! Et id nostrum, 311 officiis facilis voluptas fugiat. 312 </p> 313 <p> 314 Ratione praesentium atque, eveniet nulla expedita distinctio assumenda odit suscipit non 315 architecto accusamus quaerat quod fuga omnis veniam error reprehenderit. At aut impedit 316 excepturi tenetur nulla molestias possimus totam vitae. 317 </p> 318 <p> 319 Molestiae, delectus quae itaque illum impedit eligendi. Molestiae cumque, nam repellat modi 320 dolorum quisquam sequi voluptates velit repudiandae numquam vel quis. Excepturi adipisci hic 321 velit veritatis tenetur, aliquid quod maiores? 322 </p> 323 <p> 324 Pariatur, sint nostrum accusamus dolorum eveniet esse totam praesentium nemo ipsum mollitia 325 quod ad nisi beatae. Veniam, rem illum ratione alias dolores eos sit officia necessitatibus 326 tempora, earum adipisci iure! 327 </p> 328 </ModalTwoContent> 329 <ModalTwoFooter> 330 <Button>Secondary action</Button> 331 <Button color="norm">Primary action</Button> 332 </ModalTwoFooter> 333 </ModalTwo> 334 )} 335 </div> 336 ); 337};
338 339export const WithFormRoot = () => { 340 const [modalProps, handleSetOpen, render] = useModalState(); 341 const [value, setValue] = useState(''); 342 343 const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => { 344 e.preventDefault(); 345 window.alert(`Form submitted, value: ${value}.`); 346 }; 347 348 return ( 349 <div className="text-center"> 350 <Button 351 className="mr-2" 352 onClick={() => { 353 handleSetOpen(true); 354 }} 355 > 356 Open modal with form root 357 </Button> 358 {render && ( 359 <ModalTwo {...modalProps} as={Form} onSubmit={handleSubmit}> 360 <ModalTwoHeader title="Size" /> 361 <ModalTwoContent> 362 <p> 363 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 364 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 365 amet qui vero, blanditiis quos? 366 </p> 367 <p> 368 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 369 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 370 amet qui vero, blanditiis quos? 371 </p> 372 <p> 373 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 374 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 375 amet qui vero, blanditiis quos? 376 </p> 377 <p> 378 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 379 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 380 amet qui vero, blanditiis quos? 381 </p> 382 <p> 383 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 384 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 385 amet qui vero, blanditiis quos? 386 </p> 387 <p> 388 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 389 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 390 amet qui vero, blanditiis quos? 391 </p> 392 <p> 393 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 394 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 395 amet qui vero, blanditiis quos? 396 </p> 397 <div className="mt-4"> 398 <InputFieldTwo 399 label="Name" 400 value={value} 401 onValue={setValue} 402 placeholder="e.g. John Fitzgerald" 403 /> 404 </div> 405 </ModalTwoContent> 406 <ModalTwoFooter> 407 <Button 408 onClick={() => { 409 modalProps.onClose(); 410 }} 411 > 412 Cancel 413 </Button> 414 <Button type="submit" color="norm"> 415 Submit 416 </Button> 417 </ModalTwoFooter> 418 </ModalTwo> 419 )} 420 </div> 421 ); 422}; 423 424export const FullscreenOnMobile = () => { 425 const [modalProps, handleSetOpen, render] = useModalState(); 426 427 return ( 428 <div className="text-center"> 429 <Button 430 className="mr-2" 431 onClick={() => { 432 handleSetOpen(true); 433 }} 434 > 435 Open full screen on mobile modal 436 </Button> 437 {render && ( 438 <ModalTwo fullscreenOnMobile {...modalProps}> 439 <ModalTwoHeader /> 440 <ModalTwoContent> 441 <p> 442 If I&apos;m not full screen you&apos;ll have to make your screen&apos;s width smaller. If 443 you did that and I&apos;m still not fullscreen that means my developers did a shlopey job. 444 </p> 445 <p> 446 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 447 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure 448 amet qui vero, blanditiis quos? 449 </p> 450 </ModalTwoContent> 451 <ModalTwoFooter> 452 <Button>Secondary action</Button> 453 <Button color="norm">Primary action</Button> 454 </ModalTwoFooter> 455 </ModalTwo> 456 )} 457 </div> 458 ); 459}; 460 461export const PromptBasic = () => { 462 const [modalProps, handleSetOpen, render] = useModalState(); 463 464 return ( 465 <div className="text-center"> 466 <Button onClick={() => handleSetOpen(true)}>Open Prompt</Button> 467 {render && ( 468 <Prompt 469 title="Title" 470 subline="Subline" 471 buttons={[ 472 <Button color="danger">Continue</Button>, 473 <Button onClick={() => modalProps.onClose()}>Cancel</Button>, 474 ]} 475 actions={[<Checkbox>Accept me</Checkbox>]} 476 {...modalProps} 477 > 478 <p> 479 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 480 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure amet 481 qui vero, blanditiis quos? 482 </p> 483 </Prompt> 484 )} 485 </div> 486 ); 487}; 488 489export const PromptWithOnlyOneButton = () => { 490 const [modalProps, handleSetOpen, render] = useModalState(); 491 492 return ( 493 <div className="text-center"> 494 <Button onClick={() => handleSetOpen(true)}>Open Prompt with only one Button</Button> 495 {render && ( 496 <Prompt 497 title="Title" 498 subline="Subline" 499 buttons={<Button onClick={() => modalProps.onClose()}>I understand</Button>} 500 {...modalProps} 501 > 502 <p> 503 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 504 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure amet 505 qui vero, blanditiis quos? 506 </p> 507 </Prompt> 508 )} 509 </div> 510 ); 511}; 512 513export const PromptWithFootnote = () => { 514 const [modalProps, handleSetOpen, render] = useModalState(); 515 return ( 516 <div className="text-center"> 517 <Button onClick={() => handleSetOpen(true)}>Open Prompt with footnote</Button> 518 {render && ( 519 <Prompt 520 title="Title" 521 subline="Subline" 522 buttons={[ 523 <Button color="danger">Continue</Button>, 524 <Button onClick={() => modalProps.onClose()}>Cancel</Button>, 525 ]} 526 actions={[<Checkbox>Accept me</Checkbox>]} 527 footnote="This is a footnote" 528 {...modalProps} 529 > 530 <p> 531 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem 532 accusamus obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure amet 533 qui vero, blanditiis quos? 534 </p> 535 </Prompt> 536 )} 537 </div> 538 ); 539}; 540 541export const Basic = () => { 542 const [open, setOpen] = useState(false); 543 544 return ( 545 <div className="text-center"> 546 <Button onClick={() => setOpen(true)}>Open Basic Modal with only one Button</Button> 547 <BasicModal 548 title="Title" 549 isOpen={open} 550 onClose={() => setOpen(false)} 551 footer={ 552 <> 553 <Button onClick={() => setOpen(false)}>I understand</Button> 554 <Button color="norm" onClick={() => setOpen(false)}> 555 I do not understand 556 </Button> 557 </> 558 } 559 > 560 <p> 561 Lorem ipsum dolor sit amet consectetur adipisicing elit. Praesentium unde, blanditiis rem accusamus 562 obcaecati enim amet, voluptatibus nemo facilis illum aut itaque in? Deleniti iure amet qui vero, 563 blanditiis quos? 564 </p> 565 </BasicModal> 566 </div> 567 ); 568};