For the Rails version of the dialog kit, the clickable element being used to open the dialog must be given a open-dialog data attribute with a value that is the same as the id being given to the dialog itself. See code example below to see this in action.
Additionally, both the cancel button and the confirm button have optional id props which can be used to pass in a custom id to allow developers to target that button with custom javascript if needed (confirm_button_id and cancel_button_id).
import React, { useState } from 'react' import { Button, Dialog } from 'playbook-ui' const DialogDefault = () => { const [isOpen, setIsOpen] = useState(false) const close = () => setIsOpen(false) const open = () => setIsOpen(true) return ( <> <Button onClick={open}>{'Open Dialog'}</Button> <Dialog cancelButton="Cancel Button" confirmButton="Okay" onCancel={close} onClose={close} onConfirm={close} opened={isOpen} size="sm" text="Hello Body Text, Nice to meet ya." title="Header Title is the Title Prop" /> </> ) } export default DialogDefault
The dialog kit also supports customizing your dialog with a compound component structure.
This allows for greater flexibility and more complex dialogs.
For the Rails version, when using the kit as a compound component it is necessary to pass the same value as the id for the dialog, the dialog header and the dialog footer in order for the opening and closing of the dialog to function as expected.
If you are using the datepicker within the Rails dialog, do not use the static_position prop on the datepicker.
import React, { useState } from 'react' import { Body, Button, Caption, Dialog, Textarea, Typeahead } from 'playbook-ui' const DialogCompound = () => { const [isOpen, setIsOpen] = useState(false) const close = () => setIsOpen(false) const open = () => setIsOpen(true) return ( <> <Button onClick={open}>{'Open a Complex Dialog'}</Button> <Dialog fullHeight onClose={close} opened={isOpen} size="lg" > <Dialog.Header> <Body>{'What do you need us to take care of?'}</Body> </Dialog.Header> <Dialog.Body> <Textarea id="default-example-1" label="Description" rows={4} /> <br /> <Caption> { 'Type in a word or term too help find tickets later. ex. training,' } {'phone setup, hr'} </Caption> <Typeahead placeholder="Tags.." /> </Dialog.Body> <Dialog.Footer> <Button onClick={close}>{'Send My Issue'}</Button> <Button onClick={close} variant="link" > {'Back'} </Button> </Dialog.Footer> </Dialog> </> ) } export default DialogCompound
import React, { useState } from 'react' import { Button, Dialog, Flex } from 'playbook-ui' const useDialog = (visible = false) => { const [opened, setOpened] = useState(visible) const toggle = () => setOpened(!opened) return [opened, toggle] } const DialogSizes = () => { const [smDialogOpened, toggleSmDialog] = useDialog() const [mdDialogOpened, toggleMdDialog] = useDialog() const [lgDialogOpened, toggleLgDialog] = useDialog() /* eslint-disable react/jsx-handler-names */ const dialogs = [ { size: 'sm', text: 'Body on small dialog', title: 'Header on small dialog', toggle: toggleSmDialog, visible: smDialogOpened, }, { size: 'md', text: 'Body on medium dialog', title: 'Header on medium dialog', toggle: toggleMdDialog, visible: mdDialogOpened, }, { size: 'lg', text: 'Body on large dialog', title: 'Header on large dialog', toggle: toggleLgDialog, visible: lgDialogOpened, }, ] return ( <div> <Flex rowGap="xs" wrap > <Button id="sm" marginRight="md" onClick={toggleSmDialog} > {'Small Dialog'} </Button> <Button marginRight="md" onClick={toggleMdDialog} > {'Medium Dialog'} </Button> <Button marginRight="md" onClick={toggleLgDialog} > {'Large Dialog'} </Button> </Flex> <Flex> {dialogs.map((dialog) => ( <Dialog key={dialog.size} onClose={dialog.toggle} opened={dialog.visible} size={dialog.size} > <Dialog.Header>{dialog.title}</Dialog.Header> <Dialog.Body>{dialog.text}</Dialog.Body> <Dialog.Footer> <Button onClick={dialog.toggle}>{'Okay'}</Button> <Button onClick={dialog.toggle} variant="link" > {'Cancel'} </Button> </Dialog.Footer> </Dialog> ))} </Flex> </div> ) } export default DialogSizes
The dialog will create a scroll container automatically when the text exceeds the height of the page. No prop or configuration is needed.
When such a scroll container is created, the dialog header will remain fixed at top of dialog and not scroll with the body content.
If the dialog is a fullHeight variant, the header and footer will both be sticky and not scroll with the body content.
import React, { useState } from 'react' import { Button, Dialog } from 'playbook-ui' const DialogScrollable = () => { const useDialog = (visible = false) => { const [opened, setOpened] = useState(visible) const toggle = () => setOpened(!opened) return [opened, toggle] } const [dialog1Opened, toggleDialog1] = useDialog() const [dialog2Opened, toggleDialog2] = useDialog() return ( <> <Button marginRight="md" onClick={toggleDialog1} >{'Open Dialog'} </Button> <Button marginRight="md" onClick={toggleDialog2} >{'Open Full Height Dialog'} </Button> <Dialog cancelButton="Cancel" confirmButton="Okay" onCancel={toggleDialog1} onClose={toggleDialog1} onConfirm={toggleDialog1} opened={dialog1Opened} size="md" text="At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat." title="Header Title is the Title Prop" /> <Dialog cancelButton="Cancel" confirmButton="Okay" fullHeight onCancel={toggleDialog2} onClose={toggleDialog2} onConfirm={toggleDialog2} opened={dialog2Opened} size="sm" text="At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat. At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in. At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in." title="Header Title is the Title Prop" /> </> ) } export default DialogScrollable
When shouldCloseOnOverlayClick is explicitly set to false, click events on the overlay will not close the modal.
By default, shouldCloseOnOverlayClick is set to true.
import React, { useState } from 'react' import { Button, Dialog } from 'playbook-ui' const DialogShouldCloseOnOverlay = () => { const [isOpen, setIsOpen] = useState(false) const close = () => setIsOpen(false) const open = () => setIsOpen(true) return ( <> <Button onClick={open}>{'Open Dialog'}</Button> <Dialog cancelButton="Cancel" confirmButton="Okay" onCancel={close} onClose={close} onConfirm={close} opened={isOpen} shouldCloseOnOverlayClick={false} size="sm" text="Click on the overlay all day. I will stay open." title="Neat Header" /> </> ) } export default DialogShouldCloseOnOverlay
The Dialog kit also offers customizable Status Alert options as seen here.
For the rails version of the kit, when using custom confirm and cancel buttons as shown in these examples, the 'cancel' button must be given a close-dialog data attribute with a value that is the same as the id given to the dialog itself.
/* eslint-disable react/jsx-handler-names */ import React, { useState } from "react" import { Button, Dialog, Flex } from 'playbook-ui' const useDialog = (visible = false) => { const [opened, setOpened] = useState(visible) const toggle = () => setOpened(!opened) return [opened, toggle] } const DialogStatus = () => { const [defaultAlertOpened, toggleDefaultAlert] = useDialog() const [cautionAlertOpened, toggleCautionAlert] = useDialog() const [deleteAlertOpened, toggleDeleteAlert] = useDialog() const [infoAlertOpened, toggleInfoAlert] = useDialog() const [successAlertOpened, toggleSuccessAlert] = useDialog() const [errorAlertOpened, toggleErrorAlert] = useDialog() const dialogs = [ { size: "status_size", status: "default", text: "Text explaining why there is an alert", title: "Are you sure?", toggle: toggleDefaultAlert, visible: defaultAlertOpened, buttonOneText:"Yes, Action", buttonTwoText: "No, Cancel" }, { size: "status_size", status: "caution", text: "This is the action you will be taking", title: "Are you sure?", toggle: toggleCautionAlert, visible: cautionAlertOpened, buttonOneText:"Yes, Action", buttonTwoText: "No, Cancel" }, { size: "status_size", status: "delete", text: "You are about to delete ...", title: "Delete", toggle: toggleDeleteAlert, visible: deleteAlertOpened, buttonOneText:"Yes, Delete", buttonTwoText: "No, Cancel" }, { size: "sm", status: "info", text: "Text explaining why there is an alert", title: "Information", toggle: toggleInfoAlert, visible: infoAlertOpened, buttonOneText:"Ok, Thanks!", }, { size: "sm", status: "success", text: "Text explaining what is successful", title: "Success!", toggle: toggleSuccessAlert, visible: successAlertOpened, buttonOneText: "Great!", }, { size: "sm", status: "error", text: "Text explaining the error", title: "Error Message", toggle: toggleErrorAlert, visible: errorAlertOpened, buttonOneText:"Oh no!", }, ] return ( <div> <Flex rowGap="xs" wrap > <Button marginRight="md" onClick={toggleDefaultAlert} > {"Default Status"} </Button> <Button marginRight="md" onClick={toggleCautionAlert} > {"Caution Status"} </Button> <Button marginRight="md" onClick={toggleDeleteAlert} > {"Delete Status"} </Button> <Button marginRight="md" onClick={toggleInfoAlert} > {"Information Status"} </Button> <Button marginRight="md" onClick={toggleSuccessAlert} > {"Success Status"} </Button> <Button marginRight="md" onClick={toggleErrorAlert} > {"Error Status"} </Button> </Flex> <Flex> {dialogs.map((dialog) => ( <Dialog key={dialog.status} onClose={dialog.toggle} opened={dialog.visible} size={dialog.size} status={dialog.status} text={dialog.text} title={dialog.title} > <Dialog.Footer paddingBottom="md" paddingX="md" > {!dialog.buttonTwoText && ( <Button fullWidth onClick={dialog.toggle} > {dialog.buttonOneText} </Button> )} {dialog.buttonTwoText && ( <React.Fragment> <Button onClick={dialog.toggle} paddingRight="xl" variant={dialog.status == "delete" ? "danger" : "primary"} > {dialog.buttonOneText} </Button> <Button onClick={dialog.toggle} variant="secondary" > {dialog.buttonTwoText} </Button> </React.Fragment> )} </Dialog.Footer> </Dialog> ))} </Flex> </div> ) } export default DialogStatus
These examples highlight how the buttons within the Dialog can be stacked when using the Status Alert variant. It also has a link style for the buttons for the mobile views.
/* eslint-disable react/jsx-handler-names */ import React, { useState } from "react" import { Button, Dialog, Flex } from 'playbook-ui' const useDialog = (visible = false) => { const [opened, setOpened] = useState(visible) const toggle = () => setOpened(!opened) return [opened, toggle] } const DialogStackedAlert = () => { const [defaultAlertOpened, toggleDefaultAlert] = useDialog() const [cautionAlertOpened, toggleCautionAlert] = useDialog() const [deleteAlertOpened, toggleDeleteAlert] = useDialog() const dialogs = [ { size: "sm", status: "default", text: "Text explaining why there is an alert", title: "Are you sure?", toggle: toggleDefaultAlert, visible: defaultAlertOpened, buttonOneText:"Yes, Action", buttonTwoText: "No, Cancel" }, { size: "sm", status: "caution", text: "This is the action you will be taking", title: "Are you sure?", toggle: toggleCautionAlert, visible: cautionAlertOpened, buttonOneText:"Yes, Action", buttonTwoText: "No, Cancel" }, { size: "sm", status: "delete", text: "You are about to delete ...", title: "Delete", toggle: toggleDeleteAlert, visible: deleteAlertOpened, buttonOneText:"Yes, Delete", buttonTwoText: "No, Cancel" } ] return ( <div> <Flex rowGap="xs" wrap > <Button marginRight="md" onClick={toggleDefaultAlert} > {"Default Status"} </Button> <Button marginRight="md" onClick={toggleCautionAlert} > {"Caution Status"} </Button> <Button marginRight="md" onClick={toggleDeleteAlert} > {"Delete Status"} </Button> </Flex> <Flex> {dialogs.map((dialog) => ( <Dialog alertStyle={dialog.alertStyle} key={dialog.status} onClose={dialog.toggle} opened={dialog.visible} size={dialog.size} status={dialog.status} text={dialog.text} title={dialog.title} > <Dialog.Footer padding="sm" paddingBottom = "none" paddingX="md" > <Button fullWidth onClick={dialog.toggle} variant= {dialog.status == "delete" ? "danger" : "primary"} > {dialog.buttonOneText} </Button> </Dialog.Footer> <Dialog.Footer padding="sm" paddingBottom = "md" paddingX="md" > <Button fullWidth onClick={dialog.toggle} variant="secondary" > {dialog.buttonTwoText} </Button> </Dialog.Footer> </Dialog> ))} </Flex> </div> ) } export default DialogStackedAlert
To render a full height Dialog, use the fullHeight (react) or full_height (rails) prop. A full height Dialog can be size small, medium, or large. By default it will be center aligned.
import React, { useState } from "react"; import { Body, Button, Dialog, Flex, Caption, Textarea, Typeahead } from 'playbook-ui' const useDialog = (visible = false) => { const [opened, setOpened] = useState(visible); const toggle = () => setOpened(!opened); return [opened, toggle]; }; const DialogFullHeight = () => { const [headerSeparatorDialogOpened, toggleHeaderSeparatorDialog] = useDialog(); const [footerSeparatorDialogOpened, toggleFooterSeparatorDialog] = useDialog(); const [bothSeparatorsDialogOpened, toggleBothSeparatorsDialog] = useDialog(); const dialogs = [ { size: "sm", title: "Small Dialog", toggle: toggleHeaderSeparatorDialog, visible: headerSeparatorDialogOpened, }, { size: "md", title: "Medium Dialog", toggle: toggleFooterSeparatorDialog, visible: footerSeparatorDialogOpened, }, { size: "lg", title: "Large Dialog", toggle: toggleBothSeparatorsDialog, visible: bothSeparatorsDialogOpened, }, ]; return ( <> <Flex wrap> <Button id="sm" marginRight="md" onClick={toggleHeaderSeparatorDialog} > {"Small Dialog"} </Button> <Button marginRight="md" onClick={toggleFooterSeparatorDialog} > {"Medium Dialog"} </Button> <Button marginRight="md" onClick={toggleBothSeparatorsDialog} > {"Large Dialog"} </Button> </Flex> <Flex> {dialogs.map(({toggle, visible, placement, size, title}, index) => ( <Dialog fullHeight key={index} onClose={toggle} opened={visible} placement={placement} size={size} > <Dialog.Header> <Body>{title}</Body> </Dialog.Header> <Dialog.Body> <Textarea id="default-example-1" label="Description" rows={4} /> <br /> <Caption> { "Type in a word or term too help find tickets later. ex. training," } {"phone setup, hr"} </Caption> <Typeahead placeholder="Tags.." /> </Dialog.Body> <Dialog.Footer> <Button onClick={toggle}>{"Send My Issue"}</Button> <Button onClick={toggle} variant="link" > {"Back"} </Button> </Dialog.Footer> </Dialog> ))} </Flex> </> ); }; export default DialogFullHeight;
The full height dialog is centered by default, but the placement can be changed via the placement prop with one of the following values: left, center, right.
The large variant however will always be centered, even if the placement prop is used.
All dialogs with the fullHeight prop will be displayed full-width on mobile screens.
import React, { useState } from "react"; import { Body, Button, Dialog, Flex, Caption, Textarea, Typeahead } from 'playbook-ui' const useDialog = (visible = false) => { const [opened, setOpened] = useState(visible); const toggle = () => setOpened(!opened); return [opened, toggle]; }; const DialogFullHeightPlacement = () => { const [headerSeparatorDialogOpened, toggleHeaderSeparatorDialog] = useDialog(); const [footerSeparatorDialogOpened, toggleFooterSeparatorDialog] = useDialog(); const [bothSeparatorsDialogOpened, toggleBothSeparatorsDialog] = useDialog(); const dialogs = [ { title: "Left Dialog", toggle: toggleHeaderSeparatorDialog, visible: headerSeparatorDialogOpened, placement: "left", }, { title: "Center Dialog", toggle: toggleFooterSeparatorDialog, visible: footerSeparatorDialogOpened, }, { title: "Right Dialog", toggle: toggleBothSeparatorsDialog, visible: bothSeparatorsDialogOpened, placement: "right", }, ]; return ( <> <Flex wrap> <Button id="sm" marginRight="md" onClick={toggleHeaderSeparatorDialog} > {"Left Dialog"} </Button> <Button marginRight="xl" onClick={toggleFooterSeparatorDialog} > {"Center Dialog"} </Button> <Button marginRight="xl" onClick={toggleBothSeparatorsDialog} > {"Right Dialog"} </Button> </Flex> <Flex> {dialogs.map(({toggle, visible, placement, title}, index) => ( <Dialog fullHeight key={index} onClose={toggle} opened={visible} placement={placement} size={"md"} > <Dialog.Header> <Body>{title}</Body> </Dialog.Header> <Dialog.Body> <Textarea id={`default-example-2-${index}`} label="Description" rows={4} /> <br /> <Caption> { "Type in a word or term too help find tickets later. ex. training," } {"phone setup, hr"} </Caption> <Typeahead placeholder="Tags.." /> </Dialog.Body> <Dialog.Footer> <Button onClick={toggle}>{"Send My Issue"}</Button> <Button onClick={toggle} variant="link" > {"Back"} </Button> </Dialog.Footer> </Dialog> ))} </Flex> </> ); }; export default DialogFullHeightPlacement;
Pressing the "Okay" button will trigger a loading state where the button content is replaced by a spinner icon and both buttons are disabled.
import React, { useState } from 'react' import { Button, Dialog } from 'playbook-ui' const DialogLoading = () => { const [isOpen, setIsOpen] = useState(false) const close = () => { if (!isLoading) { setIsOpen(false) } } const open = () => setIsOpen(true) const [isLoading, setIsLoading] = useState(false) const submit = async () => { setIsLoading(true) try { await new Promise((r) => setTimeout(r, 3000)) setIsOpen(false) } catch (error) { console.error("An error occurred.") } finally { setIsLoading(false) } } return ( <> <Button onClick={open}>{'Open Dialog'}</Button> <Dialog cancelButton="Cancel" className="wrapper" confirmButton="Okay" loading={isLoading} onCancel={close} onClose={close} onConfirm={submit} opened={isOpen} size="sm" text="Make a 3 second request?" title="Loading Example" /> </> ) } export default DialogLoading
Use the overflow="visible" global prop to allow Date Picker and Typeahead dropdown menus to appear outside the dialog boundaries. By default, dialogs clip content that extends beyond their edges, but this prop enables pop-up elements to render above the dialog overlay.
import React, { useState } from 'react' import { Body, Button, Dialog, Typeahead } from 'playbook-ui' const DialogOverflowVisible = () => { const [isOpen, setIsOpen] = useState(false) const close = () => setIsOpen(false) const open = () => setIsOpen(true) const typeaheadOptions = [ { label: "United States", value: "unitedStates", id: "us" }, { label: "United Kingdom", value: "unitedKingdom", id: "gb" }, { label: "Canada", value: "canada", id: "ca" }, { label: "Australia", value: "australia", id: "au" }, { label: "Germany", value: "germany", id: "de" }, { label: "France", value: "france", id: "fr" }, { label: "Japan", value: "japan", id: "jp" }, { label: "Brazil", value: "brazil", id: "br" }, ] return ( <> <Button onClick={open}>{'Open Dialog with Overflow Visible'}</Button> <Dialog onClose={close} opened={isOpen} overflow="visible" size="md" > <Dialog.Header> <Body>{'Select Location'}</Body> </Dialog.Header> <Dialog.Body> <Typeahead options={typeaheadOptions} placeholder="Select a location..." /> </Dialog.Body> <Dialog.Footer> <Button onClick={close}>{'Save'}</Button> <Button onClick={close} variant="link" > {'Cancel'} </Button> </Dialog.Footer> </Dialog> </> ) } export default DialogOverflowVisible
The closeable prop can be set to false to optionally render the Dialog header without the close “X” button. closeable is set to true by default.
This prop can be used with the simple as well as the complex version of the Dialog as can be seen here.
import React, { useState } from 'react' import { Button, Dialog } from 'playbook-ui' const DialogCloseable = () => { // Simple example const [isOpenSimple, setIsOpenSimple] = useState(false) const closeSimple = () => setIsOpenSimple(false) const openSimple = () => setIsOpenSimple(true) // Complex example const [isOpenComplex, setIsOpenComplex] = useState(false) const closeComplex = () => setIsOpenComplex(false) const openComplex = () => setIsOpenComplex(true) return ( <> <Button marginRight='md' onClick={openSimple} > {'Open Simple Dialog'} </Button> <Button onClick={openComplex}>{'Open Complex Dialog'}</Button> <Dialog cancelButton="Cancel Button" closeable={false} confirmButton="Okay" onCancel={closeSimple} onClose={closeSimple} onConfirm={closeSimple} opened={isOpenSimple} size="sm" text="Hello Body Text, Nice to meet ya." title="Header Title is the Title Prop" /> <Dialog onClose={closeComplex} opened={isOpenComplex} size="sm" > <Dialog.Header closeable={false}>{'Header Title inside Dialog.Header'}</Dialog.Header> <Dialog.Body>{'Hello Body Text, Nice to meet ya.'}</Dialog.Body> <Dialog.Footer> <Button onClick={closeComplex}>{'Okay'}</Button> <Button onClick={closeComplex} variant="link" > {'Cancel Button'} </Button> </Dialog.Footer> </Dialog> </> ) } export default DialogCloseable
import React from 'react' import { FixedConfirmationToast } from 'playbook-ui' const FixedConfirmationToastDefault = (props) => { return ( <div> <div> <FixedConfirmationToast closeable status="error" text="Error Message" /> </div> <br /> <div> <FixedConfirmationToast status="success" text="Items Successfully Moved" /> </div> <br /> <div> <FixedConfirmationToast status="neutral" text="Scan to Assign Selected Items" /> </div> </div> ) } export default FixedConfirmationToastDefault
Use the navMarginTop prop to position the toast lower on the page. This is useful for cases where we want to position the toast below a header or nav.
import React, { useState } from 'react' import { Button, FixedConfirmationToast } from 'playbook-ui' const FixedConfirmationToastNavMargin = (props) => { const [openToast, setOpenToast] = useState(false) const handleClickShort = () => { setOpenToast(true) } const handleCloseShort = () => { setOpenToast(false) } return ( <div> <Button onClick={handleClickShort} text="Top Nav Margin" variant="secondary" /> <FixedConfirmationToast closeable horizontal='center' navMarginTop onClose={handleCloseShort} open={openToast} status="tip" text="Top nav Margin." vertical='top' /> </div> ) } export default FixedConfirmationToastNavMargin
Multi-line is used when the given text will not fit on one line. Using Multi Line allows the height of the confirmation toast to grow. Simply resize the screen to see the fixed confirmation toast wrap the text.
import React, { useState } from 'react' import { Button, FixedConfirmationToast } from 'playbook-ui' const FixedConfirmationToastMultiLine = (props) => { const [openShort, setOpenShort] = useState(false) const [openLong, setOpenLong] = useState(false) const handleClickShort = () => { setOpenShort(true) } const handleClickLong= () => { setOpenLong(true) } const handleCloseShort = () => { setOpenShort(false) } const handleCloseLong= () => { setOpenLong(false) } return ( <> <Button onClick={handleClickShort} text="Short Multiline" variant="secondary" /> {' '} <Button onClick={handleClickLong} text="Long Multiline" variant="secondary" /> <FixedConfirmationToast closeable horizontal='center' multiLine onClose={handleCloseShort} open={openShort} status='tip' text='Multi-line is used when the given text will not fit on one line.' vertical='top' /> <FixedConfirmationToast closeable horizontal='center' multiLine onClose={handleCloseLong} open={openLong} status='tip' text='Multi-line is used when the given text will not fit on one line. Using Multi Line allows the height of the confirmation toast to grow. Simply resize the screen to see the fixed confirmation toast wrap the text.' vertical='top' /> </> ) } export default FixedConfirmationToastMultiLine
import React from 'react' import { FixedConfirmationToast } from 'playbook-ui' const FixedConfirmationToastClose = (props) => { return ( <div> <div> <FixedConfirmationToast closeable status="error" text="Error Message" /> </div> <br /> <div> <FixedConfirmationToast closeable status="success" text="Items Successfully Moved" /> </div> <br /> <div> <FixedConfirmationToast closeable status="neutral" text="Scan to Assign Selected Items" /> </div> </div> ) } export default FixedConfirmationToastClose
import React, { useState } from 'react' import { Button, FixedConfirmationToast } from 'playbook-ui' const FixedConfirmationToastPositions = (props) => { const [state, setState] = useState({ open: false, vertical: 'top', horizontal: 'center', }) const { vertical, horizontal, open } = state const handleClick = (newState) => () => { setState({ open: true, ...newState }) } const handleClose = () => { setState({ ...state, open: false }) } return ( <div> <Button onClick={handleClick({ horizontal: 'center', open: true, vertical: 'top', })} text="Top Center" variant="secondary" /> {' '} <Button onClick={handleClick({ horizontal: 'left', open: true, vertical: 'top', })} text="Top Left" variant="secondary" /> {' '} <Button onClick={handleClick({ horizontal: 'right', open: true, vertical: 'top', })} text="Top Right" variant="secondary" /> {' '} <Button onClick={handleClick({ horizontal: 'center', open: true, vertical: 'bottom', })} text="Bottom Center" variant="secondary" /> {' '} <Button onClick={handleClick({ horizontal: 'left', open: true, vertical: 'bottom', })} text="Bottom Left" variant="secondary" /> {' '} <Button onClick={handleClick({ horizontal: 'right', open: true, vertical: 'bottom', })} text="Bottom Right" variant="secondary" /> <FixedConfirmationToast closeable horizontal={horizontal} onClose={handleClose} open={open} status="neutral" text={`${vertical} ${horizontal}`} vertical={vertical} /> </div> ) } export default FixedConfirmationToastPositions
Auto close is used when you want the confirmation toast to close automatically after a certain time. autoClose property will be a delay number in ms.
import React, { useState } from 'react' import { Button, FixedConfirmationToast } from 'playbook-ui' const FixedConfirmationToastAutoClose = (props) => { const [open, setOpen] = useState(false) const [openCloseable, setOpenCloseable] = useState(false) const handleClick = () => { setOpen(true) } const handleClickCloseable = () => { setOpenCloseable(true) } const handleClose = () => { setOpen(false) } const handleCloseCloseable = () => { setOpenCloseable(false) } return ( <> <Button onClick={handleClick} text="Show Auto Close Toast" variant="secondary" /> {' '} <Button onClick={handleClickCloseable} text="Show Closeable Auto Close Toast" variant="secondary" /> <FixedConfirmationToast autoClose={3000} horizontal='center' onClose={handleClose} open={open} status='tip' text='I will disappear in 3 seconds.' vertical='top' /> <FixedConfirmationToast autoClose={10000} closeable horizontal='center' onClose={handleCloseCloseable} open={openCloseable} status='tip' text='I will disappear in 10 seconds.' vertical='top' /> </> ) } export default FixedConfirmationToastAutoClose
Pass anything (including any of our kits) to the children prop to customize the content of the fixed confirmation toast.
NOTE: passing children overrides any content passed to text
import React from 'react' import { FixedConfirmationToast, Button, Title } from 'playbook-ui' const FixedConfirmationToastChildren = (props) => { return ( <> <FixedConfirmationToast paddingY="none" status="success" > <Title dark marginLeft="md" size={4} text="Design & Handoff Process was moved to UX Designer Learning Track." /> <Button dark onClick={() => alert("button clicked!")} paddingRight="none" text="Undo" variant="link" /> </FixedConfirmationToast> </> ) } export default FixedConfirmationToastChildren
import React from 'react' import { FixedConfirmationToast } from 'playbook-ui' const FixedConfirmationToastCustomIcon = (props) => { return ( <div> <div> <FixedConfirmationToast closeable icon="wrench" marginBottom="md" status="error" text="Fix before proceeding" /> </div> <div> <FixedConfirmationToast icon="star" marginBottom="md" status="success" text="Thank you for completing the form!" /> </div> <div> <FixedConfirmationToast icon="file-pdf" marginBottom="md" status="neutral" text="Saved as PDF" /> </div> <div> <FixedConfirmationToast icon="arrow-down" status="tip" text="New Messages" /> </div> </div> ) } export default FixedConfirmationToastCustomIcon
Setting icon prop to "none" will render the fixed confirmation toast without the left side icon.
import React from 'react' import { FixedConfirmationToast } from 'playbook-ui' const FixedConfirmationToastNoIcon = (props) => { return ( <div> <div> <FixedConfirmationToast closeable icon="none" status="error" text="Error Message" /> </div> <br /> <div> <FixedConfirmationToast icon="none" status="success" text="Items Successfully Moved" /> </div> <br /> <div> <FixedConfirmationToast icon="none" status="neutral" text="Scan to Assign Selected Items" /> </div> </div> ) } export default FixedConfirmationToastNoIcon
import React, { useState } from 'react' import { Body, CircleIconButton, Flex, PbReactPopover } from 'playbook-ui' const PopoverDefault = (props) => { const [showPopover, setShowPopover] = useState(false) const handleTogglePopover = () => { setShowPopover(!showPopover) } const popoverReference = ( <CircleIconButton icon="info" onClick={handleTogglePopover} variant="secondary" /> ) return ( <Flex orientation="row" vertical="center" > <Body text="Click info for more details" /> <PbReactPopover offset placement="top" reference={popoverReference} show={showPopover} > {'I\'m a popover. I can show content of any size.'} </PbReactPopover> </Flex> ) } export default PopoverDefault
Notice offset is not set so the popover is flush with the content.
import React, { useState } from 'react' import { Button, Flex, PbReactPopover, Icon, List, ListItem } from 'playbook-ui' const PopoverWithButton = (props) => { const [showPopover, setShowPopover] = useState(false) const handleTogglePopover = () => { setShowPopover(!showPopover) } const popoverReference = ( <Button onClick={handleTogglePopover} variant="secondary" > <Flex align="center"> {"Filter By"} <Flex className={showPopover ? "fa-flip-vertical" : ""} display="inline_flex" > <Icon fixedWidth icon="angle-down" margin-left="xxs" /> </Flex> </Flex> </Button> ) return ( <PbReactPopover padding="none" placement="bottom" reference={popoverReference} show={showPopover} > <List xpadding> <ListItem><a>{'Popularity'}</a></ListItem> <ListItem><a>{'Title'}</a></ListItem> <ListItem><a>{'Duration'}</a></ListItem> <ListItem><a>{'Date Started'}</a></ListItem> <ListItem><a>{'Date Ended'}</a></ListItem> </List> </PbReactPopover> ) } export default PopoverWithButton
import React, { useState } from 'react' import { Button, Flex, PbReactPopover } from 'playbook-ui' const PopoverClose = (props) => { const [showInsidePopover, setInsideShowPopover] = useState(false) const [showOutsidePopover, setOutsideShowPopover] = useState(false) const [showAnyPopover, setAnyShowPopover] = useState(false) const handleInsideShouldClosePopover = (shouldClosePopover) => { setInsideShowPopover(!shouldClosePopover) } const handleInsideTogglePopover = () => { setInsideShowPopover(!showInsidePopover) } const handleOutsideShouldClosePopover = (shouldClosePopover) => { setOutsideShowPopover(!shouldClosePopover) } const handleOutsideTogglePopover = () => { setOutsideShowPopover(!showOutsidePopover) setAnyShowPopover(false) } const handleAnyShouldClosePopover = (shouldClosePopover) => { setAnyShowPopover(!shouldClosePopover) } const handleAnyTogglePopover = () => { setAnyShowPopover(!showAnyPopover) setOutsideShowPopover(false) } const insidePopoverTrigger = ( <Button onClick={handleInsideTogglePopover} text="Click Inside" variant="secondary" /> ) const outsidePopoverTrigger = ( <Button onClick={handleOutsideTogglePopover} text="Click Outside" variant="secondary" /> ) const anyPopoverTrigger = ( <Button onClick={handleAnyTogglePopover} text="Click Anywhere" variant="secondary" /> ) return ( <Flex spacing="between"> <PbReactPopover closeOnClick="inside" offset placement="bottom" reference={insidePopoverTrigger} shouldClosePopover={handleInsideShouldClosePopover} show={showInsidePopover} > {'Click on me!'} </PbReactPopover> <PbReactPopover closeOnClick="outside" offset placement="top" reference={outsidePopoverTrigger} shouldClosePopover={handleOutsideShouldClosePopover} show={showOutsidePopover} > {'Click anywhere but me!'} </PbReactPopover> <PbReactPopover closeOnClick="any" offset placement="right" reference={anyPopoverTrigger} shouldClosePopover={handleAnyShouldClosePopover} show={showAnyPopover} > {'Click anything!'} </PbReactPopover> </Flex> ) } export default PopoverClose
import React, { useState } from 'react' import { Body, Button, PbReactPopover } from 'playbook-ui' const PopoverZIndex = (props) => { const [showPopover, setShowPopover] = useState(false) const handleTogglePopover = () => { setShowPopover(!showPopover) } const handleShouldClosePopover = (shouldClosePopover) => { setShowPopover(!shouldClosePopover) } const popoverTrigger = ( <Button onClick={handleTogglePopover} text="Click Me" variant="secondary" /> ) return ( <> <div style={{ position: 'relative', zIndex: 2 }}> <Body marginBottom="md" text="I've got a z-index of 2" /> </div> <PbReactPopover closeOnClick="outside" offset padding="sm" placement="top" reference={popoverTrigger} shouldClosePopover={handleShouldClosePopover} show={showPopover} zIndex={3} > {'I have a custom z-index of 3'} </PbReactPopover> </> ) } export default PopoverZIndex
import React, { useState } from 'react' import { Body, Button, PbReactPopover, Title } from 'playbook-ui' const PopoverScrollHeight = (props) => { const [showPopover, setShowPopover] = useState(false) const handleTogglePopover = () => { setShowPopover(!showPopover) } const handleShouldClosePopover = (shouldClosePopover) => { setShowPopover(!shouldClosePopover) } const popoverTrigger = ( <Button onClick={handleTogglePopover} text="Click Me" variant="secondary" /> ) return ( <PbReactPopover closeOnClick="any" maxHeight="150px" maxWidth="240px" offset padding="md" paddingBottom="sm" paddingTop="sm" placement="top" reference={popoverTrigger} shouldClosePopover={handleShouldClosePopover} show={showPopover} > <Body marginBottom="sm" text="So many people live within unhappy circumstances and yet will not take the initiative to change their situation because they are conditioned to a life of security, conformity, and conservation, all of which may appear to give one peace of mind, but in reality, nothing is more damaging to the adventurous spirit." /> <Title size={4} text="- Christopher McCandless" /> </PbReactPopover> ) } export default PopoverScrollHeight
import React, { useState } from 'react' import { Body, Button, CircleIconButton, Flex, PbReactPopover } from 'playbook-ui' const PopoverActionableContent = (props) => { const [showPopover, setShowPopover] = useState(false) const handleTogglePopover = () => { setShowPopover(!showPopover) } const handleShouldClosePopover = (shouldClose) => { setShowPopover(!shouldClose) } const popoverReference = ( <CircleIconButton icon="info" onClick={handleTogglePopover} variant="secondary" /> ) return ( <Flex orientation="row" vertical="center" > <Body text="Click info for more details" /> <PbReactPopover closeOnClick="inside" offset placement="top" reference={popoverReference} shouldClosePopover={handleShouldClosePopover} show={showPopover} > <Body textAlign="center"> <Button onClick={() => {alert("Let's do this!")}} text="Learn More" /> </Body> </PbReactPopover> </Flex> ) } export default PopoverActionableContent
By default, the popover tooltip attaches to the <body>. To attach it elsewhere, use the appendTo prop. Set it to "parent" to place the tooltip inside its parent element, or pass any CSS selector (#id or .class) to specify a custom container.
import React, { useState } from "react"; import { PbReactPopover, Body, Flex, CircleIconButton } from 'playbook-ui' const PopoverAppendTo = (props) => { const [showParentPopover, setShowParentPopover] = useState(false); const [showSelectorPopover, setShowSelectorPopover] = useState(false); const parentPopoverReference = ( <CircleIconButton icon="info" onClick={() => setShowParentPopover(!showParentPopover)} variant="secondary" /> ); const selectorPopoverReference = ( <CircleIconButton icon="info" onClick={() => setShowSelectorPopover(!showSelectorPopover)} variant="secondary" /> ); return ( <> <Flex marginBottom="md" orientation="row" vertical="center" > <Body text="Click info for more details" /> <PbReactPopover appendTo="parent" offset placement="top" reference={parentPopoverReference} show={showParentPopover} > {'I\'m a popover. I have been appended to my parent element.'} </PbReactPopover> </Flex> <Flex orientation="row" vertical="center" > <Body text="Click info for more details" /> <PbReactPopover appendTo=".pb--page--sideNav" offset placement="top" reference={selectorPopoverReference} show={showSelectorPopover} zIndex={10} > {'I\'m a popover. I have been appended to the .pb--page--sideNav.'} </PbReactPopover> </Flex> </> ); }; export default PopoverAppendTo;
Use the placement prop to control where the popover appears relative to its trigger. Valid values include top, bottom, left, right, and aligned variants such as top-start, top-end, bottom-start, bottom-end, left-start, left-end, right-start, and right-end.
import React, { useState } from 'react' import { Button, Flex, PbReactPopover } from 'playbook-ui' const ROWS = [ [ { placement: 'top', label: 'Top' }, { placement: 'top-start', label: 'Top start' }, { placement: 'top-end', label: 'Top end' }, ], [ { placement: 'bottom', label: 'Bottom' }, { placement: 'bottom-start', label: 'Bottom start' }, { placement: 'bottom-end', label: 'Bottom end' }, ], [ { placement: 'left', label: 'Left' }, { placement: 'left-start', label: 'Left start' }, { placement: 'left-end', label: 'Left end' }, ], [ { placement: 'right', label: 'Right' }, { placement: 'right-start', label: 'Right start' }, { placement: 'right-end', label: 'Right end' }, ], ] const PopoverPlacement = (props) => { const [open, setOpen] = useState({}) const isOpen = (placement) => open[placement] === true const setOpenFor = (placement) => (value) => setOpen((prev) => ({ ...prev, [placement]: value })) const toggle = (placement) => setOpenFor(placement)(!isOpen(placement)) const handleShouldClose = (placement) => (shouldClose) => { if (shouldClose) setOpenFor(placement)(false) } return ( <> {ROWS.map((placements, rowIndex) => ( <Flex justify="around" key={placements[0].placement} marginBottom={rowIndex < ROWS.length - 1 ? 'sm' : undefined} orientation="row" wrap > {placements.map(({ placement, label }) => { const trigger = ( <Button key={placement} onClick={() => toggle(placement)} text={label} variant="secondary" /> ) return ( <PbReactPopover closeOnClick="outside" key={placement} offset placement={placement} reference={trigger} shouldClosePopover={handleShouldClose(placement)} show={isOpen(placement)} > {`Popover: ${label.toLowerCase()}`} </PbReactPopover> ) })} </Flex> ))} </> ) } export default PopoverPlacement
You can define the tooltip placement sending the prop placement with one of the available options: top | right | bottom | left.
If you don't specify a desired placement, the component will automatically choose the one that fits better.
If the desired placement doesn't fit on screen, the component will automatically switch to the one that fits better.
import React from 'react' import { Tooltip, Flex, FlexItem } from 'playbook-ui' const TooltipDefaultReact = (props) => { return ( <Flex flexDirection='row' gap='md' wrap > <FlexItem> <Tooltip placement='top' text="Whoa. I'm a Tooltip" zIndex={10} > {'Hover here (Top)'} </Tooltip> </FlexItem> <FlexItem> <Tooltip placement='bottom' text="Whoa. I'm a Tooltip" zIndex={10} > {'Hover here (Bottom)'} </Tooltip> </FlexItem> <FlexItem> <Tooltip placement='right' text="Whoa. I'm a Tooltip" zIndex={10} > {'Hover here (Right)'} </Tooltip> </FlexItem> <FlexItem> <Tooltip placement='left' text="Whoa. I'm a Tooltip" zIndex={10} > {'Hover here (Left)'} </Tooltip> </FlexItem> </Flex> ) } export default TooltipDefaultReact
Set the prop interaction as true for cases that require users to copy the content inside the tooltip.
import React from 'react' import { Button, Tooltip, Flex, FlexItem } from 'playbook-ui' const TooltipInteraction = (props) => { return ( <Flex flexDirection='row' gap='md' wrap > <FlexItem> <Tooltip interaction placement='top' text="You can copy me" zIndex={10} > <Button text="With Interaction"/> </Tooltip> </FlexItem> <FlexItem> <Tooltip placement='top' text="I'm just a regular tooltip" zIndex={10} > <Button text="No Interaction"/> </Tooltip> </FlexItem> </Flex> ) } export default TooltipInteraction
You should set margin in the tooltip component itself. If you add this prop to the child, it will cause the tooltip to be pulled away from the trigger.
It is not recommended to set padding in the tooltip nor its child, doing so will cause it to be pulled away from its trigger element.
import React from 'react' import { Tooltip, Flex, CircleIconButton } from 'playbook-ui' const TooltipMargin = (props) => { return ( <Flex flexDirection='row' wrap > <Tooltip margin='md' placement='top' text='Send Email' zIndex={10} > <CircleIconButton icon='paper-plane' /> </Tooltip> <Tooltip margin='md' placement='top' text='Send Email' zIndex={10} > <CircleIconButton icon='paper-plane' /> </Tooltip> </Flex> ) } export default TooltipMargin
You can customize the height and width of the tooltip's popover.
When using maxHeight, be sure to set a width as well. The text needs to truncate within the width prop.
import React from 'react' import { Tooltip, Button, Flex, FlexItem } from 'playbook-ui' const TooltipSizing = (props) => { return ( <Flex flexDirection='row' gap='md' wrap > <FlexItem> <Tooltip height='150px' placement='top' text="I'm 150px high and 100px wide!" width='100px' > <Button text="Height and Width"/> </Tooltip> </FlexItem> <FlexItem> <Tooltip maxHeight='100px' placement='top' text="I have a maxHeight of 100px! Lorem ipsum dolor sit amet consectetur adipisicing elit." width='250px' > <Button text="maxHeight"/> </Tooltip> </FlexItem> <FlexItem> <Tooltip maxWidth='150px' placement='top' text="I have a maxWidth of 150px! Lorem ipsum dolor sit amet consectetur adipisicing elit." > <Button text="maxWidth"/> </Tooltip> </FlexItem> <FlexItem> <Tooltip minWidth='300px' placement='top' text="I have a minWidth of 300px!" > <Button text="minWidth"/> </Tooltip> </FlexItem> <FlexItem> <Tooltip maxWidth='150px' minHeight='300px' placement='top' text="I have a minHeight of 300px!" > <Button text="minHeight"/> </Tooltip> </FlexItem> </Flex> ) } export default TooltipSizing
Set the prop icon with the desired icon to display inside the tooltip.
import React from 'react' import { Button, Tooltip, Flex } from 'playbook-ui' const TooltipIcon = (props) => { return ( <Flex flexDirection='row' gap='md' wrap > <Tooltip icon='paper-plane' placement='top' text='Send Email' zIndex={10} > <Button text='Tooltip With Icon' /> </Tooltip> <Tooltip icon='paper-plane' placement='bottom' text='Send Email' zIndex={10} > <Button text='Tooltip With Icon' /> </Tooltip> <Tooltip icon='paper-plane' placement='right' text='Send Email' zIndex={10} > <Button text='Tooltip With Icon' /> </Tooltip> <Tooltip icon='paper-plane' placement='left' text='Send Email' zIndex={10} > <Button text='Tooltip With Icon' /> </Tooltip> </Flex> ) } export default TooltipIcon
Waits for the specified time when the event listener runs before triggering the tooltip.
The delay accepts number in ms or an object with open and close properties.
The default is 0.
import React from 'react' import { Button, Tooltip, Flex, FlexItem } from 'playbook-ui' const TooltipDelay = (props) => { return ( <Flex flexDirection='row' gap='md' wrap > <FlexItem> <Tooltip delay={1000} placement='top' text="1s open/close delay" zIndex={10} > <Button text="1s delay"/> </Tooltip> </FlexItem> <FlexItem> <Tooltip delay={{ open: 1000 }} placement='top' text="1s open delay" zIndex={10} > <Button text="Open only"/> </Tooltip> </FlexItem> <FlexItem> <Tooltip delay={{ close: 1000 }} placement='top' text="1s close delay" zIndex={10} > <Button text="Close only"/> </Tooltip> </FlexItem> </Flex> ) } export default TooltipDelay
You can build your own logic to control whether to show the tooltip using the showTooltip prop. Its default value is true.
Click on the Toggle state button to change the state of the component and hover over the 'hover me' text to see it in action.
import React, { useState } from 'react' import { Button, Body, Tooltip, Flex, FlexItem } from 'playbook-ui' const TooltipShowTooltipReact = (props) => { const [showTooltip, setShowTooltip] = useState(true); return ( <Flex flexDirection='column' gap='md' wrap > <FlexItem> <Button onClick={()=> setShowTooltip(!showTooltip)} text="Toggle state" /> </FlexItem> <FlexItem> <Body > <p> {'Tooltip is: '} <code>{showTooltip ? "enabled" : "disabled"}</code> </p> </Body> </FlexItem> <FlexItem> <Tooltip placement='right' showTooltip={showTooltip} text='Tooltip is enabled' zIndex={10} > {'Hover me.'} </Tooltip> </FlexItem> </Flex> ) } export default TooltipShowTooltipReact
Set the prop useClickToOpen so that the tooltip will only appear when an item is clicked rather than hovered over.
import React from 'react' import { Button, Tooltip, Flex } from 'playbook-ui' const TooltipClickOpen = (props) => { return ( <Flex flexDirection='row' gap='md' wrap > <Tooltip placement='top' text='Tooltip Opened' useClickToOpen zIndex={10} > <Button text='Click to Open' /> </Tooltip> </Flex> ) } export default TooltipClickOpen