import React from 'react' import { Icon } from 'playbook-ui' const IconRotate = (props) => { return ( <div> <Icon fixedWidth icon="user" rotation={90} size="2x" /> <Icon fixedWidth icon="user" rotation={180} size="2x" /> <Icon fixedWidth icon="user" rotation={270} size="2x" /> </div> ) } export default IconRotate
import React from 'react' import { Icon } from 'playbook-ui' const IconFlip = (props) => { return ( <div> <Icon fixedWidth flip="horizontal" icon="question-circle" size="2x" /> <Icon fixedWidth flip="vertical" icon="question-circle" size="2x" /> <Icon fixedWidth flip="both" icon="question-circle" size="2x" /> </div> ) } export default IconFlip
A spinner icon can show a user that something is loading or saving.
import React from 'react' import { Icon } from 'playbook-ui' const IconAnimate = (props) => { return ( <div> <p> <Icon fixedWidth icon="spinner" size="2x" spin /> {' '} <span>{'Spin'}</span> </p> <br /> <p> <Icon fixedWidth icon="spinner" pulse size="2x" /> {' '} <span>{'Pulse'}</span> </p> </div> ) } export default IconAnimate
Icon Pull can be used to indicate that the user can perform a pull action.
import React from 'react' import { Icon } from 'playbook-ui' const IconSizes = (props) => { return ( <div> <p> <Icon icon="user" size="lg" /> {' '} <span>{'Large'}</span> </p> <p> <Icon icon="user" size="sm" /> {' '} <span>{'Small'}</span> </p> <p> <Icon icon="user" size="xs" /> {' '} <span>{'XSmall'}</span> </p> <br /> <br /> <p> <Icon icon="user" size="1x" /> {' '} <span>{'1x'}</span> </p> <p> <Icon icon="user" size="2x" /> {' '} <span>{'2x'}</span> </p> <p> <Icon icon="user" size="3x" /> {' '} <span>{'3x'}</span> </p> <p> <Icon icon="user" size="4x" /> {' '} <span>{'4x'}</span> </p> <p> <Icon icon="user" size="5x" /> {' '} <span>{'5x'}</span> </p> <p> <Icon icon="user" size="6x" /> {' '} <span>{'6x'}</span> </p> <p> <Icon icon="user" size="7x" /> {' '} <span>{'7x'}</span> </p> <p> <Icon icon="user" size="8x" /> {' '} <span>{'8x'}</span> </p> <p> <Icon icon="user" size="9x" /> {' '} <span>{'9x'}</span> </p> <p> <Icon icon="user" size="10x" /> {' '} <span>{'10x'}</span> </p> </div> ) } export default IconSizes
When using custom icons it is important to introduce a "clean" SVG. In order to ensure these custom icons perform as intended within your kit(s), ensure these things have been modified from the original SVG markup:
Attributes must be React compatible e.g. xmlns:xlink should be xmlnsXlink and so on. There should be no hyphenated attributes and no semi-colons!.
Fill colors with regards to g or path nodes, e.g. fill="black", should be replaced with currentColor ala fill="currentColor". Your mileage may vary depending on the complexity of your SVG.
Pay attention to your custom icon's dimensions and viewBox attribute. It is best to use a viewBox="0 0 512 512" starting point when designing instead of trying to retrofit the viewbox afterwards!
You must source your own SVG into component/view you are working on. This can easily be done in programmatic and maintainable ways.
Sending the absolute path to the icon prop results in an <SVG> tag within the working view.
import React from 'react' import { Icon } from 'playbook-ui' const config = { icon: ( <svg viewBox="0 -256 1792 1792" xmlns="http://www.w3.org/2000/svg" > <g transform="matrix(1,0,0,-1,53.152542,1217.0847)"> <path d="m 384,64 q 0,26 -19,45 -19,19 -45,19 -26,0 -45,-19 -19,-19 -19,-45 0,-26 19,-45 19,-19 45,-19 26,0 45,19 19,19 19,45 z m 644,420 -682,-682 q -37,-37 -90,-37 -52,0 -91,37 L 59,-90 Q 21,-54 21,0 21,53 59,91 L 740,772 Q 779,674 854.5,598.5 930,523 1028,484 z m 634,435 q 0,-39 -23,-106 Q 1592,679 1474.5,595.5 1357,512 1216,512 1031,512 899.5,643.5 768,775 768,960 q 0,185 131.5,316.5 131.5,131.5 316.5,131.5 58,0 121.5,-16.5 63.5,-16.5 107.5,-46.5 16,-11 16,-28 0,-17 -16,-28 L 1152,1120 V 896 l 193,-107 q 5,3 79,48.5 74,45.5 135.5,81 61.5,35.5 70.5,35.5 15,0 23.5,-10 8.5,-10 8.5,-25 z" /> </g> </svg> ), } const IconCustom = (props) => { return ( <React.Fragment> <p> <Icon icon={config.icon} /> </p> <p> <Icon icon={config.icon} rotation={90} size="2x" /> </p> <p> <Icon icon={config.icon} size="3x" spin /> </p> <p> <Icon icon={config.icon} size="5x" /> </p> <p> <Icon flip="horizontal" icon={config.icon} size="5x" /> </p> </React.Fragment> ) } export default IconCustom
Our Icon kit allows integration with FontAwesome's custom kit functionality out-of-the-box.
All you need to do is 3 things:
1) Import your custom-icon.js file as outlined in the FontAwesome docs.
2) Use our fontStyle prop called "fak" so that our Icon component knows you are using a "fa-kit" icon.
3) Pass in your FaKit name as a string to our icon prop (This is the name that you designated when you uploaded the icon on their site).
Pass any text, status, data, product, or category Playbook color token to the color prop to change any icon's color.
import React from "react" import { Icon, Flex } from 'playbook-ui' const IconDefault = (props) => { return ( <div> <Flex marginBottom="sm"> <Icon color="primary" fixedWidth icon="user" size="2x" /> <Icon color="data_4" fixedWidth icon="recycle" size="2x" /> <Icon color="product_5_background" fixedWidth icon="product-roofing" size="2x" /> </Flex> <Flex> <Icon color="light" fixedWidth icon="user" size="2x" /> <Icon color="lighter" fixedWidth icon="recycle" size="2x" /> <Icon color="link" fixedWidth icon="product-roofing" size="2x" /> </Flex> </div> ) } export default IconDefault
import React from 'react' import { IconCircle } from 'playbook-ui' const IconCircleSizes = (props) => { return ( <div> <IconCircle icon="rocket" size="xxs" /> <br /> <IconCircle icon="rocket" size="xs" /> <br /> <IconCircle icon="rocket" size="sm" /> <br /> <IconCircle icon="rocket" size="md" /> <br /> <IconCircle icon="rocket" size="lg" /> <br /> <IconCircle icon="rocket" size="xl" /> </div> ) } export default IconCircleSizes
Customize your icon circle by passing one of our seven base colors to the variant prop: royal orange purple teal red yellow green
import React from 'react' import { IconCircle } from 'playbook-ui' const IconCircleColor = (props) => { return ( <div> <IconCircle icon="rocket" size="sm" variant="royal" /> <br /> <IconCircle icon="rocket" size="sm" variant="orange" /> <br /> <IconCircle icon="rocket" size="sm" variant="purple" /> <br /> <IconCircle icon="rocket" size="sm" variant="teal" /> <br /> <IconCircle icon="rocket" size="sm" variant="red" /> <br /> <IconCircle icon="rocket" size="sm" variant="yellow" /> <br /> <IconCircle icon="rocket" size="sm" variant="green" /> </div> ) } export default IconCircleColor
The Icon Circle also allows you to pass in an HTML emoji in place of an icon if needed. To do so, pass any emoji or its hexa/decimal ref (see here) as a string to the icon prop as shown in the code snippet below.
import React from 'react' import { IconCircle } from 'playbook-ui' const IconCircleEmoji = (props) => { return ( <div> <IconCircle icon="😁" size="sm" /> <br/> <IconCircle icon="😍" size="md" variant="red" /> <br/> <IconCircle icon="🎉" size="lg" variant="teal" /> </div> ) } export default IconCircleEmoji
import React from 'react' import { IconStatValue } from 'playbook-ui' const IconStatValueDefault = (props) => { return ( <div> <IconStatValue icon="lightbulb-on" text="Electric" unit="kw" value={64.18} /> <br /> <IconStatValue icon="calendar" text="deadline" unit="days" value={24} /> </div> ) } export default IconStatValueDefault
import React from 'react' import { IconStatValue } from 'playbook-ui' const IconStatValueSizes = (props) => { return ( <div> <IconStatValue icon="car" size="sm" text="distance driven" unit="mi" value={158.3} /> <br /> <IconStatValue icon="car" size="md" text="distance driven" unit="mi" value={158.3} /> <br /> <IconStatValue icon="car" size="lg" text="distance driven" unit="mi" value={158.3} /> </div> ) } export default IconStatValueSizes
import React from 'react' import { IconStatValue } from 'playbook-ui' const IconStatValueColor = (props) => { return ( <div> <IconStatValue icon="globe-europe" text="Mercury" unit="AU" value={0.39} variant="royal" /> <br /> <IconStatValue icon="planet-ringed" text="Venus" unit="AU" value={0.723} variant="purple" /> <br /> <IconStatValue icon="planet-moon" text="Earth" unit="AU" value={1.0} variant="teal" /> <br /> <IconStatValue icon="solar-system" text="Mars" unit="AU" value={1.524} variant="red" /> <br /> <IconStatValue icon="globe-americas" text="Jupiter" unit="AU" value={5.203} variant="yellow" /> <br /> <IconStatValue icon="globe-africa" text="Saturn" unit="AU" value={9.539} variant="green" /> <br /> <IconStatValue icon="globe" text="Uranus" unit="AU" value={19.18} variant="orange" /> </div> ) } export default IconStatValueColor
import React from 'react' import { IconValue } from 'playbook-ui' const IconValueDefault = (props) => { return ( <div> <IconValue icon="clipboard" text="33-123456" /> <br /> <IconValue icon="heart" text="93" /> <br /> <IconValue icon="clock" text="15min" /> </div> ) } export default IconValueDefault
import React from 'react' import { IconValue } from 'playbook-ui' const IconValueAlign = (props) => { return ( <div> <IconValue icon="heart" text="93" /> <br /> <IconValue align="center" icon="comment" text="5" /> <br /> <IconValue align="right" icon="clock" text="15min" /> </div> ) } export default IconValueAlign
Use these to represent what affiliation an employee has.
import React from 'react' import { UserBadge } from 'playbook-ui' const UserBadgeSize = () => { return ( <div> <div> <UserBadge badge="veteran" size="sm" /> </div> <br /> <br /> <div> <UserBadge badge="veteran" size="md" /> </div> <br /> <br /> <div> <UserBadge badge="veteran" size="lg" /> </div> </div> ) } export default UserBadgeSize
import React from 'react' import { Image } from 'playbook-ui' const DefaultImage = (props) => { return ( <> <br /> <div> <Image alt="picture of a misty forest" size="xs" url="https://unsplash.it/500/400/?image=634" /> </div> <div> <Image alt="picture of a misty forest" size="sm" url="https://unsplash.it/500/400/?image=634" /> </div> <div> <Image alt="picture of a misty forest" size="md" url="https://unsplash.it/500/400/?image=634" /> </div> <div> <Image alt="picture of a misty forest" size="lg" url="https://unsplash.it/500/400/?image=634" /> </div> <div> <Image alt="picture of a misty forest" size="xl" url="https://unsplash.it/500/400/?image=634" /> </div> <div> <Image alt="picture of a misty forest" url="https://unsplash.it/500/400/?image=634" /> </div> </> ) } export default DefaultImage
import React from 'react' import { Image } from 'playbook-ui' const RoundedImage = (props) => { return ( <> <br /> <div> <Image alt="" rounded size="xs" url="https://unsplash.it/500/400/?image=634" /> </div> <div> <Image alt="" rounded size="sm" url="https://unsplash.it/500/400/?image=634" /> </div> <div> <Image alt="" rounded size="md" url="https://unsplash.it/500/400/?image=634" /> </div> <div> <Image alt="" rounded size="lg" url="https://unsplash.it/500/400/?image=634" /> </div> <div> <Image alt="" rounded size="xl" url="https://unsplash.it/500/400/?image=634" /> </div> </> ) } export default RoundedImage
import React from 'react' import { Image, Body } from 'playbook-ui' const CustomErrorImage = (props) => { return ( <> <Body text="Handle when an image fails to load or a broken link is passed. This is not neccessary most of the time." /> <br /> <Body text="Alter the display when the image fails to load:" /> <Image alt="This is the alt text!" onError={(e) => e.target.style.color = 'red'} rounded size="xs" url="not_a_valid_url" /> <br /> <br /> <Body text="Give it an error class:" /> <Image alt="This is the alt text!" onError={(e) => e.target.classList.add('image-error')} rounded size="sm" url="not_a_valid_url" /> <br /> <br /> <Body text="Set an inline style" /> <Image alt="This is the alt text!" onError={(e) => e.target.style.outline = '1px solid red'} rounded size="md" url="not_a_valid_url" /> <br /> <br /> <Body text="Hide it completely!" /> <Image alt="This is the alt text!" onError={(e) => e.target.style.display = 'none'} rounded size="md" url="not_a_valid_url" /> </> ) } export default CustomErrorImage
To add a transition, simply use the transition prop and one of the three string options "fade", "blur", or "scale".
import React, { useState } from 'react' import { Image, Select, FlexItem, Flex, Button } from 'playbook-ui' const TransitionImage = (props) => { const [transition, setTransition] = useState('') const [apply, setApply] = useState({ url: '', transition: '', }) const loadImage = () => { document.querySelector('.image').classList.remove(transition, 'lazyloaded') setApply({ url: 'https://unsplash.it/500/400/?image=634', transition: transition, }, document.querySelector('.image').classList.add(transition, 'lazyload') ) } const handleTransition = ({ target }) => { setTransition(target.value) } const options = [ { value: 'fade', }, { value: 'blur', }, { value: 'scale', }, ] return ( <> <Flex> <FlexItem fixedSize="250px"> <Select blankSelection="Select a Transition..." label="" onChange={handleTransition} options={options} /> </FlexItem> <FlexItem> <Button disabled={transition === '' ? true : false} marginLeft="sm" onClick={loadImage} text="Load Image" /> </FlexItem> </Flex> <div style={{ display: apply.url === '' ? 'none' : 'block' }}> <Image alt="picture of a misty forest" className="image" transition={apply.transition} url={apply.url} /> </div> </> ) } export default TransitionImage
Lightbox contains several props: photos (an array of urls), initialPhoto (a number), onClickLeft (an optional callback function for top left close button), title and description (string or custom components), icon ( optional prop for the close button in the top left of the header), navRight (optional prop that renders clickable text in the top right section of the header), onClickRight (optional callback function of navRight) and onChange (optional event handler prop exposing index of current photo).
import React, { useState } from 'react' import { Flex, Image, Lightbox } from 'playbook-ui' const LightboxDefault = (props) => { const photos = [ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', ] const [selectedPhoto, setSelectedPhoto] = useState(0) const [showLightbox, toggleShowLightbox] = useState(false) const handleCloseLightbox = () => { toggleShowLightbox(!showLightbox) setSelectedPhoto(null) } const onPhotoClick = (photoIndex) => { toggleShowLightbox(!showLightbox) setSelectedPhoto(photoIndex) } return ( <> <div> {showLightbox ? ( <Lightbox icon="times" initialPhoto={selectedPhoto} onClose={handleCloseLightbox} photos={photos} /> ) : ( <div className="PhotoViewer"> <Flex> {photos.map((photo, index) => { return ( <div key={photo[index]} onClick={() => onPhotoClick(index)} > <Image cursor="pointer" marginRight="xl" rounded size="lg" url={photo} /> <div className="overlay" /> </div> ) })} </Flex> </div> )} </div> </> ) } export default LightboxDefault
When multiple images are passed to the Lightbox kit, it will also display scrollable thumbnails at the bottom of the screen for easier access to all images. In addition to the scrollable thumbnails, larger screens provide arrow buttons on the left and right of the image itself for easier scrolling while on mobile devices the kit allows for swiping.
This example also highlights the use of the optional onChange prop which is an event handler prop that tracks the index of the image being viewed and exposes it for use by the developer.
import React, { useState } from 'react' import { Flex, Image, Lightbox } from 'playbook-ui' const LightboxMultiple = (props) => { const photos = [ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', ] const [selectedPhoto, setSelectedPhoto] = useState(0) const [light, toggleLight] = useState(false) const handleCloseLightbox = () => { toggleLight(!light) setSelectedPhoto(null) } const onPhotoClick = (photo) => { toggleLight(!light) setSelectedPhoto(photo) } const exampleStyles = { width: "100%", overflow: "auto" } return ( <div> {light ? ( <Lightbox icon="times" initialPhoto={selectedPhoto} onChange={(index) => console.log(`current photo index: ${index}`)} onClose={handleCloseLightbox} photos={photos} /> ) : ( <div className="PhotoViewer" style={exampleStyles} > <Flex> {photos.map((photo, index) => { return ( <div key={index} onClick={() => onPhotoClick(index)} > <Image cursor="pointer" marginRight="xl" rounded size="lg" url={photo} /> <div className="overlay" /> </div> ) })} </Flex> </div> )} </div> ) } export default LightboxMultiple
title and description are optional props that can be passed to the kit if needed. Each of these props can take a string OR a custom component. This example highlights what the kit will look like when only strings are passed as title and description.
import React, { useState } from 'react' import { Flex, Image, Lightbox } from 'playbook-ui' const LightboxCompoundComponent = (props) => { const photos = [ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1501045337096-542a73dafa4f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2052&q=80', 'https://images.unsplash.com/photo-1563693998336-93c10e5d8f91?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80,', ] const [selectedPhoto, setSelectedPhoto] = useState(0) const [showLightbox, toggleShowLightbox] = useState(false) const handleCloseLightbox = () => { toggleShowLightbox(!showLightbox) setSelectedPhoto(null) } const onPhotoClick = (photo) => { toggleShowLightbox(!showLightbox) setSelectedPhoto(photo) } const exampleStyles = { width: "100%", overflow: "auto" } return ( <> <div> {showLightbox ? ( <Lightbox description='Description Content Goes Here.' initialPhoto={selectedPhoto} onClose={handleCloseLightbox} photos={photos} title='Windows, Sidings, & Gutters' /> ) : ( <div className="PhotoViewer" style={exampleStyles} > <Flex> {photos.map((photo, index) => { return ( <div key={index} onClick={() => onPhotoClick(index)} > <Image cursor="pointer" marginRight="xl" rounded size="lg" url={photo} /> <div className="overlay" /> </div> ) })} </Flex> </div> )} </div> </> ) } export default LightboxCompoundComponent
title and description props also accept custom components if needed. The optional navRight prop only accepts a string that translates into a clickable button. onClickRight prop can be used to pass in click function for navRight.
import React, { useState } from "react"; import { Flex, Image, Title, Pill, Lightbox } from 'playbook-ui' const LightboxCustomHeader = (props) => { const photos = [ "https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80", "https://images.unsplash.com/photo-1501045337096-542a73dafa4f?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2052&q=80", "https://images.unsplash.com/photo-1563693998336-93c10e5d8f91?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1470&q=80,", ]; const [selectedPhoto, setSelectedPhoto] = useState(0); const [showLightbox, toggleShowLightbox] = useState(false); const handleCloseLightbox = () => { toggleShowLightbox(!showLightbox); setSelectedPhoto(null); }; const onPhotoClick = (photo) => { toggleShowLightbox(!showLightbox); setSelectedPhoto(photo); }; const exampleStyles = { width: "100%", overflow: "auto", }; const customTitle = ( <Title dark paddingBottom="xxs" size={4} > My Custom Title </Title> ); const customDescription = ( <> <Title dark size={4} text="Tags" /> <Pill text="3" variant="success" /> </> ); return ( <> <div> {showLightbox ? ( <Lightbox description={customDescription} initialPhoto={selectedPhoto} navRight="All Photos" onClickRight={()=> alert("Clicked!")} onClose={handleCloseLightbox} photos={photos} title={customTitle} /> ) : ( <div className="PhotoViewer" style={exampleStyles} > <Flex> {photos.map((photo, index) => { return ( <div key={index} onClick={() => onPhotoClick(index)} > <Image marginRight="xl" rounded size="lg" url={photo} /> <div className="overlay" /> </div> ); })} </Flex> </div> ) } </div> </> ); }; export default LightboxCustomHeader;
The currentPhotoIndex prop allows the user to pass a number to the lightbox that will set the current slide by index. This can be leveraged if the user wants to change slides using custom buttons. To do this, the user must also make use of the current slide's index that is exposed by the onChange prop.
import React, { useState } from 'react' import { Flex, Image, Button, Body, FlexItem, Lightbox } from 'playbook-ui' const LightboxCurrentPhoto = (props) => { const photos = [ 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', 'https://images.unsplash.com/photo-1638727228877-d2a79ab75e68?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2668&q=80', 'https://images.unsplash.com/photo-1526657782461-9fe13402a841?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=1984&q=80', 'https://images.unsplash.com/photo-1523057530100-383d7fbc77a1?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=2669&q=80', ] const [light, toggleLight] = useState(false) //Setting state with the index of the current slide exposed by the onChange prop const [active, setActive] = useState(0) //Setting state for the current photo to pass to the kit const [currentPhoto, setCurrentPhoto] = useState(active) const handleCloseLightbox = () => { toggleLight(!light) } const onPhotoClick = () => { toggleLight(!light) } const exampleStyles = { width: "100%", overflow: "auto" } return ( <div className="lightbox_doc_example_custom"> {light ? ( <> <Flex alignItems="center" className='custom_lightbox_sidebar' justifyContent="center" > <Flex margin='lg' orientation='column' > <Body marginBottom='md'> This UI is for demonstration purposes only to demonstrate how external buttons can be used to change the slides. </Body> <FlexItem alignSelf="center"> <Flex justifyContent="center"> <Button onClick={()=> setCurrentPhoto(active > 0 ? active - 1 : 0)} > Back </Button> <Button marginLeft='sm' onClick={() => setCurrentPhoto(active < photos.length - 1 ? active + 1 : photos.length - 1)} > Next </Button> </Flex> </FlexItem> </Flex> </Flex> <Lightbox currentPhotoIndex={currentPhoto} icon="times" onChange={(index) => setActive(index)} onClose={handleCloseLightbox} photos={photos} /> </> ) : ( <div className="PhotoViewer" style={exampleStyles} > <Flex> {photos.map((photo, index) => { return ( <div key={index} onClick={() => onPhotoClick(index)} > <Image cursor="pointer" marginRight="xl" rounded size="lg" url={photo} /> <div className="overlay" /> </div> ) })} </Flex> </div> )} </div> ) } export default LightboxCurrentPhoto
import React from 'react' import { StarRating } from 'playbook-ui' const StarRatingDefault = (props) => ( <> <StarRating paddingBottom="xs" /> <StarRating paddingBottom="xs" rating={0.9} /> <StarRating paddingBottom="xs" rating={1.5} /> <StarRating paddingBottom="xs" rating={3} /> <StarRating paddingBottom="xs" rating={4.2} /> <StarRating paddingBottom="xs" rating={5} /> </> ) export default StarRatingDefault
import React from 'react' import { StarRating } from 'playbook-ui' const StarRatingColorOptions = (props) => ( <> <StarRating paddingBottom="xs" rating={3} /> <StarRating colorOption='primary' paddingBottom="xs" rating={3} /> <StarRating colorOption='subtle' paddingBottom="xs" rating={3} /> </> ) export default StarRatingColorOptions
import React from 'react' import { StarRating } from 'playbook-ui' const StarRatingHide = (props) => ( <> <StarRating paddingBottom="xs" rating={3} /> <StarRating layoutOption={"number"} paddingBottom="xs" rating={2.8} /> <StarRating layoutOption={"number"} paddingBottom="xs" rating={3} /> <StarRating layoutOption={"onestar"} paddingBottom="xs" rating={1} /> </> ) export default StarRatingHide
import React from 'react' import { StarRating } from 'playbook-ui' const StarRatingNumberConfig = (props) => ( <> <StarRating denominator={3} paddingBottom="xs" rating={3} /> <StarRating denominator={4} paddingBottom="xs" rating={3} /> <StarRating denominator={5} paddingBottom="xs" rating={3} /> <StarRating denominator={6} paddingBottom="xs" rating={3} /> <StarRating denominator={7} paddingBottom="xs" rating={3} /> <StarRating denominator={8} paddingBottom="xs" rating={3} /> </> ) export default StarRatingNumberConfig
import React from 'react' import { StarRating } from 'playbook-ui' const StarRatingSizeOptions = (props) => ( <> <StarRating paddingBottom="xs" rating={3} size="xs" /> <StarRating paddingBottom="xs" rating={3} size="sm" /> <StarRating paddingBottom="xs" rating={3} size="md" /> <StarRating paddingBottom="xs" rating={3} size="lg" /> <StarRating layoutOption="number" paddingBottom="xs" rating={3} size="lg" /> <StarRating layoutOption="onestar" paddingBottom="xs" rating={3} size="lg" /> </> ) export default StarRatingSizeOptions