This kit provides a wrapping class to place around the MapLibre library. Complete docs for using the library can be found here.
Basic setup to start using MapLibre:
yarn add maplibre-gl@import url("https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css");
OR include it as a link in the tag <link href='https://unpkg.com/maplibre-gl@2.4.0/dist/maplibre-gl.css' rel='stylesheet' />Notes :
zoomBtns and flyTo to true and pass in zoomInClick, zoomOutClick and flyToClick as shown in this doc example. mapTheme.marker to set the Marker color. scrollZoom has been disabled in these doc examples for page usabilityimport React, { useRef, useEffect, useState } from 'react' import { Map, mapTheme } from 'playbook-ui' import maplibregl from 'maplibre-gl' const MapDefault = (props) => { //set Map instance to access from outside useEffect const [mapInstance, setMapInstance] = useState(null) const mapContainerRef = useRef(null) //Set default position const defaultPosition = [-75.379143, 39.831200] // linking Maplibre methods to PB custom zoom in, zoom out, and fly to buttons const handleZoomIn = (map) => {map.zoomIn({...mapTheme.zoomConfig})} const handleZoomOut = (map) => {map.zoomOut({...mapTheme.zoomConfig})} const handleFlyTo = (map) => {map.flyTo({ center: defaultPosition, ... mapTheme.flyToConfig });} //This function is called by the useEffect when map instance first loads const loadMap = ( { target: map }) => { //set marker/pin new maplibregl.Marker({ color: mapTheme.marker, }).setLngLat(defaultPosition) .setPopup(new maplibregl.Popup({closeButton: false}).setHTML(`<h4 class="pb_title_kit pb_title_4">Hello World!</h4>`)) // add popup .addTo(map); // disable map zoom when using scroll map.scrollZoom.disable(); //add attributioncontrols map.addControl(new maplibregl.AttributionControl({ compact: true })); //set map instance setMapInstance(map) } useEffect(() => { new maplibregl.Map({ container: mapContainerRef.current, center: defaultPosition, ...mapTheme.mapConfig }).on('load', loadMap) }, []) return ( <Map flyTo flyToClick={()=> {handleFlyTo(mapInstance)}} zoomBtns zoomInClick={() => {handleZoomIn(mapInstance)}} zoomOutClick={()=> {handleZoomOut(mapInstance)}} > <div ref={mapContainerRef} style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, }} /> </Map> ) } export default MapDefault
Various plugins are available for use with MapLibre, one of which is the mapbox-gl-draw. This plugin is recommended by MapLibre if you need to add the functionality of drawing polygons on the map.
To test this tool:
import React, { useRef, useEffect, useState } from 'react' import { Map, mapTheme } from 'playbook-ui' import maplibregl from 'maplibre-gl' import MapboxDraw from "@mapbox/mapbox-gl-draw"; const MapWithPlugin = (props) => { //set Map instance to access from outside useEffect const [mapInstance, setMapInstance] = useState(null) const mapContainerRef = useRef(null) //Set default position const defaultPosition = [-75.379143, 39.831200] // linking Maplibre methods to PB custom zoom in, zoom out, and fly to buttons const handleZoomIn = (map) => {map.zoomIn({...mapTheme.zoomConfig})} const handleZoomOut = (map) => {map.zoomOut({...mapTheme.zoomConfig})} const handleFlyTo = (map) => {map.flyTo({ center: defaultPosition, ... mapTheme.flyToConfig });} //This function should contain all maplibre related code const loadMap = ( { target: map }) => { //set marker/pin new maplibregl.Marker({ color: mapTheme.marker, }).setLngLat(defaultPosition) .setPopup(new maplibregl.Popup({closeButton: false}).setHTML(`<h4 class="pb_title_kit pb_title_4">Hello World!</h4>`)) // add popup .addTo(map); //add maplibre default zoom controls // map.addControl(new maplibregl.NavigationControl({showCompass: false})) // disable map zoom when using scroll map.scrollZoom.disable(); //Add polygon draw button using map-box-gl-draw plugin var draw = new MapboxDraw({ displayControlsDefault: false, controls: { polygon: true, trash: true } }); map.addControl(draw); //add attributioncontrols map.addControl(new maplibregl.AttributionControl({ compact: true })); //set map instance setMapInstance(map) } useEffect(() => { new maplibregl.Map({ container: mapContainerRef.current, center: defaultPosition, ...mapTheme.mapConfig }).on('load', loadMap) }, []) return ( <Map flyTo flyToClick={()=> {handleFlyTo(mapInstance)}} zoomBtns zoomInClick={() => {handleZoomIn(mapInstance)}} zoomOutClick={()=> {handleZoomOut(mapInstance)}} > <div ref={mapContainerRef} style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, }} /> </Map> ) } export default MapWithPlugin
If you want to add custom buttons to the Map, you can use the MapCustomButton component nested inside Map.Controls as shown in the code snippet below. Note that when Map.Controls is used in this way, the props for the rest of the buttons must also be passed to Map.Controls instead of the Map itself.
import React, { useRef, useEffect, useState } from 'react' import { Map, mapTheme, MapCustomButton } from 'playbook-ui' import maplibregl from 'maplibre-gl' const MapWithCustomButton = (props) => { //set Map instance to access from outside useEffect const [mapInstance, setMapInstance] = useState(null) const mapContainerRef = useRef(null) //Set default position const defaultPosition = [-75.379143, 39.831200] // linking Maplibre methods to PB custom zoom in, zoom out, and fly to buttons const handleZoomIn = (map) => {map.zoomIn({...mapTheme.zoomConfig})} const handleZoomOut = (map) => {map.zoomOut({...mapTheme.zoomConfig})} const handleFlyTo = (map) => {map.flyTo({ center: defaultPosition, ... mapTheme.flyToConfig });} //This function is called by the useEffect when map instance first loads const loadMap = ( { target: map }) => { //set marker/pin new maplibregl.Marker({ color: mapTheme.marker, }).setLngLat(defaultPosition) .setPopup(new maplibregl.Popup({closeButton: false}).setHTML(`<h4 class="pb_title_kit pb_title_4">Hello World!</h4>`)) // add popup .addTo(map); // disable map zoom when using scroll map.scrollZoom.disable(); //add attributioncontrols map.addControl(new maplibregl.AttributionControl({ compact: true })); //set map instance setMapInstance(map) } useEffect(() => { new maplibregl.Map({ container: mapContainerRef.current, center: defaultPosition, ...mapTheme.mapConfig }).on('load', loadMap) }, []) return ( <Map > <Map.Controls flyTo flyToClick={()=> {handleFlyTo(mapInstance)}} zoomBtns zoomInClick={() => {handleZoomIn(mapInstance)}} zoomOutClick={()=> {handleZoomOut(mapInstance)}} > <MapCustomButton icon="home" onClick={() => alert("button clicked!")} /> <MapCustomButton icon="search" onClick={() => alert("button clicked!")} /> </Map.Controls> <div ref={mapContainerRef} style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0, }} /> </Map> ) } export default MapWithCustomButton
Use table size "sm" when data density is a priority. Smaller row height enables the user to view more data without the need for scrolling.
Table can leverage the max-width property. Learn more on our Max Width Global Props page.
import React from 'react' import { Table } from 'playbook-ui' const TableSm = (props) => { return ( <Table size="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) } export default TableSm
Use table size "md" to add padding around each row to increase reading comfortability.
import React from 'react' import { Table } from 'playbook-ui' const TableMd = (props) => { return ( <Table size="md" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) } export default TableMd
Use table size "lg" to add padding around each row to maximize reading comfortability.
import React from 'react' import { Table } from 'playbook-ui' const TableLg = (props) => { return ( <Table size="lg" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) } export default TableLg
React: Use sticky on a table to allow the table header to be fixed in place when the user scrolls up and down on the page.
Rails: Pass sticky: true to props.
If the table header is not sticking in the right place you will need to pass a inline top style to the thead.
React Example: <thead style={{ top: "-16px" }}>
Rails Example: <thead style="top: -16px">
Sticky may not work if any parent/ancestor of the sticky element has any of the overflow properties set. Additionally, specifying a height on the overflowing container provides measurement for this feature to work properly. In some cases, it may be necessary to set the same parent/ancestor container to position: static as well.
import React from "react" import { Table } from 'playbook-ui' const TableSticky = (props) => ( <Table sticky > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) export default TableSticky
The stickyLeftColumn prop expects an array of the column data-sticky-ids you want to be sticky. Make sure to add the corresponding data-sticky-id to the <th> and <td>.
If you are using the sub-component variant, then you will pass the data-sticky-id to <Table.Header> and <Table.Cell>
Please ensure that unique data-sticky-ids are used for all columns across multiple tables. Using the same columns data-sticky-ids on multiple tables can lead to issues when using stickyLeftColumn prop.
import React from 'react' import { Table } from 'playbook-ui' const TableStickyLeftColumns = () => { return ( <Table responsive="scroll" size="md" stickyLeftColumn={["1", "2", "3"]} > <thead> <tr> <th data-sticky-id="1">{'Column 1'}</th> <th data-sticky-id="2">{'Column 2'}</th> <th data-sticky-id="3">{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> <th>{'Column 6'}</th> <th>{'Column 7'}</th> <th>{'Column 8'}</th> <th>{'Column 9'}</th> <th>{'Column 10'}</th> <th>{'Column 11'}</th> <th>{'Column 12'}</th> <th>{'Column 13'}</th> <th>{'Column 14'}</th> <th>{'Column 15'}</th> </tr> </thead> <tbody> <tr> <td data-sticky-id="1">{'Value 1'}</td> <td data-sticky-id="2">{'Value 2'}</td> <td data-sticky-id="3">{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> <td>{'Value 6'}</td> <td>{'Value 7'}</td> <td>{'Value 8'}</td> <td>{'Value 9'}</td> <td>{'Value 10'}</td> <td>{'Value 11'}</td> <td>{'Value 12'}</td> <td>{'Value 13'}</td> <td>{'Value 14'}</td> <td>{'Value 15'}</td> </tr> <tr> <td data-sticky-id="1">{'Value 1'}</td> <td data-sticky-id="2">{'Value 2'}</td> <td data-sticky-id="3">{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> <td>{'Value 6'}</td> <td>{'Value 7'}</td> <td>{'Value 8'}</td> <td>{'Value 9'}</td> <td>{'Value 10'}</td> <td>{'Value 11'}</td> <td>{'Value 12'}</td> <td>{'Value 13'}</td> <td>{'Value 14'}</td> <td>{'Value 15'}</td> </tr> <tr> <td data-sticky-id="1">{'Value 1'}</td> <td data-sticky-id="2">{'Value 2'}</td> <td data-sticky-id="3">{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> <td>{'Value 6'}</td> <td>{'Value 7'}</td> <td>{'Value 8'}</td> <td>{'Value 9'}</td> <td>{'Value 10'}</td> <td>{'Value 11'}</td> <td>{'Value 12'}</td> <td>{'Value 13'}</td> <td>{'Value 14'}</td> <td>{'Value 15'}</td> </tr> </tbody> </Table> ) } export default TableStickyLeftColumns
The stickyRightColumn prop works in the same way as the above stickyLeftColumn prop. It expects an array of the column data-sticky-ids you want to be sticky. Make sure to add the corresponding data-sticky-id to the <th> and <td>.
If you are using the sub-component variant, then you will pass the data-sticky-id to <Table.Header> and <Table.Cell>
Please ensure that unique data-sticky-ids are used for all columns across multiple tables. Using the same columns data-sticky-ids on multiple tables can lead to issues when using the stickyRightColumn prop.
import React from 'react' import { Table } from 'playbook-ui' const TableStickyRightColumns = () => { return ( <Table responsive="scroll" size="md" stickyRightColumn={["13", "14", "15"]} > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> <th>{'Column 6'}</th> <th>{'Column 7'}</th> <th>{'Column 8'}</th> <th>{'Column 9'}</th> <th>{'Column 10'}</th> <th>{'Column 11'}</th> <th>{'Column 12'}</th> <th data-sticky-id="13">{'Column 13'}</th> <th data-sticky-id="14">{'Column 14'}</th> <th data-sticky-id="15">{'Column 15'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> <td>{'Value 6'}</td> <td>{'Value 7'}</td> <td>{'Value 8'}</td> <td>{'Value 9'}</td> <td>{'Value 10'}</td> <td>{'Value 11'}</td> <td>{'Value 12'}</td> <td data-sticky-id="13">{'Value 13'}</td> <td data-sticky-id="14">{'Value 14'}</td> <td data-sticky-id="15">{'Value 15'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> <td>{'Value 6'}</td> <td>{'Value 7'}</td> <td>{'Value 8'}</td> <td>{'Value 9'}</td> <td>{'Value 10'}</td> <td>{'Value 11'}</td> <td>{'Value 12'}</td> <td data-sticky-id="13">{'Value 13'}</td> <td data-sticky-id="14">{'Value 14'}</td> <td data-sticky-id="15">{'Value 15'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> <td>{'Value 6'}</td> <td>{'Value 7'}</td> <td>{'Value 8'}</td> <td>{'Value 9'}</td> <td>{'Value 10'}</td> <td>{'Value 11'}</td> <td>{'Value 12'}</td> <td data-sticky-id="13">{'Value 13'}</td> <td data-sticky-id="14">{'Value 14'}</td> <td data-sticky-id="15">{'Value 15'}</td> </tr> </tbody> </Table> ) } export default TableStickyRightColumns
The stickyLeftColumn and stickyRightColumn props can be used together on the same table as needed.
Please ensure that unique data-sticky-ids are used for all columns across multiple tables. Using the same columns data-sticky-ids on multiple tables can lead to issues when using props.
import React from 'react' import { Table } from 'playbook-ui' const TableStickyColumns = () => { return ( <Table responsive="scroll" size="md" stickyLeftColumn={["a"]} stickyRightColumn={["b"]} > <thead> <tr> <th data-sticky-id="a">{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> <th>{'Column 6'}</th> <th>{'Column 7'}</th> <th>{'Column 8'}</th> <th>{'Column 9'}</th> <th>{'Column 10'}</th> <th>{'Column 11'}</th> <th>{'Column 12'}</th> <th>{'Column 13'}</th> <th>{'Column 14'}</th> <th data-sticky-id="b">{'Column 15'}</th> </tr> </thead> <tbody> <tr> <td data-sticky-id="a">{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> <td>{'Value 6'}</td> <td>{'Value 7'}</td> <td>{'Value 8'}</td> <td>{'Value 9'}</td> <td>{'Value 10'}</td> <td>{'Value 11'}</td> <td>{'Value 12'}</td> <td>{'Value 13'}</td> <td>{'Value 14'}</td> <td data-sticky-id="b">{'Value 15'}</td> </tr> <tr> <td data-sticky-id="a">{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> <td>{'Value 6'}</td> <td>{'Value 7'}</td> <td>{'Value 8'}</td> <td>{'Value 9'}</td> <td>{'Value 10'}</td> <td>{'Value 11'}</td> <td>{'Value 12'}</td> <td>{'Value 13'}</td> <td>{'Value 14'}</td> <td data-sticky-id="b">{'Value 15'}</td> </tr> <tr> <td data-sticky-id="a">{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> <td>{'Value 6'}</td> <td>{'Value 7'}</td> <td>{'Value 8'}</td> <td>{'Value 9'}</td> <td>{'Value 10'}</td> <td>{'Value 11'}</td> <td>{'Value 12'}</td> <td>{'Value 13'}</td> <td>{'Value 14'}</td> <td data-sticky-id="b">{'Value 15'}</td> </tr> </tbody> </Table> ) } export default TableStickyColumns
Pass our textAlign global prop to any table.row subcomponent to change the text alignment of all cells within that row.
The header/ first row is the default, followed by the second row being centered, and then the last row shifted to the right.
import React from 'react' import { Table } from 'playbook-ui' const TableAlignmentRow = (props) => { return ( <Table > <Table.Head> <Table.Row> <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header>{'Column 4'}</Table.Header> <Table.Header>{'Column 5'}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> </Table.Row> <Table.Row textAlign="center"> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> </Table.Row> <Table.Row textAlign="right"> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableAlignmentRow
Pass our textAlign global prop to any table.cell subcomponent to change the text alignment of individual cells, or apply this prop persistently to align entire columns.
In the table above the "Rating" column contents is centered and the "Money" column contents is right aligned.
import React from 'react' import { Table } from 'playbook-ui' const TableAlignmentColumn = (props) => { return ( <Table > <Table.Head> <Table.Row> <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header textAlign="center">{'Rating'}</Table.Header> <Table.Header textAlign="right">{'Money'}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell textAlign="center">{'3'}</Table.Cell> <Table.Cell textAlign="right">{'$57.32'}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell textAlign="center">{'2'}</Table.Cell> <Table.Cell textAlign="right">{'$5,657.08'}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell textAlign="center">{'4'}</Table.Cell> <Table.Cell textAlign="right">{'$358.77'}</Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableAlignmentColumn
Pass our verticalAlign global prop to any table.row subcomponent to change the vertical alignment of all cells within that row.
import React from 'react' import { Table } from 'playbook-ui' const TableAlignmentShiftRow = (props) => { return ( <Table> <Table.Head> <Table.Row> <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header>{'Column 4'}</Table.Header> <Table.Header>{'Column 5'}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row> <Table.Cell> {'Value 1a'} <br /> {'Value 1a'} <br /> {'Value 1a'} </Table.Cell> <Table.Cell>{'Value 2a'}</Table.Cell> <Table.Cell>{'Value 3a'}</Table.Cell> <Table.Cell>{'Value 4a'}</Table.Cell> <Table.Cell>{'Value 5a'}</Table.Cell> </Table.Row> <Table.Row verticalAlign="middle"> <Table.Cell> {'Value 1b'} <br /> {'Value 1b'} <br /> {'Value 1b'} </Table.Cell> <Table.Cell>{'Value 2b'}</Table.Cell> <Table.Cell>{'Value 3b'}</Table.Cell> <Table.Cell>{'Value 4b'}</Table.Cell> <Table.Cell>{'Value 5b'}</Table.Cell> </Table.Row> <Table.Row verticalAlign="bottom"> <Table.Cell> {'Value 1c'} <br /> {'Value 1c'} <br /> {'Value 1c'} </Table.Cell> <Table.Cell>{'Value 2c'}</Table.Cell> <Table.Cell>{'Value 3c'}</Table.Cell> <Table.Cell>{'Value 4c'}</Table.Cell> <Table.Cell>{'Value 5c'}</Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableAlignmentShiftRow
Pass our verticalAlign global prop to any table.cell subcomponent to change the text alignment of individual cells, or apply this prop persistently to align entire columns.
The first table shifts "Total" down, whereas the second table shifts the "Espresso Drinks" column contents up.
import React from 'react' import { Table } from 'playbook-ui' const TableAlignmentShiftData = (props) => { return ( <div> <Table marginBottom="md" > <Table.Head> <Table.Row> <Table.Header> </Table.Header> <Table.Header>{'Price'}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row> <Table.Cell verticalAlign="bottom">{'Total'}</Table.Cell> <Table.Cell> {'$12'} <br /> {'$46'} <br /> {'$25'} <br /> {'-------'} <br /> {'$83'} </Table.Cell> </Table.Row> </Table.Body> </Table> <Table > <Table.Head> <Table.Row> <Table.Header>{'Espresso Drinks'}</Table.Header> <Table.Header>{'Ingredients'}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row> <Table.Cell verticalAlign="top">{'Cappuccino'} </Table.Cell> <Table.Cell> {'Steamed Milk'} <br /> {'Milk Foam'} </Table.Cell> </Table.Row> <Table.Row> <Table.Cell verticalAlign="top"> {'Macchiato'} </Table.Cell> <Table.Cell verticalAlign="top"> {'Espresso'} <br /> {'Steamed Milk'} </Table.Cell> </Table.Row> <Table.Row> <Table.Cell> {'Mocha'} </Table.Cell> <Table.Cell> {'Hot Chocolate'} <br /> {'Steamed Milk'} </Table.Cell> </Table.Row> </Table.Body> </Table> </div> ) } export default TableAlignmentShiftData
Side highlight can take product, status, and category colors. To view full list of colors, visit token colors.
Note: Only use category colors for categories. Do not mix it with product or status colors.
import React from 'react' import { Table } from 'playbook-ui' const TableSideHighlight = (props) => { return ( <div> <Table size="sm" > <thead> <tr> <th>{'Product colors'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <Table.Row sideHighlightColor="product_1_highlight" > <td>{'Product 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> <Table.Row sideHighlightColor="product_2_highlight" > <td>{'Product 2'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> <Table.Row sideHighlightColor="product_3_highlight" > <td>{'Product 3'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> <Table.Row sideHighlightColor="none" > <td>{'None'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> </tbody> </Table> <br /> <Table size="sm" > <thead> <tr> <th>{'Status colors'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <Table.Row sideHighlightColor="success" > <td>{'Success'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> <Table.Row sideHighlightColor="warning" > <td>{'Warning'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> <Table.Row sideHighlightColor="error" > <td>{'Error'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> <Table.Row sideHighlightColor="none" > <td>{'None'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> </tbody> </Table> <br /> <Table size="sm" > <thead> <tr> <th>{'Category Colors'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <Table.Row sideHighlightColor="category_1" > <td>{'Category Color 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> <Table.Row sideHighlightColor="category_2" > <td>{'Category Color 2'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> <Table.Row sideHighlightColor="category_3" > <td>{'Category Color 3'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> <Table.Row sideHighlightColor="none" > <td>{'None'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </Table.Row> </tbody> </Table> </div> ) } export default TableSideHighlight
import React from 'react' import { Table } from 'playbook-ui' const TableContainer = (props) => { return ( <Table container={false} size="md" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) } export default TableContainer
import React from 'react' import { Table } from 'playbook-ui' const TableDisableHover = (props) => { return ( <Table disableHover size="md" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) } export default TableDisableHover
import React from 'react' import { Table } from 'playbook-ui' const TableMultiline = (props) => { return ( <Table size="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td> {'Value 1'} <br /> {'Value 1'} <br /> {'Value 1'} </td> <td>{'Value 2'}</td> <td> {'Value 3'} <br /> {'Value 3'} </td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td> {'Value 1'} <br /> {'Value 1'} <br /> {'Value 1'} </td> <td>{'Value 2'}</td> <td> {'Value 3'} <br /> {'Value 3'} </td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td> {'Value 1'} <br /> {'Value 1'} <br /> {'Value 1'} </td> <td>{'Value 2'}</td> <td> {'Value 3'} <br /> {'Value 3'} </td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) } export default TableMultiline
import React from 'react' import { Table } from 'playbook-ui' const TableSingleLine = (props) => { return ( <Table singleLine size="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td> {'Value 1'} <br /> {'Value 1'} <br /> {'Value 1'} </td> <td>{'Value 2'}</td> <td> {'Value 3'} <br /> {'Value 3'} </td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td> {'Value 1'} <br /> {'Value 1'} <br /> {'Value 1'} </td> <td>{'Value 2'}</td> <td> {'Value 3'} <br /> {'Value 3'} </td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td> {'Value 1'} <br /> {'Value 1'} <br /> {'Value 1'} </td> <td>{'Value 2'}</td> <td> {'Value 3'} <br /> {'Value 3'} </td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) } export default TableSingleLine
Tighter spacing in first- and last-child cells of each row for data-heavy tables.
import React from 'react' import { Table } from 'playbook-ui' const TableDataTable = (props) => { return ( <Table dataTable > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) } export default TableDataTable
import React from 'react' import { Table, Title } from 'playbook-ui' const TableResponsiveTable = (props) => { return ( <div> <Title size={4} text="Not Responsive" /> <Table responsive="none" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> <br /> <br /> <Title size={4} text="Collapse Mobile" /> <Table collapse="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> <br /> <br /> <Title size={4} text="Collapse Tablet" /> <Table collapse="md" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> <br /> <br /> <Title size={4} text="Collapse Desktop" /> <Table collapse="lg" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> </div> ) } export default TableResponsiveTable
If there is one button on each row of the table, ideally, it should use the secondary variant and be placed at the end of the row
import React from 'react' import { Table, Button } from 'playbook-ui' const TableOneAction = (props) => { return ( <Table size="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{''}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> {' '} <Button onClick={() => alert('button clicked!')} text="Action" variant="secondary" /> {' '} </td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> {' '} <Button onClick={() => alert('button clicked!')} text="Action" variant="secondary" /> {' '} </td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> {' '} <Button onClick={() => alert('button clicked!')} text="Action" variant="secondary" /> {' '} </td> </tr> </tbody> </Table> ) } export default TableOneAction
If there are two actions on each of the row, one should ideally one should use the secondary variant and the other use the link variant. The button using the secondary variant should be placed at the end.
import React from 'react' import { Table, Button } from 'playbook-ui' const TableOneAction = (props) => { return ( <Table size="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{''}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> <Button onClick={() => alert('button clicked!')} paddingLeft="none" text="Tertiary Action" variant="link" /> <Button onClick={() => alert('button clicked!')} text="Secondary Action" variant="secondary" /> </td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> <Button onClick={() => alert('button clicked!')} paddingLeft="none" text="Tertiary Action" variant="link" /> <Button onClick={() => alert('button clicked!')} text="Secondary Action" variant="secondary" /> </td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> <Button onClick={() => alert('button clicked!')} paddingLeft="none" text="Tertiary Action" variant="link" /> <Button onClick={() => alert('button clicked!')} text="Secondary Action" variant="secondary" /> </td> </tr> </tbody> </Table> ) } export default TableOneAction
If there are more than two actions on each row, then they should be contained in secondary circle icon button with the ellipsis-h icon (horizontal ellipsis) at the end of the row
import React from 'react' import { Table, CircleIconButton } from 'playbook-ui' const TableTwoPlusActions = (props) => { return ( <Table size="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{''}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> {' '} <CircleIconButton icon="ellipsis-h" variant="secondary" /> </td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> {' '} <CircleIconButton icon="ellipsis-h" variant="secondary" /> </td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> {' '} <CircleIconButton icon="ellipsis-h" variant="secondary" /> </td> </tr> </tbody> </Table> ) } export default TableTwoPlusActions
If the button is towards the middle of the table, it should likely use button variant link
import React from 'react' import { Table, Button } from 'playbook-ui' const TableActionMiddle = (props) => { return ( <Table size="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td> {' '} <Button onClick={() => alert('button clicked!')} paddingLeft="none" text="Action" variant="link" /> </td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td> {' '} <Button onClick={() => alert('button clicked!')} paddingLeft="none" text="Action" variant="link" /> </td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td> {' '} <Button onClick={() => alert('button clicked!')} paddingLeft="none" text="Action" variant="link" /> </td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) } export default TableActionMiddle
Icon buttons are great to use if space is limited. If the icon isn’t VERY self explanatory (for example pencil/pen for edit, trashcan for delete) then it should use a tooltip explaining what the action does. The tooltip shouldn’t be longer than a few words and essentially serves as a replacement for what the button would say if it weren’t an icon
import React from 'react' import { Table, CircleIconButton, Flex, FlexItem } from 'playbook-ui' const TableIconButtons = (props) => { return ( <Table size="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{''}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> <Flex justifyContent="end" orientation="row" > <FlexItem> <CircleIconButton icon="trash-alt" variant="link" /> </FlexItem> <FlexItem> <CircleIconButton icon="pencil" variant="secondary" /> </FlexItem> </Flex> </td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> <Flex justifyContent="end" orientation="row" > <FlexItem> <CircleIconButton icon="trash-alt" variant="link" /> </FlexItem> <FlexItem> <CircleIconButton icon="pencil" variant="secondary" /> </FlexItem> </Flex> </td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value lk'}</td> <td align="right"> <Flex justifyContent="end" orientation="row" > <FlexItem> <CircleIconButton icon="trash-alt" variant="link" /> </FlexItem> <FlexItem> <CircleIconButton icon="pencil" variant="secondary" /> </FlexItem> </Flex> </td> </tr> </tbody> </Table> ) } export default TableIconButtons
import React from 'react' import { Table, Background } from 'playbook-ui' const TableWithBackgroundKit = (props) => { return ( <div> <div> <Table > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </tr> <Background backgroundColor="error_subtle" tag='tr' > <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </Background> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </tr> <Background backgroundColor="warning_subtle" tag='tr' > <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </Background> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </tr> </tbody> </Table> </div> <div> <Table paddingTop="sm" > <colgroup> <Background backgroundColor="error_subtle" tag='col' /> <Background backgroundColor="info_subtle" tag='col' /> <Background backgroundColor="warning_subtle" tag='col' /> </colgroup> <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> </tr> </tbody> </Table> </div> </div> ) } export default TableWithBackgroundKit
import React from 'react' import { Table } from 'playbook-ui' const TableVerticalBorder = (props) => { return ( <Table size="sm" verticalBorder > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) } export default TableVerticalBorder
Optionally pass the striped (boolean, defaults to false) prop to set odd rows to a contrasting background color. This helps with readability on larger tables with lots of data.
import React from "react" import { Table } from 'playbook-ui' const TableStriped = (props) => ( <Table striped > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> ) export default TableStriped
You can optionally build your table using our sub-components, which map to their respective html table elements:
Table.Head = thead
Table.Body = tbody
Table.Row = tr
Table.Header = th
Table.Cell = td
import React from 'react' import { Table } from 'playbook-ui' const TableWithSubcomponents = (props) => { return ( <Table size="sm" > <Table.Head> <Table.Row> <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header>{'Column 4'}</Table.Header> <Table.Header>{'Column 5'}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableWithSubcomponents
Optionally build your table with divs by passing div to the tag prop of all* your sub-components.
*NOTE: The tag prop defaults to table, which returns html elements. If divs are desired, sub-components must be used and all table elements, including the initial kit call, must use div as their tag in order for the table to render properly.
import React from 'react' import { Table } from 'playbook-ui' const TableWithSubcomponentsAsDivs = (props) => { return ( <Table size="sm" tag="div" > <Table.Head tag="div"> <Table.Row tag="div"> <Table.Header tag="div">{'Column 1'}</Table.Header> <Table.Header tag="div">{'Column 2'}</Table.Header> <Table.Header tag="div">{'Column 3'}</Table.Header> <Table.Header tag="div">{'Column 4'}</Table.Header> <Table.Header tag="div">{'Column 5'}</Table.Header> </Table.Row> </Table.Head> <Table.Body tag="div"> <Table.Row tag="div"> <Table.Cell tag="div">{'Value 1'}</Table.Cell> <Table.Cell tag="div">{'Value 2'}</Table.Cell> <Table.Cell tag="div">{'Value 3'}</Table.Cell> <Table.Cell tag="div">{'Value 4'}</Table.Cell> <Table.Cell tag="div">{'Value 5'}</Table.Cell> </Table.Row> <Table.Row tag="div"> <Table.Cell tag="div">{'Value 1'}</Table.Cell> <Table.Cell tag="div">{'Value 2'}</Table.Cell> <Table.Cell tag="div">{'Value 3'}</Table.Cell> <Table.Cell tag="div">{'Value 4'}</Table.Cell> <Table.Cell tag="div">{'Value 5'}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell tag="div">{'Value 1'}</Table.Cell> <Table.Cell tag="div">{'Value 2'}</Table.Cell> <Table.Cell tag="div">{'Value 3'}</Table.Cell> <Table.Cell tag="div">{'Value 4'}</Table.Cell> <Table.Cell tag="div">{'Value 5'}</Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableWithSubcomponentsAsDivs
Pass any of our spacing tokens to the outerPadding / outer_padding prop to customize a table's outer padding (both the left padding of the first column and the right padding of the last column).
import React from 'react' import { Table, Button } from 'playbook-ui' const TableOuterPadding = (props) => { return ( <Table outerPadding="sm" size="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{''}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> {' '} <Button onClick={() => alert('button clicked!')} text="Action" variant="secondary" /> {' '} </td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> {' '} <Button onClick={() => alert('button clicked!')} text="Action" variant="secondary" /> {' '} </td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td align="right"> {' '} <Button onClick={() => alert('button clicked!')} text="Action" variant="secondary" /> {' '} </td> </tr> </tbody> </Table> ) } export default TableOuterPadding
The collapsible prop can be used on any Table Row to add a collapsible area. Use the additional collapsibleContent prop to add any content to the collapsible Row.
import React from 'react' import { Table, Icon, Card, Body } from 'playbook-ui' const TableWithCollapsible = (props) => { const Content = () => { return ( <Card borderNone borderRadius="none" padding="md" > <Body>Nested content inside a Table Row</Body> </Card> ); }; return ( <Table size="sm" > <Table.Head> <Table.Row> <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header>{'Column 4'}</Table.Header> <Table.Header>{'Column 5'}</Table.Header> <Table.Header>{''}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row collapsible collapsibleContent={<Content/>} > <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell textAlign="right">{ <Icon color="primary" fixedWidth icon="chevron-down" />} </Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell>{''}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell>{''}</Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableWithCollapsible
The collapsible prop can be used on any Table Row to add a collapsible area. Use the additional collapsibleContent prop to add any content to the collapsible Row.
Follow this example to make the icons dynamic following the state of the collapsible.
import React, { useState } from 'react' import { Table, Icon, Card, Body } from 'playbook-ui' const TableWithDynamicCollapsible = (props) => { const [isOpen, setIsOpen] = useState(false); const handleToggleArrows = () => { setIsOpen(!isOpen) } const Content = () => { return ( <Card borderNone borderRadius="none" padding="md" > <Body>Nested content inside a Table Row</Body> </Card> ); }; return ( <Table size="sm" > <Table.Head> <Table.Row> <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header>{'Column 4'}</Table.Header> <Table.Header>{'Column 5'}</Table.Header> <Table.Header>{''}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row collapsible collapsibleContent={<Content />} > <Table.Cell htmlOptions={{ onClick: handleToggleArrows }}>{'Value 1'}</Table.Cell> <Table.Cell htmlOptions={{ onClick: handleToggleArrows }}>{'Value 2'}</Table.Cell> <Table.Cell htmlOptions={{ onClick: handleToggleArrows }}>{'Value 3'}</Table.Cell> <Table.Cell htmlOptions={{ onClick: handleToggleArrows }}>{'Value 4'}</Table.Cell> <Table.Cell htmlOptions={{ onClick: handleToggleArrows }}>{'Value 5'}</Table.Cell> <Table.Cell htmlOptions={{ onClick: handleToggleArrows }} textAlign="right" > { <Icon color="primary" fixedWidth icon={isOpen ? 'chevron-up' : 'chevron-down'} />} </Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell>{''}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell>{''}</Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableWithDynamicCollapsible
When using the collapsible prop, the default functionality is that the entire Row will be clickable to toggle the Row. To limit the click event to a specific Table Cell, you can use the toggleCellId prop to pass in the id of the Cell you want to use as the trigger.
NOTE: toggleCellId and the id on the Cell you want to use as the trigger MUST be the same.
import React from 'react' import { Table, Icon, Card, Body } from 'playbook-ui' const TableWithCollapsibleWithCustomClick = (props) => { const Content = () => { return ( <Card borderNone borderRadius="none" padding="md" > <Body>Nested content inside a Table Row</Body> </Card> ); }; return ( <Table size="sm" > <Table.Head> <Table.Row> <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header>{'Column 4'}</Table.Header> <Table.Header>{'Column 5'}</Table.Header> <Table.Header>{''}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row collapsible collapsibleContent={<Content/>} toggleCellId="cell-1" > <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell cursor="pointer" id="cell-1" textAlign="right" > <Icon color="primary" fixedWidth icon="chevron-down" /> </Table.Cell> </Table.Row> <Table.Row collapsible collapsibleContent={<Content/>} toggleCellId="cell-2" > <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell cursor="pointer" id="cell-2" textAlign="right" > <Icon color="primary" fixedWidth icon="chevron-down" /> </Table.Cell> </Table.Row> <Table.Row collapsible collapsibleContent={<Content/>} toggleCellId="cell-3" > <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell cursor="pointer" id="cell-3" textAlign="right" > <Icon color="primary" fixedWidth icon="chevron-down" /> </Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableWithCollapsibleWithCustomClick
import React from 'react' import { Table, Icon, Card, Body, Image, Flex } from 'playbook-ui' const TableWithCollapsibleWithCustomContent = (props) => { const Content = () => { return ( <Card borderNone borderRadius="none" color="light" paddingX="xl" paddingY="md" > <Body paddingBottom="sm" text="Expanded Custom Layout" /> <Flex justify="between"> <Image size="sm" url="https://unsplash.it/500/400/?image=634" /> <Image size="sm" url="https://unsplash.it/500/400/?image=634" /> <Image size="sm" url="https://unsplash.it/500/400/?image=634" /> <Image size="sm" url="https://unsplash.it/500/400/?image=634" /> </Flex> </Card> ); }; return ( <Table size="sm" > <Table.Head> <Table.Row> <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header>{'Column 4'}</Table.Header> <Table.Header>{'Column 5'}</Table.Header> <Table.Header>{''}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row collapsible collapsibleContent={<Content/>} > <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell textAlign="right">{ <Icon color="primary" fixedWidth icon="chevron-down" />} </Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell>{''}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell>{''}</Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableWithCollapsibleWithCustomContent
The collapsibleContent can display any content, including nested Table Rows.
Additionally, the collapsibleSideHighlight can also be removed by setting it to false if needed. This prop is set to true by default.
NOTE: We advise against using the disableHover Table prop when nesting Table Rows within a Table.
import React from 'react' import { Table, Icon, Background } from 'playbook-ui' const TableWithCollapsibleWithNestedRows = (props) => { const Content = () => { return ( <Table borderRadius="none" container={false} size="sm" > <Background tag="tr" > <Table.Cell>Expanded</Table.Cell> <Table.Cell>Expanded</Table.Cell> <Table.Cell>Expanded</Table.Cell> <Table.Cell>Expanded</Table.Cell> <Table.Cell>Expanded</Table.Cell> </Background> </Table> ); }; return ( <Table size="sm" > <Table.Head> <Table.Row> <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header>{'Column 4'}</Table.Header> <Table.Header>{'Column 5'}</Table.Header> <Table.Header>{''}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row collapsible collapsibleContent={<Content/>} collapsibleSideHighlight={false} > <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell textAlign="right">{ <Icon color="primary" fixedWidth icon="chevron-down" />} </Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell>{''}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell>{''}</Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableWithCollapsibleWithNestedRows
The collapsibleContent can also be used to display nested Tables within each Row.
NOTE: We advise against using the disableHover Table prop when nesting Tables within a Table.
import React from 'react' import { Pill, Background, Table, Icon } from 'playbook-ui' const TableWithCollapsibleWithNestedTable = (props) => { const Content = () => { return ( <Table borderRadius="none" container={false} size="sm" > <Table.Head> <Background tag="tr" > <Table.Header>{"Alt Header"}</Table.Header> <Table.Header>{"Alt Header"}</Table.Header> <Table.Header>{"Alt Header"}</Table.Header> <Table.Header>{"Alt Header"}</Table.Header> </Background> </Table.Head> <Table.Body> <Table.Row> <Table.Cell>{"Expanded"}</Table.Cell> <Table.Cell>{"Expanded"}</Table.Cell> <Table.Cell>{"Expanded"}</Table.Cell> <Table.Cell> <Pill text="Pill" variant="primary" /> </Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{"Expanded"}</Table.Cell> <Table.Cell>{"Expanded"}</Table.Cell> <Table.Cell>{"Expanded"}</Table.Cell> <Table.Cell> <Pill text="Pill" variant="primary" /> </Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{"Expanded"}</Table.Cell> <Table.Cell>{"Expanded"}</Table.Cell> <Table.Cell>{"Expanded"}</Table.Cell> <Table.Cell> <Pill text="Pill" variant="primary" /> </Table.Cell> </Table.Row> </Table.Body> </Table> ); }; return ( <Table size="sm" > <Table.Head> <Table.Row> <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header>{'Column 4'}</Table.Header> <Table.Header>{'Column 5'}</Table.Header> <Table.Header>{''}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row collapsible collapsibleContent={<Content/>} collapsibleSideHighlight={false} > <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell textAlign="right">{ <Icon color="primary" fixedWidth icon="chevron-down" />} </Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell>{''}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> <Table.Cell>{''}</Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableWithCollapsibleWithNestedTable
Clickable table rows do not require any additional props. This doc example showcases how to set them up using html_options/htmlOptions and click events. Using the global prop for cursor to set it to "pointer" is also recommended for better UX.
import React from 'react' import { Table, Icon } from 'playbook-ui' const TableWithClickableRows = (props) => { return ( <Table size="sm" > <Table.Head> <Table.Row> <Table.Header>{"Column 1"}</Table.Header> <Table.Header>{"Column 2"}</Table.Header> <Table.Header>{"Column 3"}</Table.Header> <Table.Header>{"Column 4"}</Table.Header> <Table.Header>{"Column 5"}</Table.Header> <Table.Header>{""}</Table.Header> </Table.Row> </Table.Head> <Table.Body> <Table.Row cursor="pointer" htmlOptions={{ onClick: () => alert("Row 1 clicked") }} > <Table.Cell>{"Value 1"}</Table.Cell> <Table.Cell>{"Value 2"}</Table.Cell> <Table.Cell>{"Value 3"}</Table.Cell> <Table.Cell>{"Value 4"}</Table.Cell> <Table.Cell>{"Value 5"}</Table.Cell> <Table.Cell textAlign="right"> <Icon color="primary_action" fixedWidth icon="chevron-right" size="xs" /> </Table.Cell> </Table.Row> <Table.Row cursor="pointer" htmlOptions={{ onClick: () => alert("Row 2 clicked") }} > <Table.Cell>{"Value 1"}</Table.Cell> <Table.Cell>{"Value 2"}</Table.Cell> <Table.Cell>{"Value 3"}</Table.Cell> <Table.Cell>{"Value 4"}</Table.Cell> <Table.Cell>{"Value 5"}</Table.Cell> <Table.Cell textAlign="right"> <Icon color="primary_action" fixedWidth icon="chevron-right" size="xs" /> </Table.Cell> </Table.Row> <Table.Row cursor="pointer" htmlOptions={{ onClick: () => alert("Row 3 clicked") }} > <Table.Cell>{"Value 1"}</Table.Cell> <Table.Cell>{"Value 2"}</Table.Cell> <Table.Cell>{"Value 3"}</Table.Cell> <Table.Cell>{"Value 4"}</Table.Cell> <Table.Cell>{"Value 5"}</Table.Cell> <Table.Cell textAlign="right"> <Icon color="primary_action" fixedWidth icon="chevron-right" size="xs" /> </Table.Cell> </Table.Row> </Table.Body> </Table> ) } export default TableWithClickableRows
Use the Checkbox kit with the Table to achieve the selectable row functionality seen here.
import React, { useState } from 'react' import { Table, Image, Flex, Checkbox, Button } from 'playbook-ui' const TableWithSelectableRows = (props) => { const [checkboxes, setCheckboxes] = useState([ { name: "Coffee", checked: false }, { name: "Ice Cream", checked: false }, { name: "Chocolate", checked: true }, ]); const isAllChecked = !checkboxes.find((checkbox) => !checkbox.checked); const isNoneChecked = !checkboxes.find((checkbox) => checkbox.checked); const processCheckboxes = (checked) => checkboxes.slice(0).map((checkbox) => { checkbox.checked = checked; return checkbox; }); const onToggleAll = () => { setCheckboxes( isNoneChecked ? processCheckboxes(true) : processCheckboxes(false) ); }; const updateCheckboxes = (checkbox, index) => { const newCheckboxes = checkboxes.slice(0); newCheckboxes[index].checked = !checkbox.checked; setCheckboxes(newCheckboxes); }; return ( <> <Flex justify="end" marginBottom="sm" > {!isNoneChecked && ( <Flex justify="end" marginBottom="sm" > <Button>Delete</Button> </Flex> )} </Flex> <Table size="sm" > <Table.Head> <Table.Row> <Table.Header> <Checkbox checked={isAllChecked} indeterminate={!isAllChecked && !isNoneChecked} name="checkbox-name" onChange={onToggleAll} value="check-box value" /> </Table.Header> <Table.Header>{"Column 1"}</Table.Header> <Table.Header>{"Column 2"}</Table.Header> <Table.Header>{"Column 3"}</Table.Header> <Table.Header>{"Column 4"}</Table.Header> <Table.Header>{"Column 5"}</Table.Header> </Table.Row> </Table.Head> <Table.Body> {checkboxes.map((checkbox, index) => ( <Table.Row key={index}> <Table.Cell> <Checkbox checked={checkbox.checked} name={checkbox.name} onChange={() => { updateCheckboxes(checkbox, index); }} value="check-box value" /> </Table.Cell> <Table.Cell> <Image alt="picture of a misty forest" size="xs" url="https://unsplash.it/500/400/?image=634" /> </Table.Cell> <Table.Cell>{"Value 2"}</Table.Cell> <Table.Cell>{"Value 3"}</Table.Cell> <Table.Cell>{"Value 4"}</Table.Cell> <Table.Cell>{"Value 5"}</Table.Cell> </Table.Row> ))} </Table.Body> </Table> </> ) } export default TableWithSelectableRows
Customize your header by removing the header borders with the headerStyle="borderless" prop.
import React from 'react' import { Table } from 'playbook-ui' const TableWithHeaderStyleBorderless = (props) => { return ( <> <Table headerStyle="borderless" size="sm" > <thead> <tr> <th>{'Column 1'}</th> <th>{'Column 2'}</th> <th>{'Column 3'}</th> <th>{'Column 4'}</th> <th>{'Column 5'}</th> </tr> </thead> <tbody> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> <tr> <td>{'Value 1'}</td> <td>{'Value 2'}</td> <td>{'Value 3'}</td> <td>{'Value 4'}</td> <td>{'Value 5'}</td> </tr> </tbody> </Table> </> ) } export default TableWithHeaderStyleBorderless
Further customize your header by using the table with background kit logic to give your table header a custom background color. Use the headerStyle="floating" prop to visually nest the borderless table within a card or collapsible with a matching background color (the backgroundColor passed to Background kit should match the background or backgroundColor for the element in which it is nested).
import React from 'react' import { Background, Card, Table } from 'playbook-ui' const TableWithHeaderStyleFloating = (props) => { return ( <> <Card background="light" > <Table headerStyle="floating" size="sm" > <Table.Head> <Background backgroundColor="light" tag="tr" > <Table.Header>{'Column 1'}</Table.Header> <Table.Header>{'Column 2'}</Table.Header> <Table.Header>{'Column 3'}</Table.Header> <Table.Header>{'Column 4'}</Table.Header> <Table.Header>{'Column 5'}</Table.Header> </Background> </Table.Head> <Table.Body> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> </Table.Row> <Table.Row> <Table.Cell>{'Value 1'}</Table.Cell> <Table.Cell>{'Value 2'}</Table.Cell> <Table.Cell>{'Value 3'}</Table.Cell> <Table.Cell>{'Value 4'}</Table.Cell> <Table.Cell>{'Value 5'}</Table.Cell> </Table.Row> </Table.Body> </Table> </Card> </> ) } export default TableWithHeaderStyleFloating
Set the variant prop to withFilter to render a Table with a filter. The variant automatically handles:
title prop to render title above the cardvariant="withFilter": Enables the filter variantfilterContent: A function that receives { closePopover } and returns the filter's body content (inputs, buttons, etc.). Use this to pass in all input kits, etc needed inside the Filter itself.filterProps: An object containing Filter-specific props like results, sortOptions, sortValue, etc.title: Displays a title above the cardsize, collapse, etc.) can be used, but defaults are already set to match Design guidelinesThe Table kit automatically sets these Filter defaults (which you can override via filterProps):
background={false}maxHeight="50vh"minWidth="xs"popoverProps={{ width: "350px" }}IMPORTANT NOTE:
The purpose of this variant is to provide an easy way to set up a Table with a Filter with Design standards applied by default.
If you are looking for more customization than this embedded variant provides, you may be better served by using the individual kits as demonstrated in our Table Filter Card Building Block here.
import React, { useState } from "react" import { Button, Date as DateKit, DatePicker, Dropdown, Select, Table, TextInput, Typeahead, Flex } from 'playbook-ui' // Mock Data for Table const users = [ { id: 1, name: "Jennifer", title: "Associate Scrum Master", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-01" }, { id: 2, name: "Nick", title: "UX Engineer II", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-02" }, { id: 3, name: "Nida", title: "Senior UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-03" }, { id: 4, name: "Justin", title: "Director of User Experience Engineering", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-04" }, { id: 5, name: "Edward", title: "UX Designer II", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-05" }, { id: 6, name: "Elisa", title: "UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-06" }, { id: 7, name: "Gary", title: "UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-07" }, { id: 8, name: "Barkley", title: "Nitro Quality Ninja", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-08" }, { id: 9, name: "Aaron", title: "Associate Nitro Quality Ninja", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-09" }, ] const TableWithFilterVariant = () => { const [territory, setTerritory] = useState("") // --------Filter content example ------ const filterContent = ({ closePopover }) => ( <> <TextInput label="Territory ID" onChange={event => setTerritory(event.target.value)} value={territory} /> <Typeahead label="Title" options={[ { key: "senior-ux-engineer", label: "Senior UX Engineer", value: "senior-ux-engineer" }, { key: "ux-engineer", label: "UX Engineer", value: "ux-engineer" }, { key: "ux-designer", label: "UX Designer", value: "ux-designer" } ]} /> <Select blankSelection="All Departments" label="Department" options={[ { value: "Business Technology", label: "Business Technology", key: "business-technology" }, { value: "Customer Development", label: "Customer Development", key: "customer-development" }, { value: "Talent Acquisition", label: "Talent Acquisition", key: "talent-acquisition" } ]} /> <Dropdown label="Branch" options={[ { key: "Philadelphia", label: "Philadelphia", value: "philadelphia" }, { key: "New York", label: "New York", value: "new-york" }, { key: "Austin", label: "Austin", value: "austin" } ]} /> <DatePicker label="Start Date" paddingY="sm" pickerId="startedOn" /> <Flex spacing="between"> <Button onClick={() => { alert("No filtering functionality - just a pattern demo!") closePopover() }} text="Filter" /> <Button text="Defaults" variant="secondary" /> </Flex> </> ) // -------End Filter content example ------ return ( <Table filterContent={filterContent} filterProps={{ results: 50, sortOptions: { territory_id: "Territory ID", first_name: "Name", started_on: "Start Date", department_name: "Department", title_name: "Title", branch_branch_name: "Branch", }, sortValue: [{ name: 'started_on', dir: 'asc' }], }} title="Table Title Here" variant="withFilter" > <Table.Head> <Table.Row> <Table.Header>{'Territory ID'}</Table.Header> <Table.Header>{'Name'}</Table.Header> <Table.Header>{'Title'}</Table.Header> <Table.Header>{'Department'}</Table.Header> <Table.Header>{'Branch'}</Table.Header> <Table.Header textAlign="right">{'Start Date'}</Table.Header> </Table.Row> </Table.Head> <Table.Body> {users.map((user) => ( <Table.Row key={user.id}> <Table.Cell marginX={{ xs: "sm" }} numberSpacing="tabular" > {user.id} </Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.name}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.title}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.department}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.branch}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}> <DateKit alignment="right" showCurrentYear value={user.startDate} /> </Table.Cell> </Table.Row> ))} </Table.Body> </Table> ) } export default TableWithFilterVariant
The withFilter variant can also be used with the Pagination kit as shown here. Simply set up your Pagination as normal, and pass the Pagination kit to the prop pagination as shown.
For more information on the Pagination Kit and how to use it, see the documentation here
import React, { useState } from "react" import { Button, Date as DateKit, DatePicker, Dropdown, Pagination, Select, Table, TextInput, Typeahead, Flex } from 'playbook-ui' // Mock Data for Table const users = [ { id: 1, name: "Jennifer", title: "Associate Scrum Master", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-01" }, { id: 2, name: "Nick", title: "UX Engineer II", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-02" }, { id: 3, name: "Nida", title: "Senior UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-03" }, { id: 4, name: "Justin", title: "Director of User Experience Engineering", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-04" }, { id: 5, name: "Edward", title: "UX Designer II", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-05" }, { id: 6, name: "Elisa", title: "UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-06" }, { id: 7, name: "Gary", title: "UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-07" }, { id: 8, name: "Barkley", title: "Nitro Quality Ninja", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-08" }, { id: 9, name: "Aaron", title: "Associate Nitro Quality Ninja", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-09" }, { id: 10, name: "Sarah", title: "Senior Product Manager", department: "Business Technology", branch: "New York", startDate: "2025-01-10" }, { id: 11, name: "Michael", title: "Software Engineer III", department: "Business Technology", branch: "Austin", startDate: "2025-01-11" }, { id: 12, name: "Emma", title: "Data Analyst II", department: "Customer Development", branch: "Philadelphia", startDate: "2025-01-12" }, { id: 13, name: "David", title: "QA Engineer", department: "Business Technology", branch: "New York", startDate: "2025-01-13" }, { id: 14, name: "Lisa", title: "UX Researcher", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-14" }, { id: 15, name: "James", title: "DevOps Engineer", department: "Business Technology", branch: "Austin", startDate: "2025-01-15" }, { id: 16, name: "Anna", title: "Product Designer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-16" }, { id: 17, name: "Robert", title: "Backend Engineer", department: "Business Technology", branch: "New York", startDate: "2025-01-17" }, { id: 18, name: "Maria", title: "Frontend Developer", department: "Business Technology", branch: "Austin", startDate: "2025-01-18" }, { id: 19, name: "William", title: "Tech Lead", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-19" }, { id: 20, name: "Jessica", title: "Scrum Master", department: "Business Technology", branch: "New York", startDate: "2025-01-20" }, { id: 21, name: "Daniel", title: "Software Architect", department: "Business Technology", branch: "Austin", startDate: "2025-01-21" }, { id: 22, name: "Laura", title: "Business Analyst", department: "Customer Development", branch: "Philadelphia", startDate: "2025-01-22" }, { id: 23, name: "Chris", title: "Security Engineer", department: "Business Technology", branch: "New York", startDate: "2025-01-23" }, { id: 24, name: "Ashley", title: "UX Engineer III", department: "Business Technology", branch: "Austin", startDate: "2025-01-24" }, { id: 25, name: "Kevin", title: "Platform Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-25" }, { id: 26, name: "Michelle", title: "Content Designer", department: "Business Technology", branch: "New York", startDate: "2025-01-26" }, ] const TableWithFilterVariantWithPagination = () => { const [territory, setTerritory] = useState("") // ------Pagination----- const [activePage, setActivePage] = useState(1) // Calculate pagination const itemsPerPage = 20 const totalPages = Math.ceil(users.length / itemsPerPage) const startIndex = (activePage - 1) * itemsPerPage const endIndex = startIndex + itemsPerPage const currentData = users.slice(startIndex, endIndex) const onPageChange = (page) => { setActivePage(page) } // ------End Pagination----- // -------Filter content example ------ const filterContent = ({ closePopover }) => ( <> <TextInput label="Territory ID" onChange={event => setTerritory(event.target.value)} value={territory} /> <Typeahead label="Title" options={[ { key: "senior-ux-engineer", label: "Senior UX Engineer", value: "senior-ux-engineer" }, { key: "ux-engineer", label: "UX Engineer", value: "ux-engineer" }, { key: "ux-designer", label: "UX Designer", value: "ux-designer" } ]} /> <Select blankSelection="All Departments" label="Department" options={[ { value: "Business Technology", label: "Business Technology", key: "business-technology" }, { value: "Customer Development", label: "Customer Development", key: "customer-development" }, { value: "Talent Acquisition", label: "Talent Acquisition", key: "talent-acquisition" } ]} /> <Dropdown label="Branch" options={[ { key: "Philadelphia", label: "Philadelphia", value: "philadelphia" }, { key: "New York", label: "New York", value: "new-york" }, { key: "Austin", label: "Austin", value: "austin" } ]} /> <DatePicker label="Start Date" paddingY="sm" pickerId="startedOn" /> <Flex spacing="between"> <Button onClick={() => { alert("No filtering functionality - just a pattern demo!") closePopover() }} text="Filter" /> <Button text="Defaults" variant="secondary" /> </Flex> </> ) // -------End Filter content example ------ // -------Pagination element example ------ const paginationElement = ( <Pagination current={activePage} key={`pagination-${activePage}`} marginLeft="lg" onChange={onPageChange} paddingY="xs" range={5} total={totalPages} /> ) // -------End Pagination element example ------ return ( <Table filterContent={filterContent} filterProps={{ results: 50, sortOptions: { territory_id: "Territory ID", first_name: "Name", started_on: "Start Date", department_name: "Department", title_name: "Title", branch_branch_name: "Branch", }, sortValue: [{ name: 'started_on', dir: 'asc' }], }} pagination={paginationElement} title="Table Title Here" variant="withFilter" > <Table.Head> <Table.Row> <Table.Header>{'Territory ID'}</Table.Header> <Table.Header>{'Name'}</Table.Header> <Table.Header>{'Title'}</Table.Header> <Table.Header>{'Department'}</Table.Header> <Table.Header>{'Branch'}</Table.Header> <Table.Header textAlign="right">{'Start Date'}</Table.Header> </Table.Row> </Table.Head> <Table.Body> {currentData.map((user) => ( <Table.Row key={user.id}> <Table.Cell marginX={{ xs: "sm" }} numberSpacing="tabular" > {user.id} </Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.name}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.title}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.department}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.branch}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}> <DateKit alignment="right" showCurrentYear value={user.startDate} /> </Table.Cell> </Table.Row> ))} </Table.Body> </Table> ) } export default TableWithFilterVariantWithPagination
The withFilter variant also offers 2 additional optional props:
cardProps: An object containing Card-specific props.
titleProps: An object containing Title-specific props.
The Table kit automatically sets these Card defaults (which you can override via cardProps):
padding="none"The Table kit automatically sets these Title defaults (which you can override via titleProps):
size={3}paddingY="md"import React, { useState } from "react" import { Button, Date as DateKit, DatePicker, Dropdown, Select, Table, TextInput, Typeahead, Flex } from 'playbook-ui' // Mock Data for Table const users = [ { id: 1, name: "Jennifer", title: "Associate Scrum Master", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-01" }, { id: 2, name: "Nick", title: "UX Engineer II", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-02" }, { id: 3, name: "Nida", title: "Senior UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-03" }, { id: 4, name: "Justin", title: "Director of User Experience Engineering", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-04" }, { id: 5, name: "Edward", title: "UX Designer II", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-05" }, { id: 6, name: "Elisa", title: "UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-06" }, { id: 7, name: "Gary", title: "UX Engineer", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-07" }, { id: 8, name: "Barkley", title: "Nitro Quality Ninja", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-08" }, { id: 9, name: "Aaron", title: "Associate Nitro Quality Ninja", department: "Business Technology", branch: "Philadelphia", startDate: "2025-01-09" }, ] const TableWithFilterWithCardTitleProps = () => { const [territory, setTerritory] = useState("") // --------Filter content example ------ const filterContent = ({ closePopover }) => ( <> <TextInput label="Territory ID" onChange={event => setTerritory(event.target.value)} value={territory} /> <Typeahead label="Title" options={[ { key: "senior-ux-engineer", label: "Senior UX Engineer", value: "senior-ux-engineer" }, { key: "ux-engineer", label: "UX Engineer", value: "ux-engineer" }, { key: "ux-designer", label: "UX Designer", value: "ux-designer" } ]} /> <Select blankSelection="All Departments" label="Department" options={[ { value: "Business Technology", label: "Business Technology", key: "business-technology" }, { value: "Customer Development", label: "Customer Development", key: "customer-development" }, { value: "Talent Acquisition", label: "Talent Acquisition", key: "talent-acquisition" } ]} /> <Dropdown label="Branch" options={[ { key: "Philadelphia", label: "Philadelphia", value: "philadelphia" }, { key: "New York", label: "New York", value: "new-york" }, { key: "Austin", label: "Austin", value: "austin" } ]} /> <DatePicker label="Start Date" paddingY="sm" pickerId="startedOn" /> <Flex spacing="between"> <Button onClick={() => { alert("No filtering functionality - just a pattern demo!") closePopover() }} text="Filter" /> <Button text="Defaults" variant="secondary" /> </Flex> </> ) // -------End Filter content example ------ return ( <Table cardProps={{marginX: { xs: "sm", sm: "sm", md: "xl", lg: "xl", xl: "xl", default: "xl", }}} filterContent={filterContent} filterProps={{ results: 50, sortOptions: { territory_id: "Territory ID", first_name: "Name", started_on: "Start Date", department_name: "Department", title_name: "Title", branch_branch_name: "Branch", }, sortValue: [{ name: 'started_on', dir: 'asc' }], }} title="Table Title Here" titleProps={{ paddingLeft:{ xs: "sm", sm: "sm", md: "xl", lg: "xl", xl: "xl", default: "xl", } }} variant="withFilter" > <Table.Head> <Table.Row> <Table.Header>{'Territory ID'}</Table.Header> <Table.Header>{'Name'}</Table.Header> <Table.Header>{'Title'}</Table.Header> <Table.Header>{'Department'}</Table.Header> <Table.Header>{'Branch'}</Table.Header> <Table.Header textAlign="right">{'Start Date'}</Table.Header> </Table.Row> </Table.Head> <Table.Body> {users.map((user) => ( <Table.Row key={user.id}> <Table.Cell marginX={{ xs: "sm" }} numberSpacing="tabular" > {user.id} </Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.name}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.title}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.department}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}>{user.branch}</Table.Cell> <Table.Cell marginX={{ xs: "sm" }}> <DateKit alignment="right" showCurrentYear value={user.startDate} /> </Table.Cell> </Table.Row> ))} </Table.Body> </Table> ) } export default TableWithFilterWithCardTitleProps
import React from 'react' import { List, ListItem } from 'playbook-ui' const ListLg = (props) => { return ( <> <List size="large" > <ListItem>{'Item 1'}</ListItem> <ListItem>{'Item 2'}</ListItem> <ListItem>{'Item 3'}</ListItem> <ListItem>{'Item 4'}</ListItem> <ListItem>{'Item 5'}</ListItem> </List> </> ) } export default ListLg
import React from 'react' import { List, ListItem } from 'playbook-ui' const ListOrdered = (props) => { return ( <> <List ordered > <ListItem>{'Item 1'}</ListItem> <ListItem>{'Item 2'}</ListItem> <ListItem>{'Item 3'}</ListItem> <ListItem>{'Item 4'}</ListItem> <ListItem>{'Item 5'}</ListItem> </List> </> ) } export default ListOrdered
import React from 'react' import { List, ListItem } from 'playbook-ui' const ListBorderless = (props) => { return ( <> <List borderless > <ListItem>{'Item 1'}</ListItem> <ListItem>{'Item 2'}</ListItem> <ListItem>{'Item 3'}</ListItem> <ListItem>{'Item 4'}</ListItem> <ListItem>{'Item 5'}</ListItem> </List> </> ) } export default ListBorderless
import React from 'react' import { List, ListItem } from 'playbook-ui' const ListXpadding = (props) => { return ( <> <List xpadding > <ListItem>{'Item 1'}</ListItem> <ListItem>{'Item 2'}</ListItem> <ListItem>{'Item 3'}</ListItem> <ListItem>{'Item 4'}</ListItem> <ListItem>{'Item 5'}</ListItem> </List> </> ) } export default ListXpadding
import React from 'react' import { List, ListItem, Currency, Title } from 'playbook-ui' const ListLayoutLeft = (props) => { return ( <> <List layout="left" > <ListItem> <Title size={4} text="Label" /> <Currency amount="2,000.50" label="Caption" size="sm" /> </ListItem> <ListItem> <Title size={4} text="Label" /> <Currency amount="2,000.50" label="Caption" size="sm" /> </ListItem> <ListItem> <Title size={4} text="Label" /> <Currency amount="2,000.50" label="Caption" size="sm" /> </ListItem> <ListItem> <Title size={4} text="Label" /> <Currency amount="2,000.50" label="Caption" size="sm" /> </ListItem> <ListItem> <Title size={4} text="Label" /> <Currency amount="2,000.50" label="Caption" size="sm" /> </ListItem> </List> </> ) } export default ListLayoutLeft
import React from 'react' import { List, ListItem, Currency, Title } from 'playbook-ui' const ListLayoutRight = (props) => { return ( <> <List layout="right" > <ListItem> <Title size={4} text="Label" /> <Currency amount="2,000.50" label="Caption" size="sm" /> </ListItem> <ListItem> <Title size={4} text="Label" /> <Currency amount="2,000.50" label="Caption" size="sm" /> </ListItem> <ListItem> <Title size={4} text="Label" /> <Currency amount="2,000.50" label="Caption" size="sm" /> </ListItem> <ListItem> <Title size={4} text="Label" /> <Currency amount="2,000.50" label="Caption" size="sm" /> </ListItem> <ListItem> <Title size={4} text="Label" /> <Currency amount="2,000.50" label="Caption" size="sm" /> </ListItem> </List> </> ) } export default ListLayoutRight
To display the "No Filters Selected" text, the filters prop must be null. As a suggestion, check the values of each key in your filters object. If they are all falsy, return null.
import React, { useState } from 'react' import { Button, Filter, Flex, Select, TextInput } from 'playbook-ui' const FilterDefault = (props) => { const [sortValue, setSortValue] = useState([{ name: 'popularity', dir: 'desc' }]) const [sortValue2, setSortValue2] = useState([{ name: 'popularity', dir: 'desc' }]) const handleSortChange = (sortOptions) => { setSortValue(sortOptions) alert(JSON.stringify(sortOptions[0])) } const handleSortChange2 = (sortOptions) => { setSortValue2(sortOptions) } const options = [ { value: 'USA' }, { value: 'Canada' }, { value: 'Brazil' }, { value: 'Philippines' }, { value: 'A galaxy far far away, like really far away...' }, ] return ( <> <Filter double filters={{ 'Full Name': 'John Wick', 'City': 'San Francisco', }} marginBottom="xl" minWidth="375px" onSortChange={handleSortChange} results={1} sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={sortValue} > {({ closePopover }) => ( <form> <TextInput label="Full Name" placeholder="Enter name" /> <Select blankSelection="Select One..." label="Territory" maxWidth="sm" name="location" options={options} /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> <Filter double minWidth="375px" onSortChange={handleSortChange2} results={0} sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={sortValue2} > {({ closePopover }) => ( <form> <TextInput label="Example Text Field" placeholder="Enter Text" /> <Select blankSelection="Select One..." label="Example Collection Select" name="Collection Select" options={options} /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> </> ) } export default FilterDefault
To remove the background from a filter, add the prop background with a value of false.
import React from 'react' import { Button, Filter, Flex, Select, TextInput } from 'playbook-ui' const FilterNoBackground = (props) => { const options = [ { value: 'USA' }, { value: 'Canada' }, { value: 'Brazil' }, { value: 'Philippines' }, { value: 'A galaxy far far away...' }, ] return ( <> <Filter background={false} filters={{ 'Full Name': 'John Wick', 'City': 'Las Vegas', }} marginBottom="xl" minWidth="360px" results={3} sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={[{ name: 'popularity', dir: 'desc' }]} > {({ closePopover }) => ( <form> <TextInput label="Full Name" placeholder="Enter name" /> <Select blankSelection="Select One..." label="Territory" name="location" options={options} /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> <Filter background={false} double filters={{ 'Full Name': 'John Wick', 'City': 'Las Vegas', }} minWidth="360px" results={3} sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={[{ name: 'popularity', dir: 'desc' }]} > {({ closePopover }) => ( <form> <TextInput label="Full Name" placeholder="Enter name" /> <Select blankSelection="Select One..." label="Territory" name="location" options={options} /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> </> ) } export default FilterNoBackground
import React from 'react' import { Filter, Button, Flex, Select, TextInput } from 'playbook-ui' const FilterSingle = (props) => { const options = [ { value: 'USA' }, { value: 'Canada' }, { value: 'Brazil' }, { value: 'Philippines' }, { value: 'A galaxy far far away...' }, ] return ( <Filter filters={{ 'Full Name': 'John Wick', }} minWidth="360px" results={546} sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={[{ name: 'popularity', dir: 'desc' }]} > {({ closePopover }) => ( <form> <TextInput label="Full Name" placeholder="Enter name" /> <Select blankSelection="Select One..." label="Territory" name="location" options={options} /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> ) } export default FilterSingle
To display results, use templates single or default.
import React from 'react' import { Button, Filter, Flex, Select, TextInput } from 'playbook-ui' const FilterNoSort = (props) => { const options = [ { value: 'USA' }, { value: 'Canada' }, { value: 'Brazil' }, { value: 'Philippines' }, { value: 'A galaxy far far away...' }, ] return ( <Filter filters={{ 'Full Name': 'John Wick', }} minWidth="360px" results={546} sortValue={[{ name: 'popularity', dir: 'desc' }]} > {({ closePopover }) => ( <form> <TextInput label="Full Name" placeholder="Enter name" /> <Select blankSelection="Select One..." label="Territory" name="location" options={options} /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> ) } export default FilterNoSort
import React from 'react' import { Button, Filter, Flex, Select, TextInput } from 'playbook-ui' const FilterOnly = (props) => { const options = [ { value: 'USA' }, { value: 'Canada' }, { value: 'Brazil' }, { value: 'Philippines' }, { value: 'A galaxy far far away...' }, ] return ( <Filter filters={{ 'Full Name': 'John Wick' }} minWidth="360px" > {({ closePopover }) => ( <form> <TextInput label="Full Name" placeholder="Enter name" /> <Select blankSelection="Select One..." label="Territory" name="location" options={options} /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> ) } export default FilterOnly
import React from 'react' import { Filter } from 'playbook-ui' const SortOnly = (props) => ( <Filter sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={[{ name: 'popularity', dir: 'desc' }]} /> ) export default SortOnly
Filter can leverage the max-width property. Learn more in our visual guidelines.
import React from 'react' import { Button, Filter, Flex, Select } from 'playbook-ui' const FilterMaxWidth = (props) => { const options = [ { value: 'USA' }, { value: 'Canada' }, { value: 'Brazil' }, { value: 'Philippines' }, { value: 'A galaxy far far away, like really far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far away...' }, ] return ( <Filter double filters={{ 'Full Name': 'John Wick', 'City': 'San Francisco', }} minWidth="360px" results={1} sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={[{ name: 'popularity', dir: 'desc' }]} > {({ closePopover }) => ( <form> <Select blankSelection="Select One..." label="Territory" maxWidth="sm" name="location" options={options} /> <Button text="Apply" /> <Select blankSelection="Select One..." label="Territory" name="location" options={options} /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> ) } export default FilterMaxWidth
import React from 'react' import { Button, Filter, Flex, Select, TextInput } from 'playbook-ui' const FilterMaxHeight = (props) => { const options = [ { value: 'USA' }, { value: 'Canada' }, { value: 'Brazil' }, { value: 'Philippines' }, { value: 'A galaxy far far away, like really far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far away...' }, ] return ( <Filter double filters={{ 'Full Name': 'John Wick', 'City': 'San Francisco', }} maxHeight="360px" minWidth="360px" results={1} sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={[{ name: 'popularity', dir: 'desc' }]} > {({ closePopover }) => ( <form> <Select blankSelection="Select One..." label="Territory" name="location" options={options} /> <TextInput label="First Name" placeholder="Enter name" /> <TextInput label="Middle Name" placeholder="Enter name" /> <TextInput label="Last Name" placeholder="Enter name" /> <TextInput label="Email" placeholder="Enter email" /> <TextInput label="Address" placeholder="Enter address" /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> ) } export default FilterMaxHeight
Click the filter button above to toggle the popover.
To change the filter's popover position, use the placement prop with one of the positions:
"top" | "right" | "bottom" | "left" | "top-start" | "top-end" | "bottom-start" | "bottom-end" | "right-start" | "right-end" | "left-start" | "left-end"
import React from 'react' import { Button, Filter, Flex, Select, TextInput } from 'playbook-ui' const SortingChangeCallback = (sortOptions) => { alert(JSON.stringify(sortOptions[0])) } const FilterPlacement = (props) => { const options = [ { value: 'USA' }, { value: 'Canada' }, { value: 'Brazil' }, { value: 'Philippines' }, { value: 'A galaxy far far away...' }, ] return ( <> <Filter double minWidth="360px" onSortChange={SortingChangeCallback} placement={"right"} results={1} sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={[{ name: 'popularity', dir: 'desc' }]} > {({ closePopover }) => ( <form> <TextInput label="Example Text Field" placeholder="Enter Text" /> <Select blankSelection="Select One..." label="Example Collection Select" name="Collection Select" options={options} /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> </> ) } export default FilterPlacement
This kit uses the Popover kit under the hood for the Filter Popover which comes with its own set of props. If you want to apply certain Popover props to that underlying kit, you can do so by using the optional popoverProps prop. This prop must be an object that contains valid Popover props. For a full list of Popover props, see here.
import React from 'react' import { Button, Filter, Flex, Select, TextInput } from 'playbook-ui' const FilterPopoverProps = (props) => { const options = [ { value: 'USA' }, { value: 'Canada' }, { value: 'Brazil' }, { value: 'Philippines' }, { value: 'A galaxy far far away, like really far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far far away...' }, ] const popoverProps = { width: "250px" } return ( <Filter double filters={{ 'Full Name': 'John Wick', 'City': 'San Francisco', }} popoverProps={popoverProps} results={1} sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={[{ name: 'popularity', dir: 'desc' }]} > {({ closePopover }) => ( <form> <TextInput label="Example Text Field" placeholder="Enter Text" /> <Select blankSelection="Select One..." label="Example Collection Select" name="Collection Select" options={options} /> <Flex spacing="between" > <Button onClick={closePopover} text="Apply" /> <Button text="Clear" variant="secondary" /> </Flex> </form> )} </Filter> ) } export default FilterPopoverProps
import React, { useState } from 'react' import { Filter, Select, TextInput, useCollapsible, SectionSeparator, Checkbox, Flex, Table, Caption, Icon } from 'playbook-ui' const people = [ { name: 'Hera Syndulla', territory: 'A galaxy far far away, like really far away...', products: ['Insulation'] }, { name: 'Kanan Jarrus', territory: 'USA', products: ['Siding', 'Roofing', 'Gutters'] }, { name: 'C1-10P', territory: 'USA', products: ['Roofing'] }, { name: 'Anakin Skywalker', territory: 'A galaxy far far away, like really far away...', products: ['Doors', 'Windows', 'Solar'] }, { name: 'Leia Organa', territory: 'Canada', products: ['Windows', 'Doors'] }, { name: 'Luke Skywalker', territory: 'Brazil', products: ['Solar', 'Roofing'] }, { name: 'Padmé Amidala', territory: 'Philippines', products: ['Siding', 'Gutters'] }, { name: 'Obi-Wan Kenobi', territory: 'USA', products: ['Windows', 'Siding'] }, { name: 'Ahsoka Tano', territory: 'Canada', products: ['Insulation', 'Solar'] }, { name: 'Boba Fett', territory: 'Brazil', products: ['Roofing', 'Gutters'] }, { name: 'Mace Windu', territory: 'Philippines', products: ['Doors', 'Siding'] }, { name: 'Grogu', territory: 'A galaxy far far away, like really far away...', products: ['Insulation'] }, { name: 'Sabine Wren', territory: 'Canada', products: ['Solar', 'Doors'] }, { name: 'C-3PO', territory: 'Brazil', products: ['Windows'] }, { name: 'R2-D2', territory: 'Philippines', products: ['Doors', 'Gutters'] }, ] const FilterSidebar = (props) => { const [name, setName] = useState('') const [ territory, setTerritory ] = useState('') const [ products, setProducts ] = useState({}) const handleUpdateName = ({ target }) => { setName(target.value) } const handleUpdateTerritory = ({ target }) => { setTerritory(target.value) } const handleCheckboxChange = ({ target }) => { setProducts(prev => ({ ...prev, [target.name]: !prev[target.name], })) } const [isCollapsed, setIsCollapsed] = useCollapsible(true) const [isProductsCollapsed, setIsProductsCollapsed] = useCollapsible(true) const options = [ { value: 'USA' }, { value: 'Canada' }, { value: 'Brazil' }, { value: 'Philippines' }, { value: 'A galaxy far far away, like really far away...' }, ] const filteredPeople = people.filter((person) => { const matchesName = person.name.toLowerCase().includes(name.toLowerCase()) const matchesTerritory = territory === '' ? true : person.territory === territory const matchesProducts = Object.values(products).every((product) => !product) ? true : person.products.some(product => products[product]) return matchesName && matchesTerritory && matchesProducts }) return ( <> <Flex> <Filter isCollapsed={isCollapsed} marginRight="xs" onCollapse={() => setIsCollapsed(!isCollapsed)} results={filteredPeople.length} sortOptions={{ popularity: 'Popularity', // eslint-disable-next-line manager_title: 'Manager\'s Title', // eslint-disable-next-line manager_name: 'Manager\'s Name', }} sortValue={[{ name: 'popularity', dir: 'desc' }]} variant="sidebar" width="xs" > <Filter.Section collapsed={isCollapsed} headerText="Full Name" > <TextInput onChange={handleUpdateName} placeholder="Enter name" value={name} /> </Filter.Section> <SectionSeparator /> <Filter.Section collapsed={isCollapsed} collapsible headerText="Territory" > <Select blankSelection="Select One..." name="location" onChange={handleUpdateTerritory} options={options} /> </Filter.Section> <SectionSeparator /> <Filter.Section collapsed={isCollapsed} collapsible headerText="Products" > <div> <Checkbox marginBottom="sm" name="Doors" onChange={handleCheckboxChange} text="Doors" /> </div> <div> <Checkbox marginBottom="sm" name="Windows" onChange={handleCheckboxChange} text="Windows" /> </div> <div> <Checkbox marginBottom="sm" name="Siding" onChange={handleCheckboxChange} text="Siding" /> </div> {!isProductsCollapsed && <> <div> <Checkbox checked={products["Roofing"]} marginBottom="sm" name="Roofing" onChange={handleCheckboxChange} text="Roofing" /> </div> <div> <Checkbox checked={products["Gutters"]} marginBottom="sm" name="Gutters" onChange={handleCheckboxChange} text="Gutters" /> </div> <div> <Checkbox checked={products["Solar"]} marginBottom="sm" name="Solar" onChange={handleCheckboxChange} text="Solar" /> </div> <div> <Checkbox checked={products["Insulation"]} marginBottom="sm" name="Insulation" onChange={handleCheckboxChange} text="Insulation" /> </div> </> } <div onClick={() => setIsProductsCollapsed(!isProductsCollapsed)}> <Flex cursor="pointer" marginBottom="sm" > <Caption color="link" marginRight="xxs" size="xs" text={isProductsCollapsed ? "Show More" : "Show Less"} /> <Icon icon={isProductsCollapsed ? "chevron-down" : "chevron-up"} /> </Flex> </div> </Filter.Section> </Filter> <Table size="sm" > <thead> <tr> <th>{'Name'}</th> <th>{'Territory'}</th> <th>{'Products'}</th> </tr> </thead> <tbody> {filteredPeople.map((person) => (<tr key={person.name}> <td>{ person.name }</td> <td>{ person.territory }</td> <td>{ person.products.join(", ") }</td> </tr>))} </tbody> </Table> </Flex> </> ) } export default FilterSidebar
import React from 'react' import { DistributionBar } from 'playbook-ui' const DistributionBarDefault = (props) => { return ( <React.Fragment> <div> <DistributionBar widths={[1, 2, 3, 4, 5, 3, 3, 7]} /> </div> <br /> <br /> <div> <DistributionBar size="sm" widths={[1, 2, 3, 4, 5, 3, 3, 7]} /> </div> </React.Fragment> ) } export default DistributionBarDefault
You can customize the order of the colors you would like to use by using the colors prop. Only the data and status colors will work for Playbook charts. See the design page for reference.
import React from 'react' import { DistributionBar } from 'playbook-ui' const DistributionBarCustomColors = (props) => { return ( <React.Fragment> <div> <DistributionBar colors={['data_7', 'data_1', 'neutral']} widths={[4, 5, 3]} /> </div> </React.Fragment> ) } export default DistributionBarCustomColors
import React from 'react' import { Legend } from 'playbook-ui' const products = ['Windows', 'Doors', 'Roofing', 'Siding', 'Solar', 'Gutters', 'Insulation', 'Other'] const LegendDefault = (props) => ( <div> { products.map((product, i) => ( <Legend color={`data_${i + 1}`} key={`legend_${i + 1}`} text={product} /> )) } </div> ) export default LegendDefault
By default legend kit uses data_1 color.
Pass the color prop and use any desired value from $data_colors, $status_colors, $product_colors and $category_colors list.
import React from 'react' import { Legend } from 'playbook-ui' const LegendColors = (props) => ( <div> <Legend color="data_8" text="Data 8" /> <Legend color="warning" text="Warning" /> <Legend color="product_6_highlight" text="Product 6 (highlight)" /> <Legend color="category_7" text="Category 7" /> </div> ) export default LegendColors
The color prop also allows for use of custom colors passed in as HEX codes.
import React from 'react' import { Legend } from 'playbook-ui' const LegendCustomColors = (props) => ( <div> <Legend color="#dc418a" text="Custom Legend Color 1" /> <Legend color="#3ef0b8" text="Custom Legend Color 2" /> <Legend color="#ab8b04" text="Custom Legend Color 3" /> </div> ) export default LegendCustomColors
In order to use this kit, 'highcharts' and 'highcharts-react-official' must be installed in your repo.
import React from 'react' import { PbGaugeChart } from 'playbook-ui/charts' const data = [{ name: "Participants", y: 84 }] const chartOptions = { series: [{ data: data }], plotOptions: { series: { animation: false, }, }, }; const PbGaugeChartDisableAnimation = (props) => ( <div> <PbGaugeChart options={chartOptions} /> </div> ) export default PbGaugeChartDisableAnimation
import React from 'react' import { PbGaugeChart } from 'playbook-ui/charts' const data = [{ name: "Score", y: 780 }] const chartOptions = { title: { text: "Credit Score", }, yAxis: { min: 300, max: 850, }, series: [{ data: data }], }; const PbGaugeChartTitle = (props) => ( <div> <PbGaugeChart options={chartOptions} /> </div> ) export default PbGaugeChartTitle
Use custom CSS with classes or inline styles (as shown in these docs) to customize the appearance of prefix and suffix units.
import React from 'react' import { colors, typography } from 'playbook-ui' import { PbGaugeChart } from 'playbook-ui/charts' const data1 = [ { name: 'Data Used', y: 32 }, ] const data2 = [ { name: 'Sales to Date', y: 65 }, ] const chartOptions1 = { title: { text: "Data Usage", }, series: [{ data: data1 }], plotOptions: { solidgauge: { dataLabels: { format: `<span class="fix">{y:,f}</span>` + `<span style="fill: ${colors.text_lt_light}; font-size: ${typography.text_larger};">GB</span>`, }, }, }, }; const chartOptions2 = { title: { text: "Sales Goal", }, series: [{ data: data2 }], plotOptions: { solidgauge: { dataLabels: { format: `<span y="28" style="fill: ${colors.text_lt_light}; font-size: ${typography.text_base};">$</span>` + `<span class="fix" y="38">{y:,f}</span>` + `<span style="fill: ${colors.text_lt_light}; font-size: ${typography.text_larger};">k</span>`, }, }, }, }; const PbGaugeChartUnits = (props) => ( <div> <PbGaugeChart options={chartOptions1} /> <PbGaugeChart options={chartOptions2} /> </div> ) export default PbGaugeChartUnits
import React from 'react' import { colors, typography } from 'playbook-ui' import { PbGaugeChart } from 'playbook-ui/charts' const data = [{ name: "Capacity", y: 75 }] const chartOptions = { title: { text: "Seating Capacity", }, series: [{ data: data }], pane: { startAngle: 0, endAngle: 360, }, plotOptions: { solidgauge: { dataLabels: { format: `<span class="fix">{y:,f}</span>` + `<span style="fill: ${colors.text_lt_light}; font-size: ${typography.text_larger};">%</span>`, }, }, }, }; const PbGaugeChartFullCircle = (props) => ( <div> <PbGaugeChart options={chartOptions} /> </div> ) export default PbGaugeChartFullCircle
By default, Highcharts set min to 0 and max to 100 but this can be customized if needed as shown here.
import React from 'react' import { colors, typography } from 'playbook-ui' import { PbGaugeChart } from 'playbook-ui/charts' const data = [{ name: "Rating", y: 4.5 }] const chartOptions = { title: { text: "Product Rating", }, yAxis: { min: 0, max: 5, lineWidth: 0, tickWidth: 0, minorTickInterval: null, tickAmount: 2, tickPositions: [0, 5], labels: { y: 26, enabled: true, style: { color: colors.neutral, fontFamily: typography.font_family_base, fontWeight: typography.bold, } }, }, series: [{ data: data }], }; const PbGaugeChartMinMax = (props) => ( <div> <PbGaugeChart options={chartOptions} /> </div> ) export default PbGaugeChartMinMax
The Gauge chart resizes dynamically to fit whatever element it's placed within.
Note: set overflow to hidden on the parent element when nesting gauges inside of flex items to best respond to shrinking screens.
import React from 'react' import { Flex, FlexItem } from 'playbook-ui' import { PbGaugeChart } from 'playbook-ui/charts' const PbGaugeChartSizing = (props) => ( <div> <Flex align="center" wrap > <FlexItem fixedSize="400px" overflow="hidden" shrink > <PbGaugeChart options={{ series: [{ data: [{ name: "Point 1", y: 100 }] }], }} /> </FlexItem> <FlexItem fixedSize="300px" overflow="hidden" shrink > <PbGaugeChart options={{ series: [{ data: [{ name: "Point 2", y: 75 }] }], }} /> </FlexItem> <FlexItem fixedSize="200px" overflow="hidden" shrink > <PbGaugeChart options={{ series: [{ data: [{ name: "Point 3", y: 50 }] }], }} /> </FlexItem> <FlexItem fixedSize="125px" overflow="hidden" shrink > <PbGaugeChart options={{ chart: { height: "100%", }, series: [{ data: [{ name: "Point 4", y: 25 }] }], }} /> </FlexItem> </Flex> </div> ) export default PbGaugeChartSizing
import React from 'react' import { colors, typography } from 'playbook-ui' import { PbGaugeChart } from 'playbook-ui/charts' const chartOptions = { title: { text: "Fixed Height in Pixels", }, chart: { height: "400", }, series: [{ data: [{ name: "Pixels", y: 400 }] }], plotOptions: { solidgauge: { dataLabels: { format: `<span class="fix">{y:,f}</span>` + `<span style="fill: ${colors.text_lt_light}; font-size: ${typography.text_larger};">px</span>`, }, }, }, }; const chartOptions2 = { title: { text: "Height as Percentage of Width", }, chart: { height: "45%", }, series: [{ data: [{ name: "Percentage", y: 45 }] }], plotOptions: { solidgauge: { dataLabels: { format: `<span class="fix">{y:,f}</span>` + `<span style="fill: ${colors.text_lt_light}; font-size: ${typography.text_larger};">%</span>`, }, }, }, }; const PbGaugeChartHeight = (props) => ( <div> <PbGaugeChart options={chartOptions} /> <PbGaugeChart options={chartOptions2} /> </div> ) export default PbGaugeChartHeight
import React, { useState, useRef } from 'react' import { Button } from 'playbook-ui' import { PbGaugeChart } from 'playbook-ui/charts' const PbGaugeChartLiveData = (props) => { const [value, setValue] = useState(50) const [name, setName] = useState('Name') const chartRef = useRef(null) const namesArray = ['Name', 'Windows', 'Doors', 'Roofing', 'Siding', 'Gutters'] const updateValue = () => { const newValue = Math.floor(Math.random() * 100) setValue(newValue) const chart = chartRef.current?.chart if (chart) { chart.series[0].points[0].update(newValue) } } const updateName = () => { let index = namesArray.indexOf(name) if (namesArray.indexOf(name) == 5) { index = 0 } else { index += 1 } setName(namesArray[index]) const chart = chartRef.current?.chart if (chart) { chart.series[0].points[0].update({ name: namesArray[index] }) } } const chartOptions = { title: { text: name, }, series: [{ data: [{ name: name, y: value }] }] } return ( <div> <Button onClick={updateValue} text="Update Value" /> <Button onClick={updateName} text="Update Name" /> <PbGaugeChart options={chartOptions} ref={chartRef} /> </div> ); } export default PbGaugeChartLiveData
Highcharts allows for any custom colors to be used. Custom data colors allow for color customization to match the needs of business requirements.
For React, pass the option plotOptions.solidgauge.borderColor with a Playbook token like colors. + data_1 | data_2 | data_3 | data_4 | data_5 | data_6 | data_7 | data_8. HEX colors are also available eg: #CA0095
For Rails, the option plotOptions.solidgauge.borderColor can only be used with HEX values as shown.
import React from 'react' import { colors } from 'playbook-ui' import { PbGaugeChart } from 'playbook-ui/charts' const data = [{ name: "Name", y: 67 }] const chartOptions = { series: [{ data: data }], plotOptions: { solidgauge: { borderColor: colors.data_7, } }, }; const PbGaugeChartColor = (props) => ( <div> <PbGaugeChart options={chartOptions} /> </div> ) export default PbGaugeChartColor
We are able to wrap the Highcharts Gauge kit within Playbook kits (such as Flex and Card components).
import React from 'react' import { Flex, FlexItem, Card, Caption, Body, SectionSeparator, Title, colors, typography } from 'playbook-ui' import { PbGaugeChart } from 'playbook-ui/charts' const data = [{ name: "Name", y: 10 }]; const chartOptions = { series: [{ data: data }], chart: { height: "150", }, plotOptions: { series: { animation: false, }, solidgauge: { dataLabels: { format: `<span class="fix">{y:,f}</span>` + `<span style="fill: ${colors.text_lt_light}; font-size: ${typography.text_larger};">%</span>`, }, }, }, }; const PbGaugeChartComplex = (props) => ( <Flex gap="sm" padding="xl" wrap > <FlexItem flex={1} grow > <Card maxWidth="xs" padding="md" > <Title paddingBottom="sm" size={4} text="Abandoned Calls" /> <Flex align="stretch" > <Flex marginRight="sm" orientation="column" > <Body color="light" paddingBottom="sm" text="Total Abandoned" /> <Flex align="baseline" paddingBottom="xs" > <Title size={1} text="39" /> <Title color="light" size={3} text="calls" /> </Flex> <Caption size="xs" text="of 390" /> </Flex> <SectionSeparator alignSelf="stretch" marginRight="sm" orientation="vertical" /> <Flex orientation="column" wrap > <Body color="light" text="% Abandoned" /> <Flex wrap > <FlexItem fixedSize="150px" overflow="hidden" shrink > <PbGaugeChart options={chartOptions} /> </FlexItem> </Flex> </Flex> </Flex> </Card> </FlexItem> </Flex> ) export default PbGaugeChartComplex
In order to use this kit, 'highcharts' and 'highcharts-react-official' must be installed in your repo.
import React from 'react' import { PbBarGraph } from 'playbook-ui/charts' const chartData = [{ name: 'Installation', data: [1475, 200, 3000, 654, 656], }, { name: 'Manufacturing', data: [4434, 524, 2320, 440, 500], }, { name: 'Sales & Distribution', data: [3387, 743, 1344, 434, 440], }, { name: 'Project Development', data: [3227, 878, 999, 780, 1000], }, { name: 'Other', data: [1111, 677, 3245, 500, 200], }] const chartOptions = { series: chartData, title: { text: 'Solar Employment Growth by Sector, 2010-2016', }, subtitle: { text: 'Source: thesolarfoundation.com', }, xAxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May'], }, yAxis: { title: { text: 'Number of Employees', }, }, } const PbBarGraphDefault = (props) => { return ( <div> <PbBarGraph options={chartOptions} /> </div> ) } export default PbBarGraphDefault
import React from 'react' import { PbBarGraph } from 'playbook-ui/charts' const chartData = [{ name: 'Number of Installations', data: [1475, 200, 3000, 654, 656], }] const chartOptions = { series: chartData, title: { text: 'Bar Graph with Legend', }, xAxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May'], }, yAxis: { title: { text: 'Number of Employees', }, }, legend: { enabled: true }, } const PbBarGraphLegend = () => { return ( <div> <PbBarGraph options={chartOptions} /> </div> ) } export default PbBarGraphLegend
Highcharts provides many options for customizing the legend display. This example showcases the following:
align can be used to align the legend left, right or center (defaults to center)
verticalAlign can be used to place the legend above the graph. Options are top, middle, bottom with default set to bottom
layout determines the position of the legend items. Options are horizontal, vertical or proximate with default set to horizontal layout: proximate will place the legend items as close as possible to the graphs they're representing. It will also determine whether to place the legend above/below or on the side of the plot area, if the legend is in a corner.
x offsets the legend relative to its horizontal alignment. Negative x moves it to the left, positive x moves it to the right (defaults to 0)
y offsets the legend relative to its vertical alignment. Negative y moves it up, positive y moves it down (defaults to 0)
import React from 'react' import { Title } from 'playbook-ui' import { PbBarGraph } from 'playbook-ui/charts' const chartData = [{ name: 'Installation', data: [1475], }, { name: 'Manufacturing', data: [4434], }, { name: 'Sales & Distribution', data: [3387], }, { name: 'Project Development', data: [3227], }, { name: 'Other', data: [1111], }] const alignChartOptions = { series: chartData, title: { text: 'Alignment of Legend', }, subtitle: { text: 'Source: thesolarfoundation.com', }, xAxis: { categories: ['Jan'], }, yAxis: { title: { text: 'Number of Employees', }, }, legend: { enabled: true, verticalAlign: 'top', align: 'right', }, } const layoutChartOptions = { series: chartData, title: { text: 'Layout of Legend', }, xAxis: { categories: ['Jan'], }, yAxis: { title: { text: 'Number of Employees', }, }, legend: { enabled: true, layout: 'vertical', }, } const offsetChartOptions = { series: chartData, title: { text: 'Offset of Legend', }, xAxis: { categories: ['Jan'], }, yAxis: { title: { text: 'Number of Employees', }, }, legend: { enabled: true, layout: 'vertical', x: 100, y: 10, }, } const PbBarGraphLegendPosition = () => { return ( <div> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="align | verticalAlign" /> <PbBarGraph options={alignChartOptions} /> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="layout" /> <PbBarGraph options={layoutChartOptions} /> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="x | y" /> <PbBarGraph options={offsetChartOptions} /> </div> ) } export default PbBarGraphLegendPosition
import React from 'react' import { PbBarGraph } from 'playbook-ui/charts' const chartData = [{ name: 'Number of Installations', data: [1475, 200, 3000, 654, 656], }] const chartOptions = { title: { text: 'Bar Graph with Legend Non Clickable', }, xAxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May'], }, yAxis: { title: { text: 'Number of Employees', }, }, legend: { enabled: true, events: { itemClick: function () { return false; } } }, series: chartData } const PbBarGraphLegendNonClickable = () => { return ( <div> <PbBarGraph options={chartOptions} /> </div> ) } export default PbBarGraphLegendNonClickable
By default, Highcharts have a height of 400px, but this can be customized. You can override the default by specifying either a percentage or a fixed pixel value.
Using a percentage maintains a consistent aspect ratio across different responsive sizes. For example, setting the height to 50% makes the chart’s height half of its width.
import React from 'react' import { PbBarGraph } from 'playbook-ui/charts' const chartData = [{ name: 'Number of Installations', data: [1475, 200, 3000, 654, 656], }] const pixelHeightChartOptions = { chart: { height: "300" }, series: chartData, title: { text: "Fixed Height (300px)", }, xAxis: { categories: ["Jan", "Feb", "Mar", "Apr", "May"], }, yAxis: { title: { text: "Number of Employees", }, }, }; const percentageHeightChartOptions = { chart: { height: "50%" }, series: chartData, title: { text: "Percentage Height (50%)", }, xAxis: { categories: ["Jan", "Feb", "Mar", "Apr", "May"], }, yAxis: { title: { text: "Number of Employees", }, }, }; const PbBarGraphHeight = () => ( <div> <PbBarGraph options={pixelHeightChartOptions} /> <br /> <br /> <PbBarGraph options={percentageHeightChartOptions} /> </div> ) export default PbBarGraphHeight
A spline can be added by including a separate chart data with the type: 'spline' attribute.
A color can also be specified for the spline.
import React from 'react' import { PbBarGraph } from 'playbook-ui/charts' const chartData = [{ name: 'Number of Installations', data: [1475, 200, 3000, 654, 656], }, { type: 'spline', name: 'Trend Line', data: [1975, 600, 2500, 924, 500], color: '#F9BB00', }] const chartOptions = { series: chartData, title: { text: "Bar Graph with Spline", }, xAxis: { categories: ["Jan", "Feb", "Mar", "Apr", "May"], }, yAxis: { title: { text: "Number of Employees", }, }, legend: { enabled: true }, }; const PbBarGraphSpline = () => { return ( <div> <PbBarGraph options={chartOptions} /> </div> ) } export default PbBarGraphSpline
Custom data colors allow for color customization to match the needs of business requirements.
You can use Playbook's color tokens or use hex values.
import React from 'react' import { colors } from 'playbook-ui' import { PbBarGraph } from 'playbook-ui/charts' const chartData = [{ name: 'Installation', data: [1475, 200, 3000, 654, 656], }, { name: 'Manufacturing', data: [4434, 524, 2320, 440, 500], }, { name: 'Sales & Distribution', data: [3387, 743, 1344, 434, 440], }, { name: 'Project Development', data: [3227, 878, 999, 780, 1000], }, { name: 'Other', data: [1111, 677, 3245, 500, 200], }] const chartOptions = { series: chartData, title: { text: "Bar Graph with Custom Data Colors", }, xAxis: { categories: ["Jan", "Feb", "Mar", "Apr", "May"], }, yAxis: { title: { text: "Number of Employees", }, }, colors: [colors.data_4, colors.data_5, colors.data_6, colors.data_7, colors.data_8], } const PbBarGraphColors = () => { return ( <div> <PbBarGraph options={chartOptions} /> </div> ) } export default PbBarGraphColors
import React from 'react' import { PbBarGraph } from 'playbook-ui/charts' const chartData = [{ name: 'Installation', data: [1475, 200, 3000, 654, 656], }, { name: 'Manufacturing', data: [1270, 800, 200, 454, 956], }, { name: 'Sales & Distribution', data: [975, 1600, 1500, 924, 500], }] const chartOptions = { series: chartData, title: { text: "Bar Graph with Stacked Columns", }, xAxis: { categories: ["Jan", "Feb", "Mar", "Apr", "May"], }, yAxis: { title: { text: "Number of Employees", }, }, plotOptions: { column: { stacking: 'normal', borderWidth: 0, } }, legend: { enabled: true }, }; const PbBarGraphStacked = () => { return ( <div> <PbBarGraph options={chartOptions} /> </div> ) } export default PbBarGraphStacked
import React from 'react' import { PbBarGraph } from 'playbook-ui/charts' const chartData = [{ name: 'Installation', data: [-475, 400, -1000, 354, -856], threshold: 0 }, { name: 'Manufacturing', data: [1475, 200, 1000, 654, -656], threshold: 0 }, { name: 'Sales & Distribution', data: [1270, 100, -1200, 554, 756], threshold: 0 }] const chartOptions = { series: chartData, title: { text: "Bar Graph with Negative Numbers", }, xAxis: { categories: ["Jan", "Feb", "Mar", "Apr", "May"], }, yAxis: { title: { text: "Number of Employees", }, }, legend: { enabled: true }, }; const PbBarGraphStacked = () => { return( <div> <PbBarGraph options={chartOptions} /> </div> ) } export default PbBarGraphStacked
import React from 'react' import { colors, typography } from 'playbook-ui' import { PbBarGraph } from 'playbook-ui/charts' const chartData = [{ name: 'Number of Installations', data: [1475, 200, 3000, 654, 656], }, { type: 'spline', name: 'Percentage', data: [48, 70, 25, 55, 72], color: '#F9BB00', yAxis: 1 }] const chartOptions = { series: chartData, title: { text: "Bar Graph with Secondary Y-axis", }, xAxis: { categories: ["Jan", "Feb", "Mar", "Apr", "May"], }, yAxis: [{ labels: { style: { fontFamily: typography.font_family_base, color: colors.text_lt_lighter, fontWeight: typography.bold, fontSize: typography.text_smaller, }, }, title: { text: "Number of Employees", style: { fontFamily: typography.font_family_base, color: colors.text_lt_lighter, fontWeight: typography.bold, fontSize: typography.text_smaller, }, }, }, { labels: { style: { fontFamily: typography.font_family_base, color: colors.text_lt_lighter, fontWeight: typography.bold, fontSize: typography.text_smaller, }, }, title: { text: "Percentage", style: { fontFamily: typography.font_family_base, color: colors.text_lt_lighter, fontWeight: typography.bold, fontSize: typography.text_smaller, }, }, opposite: true, min: 0, max: 100 }], legend: { enabled: true }, } const PbBarGraphSecondaryYAxis = () => { return ( <div> <PbBarGraph options={chartOptions} /> </div> ) } export default PbBarGraphSecondaryYAxis
import React from 'react' import { PbBarGraph } from 'playbook-ui/charts' const chartOptions = { chart: { type: 'bar' }, title: { text: 'Historic World Population by Region', align: 'left' }, subtitle: { text: 'Source: <a ' + 'href="https://en.wikipedia.org/wiki/List_of_continents_and_continental_subregions_by_population"' + 'target="_blank">Wikipedia.org</a>', align: 'left' }, xAxis: { categories: ['Africa', 'America', 'Asia', 'Europe'], lineWidth: 0 }, yAxis: { title: { text: '', }, }, tooltip: { valueSuffix: ' millions' }, plotOptions: { bar: { dataLabels: { enabled: true }, groupPadding: 0.1 } }, series: [{ name: 'Year 1990', data: [631, 727, 3202, 721] }, { name: 'Year 2000', data: [814, 841, 3714, 726] }, { name: 'Year 2018', data: [1276, 1007, 4561, 746] }], } const PbBarGraphHorizontal = () => ( <div> <PbBarGraph options={chartOptions} /> </div> ) export default PbBarGraphHorizontal
In order to use this kit, 'highcharts' and 'highcharts-react-official' must be installed in your repo.
import React from "react"; import { PbCircleChart } from 'playbook-ui/charts' const chartOptions = { series: [ { data: [ { name: "Waiting for Calls", y: 41, }, { name: "On Call", y: 49, }, { name: "After Call", y: 10, }, ], }, ], }; const PbCircleChartDefault = (props) => ( <div> <PbCircleChart options={chartOptions} /> </div> ); export default PbCircleChartDefault;
import React, { useState } from "react"; import { Button } from 'playbook-ui' import { PbCircleChart } from 'playbook-ui/charts' const chartData = [ { name: "Waiting for Calls", y: 41, }, { name: "On Call", y: 49, }, { name: "After Call", y: 10, }, ]; const chartData2 = [ { name: "Waiting for Calls", y: 48, }, { name: "On Call", y: 12, }, { name: "After Call", y: 140, }, ]; const PbCircleChartLiveData = (props) => { const [data, setData] = useState(chartData); const updateValue = () => { setData(chartData2) } const chartOptions = { series: [{ data: data }], } return ( <div> <Button onClick={updateValue} text="Update Value" /> <PbCircleChart options={chartOptions} /> </div> ); }; export default PbCircleChartLiveData;
import React from "react"; import { PbCircleChart } from 'playbook-ui/charts' const data= [ { name: "Waiting for Calls", y: 41, }, { name: "On Call", y: 49, }, { name: "After Call", y: 10, }, ] const PbCircleChartRounded = (props) => { const chartOptions = { series: [{ data: data }], plotOptions: { pie: { borderColor: null, borderWidth: 20, innerSize: '100%', }, }, }; return ( <div> <PbCircleChart options={chartOptions} /> </div> ); }; export default PbCircleChartRounded;
import React from "react"; import { Title } from 'playbook-ui' import { PbCircleChart } from 'playbook-ui/charts' const data= [ { name: "Waiting for Calls", y: 41, }, { name: "On Call", y: 49, }, { name: "After Call", y: 10, }, ] const PbCircleChartBlockContent = (props) => { const chartOptions = { series: [{ data: data, innerSize: '100%', borderWidth: 20, borderColor: null, }], chart: { events: { render: function() { const chart = this; const blockElement = document.querySelector('.pb-circle-chart-block'); if (blockElement) { blockElement.style.width = chart.chartWidth + 'px'; blockElement.style.height = chart.chartHeight + 'px'; } }, redraw: function() { const chart = this; const blockElement = document.querySelector('.pb-circle-chart-block'); if (blockElement) { blockElement.style.width = chart.chartWidth + 'px'; blockElement.style.height = chart.chartHeight + 'px'; } } } } } return ( <div style={{ position: 'relative' }}> <PbCircleChart options={chartOptions} /> <div className="pb-circle-chart-block" style={{ position: 'absolute', top: 0, left: 0, display: 'flex', justifyContent: 'center', alignItems: 'center', zIndex: 1, textAlign: 'center', pointerEvents: 'none' }} > <Title size={1} tag="div" > {'83'} </Title> </div> </div> ); }; export default PbCircleChartBlockContent;
Custom data colors allow for color customization to match the needs of business requirements.
For React, import the colors from Playbook's tokens, then set custom colors in the plotOptions.pie.colors array using the desired color variables.
For Rails, only HEX colors can be used eg: #CA0095
import React from "react"; import { colors } from 'playbook-ui' import { PbCircleChart } from 'playbook-ui/charts' const data= [ { name: "Waiting for Calls", y: 41, }, { name: "On Call", y: 49, }, { name: "After Call", y: 10, }, ] const PbCircleChartColorOverrides = (props) => { const chartOptions = { series: [{ data: data }], plotOptions: { pie: { colors: ["#144075", colors.data_4, colors.data_2], // Custom colors via hex OR Playbook color tokens }, }, }; return ( <div> <PbCircleChart options={chartOptions} /> </div> ); } export default PbCircleChartColorOverrides;
import React from "react"; import { PbCircleChart } from 'playbook-ui/charts' const data = [ { name: "Facebook", y: 2498, }, { name: "YouTube", y: 2000, }, { name: "WhatsApp", y: 2000, }, { name: "Facebook Messenger", y: 1300, }, { name: "WeChat", y: 1165, }, { name: "Instagram", y: 1000, }, { name: "Tik Tok", y: 800, }, ]; const PbCircleChartDataWithLabels = (props) => { const chartOptions = { series: [{ data: data }], plotOptions: { pie: { dataLabels: { enabled: true, }, }, }, }; return ( <div> <PbCircleChart options={chartOptions} /> </div> ); } export default PbCircleChartDataWithLabels;
import React from "react"; import { PbCircleChart } from 'playbook-ui/charts' const data = [{ name: 'Bugs', y: 8, }, { name: 'Chores', y: 1, }, { name: 'Stories', y: 12, }] const PbCircleChartDataWithLegend = (props) => { const chartOptions = { series: [{ data: data }], plotOptions: { pie: { showInLegend: true, }, }, }; return ( <div> <PbCircleChart options={chartOptions} /> </div> ); } export default PbCircleChartDataWithLegend;
Layout options from Highcharts:
align Type: String | Values: left | center | right (defaults to center)
verticalAlign Type: String | Values: top | middle | bottom (defaults to bottom)
layout Type: String | Values: horizontal | vertical | proximate (defaults to horizontal)
x Type: Number (defaults to 0)
y Type: Number (defaults to 0)
layout determines the position of the legend items
layout: proximate will place the legend items as close as possible to the graphs they're representing. It will also determine whether to place the legend above/below or on the side of the plot area, if the legend is in a corner.
x offsets the legend relative to its horizontal alignment. Negative x moves it to the left, positive x moves it to the right
y offsets the legend relative to its vertical alignment. Negative y moves it up, positive y moves it down.
import React from "react"; import { Title } from 'playbook-ui' import { PbCircleChart } from 'playbook-ui/charts' const dataFirst = [ { name: 'Waiting for Calls', y: 41, }, { name: 'On Call', y: 49, }, { name: 'After Call', y: 10, }, ] const dataSecond = [{ name: 'Bugs', y: 8, }, { name: 'Chores', y: 1, }, { name: 'Stories', y: 12, }] const dataThird = [ { name: 'Queued', y: 7, }, { name: 'In Progress', y: 6, }, { name: 'Validation', y: 3, }, { name: 'Done', y: 6, }, ] const PbCircleChartDataLegendPosition = (props) => { const chartOptionsFirst = { title: { text: "Alignment of Legend" }, series: [{ data: dataFirst }], legend: { align: 'right', verticalAlign: 'top' }, plotOptions: { pie: { showInLegend: true } } } const chartOptionsSecond = { title: { text: "Layout of Legend" }, series: [{ data: dataSecond }], legend: { layout: 'vertical' }, plotOptions: { pie: { showInLegend: true } } } const chartOptionsThird = { title: { text: "Offset of Legend" }, series: [{ data: dataThird }], legend: { layout: 'vertical', x: 100, y: 10 }, plotOptions: { pie: { showInLegend: true } } } return ( <div> <Title paddingY="sm" size={4} tag="h4" text="align | verticalAlign" /> <PbCircleChart options={chartOptionsFirst} /> <Title paddingY="sm" size={4} tag="h4" text="layout" /> <PbCircleChart options={chartOptionsSecond} /> <Title paddingY="sm" size={4} tag="h4" text="x | y" /> <PbCircleChart options={chartOptionsThird} /> </div> ); } export default PbCircleChartDataLegendPosition;
import React from "react"; import { PbCircleChart } from 'playbook-ui/charts' const data= [ { name: 'Facebook', y: 2498, }, { name: 'YouTube', y: 2000, }, { name: 'WhatsApp', y: 2000, }, { name: 'Facebook Messenger', y: 1300, }, { name: 'WeChat', y: 1165, }, { name: 'Instagram', y: 1000, }, { name: 'Tik Tok', y: 800, }, ] const PbCircleChartWithTitle = (props) => { const chartOptions = { title: { text: "Active Users on Social Media" }, series: [{ data: data }], }; return ( <div> <PbCircleChart options={chartOptions} /> </div> ); }; export default PbCircleChartWithTitle;
import React from "react"; import { PbCircleChart } from 'playbook-ui/charts' const dataFirst = [ { name: 'Bugs', y: 8, }, { name: 'Chores', y: 1, }, { name: 'Stories', y: 12, }, ] const dataSecond = [ { name: 'Queued', y: 7, }, { name: 'In Progress', y: 6, }, { name: 'Validation', y: 3, }, { name: 'Done', y: 6, }, ] const dataThird = [ { name: '1 Point Tickets', y: 2, }, { name: '3 Point Tickets', y: 5, }, { name: '5 Point Tickets', y: 6, }, { name: '8 Point Tickets', y: 3, }, { name: '13 Point Tickets', y: 1, }, ] const dataFourth = [ { name: 'Facebook', y: 2498, }, { name: 'YouTube', y: 2000, }, { name: 'WhatsApp', y: 2000, }, { name: 'Facebook Messenger', y: 1300, }, { name: 'WeChat', y: 1165, }, { name: 'Instagram', y: 1000, }, { name: 'Tik Tok', y: 800, }, ] const PbCircleChartInnerSizes= (props) => { const chartOptionsSmall = { series: [{ data: dataFirst, innerSize: '35%' }], } const chartOptionsMedium = { series: [{ data: dataSecond, innerSize: '50%' }], } const chartOptionsLarge = { series: [{ data: dataThird, innerSize: '85%' }], } const chartOptionsNone = { series: [{ data: dataFourth, innerSize: '0%' }], } return ( <div> <PbCircleChart options={chartOptionsSmall} /> <PbCircleChart options={chartOptionsMedium} /> <PbCircleChart options={chartOptionsLarge} /> <PbCircleChart options={chartOptionsNone} /> </div> ); }; export default PbCircleChartInnerSizes;
Tooltip options from Highcharts:
headerFormat Type: String | when set to null will disable the header.
pointFormat Type: String | defines the HTML template for each data point and supports custom HTML when useHTML is enabled.
useHTML Type: boolean (default false) | enables HTML rendering in tooltips.
{point.name} and {point.y} are useful values that can be referenced for each point in the graph.
import React from "react"; import { PbCircleChart } from 'playbook-ui/charts' const data = [ { name: 'Waiting for Calls', y: 41, }, { name: 'On Call', y: 49, }, { name: 'After Call', y: 10, }, ] const PbCircleChartCustomTooltip = (props) => { const chartOptions = { series: [{ data: data }], tooltip: { headerFormat: null, pointFormat: '<p>Custom tooltip for {point.name} <br/>with value: {point.y}</p>', useHTML: true, }, } return ( <div> <PbCircleChart options={chartOptions} /> </div> ); }; export default PbCircleChartCustomTooltip;
In order to use this kit, 'highcharts' and 'highcharts-react-official' must be installed in your repo.
import React from 'react' import { PbLineGraph } from 'playbook-ui/charts' const data = [{ name: 'Installation', data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], }, { name: 'Manufacturing', data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], }, { name: 'Sales & Distribution', data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387], }, { name: 'Project Development', data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227], }, { name: 'Other', data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111], }] const categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] const chartOptions = { series: data, title: { text: "Solar Employment Growth by Sector, 2010-2016" }, subtitle: { text: "Source: thesolarfoundation.com" }, xAxis: { categories: categories, }, yAxis: { title: { text: "Number of Employees", }, }, } const PbLineGraphDefault = (props) => ( <div> <PbLineGraph options={chartOptions} /> </div> ) export default PbLineGraphDefault
import React from 'react' import { PbLineGraph } from 'playbook-ui/charts' const data = [{ name: 'Number of Installations', data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], }] const categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'] const chartOptions = { series: data, title: { text: "Line Graph with Legend" }, xAxis: { categories: categories, }, yAxis: { min: 0, title: { text: "Number of Employees", }, }, legend: { enabled: true, }, } const PbLineGraphLegend = (props) => ( <div> <PbLineGraph options={chartOptions} /> </div> ) export default PbLineGraphLegend
Highcharts provides many options for customizing the legend display. This example showcases the following:
align can be used to align the legend left, right or center (defaults to center)
verticalAlign can be used to place the legend above the graph. Options are top, middle, bottom with default set to bottom
layout determines the position of the legend items. Options are horizontal, vertical or proximate with default set to horizontal layout: proximate will place the legend items as close as possible to the graphs they're representing. It will also determine whether to place the legend above/below or on the side of the plot area, if the legend is in a corner.
x offsets the legend relative to its horizontal alignment. Negative x moves it to the left, positive x moves it to the right (defaults to 0)
y offsets the legend relative to its vertical alignment. Negative y moves it up, positive y moves it down (defaults to 0)
import React from 'react' import { Title } from 'playbook-ui' import { PbLineGraph } from 'playbook-ui/charts' const data = [{ name: 'Installation', data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], }, { name: 'Manufacturing', data: [24916, 24064, 29742, 29851, 32490, 30282, 38121, 40434], }, { name: 'Sales & Distribution', data: [11744, 17722, 16005, 19771, 20185, 24377, 32147, 39387], }, { name: 'Project Development', data: [null, null, 7988, 12169, 15112, 22452, 34400, 34227], }, { name: 'Other', data: [12908, 5948, 8105, 11248, 8989, 11816, 18274, 18111], }] const categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'] const chartOptionsFirst = { title: { text: "Alignment of Legend" }, series: data, xAxis: { categories: categories, }, yAxis: { min: 0, title: { text: "Number of Employees", }, }, legend: { enabled: true, align: 'right', verticalAlign: 'top' }, } const chartOptionsSecond = { title: { text: "Layout of Legend" }, series: data, xAxis: { categories: categories, }, yAxis: { min: 0, title: { text: "Number of Employees", }, }, legend: { enabled: true, layout: 'vertical' }, } const chartOptionsThird = { title: { text: "Offset of Legend" }, series: data, xAxis: { categories: categories, }, yAxis: { min: 0, title: { text: "Number of Employees", }, }, legend: { enabled: true, layout: 'vertical', x: 100, y: 10 }, } const PbLineGraphLegendPosition = (props) => ( <div> <Title paddingY="sm" size={4} tag="h4" text="align | verticalAlign" /> <PbLineGraph options={chartOptionsFirst} /> <Title paddingY="sm" size={4} tag="h4" text="layout" /> <PbLineGraph options={chartOptionsSecond} /> <Title paddingY="sm" size={4} tag="h4" text="x | y" /> <PbLineGraph options={chartOptionsThird} /> </div> ) export default PbLineGraphLegendPosition
import React from 'react' import { PbLineGraph } from 'playbook-ui/charts' const data = [{ name: 'Number of Installations', data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], }] const categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug'] const chartOptions = { title: { text: 'Line Graph with Legend Non Clickable', }, xAxis: { categories: categories, }, yAxis: { title: { text: 'Number of Employees', }, }, legend: { enabled: true, events: { itemClick: function () { return false; } } }, series: data } const PbLineGraphLegendNonclickable = (props) => { return ( <div> <PbLineGraph options={chartOptions} /> </div> ) } export default PbLineGraphLegendNonclickable
By default, Highcharts have a height of 400px, but this can be customized. You can override the default by specifying either a percentage or a fixed pixel value.
Using a percentage maintains a consistent aspect ratio across different responsive sizes. For example, setting the height to 50% makes the chart’s height half of its width.
import React from 'react' import { PbLineGraph } from 'playbook-ui/charts' const data = [{ name: 'Number of Installations', data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], }] const categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] const chartOptionsFirst = { title: { text: 'Fixed Height (300px)', }, chart: { height: '300px' }, xAxis: { categories: categories, }, yAxis: { min: 0, title: { text: 'Number of Employees', }, }, series: data } const chartOptionsSecond = { title: { text: 'Percentage Height (50%)', }, chart: { height: '50%' }, xAxis: { categories: categories, }, yAxis: { min: 0, title: { text: 'Number of Employees', }, }, series: data } const PbLineGraphHeight = (props) => { return ( <div> <PbLineGraph options={chartOptionsFirst} /> <PbLineGraph options={chartOptionsSecond} /> </div> ) } export default PbLineGraphHeight
Custom data colors allow for color customization to match the needs of business requirements.
For React, import 'colors' from Playbook, then set custom colors in the colors array using the desired color variables. Hex colors are also available.
For Rails, HEX values are required.
import React from 'react' import { colors } from 'playbook-ui' import { PbLineGraph } from 'playbook-ui/charts' const data = [{ name: 'Installation', data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], }, { name: 'Manufacturing', data: [24916, 28064, 29742, 40851, 50590, 65282, 70121, 85434], }, { name: 'Sales & Distribution', data: [11744, 17722, 16005, 19771, 25185, 28377, 36147, 43387], }, { name: 'Project Development', data: [5332, 6344, 7988, 12169, 15112, 14452, 22400, 30227], }, { name: 'Other', data: [null, null, null, 3112, 4989, 5816, 15274, 18111], }] const categories = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] const chartOptions = { title: { text: 'Line Graph with Custom Data Colors', }, xAxis: { categories: categories, }, yAxis: { min: 0, title: { text: 'Number of Employees', }, }, series: data, colors: [colors.data_4, colors.data_5, "#144075", colors.data_7, colors.data_8] } const PbLineGraphColors = (props) => { return ( <div> <PbLineGraph options={chartOptions} /> </div> ) } export default PbLineGraphColors