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_size_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({className: 'map_popup', closeButton: false}).setHTML(`<h4 class="pb_title_kit_size_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_size_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 in our visual guidelines.
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 ids you want to be sticky. Make sure to add the corresponding id to the <th>
and <td>
.
If you are using the sub-component variant, then you will pass the id to <Table.Header>
and <Table.Cell>
Please ensure that unique ids are used for all columns across multiple tables. Using the same columns 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 id="1">{'Column 1'}</th> <th id="2">{'Column 2'}</th> <th 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 id="1">{'Value 1'}</td> <td id="2">{'Value 2'}</td> <td 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 id="1">{'Value 1'}</td> <td id="2">{'Value 2'}</td> <td 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 id="1">{'Value 1'}</td> <td id="2">{'Value 2'}</td> <td 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 ids you want to be sticky. Make sure to add the corresponding id to the <th>
and <td>
.
If you are using the sub-component variant, then you will pass the id to <Table.Header>
and <Table.Cell>
Please ensure that unique ids are used for all columns across multiple tables. Using the same columns 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 id="13">{'Column 13'}</th> <th id="14">{'Column 14'}</th> <th 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 id="13">{'Value 13'}</td> <td id="14">{'Value 14'}</td> <td 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 id="13">{'Value 13'}</td> <td id="14">{'Value 14'}</td> <td 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 id="13">{'Value 13'}</td> <td id="14">{'Value 14'}</td> <td 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 ids are used for all columns across multiple tables. Using the same columns 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 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 id="b">{'Column 15'}</th> </tr> </thead> <tbody> <tr> <td 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 id="b">{'Value 15'}</td> </tr> <tr> <td 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 id="b">{'Value 15'}</td> </tr> <tr> <td 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 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
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
NOTE: The Advanced Table kit uses the Tanstack Table v8 under the hood to render advanced tables that allow for complex, nested data structures with expansion and sort options.
The AdvancedTable kit accepts tree data and automatically renders expansion controls for nested subrows, to any depth, based on the data it is given. In it's simplest form, the kit has two required props:
tableData
accepts an array of objects as the table data. Each object is a table row, and each key:value pair within an object is a column value within that row. Nested children within a data object are automatically rendered as subrows under their parent row. Each parent row is prepended with expansion controls for toggling its nested child rows. The toggleExpansionAll
button in the first column header can also be used to toggle expansion of all parent rows within the table.
For a visual of the data structure needed for tableData
, see here.
columnDefinitions
maps to the columns prop on the Tanstack table. Column definitions are the single most important part of building a table as they are responsible for building the underlying data model that is used for all sorting, expansion, etc. ColumnDefinitions
in the AdvancedTable kit is an array of objects as seen in the code snippet below. Each object within the array has two REQUIRED items:
accessor
: this is the key from your data for the value you want rendered in that columnlabel
: this is what will be rendered as the column header labelThere is also one optional item that is only required if the table has nested data:
cellAccessors
: This is an array of strings that represent keys from your data object. This is only required for the first column in case of nested data. If you have nested data, the AdvancedTable needs to know what to render in that first column for nested items. This array represents the nested data in the order you want it rendered.import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableDefault = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableDefault
The optional loading
prop takes a boolean value that can be managed using state. If loading is true, the table will display the loading skeleton and once loading is false, the table will render with the data provided.
By default, the inital row count of the loading skeleton is set to 10. If you want more control over this initial row count, the optional initialLoadingRowsCount
prop can be used to pass in a number. NOTE: This is only for the first render of the table, subsequent loading skeleton row count logic is handled within the kit itself.
import React, { useState } from "react" import { AdvancedTable, Button } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableLoading = (props) => { const [isloading, setIsLoading] = useState(true) const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <Button marginBottom="md" onClick={()=> setIsLoading(!isloading)} text="Toggle Loading State" variant="secondary" /> <AdvancedTable columnDefinitions={columnDefinitions} loading={isloading} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableLoading
the enableSorting
prop is a boolean prop set to false by default. If true, the table will add sort logic linked to the sort button in the header. Clicking the sort button will toggle sort between ascending and descending. Currently this sort functionality is only available on the first column.
An optional prop, sortIcon
allows you to customize your icon sets by passing it an array of any comma-separated pair of icon values. The first icon value will replace the kit's default icon when sort direction is desc, and the second value will replace the default icon when sort direction is asc. sortIcon
also allows you to pass it a single icon as a string, in which case the icon will not toggle with the sort state. Default for this prop is ["arrow-up-short-wide", "arrow-down-short-wide"]
. All strings must be valid FA icons.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableSort = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} > <AdvancedTable.Header enableSorting /> <AdvancedTable.Body /> </AdvancedTable> </div> ) } export default AdvancedTableSort
sortControl
is an optional prop that can be used to gain greater control over the sort state of the Advanced Table. Tanstack handles sort itself, however it does provide for a way to handle the state manually if needed. Usecases for this include needing to store the sort state so it persists on page reload, set an initial sort state, etc.
The sort state must be an object with a single key/value pair, with the key being "desc" and the value being a boolean. The default for sort direction is desc: true
.
import React, { useState } from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableSortControl = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] //State for sort direction const [isSortDesc, setIsSortDesc] = useState({desc: false}) // //Passing sort state to AdvancedTable as prop const sortControl = { value: isSortDesc, onChange: setIsSortDesc, } return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} sortControl={sortControl} tableData={MOCK_DATA} > <AdvancedTable.Header enableSorting /> <AdvancedTable.Body /> </AdvancedTable> </div> ) } export default AdvancedTableSortControl
NOTE: If using expandedControl
the dev is expected to manage the row level expansion state themselves, the kit itself will NOT do it by default.
expandedControl
is an optional prop that can be used to gain greater control over the expansion state of the Advanced Table. Tanstack handles expansion itself, however it does provide for a way to handle the state manually if needed. Usecases for this include needing to store the expansion state so it persists on page reload, set an initial expansion state, etc.
In this example we are showing that if initial expansion state is set, it will render the table expanded according to that state.
The expanded state must be an object with key/value pairs where the key is the row id and the value is a boolean, true or false. Tanstack by default assigns row ids based on index and depth of the row as can be seen in this example. For more information on row ids, see here.
By default, the click event on the row level toggleExpansion icon simply toggles the immediate sub rows open or closed. If you want to attach further logic to that button, the optional onRowToggleClick
prop can be used. This click event provides one argument that can be hooked into: the current row
object. Any additional functionality provided through this onClick will be applied in addition to the default.
Similar to the row level click event, the default of the click event on the toggleExpansion buttons that render in the first column header (and the subRow Header rows if prop enabled) toggles all top level rows open and closed. If you want to attach further logic to that button, the optional onToggleExpansionClick
prop can be used. This click event provides one argument that can be hooked into: the current row
object. Any additional functionality provided through this onClick will be applied in addition to the default.
ToggleExpansionIcon
is another optional prop that can be used to customize the icon for the toggleExpansion button. This prop takes a string value with the default set to arrows-from-line
. All strings must be valid FA icons.
import React, { useState } from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableExpandedControl = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] //State for manually effecting what is expanded const [expanded, setExpanded] = useState({'0': true, '0.0': true, '0.0.1': true}) //Passing expanded state to AdvancedTable as prop const expandedControl = { value: expanded, onChange: setExpanded, } const onRowToggleClick = (row) => { setExpanded({ ...expanded, [row.id]: !expanded[row.id] }) } return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} expandedControl={expandedControl} onRowToggleClick={onRowToggleClick} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableExpandedControl
The expandByDepth
prop enables users to expand or collapse table rows by specific levels of nesting. When provided, it renders a dropdown that appears when the toggle icon in the header is clicked.
expandByDepth
accepts an array of objects, where each object defines the depth level to target and the label to display in the dropdown. When a user selects an option:
Expanding a depth: Expands all rows at the selected depth AND all parent levels above it (if parent levels were closed), ensuring nested content is visible.
Collapsing a depth: Only collapses rows at the selected depth, keeping parent rows expanded for context.
If you want to attach further logic to each option click, the optional onExpandByDepthClick
prop can be used. This click event provides 2 arguments that can be hooked into: the depth level of the clicked item AND all flattened table rows. Any additional functionality provided through this onClick will be applied in addition to the default.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableExpandByDepth = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const expandByDepth = [ { depth: 0, label: "Year", }, { depth: 1, label: "Quarter", }, { depth: 2, label: "Month", } ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} expandByDepth={expandByDepth} onExpandByDepthClick={(depth, rows) => {console.log(depth, rows)}} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableExpandByDepth
subRowHeaders
is an optional prop that if present will add header rows at each level of the nested data. The prop takes an array of strings, each string being the text for each header row. The array of strings must be in the order in which they need to be rendered in the UI according to depth.
enableToggleExpansion
is an additional optional prop that can be used in conjunction with the subRowHeaders prop. enableToggleExpansion
is a string that can be "all", "header" or "none". If set to "all", the toggle exapansion button will appear in the table header as well as in the subRow headers. If set to "header" button will only appear in header and NOT in subRow headers. This is set to "header" by default.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableSubrowHeaders = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] //Render the subRow header rows const subRowHeaders = ["Quarter", "Month", "Day"] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} enableToggleExpansion="all" tableData={MOCK_DATA} > <AdvancedTable.Header /> <AdvancedTable.Body subRowHeaders={subRowHeaders}/> </AdvancedTable> </div> ) } export default AdvancedTableSubrowHeaders
collapsibleTrail
is an optional prop that is set to 'true' by default. If set to 'false', it will remove the trail on the left of the rows when subRows are toggled open.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableCollapsibleTrail = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} > <AdvancedTable.Header /> <AdvancedTable.Body collapsibleTrail={false} /> </AdvancedTable> </div> ) } export default AdvancedTableCollapsibleTrail
The Tanstack table consumes the useReactTable hook to create the table. This hook takes an object that can contain any of the functions that the Tanstack table provides. The advancedTable's optional tableOptions
can be used to pass tanstack options to the kit.
In the above example, we are using the initialState option provided by tanstack that takes sort as one of it's values. Setting it to true for the first column is reversing the sort order on first render of the table. For a complete list of possible options and how to use them, see here
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableTableOptions = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const tableOptions = { initialState: { sorting: [ { id: "year", desc: true, }, ], }, } return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} tableOptions={tableOptions} /> </div> ) } export default AdvancedTableTableOptions
This kit uses the Table kit under the hood which comes with its own set of props. If you want to apply certain Table props to that underlying kit, you can do so by using the optional tableProps
prop. This prop must be an object that contains valid Table props. For a full list of Table props, see here.
This doc example showcases the use of two table props, including how to render the vertical borders between columns.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableTableProps = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const tableProps = { container: false, verticalBorder: true } return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} tableProps={tableProps} /> </div> ) } export default AdvancedTableTableProps
The TableProps
prop can also be used to render a sticky header for the Advanced Table.
This doc example showcases how to set a sticky header for a nonresponsive table (see the responsive
prop set to "none"). To achieve sticky header AND responsive functionality, see the "Sticky Header for Responsive Table" doc example below.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableStickyHeader = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const tableProps = { sticky: true } return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} responsive="none" tableData={MOCK_DATA} tableProps={tableProps} /> </div> ) } export default AdvancedTableStickyHeader
Create a sticky header that works for responsive Advanced Tables by setting sticky: true
via tableProps
and giving the AdvancedTable a maxHeight
using our Max Height global prop.
NOTE: This behavior requires a maxHeight
to work. The header is sticky within the table container, allowing for it to work along with the first column stickiness of a responsive table on smaller screen sizes.
Expand the table above to see this in action.
A sticky header on a nonresponsive table is demonstrated in the "Sticky Header" doc example above.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableTablePropsStickyHeader = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const tableProps = { sticky: true } return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} maxHeight="xs" tableData={MOCK_DATA} tableProps={tableProps} /> </div> ) } export default AdvancedTableTablePropsStickyHeader
To render sticky columns for the Advanced Table, you can use the stickyLeftColumn
prop. This prop expects an array of the column ids you want to be sticky.
To achieve this:
stickyLeftColumn
in the order in which the columns are rendered.responsive
to none when using stickyLeftColumn
since responsive just makes the first column sticky and the slightly different styling for responsive
and stickyLeftColumn
may override each other in unexpected ways.import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableStickyColumns = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", id: "year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", id: "newEnrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", id: "scheduledMeetings", }, { accessor: "attendanceRate", label: "Attendance Rate", id: "attendanceRate", }, { accessor: "completedClasses", label: "Completed Classes", id: "completedClasses", }, { accessor: "classCompletionRate", label: "Class Completion Rate", id: "classCompletionRate", }, { accessor: "graduatedStudents", label: "Graduated Students", id: "graduatedStudents", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} responsive="none" stickyLeftColumn={["year"]} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableStickyColumns
To achieve a sticky header AND sticky columns together, in addition to the stickyLeftColumn
logic outlined above, you can:
sticky: true
via tableProps
maxHeight
using our Max Height global prop. NOTE: This behavior requires a maxHeight
to work. The header is sticky within the table container, allowing for it to work along with the column stickiness.
Expand the table above to see this in action.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableStickyColumnsAndHeader = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", id: "year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", id: "newEnrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", id: "scheduledMeetings", }, { accessor: "attendanceRate", label: "Attendance Rate", id: "attendanceRate", }, { accessor: "completedClasses", label: "Completed Classes", id: "completedClasses", }, { accessor: "classCompletionRate", label: "Class Completion Rate", id: "classCompletionRate", }, { accessor: "graduatedStudents", label: "Graduated Students", id: "graduatedStudents", }, ] const tableProps = { sticky: true } return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} maxHeight="xs" responsive="none" stickyLeftColumn={["year"]} tableData={MOCK_DATA} tableProps={tableProps} /> </div> ) } export default AdvancedTableStickyColumnsAndHeader
As a default, the kit assumes that the initial dataset is complete, and it renders all expansion buttons/controls based on that data; if no children are present, no expansion controls are rendered. If, however, you want to change the initial dataset to omit some or all of its children (to improve load times of a complex dataset, perhaps), and you implement a querying logic that loads children only when its parent is expanded, then you must use the inlineRowLoading
prop to ensure your expansion controls are rendered even though your child data is not yet loaded. You must also pass an empty children
array to any node that will have children to ensure its parent maintains its ability to expand. If this prop is called AND your data contains empty children
arrays, the kit will render expansion controls on any row with empty children, and then add an inline loading state within the expanded subrow until those child row(s) are returned to the page [by your query logic].
In this code example, 2021 has an empty children array. Toggle it open to see the inline loading state. Once the correct data loads, this state will be replaced with the correct data rows.
This prop is set to false
by default.
import React from "react" import { AdvancedTable } from 'playbook-ui' import { MOCK_DATA_INLINE_LOADING } from "./_mock_data_inline_loading" const AdvancedTableInlineRowLoading = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] //Render the subRow header rows const subRowHeaders = ["Quarter", "Month", "Day"] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} enableToggleExpansion="all" inlineRowLoading tableData={MOCK_DATA_INLINE_LOADING} > <AdvancedTable.Header /> <AdvancedTable.Body subRowHeaders={subRowHeaders}/> </AdvancedTable> </div> ) } export default AdvancedTableInlineRowLoading
The responsive
prop can be set to "scroll" or "none", and is set to "scroll" by default to make Advanced Tables responsive. To disable, set responsive="none"
.
import React from "react" import { AdvancedTable, Title } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableResponsive = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <Title size={4} text="Not Responsive" /> <AdvancedTable columnDefinitions={columnDefinitions} responsive="none" tableData={MOCK_DATA} /> <Title paddingTop="sm" size={4} text="Responsive as Default" /> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableResponsive
The Advanced Table also allows for rendering custom components within individual Cells. To achieve this, you can make use of the optional customRenderer
item within each columnDefinition. This function gives you access to the current Cell's value if you just want to use that with a custom Kit, but it also gives you access to the entire row
object. The row object provides all data for the current row. To access the data, use row.original
which is the entire data object for the current row. See the code snippet below for 3 separate use cases and how they were acheived.
See here for more indepth information on columnDefinitions are how to use them.
See here for the structure of the tableData used.
import React from "react" import { AdvancedTable, Pill, Body, Flex, Detail, Caption, Badge, Title } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableCustomCell = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], customRenderer: (row, value) => ( <Flex> <Title size={4} text={value} /> <Badge dark marginLeft="xxs" text={row.original.newEnrollments > 20 ? "High" : "Low"} variant="neutral" /> </Flex> ), }, { accessor: "newEnrollments", label: "New Enrollments", customRenderer: (row, value) => ( <Pill text={value} variant="success" /> ), }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", customRenderer: (row, value) => <Body><a href="#">{value}</a></Body>, }, { accessor: "attendanceRate", label: "Attendance Rate", customRenderer: (row, value) => ( <Flex alignItems="end" orientation="column" > <Detail bold color="default" text={value} /> <Caption size="xs">{row.original.graduatedStudents}</Caption> </Flex> ), }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} enableToggleExpansion="all" responsive="none" tableData={MOCK_DATA} > <AdvancedTable.Header enableSorting /> <AdvancedTable.Body /> </AdvancedTable> </div> ) } export default AdvancedTableCustomCell
pagination
is an optional prop that can be used to add pagination to the AdvancedTable. If present, it will add pagination with default values for pageSize, etc. To customize pagination, you can also use paginationProps
shown in the next example.
import React from "react" import { AdvancedTable } from 'playbook-ui' import PAGINATION_MOCK_DATA from "./advanced_table_pagination_mock_data.json" const AdvancedTablePagination = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <> <AdvancedTable columnDefinitions={columnDefinitions} pagination tableData={PAGINATION_MOCK_DATA} /> </> ) } export default AdvancedTablePagination
paginationProps
is an optional prop that can be used to further customize pagination for the AdvancedTable. This prop is an object with 2 optional items:
pageIndex
: An optional prop to set which page is set to open on initial load. Default is '0'pageSize
: An optional prop to set total number of rows for each page before the Table paginates. Default is '20'range
: The range prop determines how many pages to display in the Pagination component. Regardless of this value, the first two and last two pages are always visible to facilitate navigation to the beginning and end of the pagination. If these always-visible pages fall within the specified range, they are included in the display. If they fall outside the range, the pagination will show additional pages up to the number defined by the range prop. See here for more details. Default is set to '5'import React from "react" import { AdvancedTable } from 'playbook-ui' import PAGINATION_MOCK_DATA from "./advanced_table_pagination_mock_data.json" const AdvancedTablePaginationWithProps = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const paginationProps = { pageIndex: 1, pageSize: 10, range: 2 } return ( <> <AdvancedTable columnDefinitions={columnDefinitions} pagination paginationProps={paginationProps} responsive="none" tableData={PAGINATION_MOCK_DATA} /> </> ) } export default AdvancedTablePaginationWithProps
Use a nested columns
array in your columnDefinitions to create multiple header rows. Any column with columns
is treated as a grouped header, and its child columns are displayed beneath it.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableColumnHeaders = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { label: "Enrollment Data", columns: [ { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, ], }, { label: "Performance Data", columns: [ { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ], }, ]; return ( <> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} /> </> ) } export default AdvancedTableColumnHeaders
Multiple levels of column headers can also be rendered as seen here.
import React from "react"; import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json"; const AdvancedTableColumnHeadersMultiple = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { label: "Enrollment Data", columns: [ { label: "Enrollment Stats", columns: [ { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, ], }, ], }, { label: "Performance Data", columns: [ { label: "Completion Metrics", columns: [ { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, ], }, { label: "Attendance", columns: [ { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, ], }, ], }, ]; return ( <> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} /> </> ); }; export default AdvancedTableColumnHeadersMultiple;
import React from "react" import { AdvancedTable, Pill } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableColumnHeadersCustomCell = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { label: "Enrollment Data", columns: [ { accessor: "newEnrollments", label: "New Enrollments", customRenderer: (row, value) => ( <Pill text={value} variant="success" /> ), }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", customRenderer: (row, value) => ( <Pill text={value} variant="info" /> ), }, ], }, { label: "Performance Data", columns: [ { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", customRenderer: (row, value) => ( <Pill text={value} variant="error" /> ), }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ], }, ]; return ( <> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} /> </> ) } export default AdvancedTableColumnHeadersCustomCell
The borders of column groups can be set to a different color using the columnGroupBorderColor
prop. In order for these borders to be visible, this prop must be used with tableProps
and verticalBorder
set to true.
The available colors for the border are Playbook's Text Colors, which can be found here.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableColumnBorderColors = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { label: "Enrollment Data", columns: [ { label: "Enrollment Stats", columns: [ { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, ], }, ], }, { label: "Performance Data", columns: [ { label: "Completion Metrics", columns: [ { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, ], }, { label: "Attendance", columns: [ { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, ], }, ], }, ]; const tableProps = { verticalBorder: true } return ( <> <AdvancedTable columnDefinitions={columnDefinitions} columnGroupBorderColor="text_lt_default" tableData={MOCK_DATA} tableProps={tableProps} /> </> ) } export default AdvancedTableColumnBorderColors
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_no_subrows.json" const AdvancedTableNoSubrows = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableNoSubrows
selectableRows
is a boolean prop that if present will add checkboxes to all rows that will allow for selecting rows.
When a parent row is clicked, it will check all nested children rows, Children rows can be manually checked or unchecked as well.
The onRowSelectionChange
prop returns an array of ids of all Rows that have been selected. Open the console on this example and check and uncheck checkboxes to see this is action! NOTE: Each object within the tableData
Array must contain a unique id in order to attach an id to all Rows for this to function.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_with_id.json" const AdvancedTableSelectableRows = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] //Render the subRow header rows const subRowHeaders = ["Quarter", "Month", "Day"] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} enableToggleExpansion="all" onRowSelectionChange={(selectedRows) => console.log(selectedRows)} selectableRows tableData={MOCK_DATA} > <AdvancedTable.Header /> <AdvancedTable.Body subRowHeaders={subRowHeaders}/> </AdvancedTable> </div> ) } export default AdvancedTableSelectableRows
selectableRows
can also be used with tables without nested row data.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_no_subrows.json" const AdvancedTableSelectableRowsNoSubrowsReact = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} onRowSelectionChange={(selectedRows) => console.log(selectedRows)} selectableRows tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableSelectableRowsNoSubrowsReact
Custom actions content can be rendered within the Actions Bar as shown in this doc example. The component passed to actions
will be rendered on the right of the actionsBar. The onRowSelectionChange
can then be used to attach the needed click events to those actions.
import React, {useState} from "react" import { AdvancedTable, CircleIconButton, Flex } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_no_subrows.json" const AdvancedTableSelectableRowsActions = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const [selectedRows, setSelectedRows] = useState() const CustomActions = () => { const rowIds = selectedRows ? Object.keys(selectedRows) : []; return ( <Flex> <CircleIconButton icon="file-csv" onClick={() => alert(rowIds.length === 0 ? "No Selection Made" : `Row ids ${rowIds.join(", ")} will be exported!`) } variant="link" /> <CircleIconButton icon="trash-alt" onClick={() => alert(rowIds.length === 0 ? "No Selection Made" : `Row ids ${rowIds.join(", ")} will be deleted!`) } variant="link" /> </Flex> ); }; return ( <div> <AdvancedTable actions={<CustomActions/>} columnDefinitions={columnDefinitions} onRowSelectionChange={(selected) => setSelectedRows(selected)} selectableRows tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableSelectableRowsActions
showActionsBar
is an optional prop that renders the header at the top showing the row count. This is set to true
by default but can be toggled off by setting it to false
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_no_subrows.json" const AdvancedTableSelectableRowsHeader = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} onRowSelectionChange={(selectedRows) => console.log(selectedRows)} selectableRows showActionsBar={false} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableSelectableRowsHeader
Inline Cell Editing can be achieved with a combination of our TextInput
kit and the customRenderer
method available through columnDefinitions.
Hover over any cell within the 'Scheduled Meetings' column to see the TextInput and type in to change values. Values can be saved by clicking away from the TextInput or by hitting 'Enter'.
See the code snippet below to see how this was achieved. Devs must manage state themselves as shown.
import React, { useState } from "react"; import { AdvancedTable, TextInput, Body } from 'playbook-ui'; import MOCK_DATA from "./advanced_table_mock_data.json"; const AdvancedTableInlineEditing = (props) => { const [editedValues, setEditedValues] = useState({}); const EditableCell = ({ rowId, originalValue, onSave }) => { const [localValue, setLocalValue] = useState(originalValue); const handleChange = (e) => setLocalValue(e.target.value); const handleBlur = () => { originalValue !== localValue && onSave(rowId, localValue); }; return ( <TextInput inline marginBottom="none" > <input onBlur={handleBlur} onChange={handleChange} onKeyDown={(e) => e.key === 'Enter' && handleBlur()} value={localValue} /> </TextInput> ); }; const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", editable: true, customRenderer: (row) => { return ( <EditableCell onSave={(id, val) => { setEditedValues((prev) => ({ ...prev, [id]: val })); }} originalValue={ editedValues[row.id] ?? row.original.scheduledMeetings } rowId={row.id} /> ); }, }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ]; return ( <div className="App"> <AdvancedTable columnDefinitions={columnDefinitions} tableData={MOCK_DATA} /> { editedValues && Object.keys(editedValues).length > 0 && ( <> <Body marginTop="md" > Edited Values by Row Id: </Body> <pre style={{color: 'white'}}>{JSON.stringify(editedValues, null, 2)}</pre> </> ) } </div> ); }; export default AdvancedTableInlineEditing;
Trigger Fullscreen mode with the allowFullScreen
and fullScreenControl
props. allowFullScreen
is a boolean that enables Fullscreen functionality for an Advanced Table. fullScreenControl
is a callback function that receives an object containing the table's internal toggleFullscreen
function, allowing you to store and trigger Fullscreen from the parent component. An external trigger (like a button) must be used to activate Fullscreen mode.
Exit Fullscreen mode by clicking the minimize top-right-corner icon or by pressing the "Escape" keyboard key.
import React, { useState } from "react" import { AdvancedTable, Button, Flex } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" import PAGINATION_MOCK_DATA from "./advanced_table_pagination_mock_data.json" const AdvancedTableFullscreen = (props) => { const [fullscreenToggleSmall, setFullscreenToggleSmall] = useState(null) const [fullscreenToggleLarge, setFullscreenToggleLarge] = useState(null) const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const tableProps = { sticky: true } return ( <div> <Flex justify="end"> <Button marginBottom="sm" onClick={() => fullscreenToggleSmall?.()} text="Fullscreen Small Table" variant="secondary" /> </Flex> <AdvancedTable allowFullScreen columnDefinitions={columnDefinitions} fullScreenControl={({ toggleFullscreen }) => setFullscreenToggleSmall(() => toggleFullscreen)} tableData={MOCK_DATA} > <AdvancedTable.Header enableSorting /> <AdvancedTable.Body /> </AdvancedTable> <Flex justify="end"> <Button marginY="sm" onClick={() => fullscreenToggleLarge?.()} text="Fullscreen Large Table" variant="secondary" /> </Flex> <AdvancedTable allowFullScreen columnDefinitions={columnDefinitions} fullScreenControl={({ toggleFullscreen }) => setFullscreenToggleLarge(() => toggleFullscreen)} responsive="none" tableData={PAGINATION_MOCK_DATA} tableProps={tableProps} > <AdvancedTable.Header enableSorting /> <AdvancedTable.Body /> </AdvancedTable> </div> ) } export default AdvancedTableFullscreen
The columnVisibilityControl
prop allows users to toggle the visibility of table columns dynamically.
The default can be enabled simply by passing { default:true }
to the prop as shown. This will render the header with the icon enabled dropdown. The dropdown contains all columns present in the Table and any can be toggled on or off via the checkboxes.
NOTE: The first column will not be shown in the dropdown as an option since all the expansion logic/functionality lives there and it should always be visible.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableColumnVisibility = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], id: "year" }, { accessor: "newEnrollments", label: "New Enrollments", id: "newEnrollments" }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", id: "scheduledMeetings" }, { accessor: "attendanceRate", label: "Attendance Rate", id: "attendanceRate" }, { accessor: "completedClasses", label: "Completed Classes", id: "completedClasses" }, { accessor: "classCompletionRate", label: "Class Completion Rate", id: "classCompletionRate" }, { accessor: "graduatedStudents", label: "Graduated Students", id: "graduatedStudents" }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} columnVisibilityControl={{default: true}} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableColumnVisibility
The columnVisibilityControl
prop also allows for greater control over the columnVisibility state. Devs can manage state themselves by passing in value
and onChange
as shown.
The additional onColumnVisibilityChange
provides a callback with the current state as the argument if needed.
import React, { useState } from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableColumnVisibilityWithState = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], id: "year" }, { accessor: "newEnrollments", label: "New Enrollments", id: "newEnrollments" }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", id: "scheduledMeetings" }, { accessor: "attendanceRate", label: "Attendance Rate", id: "attendanceRate" }, { accessor: "completedClasses", label: "Completed Classes", id: "completedClasses" }, { accessor: "classCompletionRate", label: "Class Completion Rate", id: "classCompletionRate" }, { accessor: "graduatedStudents", label: "Graduated Students", id: "graduatedStudents" }, ] const [columnVisibility, setColumnVisibility] = useState({ newEnrollments: false }) const columnVisibilityControl = { value: columnVisibility, onChange: setColumnVisibility, onColumnVisibilityChange: (currentState) => console.log(currentState), } return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} columnVisibilityControl={columnVisibilityControl} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableColumnVisibilityWithState
By using the includeIds
key/value pair as shown within the columnVisibilityControl
prop, you can control which columns show up as options in the columnVisibility dropdown.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableColumnVisibilityCustom = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], id: "year" }, { accessor: "newEnrollments", label: "New Enrollments", id: "newEnrollments" }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", id: "scheduledMeetings" }, { accessor: "attendanceRate", label: "Attendance Rate", id: "attendanceRate" }, { accessor: "completedClasses", label: "Completed Classes", id: "completedClasses" }, { accessor: "classCompletionRate", label: "Class Completion Rate", id: "classCompletionRate" }, { accessor: "graduatedStudents", label: "Graduated Students", id: "graduatedStudents" }, ] const columnVisibilityControl = { // This is the list of column ids that will be included in the column visibility control includeIds:["newEnrollments", "scheduledMeetings", "attendanceRate", "completedClasses"], } return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} columnVisibilityControl={columnVisibilityControl} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableColumnVisibilityCustom
The columnVisibilityControl
prop can also be used with multi-header columns as shown.
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableColumnVisibilityMulti = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", id: "year", cellAccessors: ["quarter", "month", "day"], }, { label: "Enrollment Data", id: "enrollmentData", columns: [ { label: "Enrollment Stats", id: "enrollmentStats", columns: [ { accessor: "newEnrollments", label: "New Enrollments", id: "newEnrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", id: "scheduledMeetings", }, ], }, ], }, { label: "Performance Data", id: "performanceData", columns: [ { label: "Completion Metrics", id: "completionMetrics", columns: [ { accessor: "completedClasses", label: "Completed Classes", id: "completedClasses", }, { accessor: "classCompletionRate", label: "Class Completion Rate", id: "classCompletionRate", }, ], }, { label: "Attendance", id: "attendance", columns: [ { accessor: "attendanceRate", label: "Attendance Rate", id: "attendanceRate", }, ], }, ], }, ]; return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} columnVisibilityControl={{default: true}} tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableColumnVisibilityMulti
Use the pinnedRows
prop to pin specific rows to the top of an Advanced Table. Pinned rows will remain at the top when scrolling through table data and reorganizing via sorting.
NOTE: This prop is in Beta. Current Requirements for V1:
sticky: true
via tableProps
(works with both responsive and non-responsive tables)top
property. For expandable rows, both parent and all its child row ids must be included individuallyimport React, { useState } from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data_with_id.json" const AdvancedTableRowPinning = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] const [pinnedRows, setPinnedRows] = useState({top: ["8", "9", "10", "11", "12", "13", "14"]}) return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} maxHeight="xs" pinnedRows={{value: pinnedRows, onChange: setPinnedRows}} tableData={MOCK_DATA} tableProps={{sticky: true}} > <AdvancedTable.Header enableSorting /> <AdvancedTable.Body /> </AdvancedTable> </div> ) } export default AdvancedTableRowPinning
import React from "react" import { AdvancedTable } from 'playbook-ui' import MOCK_DATA from "./advanced_table_mock_data.json" const AdvancedTableScrollbarNone = (props) => { const columnDefinitions = [ { accessor: "year", label: "Year", cellAccessors: ["quarter", "month", "day"], }, { accessor: "newEnrollments", label: "New Enrollments", }, { accessor: "scheduledMeetings", label: "Scheduled Meetings", }, { accessor: "attendanceRate", label: "Attendance Rate", }, { accessor: "completedClasses", label: "Completed Classes", }, { accessor: "classCompletionRate", label: "Class Completion Rate", }, { accessor: "graduatedStudents", label: "Graduated Students", }, ] return ( <div> <AdvancedTable columnDefinitions={columnDefinitions} maxHeight="xs" overflow="auto" responsive="scroll" scrollBarNone tableData={MOCK_DATA} /> </div> ) } export default AdvancedTableScrollbarNone
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 from 'react' import { Button, Filter, Flex, Select, TextInput } from 'playbook-ui' const SortingChangeCallback = (sortOptions) => { alert(JSON.stringify(sortOptions[0])) } const FilterDefault = (props) => { 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={SortingChangeCallback} 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="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={SortingChangeCallback} results={0} 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 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 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
You don't need to use the Gauge Kit to apply Playbook styles to your Highcharts gauge chart. Just import gaugeTheme.ts and merge it with your chart options—Playbook’s styling will apply automatically.
import React from 'react' import { gaugeTheme } from 'playbook-ui' import Highcharts from "highcharts" import HighchartsReact from "highcharts-react-official" import HighchartsMore from "highcharts/highcharts-more" import SolidGauge from "highcharts/modules/solid-gauge" HighchartsMore(Highcharts); SolidGauge(Highcharts); const data = [{ name: "Name", y: 45 }] const baseOptions = { series: [{ data: data }], }; const GaugePbStyles = () => { const options = Highcharts.merge({}, gaugeTheme, baseOptions); return ( <div> <HighchartsReact highcharts={Highcharts} options={options} /> </div> ); }; export default GaugePbStyles;
import React from 'react' import { Gauge } from 'playbook-ui' const data1 = [ { name: 'Data Used', value: 32 }, ] const data2 = [ { name: 'Sales to Date', value: 65 }, ] const GaugeUnits = (props) => ( <div> <Gauge chartData={data1} id="gauge-units1" suffix="GB" title="Data Usage" /> <Gauge chartData={data2} id="gauge-units2" prefix="$" suffix="k" title="Sales Goal" /> </div> ) export default GaugeUnits
import React from 'react' import { Gauge } from 'playbook-ui' const data = [ { name: 'Capacity', value: 75 }, ] const GaugeFullCircle = (props) => ( <div> <Gauge chartData={data} fullCircle id="gauge-full-circle" suffix="%" title="Seating Capacity" /> </div> ) export default GaugeFullCircle
overflow
to hidden on the parent element when nesting gauges inside of a flex items to best respond to shrinking screens. import React from 'react' import { Flex, FlexItem, Gauge } from 'playbook-ui' const GaugeSizing = (props) => ( <div> <Flex align="center" wrap > <FlexItem fixedSize="400px" overflow="hidden" shrink > <Gauge chartData={[ { name: 'Point 1', value: 100 } ]} id="gauge-sizing4" /> </FlexItem> <FlexItem fixedSize="300px" overflow="hidden" shrink > <Gauge chartData={[ { name: 'Point 2', value: 75 } ]} id="gauge-sizing3" /> </FlexItem> <FlexItem fixedSize="200px" overflow="hidden" shrink > <Gauge chartData={[ { name: 'Point 3', value: 50 } ]} id="gauge-sizing2" /> </FlexItem> <FlexItem fixedSize="125px" overflow="hidden" shrink > <Gauge chartData={[ { name: 'Point 4', value: 25 } ]} height="100%" id="gauge-sizing1" /> </FlexItem> </Flex> </div> ) export default GaugeSizing
import React from 'react' import { Gauge } from 'playbook-ui' const GaugeHeight = (props) => ( <div> <Gauge chartData={[ { name: 'Pixels', value: 400 } ]} height="400" id="gauge-height-px" suffix="px" title="Fixed Height in Pixels" /> <Gauge chartData={[ { name: 'Percentage', value: 45 } ]} height="45%" id="gauge-height-percent" suffix="%" title="Height as Percentage of Width" /> </div> ) export default GaugeHeight
import React, { useState } from 'react' import { Button, Gauge } from 'playbook-ui' const GaugeLiveData = (props) => { const [value, setValue] = useState(50) const [name, setName] = useState('Name') const updateValue = () => { setValue(Math.floor(Math.random() * 100)) } const updateName = () => { let index = namesArray.indexOf(name) if (namesArray.indexOf(name) == 5) { index = 0 } else { index += 1 } setName(namesArray[index]) } const namesArray = ['Name', 'Windows', 'Doors', 'Roofing', 'Siding', 'Gutters'] return ( <div> <Button onClick={updateValue} text="Update Value" /> <Button onClick={updateName} text="Update Name" /> <Gauge chartData={[{ name: name, value: value }]} id="gauge-live-data" /> </div> ) } export default GaugeLiveData
Custom data colors allow for color customization to match the needs of business requirements.
Pass the prop colors
and use ONE desired value data-1 | data-2 | data-3 | data-4 | data-5 | data-6 | data-7 | data-8
in an array. Hex colors are also available eg: #CA0095
We are able to wrap our Gauge kits within multiple other Flex and Card components.
import React from "react"; import { Flex, FlexItem, Gauge, Card, Caption, Body, SectionSeparator, Title } from 'playbook-ui' const data = [{ name: "Name", value: 10 }]; const GaugeComplex = (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 > <Gauge chartData={data} disableAnimation height="150" id="gauge-complex" suffix="%" /> </FlexItem> </Flex> </Flex> </Flex> </Card> </FlexItem> </Flex> ); export default GaugeComplex;
import React from 'react' import { BarGraph } from 'playbook-ui' 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 BarGraphDefault = (props) => ( <div> <BarGraph axisTitle="Number of Employees" chartData={chartData} id="bar-default" subTitle="Source: thesolarfoundation.com" title="Solar Employment Growth by Sector, 2010-2016" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May']} yAxisMin={0} /> </div> ) export default BarGraphDefault
You don't need to use the bar graph kit to apply the styles to your Highcharts bar graph. Just import the BarGraphStyles.scss to your component and the styles will apply automatically.
import React from 'react' import Highcharts from "highcharts"; import HighchartsReact from "highcharts-react-official"; import "../BarGraphStyles.scss"; // Your path might look more like this //import "playbook-ui/dist/pb_bar_graph/BarGraphStyles.scss"; const columnChartData = [ { 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 columnOptions = { chart: { type: "column", }, series: columnChartData, title: { text: "Solar Employment Growth by Sector, 2010-2016", }, subtitle: { text: "Source: thesolarfoundation.com", }, xAxis: { categories: ["Jan", "Feb", "Mar", "Apr", "May"], }, yAxis: { min: 0, title: { text: "Number of Employees", }, }, legend: { enabled: false }, credits: { enabled: false }, }; const BarGraphPbStyles = () => ( <div> <HighchartsReact highcharts={Highcharts} options={columnOptions} /> </div> ) export default BarGraphPbStyles
import React from 'react' import { BarGraph } from 'playbook-ui' const chartData = [{ name: 'Number of Installations', data: [1475, 200, 3000, 654, 656], }] const BarGraphLegend = (props) => ( <div> <BarGraph axisTitle="Number of Employees" chartData={chartData} id="bar-test-2" legend title="Bar Graph with Legend" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May']} yAxisMin={0} /> </div> ) export default BarGraphLegend
align
Type: String | Values: left | center | right (defaults to center)
verticalAlign
Type: String | Values: top | middle | bottom (defaults middle)
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 alignmnet. Negative x moves it to the left, positive x moves it to the right
y
offsets the legend relative to its vertical alignmnet. Negative y moves it up, positive y moves it down.
import React from 'react' import { BarGraph, Title } from 'playbook-ui' 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 BarGraphLegendPosition = (props) => ( <div> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="align | verticalAlign" /> <BarGraph align='right' axisTitle="Number of Employees" chartData={chartData} id="legend-position-bar" legend paddingBottom="sm" title="Alignment of Legend" verticalAlign="top" xAxisCategories={['Jan']} yAxisMin={0} /> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="layout" /> <BarGraph axisTitle="Number of Employees" chartData={chartData} id="legend-position-bar-1" layout="vertical" legend paddingBottom="sm" paddingTop="sm" title="Layout of Legend" xAxisCategories={['Jan']} yAxisMin={0} /> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="x | y" /> <BarGraph axisTitle="Number of Employees" chartData={chartData} id="legend-position-bar-2" layout="vertical" legend title="Offset of Legend" x={100} xAxisCategories={['Jan']} y={10} yAxisMin={0} /> </div> ) export default BarGraphLegendPosition
import React from 'react' import { BarGraph } from 'playbook-ui' const chartData = [{ name: 'Number of Installations', data: [1475, 200, 3000, 654, 656], }] const BarGraphLegendNonClickable = (props) => ( <div> <BarGraph axisTitle="Number of Employees" chartData={chartData} id="bar-test-3" legend title="Bar Graph with Legend Non Clickable" toggleLegendClick={false} xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May']} yAxisMin={0} /> </div> ) export default BarGraphLegendNonClickable
import React from 'react' import { BarGraph } from 'playbook-ui' const chartData = [{ name: 'Number of Installations', data: [1475, 200, 3000, 654, 656], }] const BarGraphDefault = (props) => ( <div> <BarGraph axisTitle="Number of Employees" chartData={chartData} height="300" id="bar-fixed-height" title="Fixed Height (300px)" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']} yAxisMin={0} /> <br /> <br /> <BarGraph axisTitle="Number of Employees" chartData={chartData} height="50%" id="bar-percentage-height" title="Percentage Height (50%)" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']} yAxisMin={0} /> </div> ) export default BarGraphDefault
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 { BarGraph } from 'playbook-ui' 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 BarGraphSpline = (props) => ( <div> <BarGraph axisTitle="Number of Employees" chartData={chartData} id="bar-spline" legend title="Bar Graph with Spline" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May']} yAxisMin={0} /> </div> ) export default BarGraphSpline
Custom data colors
allow for color customization to match the needs of business requirements.
Pass the prop colors and use desired values data-1 | data-2 | data-3 | data-4 | data-5 | data-6 | data-7 | data-8
in an array. Hex colors are also available eg: #CA0095
import React from 'react' import { BarGraph } from 'playbook-ui' 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 BarGraphColors = (props) => ( <div> <BarGraph axisTitle="Number of Employees" chartData={chartData} colors={['data-4', 'data-5', 'data-6', 'data-7', 'data-8']} id="bar-colors" title="Bar Graph with Custom Data Colors" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May']} yAxisMin={0} /> </div> ) export default BarGraphColors
The customOptions
prop provides comprehensive access to additional Highcharts options that are not explicitly defined as props.
It's important to note that certain options may require specific script imports to function properly.
Note: If you are having trouble getting any Highcharts options to work, please match the formatting of our staticOptions. For example, yAxis
will need to be wrapped with square brackets.
You may also need to override any of the defaults in order to get that options to work.
import React from 'react' import { BarGraph, Icon } from 'playbook-ui'import ReactDOMServer from 'react-dom/server' const chartData = [ { name: 'Role', data: [0, 200, 300, 654, 656], }, { name: 'Company', data: [150, 524, 320, 440, 500], }, ] const renderIcon = (iconName, color) => { return ReactDOMServer.renderToStaticMarkup( <Icon color={color} icon={iconName} />) }; const barGraphOptions = { yAxis: { tickInterval: 5, }, xAxis: { categories: ['1', '2', '3', '4', '5'], labels: { useHTML: true, formatter: function () { switch (this.value) { case '1': return `${renderIcon('frown', 'error')}`; case '2': return `${renderIcon('frown', 'warning')}`; case '3': return `${renderIcon('frown-open', 'neutral')}`; case '4': return `${renderIcon('smile', 'category_7')}`; case '5': return `${renderIcon('smile-beam', 'success')}`; default: return '' } }, style: { fontSize: '1.4em', }, y: 42, }, }, legend: { itemMarginTop: 62, }, } const BarGraphCustom = () => ( <div> <BarGraph chartData={chartData} customOptions={barGraphOptions} id="happiness-dashboard" legend title="Bar Graph with Custom Overrides" /> </div> ) export default BarGraphCustom
The stacking
prop can be used for a stacked bar graph. The prop allows for normal
or percent
as options.
import React from 'react' import { BarGraph } from 'playbook-ui' 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 BarGraphStacked = (props) => ( <div> <BarGraph axisTitle="Number Of Employees" chartData={chartData} id="bar-default" legend stacking="normal" title="Bar Graph with Stacked Columns" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May']} yAxisMin={0} /> </div> ) export default BarGraphStacked
import React from 'react' import { BarGraph } from 'playbook-ui' 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 BarGraphStacked = (props) => ( <div> <BarGraph axisTitle="Number of Employees" chartData={chartData} id="bar-default" legend title="Bar Graph with Negative Numbers" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May']} /> </div> ) export default BarGraphStacked
Optionally add a second yAxis to support secondary datasets (e.x., a spline) by passingyAxis: 1
to the second node of your chartData
array.
To customize the format and/or title of your secondary yAxis, pass your desired values as arrays through the axisFormat
and axisTitle
props, respectively.
import React from 'react' import { BarGraph } from 'playbook-ui' 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 axisTitles = [ {name: "Number of Installations"}, {name: "Percentage"}] const axisFormats = [{format: ""}, {format: "{value}%"}] const BarGraphSecondaryYAxis= (props) => ( <div> <BarGraph axisFormat={axisFormats} axisTitle={axisTitles} chartData={chartData} id="bar-spline" legend title="Bar Graph with Secondary Y-axis" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May']} yAxisMin={0} /> </div> ) export default BarGraphSecondaryYAxis
import React from 'react' import { BarGraph } from 'playbook-ui' const barGraphOptions = { 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: { min: 0, title: { text: 'Population (millions)', align: 'high' }, labels: { overflow: 'justify' }, }, 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 BarGraphHorizontal = (props) => ( <div> <BarGraph customOptions={barGraphOptions} id="bar-horizontal" yAxisMin={0} /> </div> ) export default BarGraphHorizontal
import React from 'react' import { CircleChart } from 'playbook-ui' const data = [ { name: 'Waiting for Calls', value: 41, }, { name: 'On Call', value: 49, }, { name: 'After Call', value: 10, }, ] const CircleChartDefault = (props) => ( <div> <CircleChart chartData={data} id="circle-chart-default" /> </div> ) export default CircleChartDefault
You don't need to use the Circle Chart Kit to apply Playbook styles to your Highcharts circle chart. Just import circleChartTheme.ts and merge it with your chart options—Playbook’s styling will apply automatically.
import React from 'react' import { circleChartTheme } from 'playbook-ui' import Highcharts from "highcharts" import HighchartsReact from "highcharts-react-official" const data = [ { name: 'Waiting for Calls', y: 41, }, { name: 'On Call', y: 49, }, { name: 'After Call', y: 10, }, ] const baseOptions = { series: [{ data: data }], } const CircleChartPbStyles = () => { const options = Highcharts.merge({}, circleChartTheme, baseOptions ) return ( <div> <HighchartsReact highcharts={Highcharts} options={options} /> </div> ); }; export default CircleChartPbStyles;
import React, { useState } from 'react' import { CircleChart, Button } from 'playbook-ui' const CircleChartLiveData = (props) => { const [data, setData] = useState([ { name: 'Waiting for Calls', value: 41, }, { name: 'On Call', value: 49, }, { name: 'After Call', value: 10, }, ]) const data2 = [ { name: 'Waiting for Calls', value: 48, }, { name: 'On Call', value: 12, }, { name: 'After Call', value: 140, }, ] const updateValue = () => { setData(data2) } return ( <div> <Button onClick={updateValue} text="Update Value" /> <CircleChart chartData={data} id="circle-chart-live-data" /> </div> ) } export default CircleChartLiveData
import React from 'react' import { CircleChart } from 'playbook-ui' const dataRounded = [ { name: 'Waiting for Calls', value: 41, }, { name: 'On Call', value: 49, }, { name: 'After Call', value: 10, }, ] const CircleChartRounded = (props) => ( <div> <CircleChart chartData={dataRounded} id="default-test-rounded" innerSize="lg" rounded /> </div> ) export default CircleChartRounded
import React from 'react' import { CircleChart, Title } from 'playbook-ui' const dataWithABlock = [ { name: 'Waiting for Calls', value: 41, }, { name: 'On Call', value: 49, }, { name: 'After Call', value: 10, }, ] const CircleChartBlock = (props) => ( <div> <CircleChart chartData={dataWithABlock} id="chart-with-a-block" innerSize="lg" marginTop="xl" rounded > <Title size={1} tag="div" > {'83'} </Title> </CircleChart> </div> ) export default CircleChartBlock
Custom data colors allow for color customization to match the needs of business requirements.
Pass the prop colors
and use desired values data-1 | data-2 | data-3 | data-4 | data-5 | data-6 | data-7 | data-8
in an array. Hex colors are also available eg: #CA0095
import React from 'react' import { CircleChart } from 'playbook-ui' const dataWithColors = [ { name: 'Waiting for Calls', value: 41, }, { name: 'On Call', value: 49, }, { name: 'After Call', value: 10, }, ] const CircleChartColors = (props) => ( <div> <CircleChart chartData={dataWithColors} colors={['data-6', 'data-4', 'data-2']} id="colors-example" /> </div> ) export default CircleChartColors
import React from 'react' import { CircleChart } from 'playbook-ui' const dataWithLabels = [ { name: 'Facebook', value: 2498, }, { name: 'YouTube', value: 2000, }, { name: 'WhatsApp', value: 2000, }, { name: 'Facebook Messenger', value: 1300, }, { name: 'WeChat', value: 1165, }, { name: 'Instagram', value: 1000, }, { name: 'Tik Tok', value: 800, }, ] const CircleChartWithLabels = (props) => ( <div> <CircleChart chartData={dataWithLabels} dataLabels id="with-labels-example" /> </div> ) export default CircleChartWithLabels
import React from 'react' import { CircleChart } from 'playbook-ui' const dataWithLegend = [{ name: 'Bugs', value: 8, }, { name: 'Chores', value: 1, }, { name: 'Stories', value: 12, }, ] const CircleChartWithLegendKit = (props) => ( <div> <CircleChart chartData={dataWithLegend} id="with-legend-example" legend /> </div> ) export default CircleChartWithLegendKit
align
Type: String | Values: left | center | right (defaults to center)
verticalAlign
Type: String | Values: top | middle | bottom (defaults middle)
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 alignmnet. Negative x moves it to the left, positive x moves it to the right
y
offsets the legend relative to its vertical alignmnet. Negative y moves it up, positive y moves it down.
import React from 'react' import { CircleChart, Title } from 'playbook-ui' const data = [ { name: 'Waiting for Calls', value: 41, }, { name: 'On Call', value: 49, }, { name: 'After Call', value: 10, }, ] const dataFirst = [{ name: 'Bugs', value: 8, }, { name: 'Chores', value: 1, }, { name: 'Stories', value: 12, }, ] const dataSecond = [ { name: 'Queued', value: 7, }, { name: 'In Progress', value: 6, }, { name: 'Validation', value: 3, }, { name: 'Done', value: 6, }, ] const CircleChartLegendPosition = (props) => ( <div> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="align | verticalAlign" /> <CircleChart align='right' chartData={data} id="legend-position-circle" legend paddingBottom="sm" title="Alignment of Legend" verticalAlign="top" /> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="layout" /> <CircleChart chartData={dataFirst} id="legend-position-circle-1" layout="vertical" legend paddingBottom="sm" paddingTop="sm" title="Layout of Legend" /> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="x | y" /> <CircleChart chartData={dataSecond} id="legend-position-circle-2" layout="vertical" legend title="Offset of Legend" x={100} y={10} /> </div> ) export default CircleChartLegendPosition
import React from 'react' import { CircleChart } from 'playbook-ui' const dataWithTitle = [ { name: 'Facebook', value: 2498, }, { name: 'YouTube', value: 2000, }, { name: 'WhatsApp', value: 2000, }, { name: 'Facebook Messenger', value: 1300, }, { name: 'WeChat', value: 1165, }, { name: 'Instagram', value: 1000, }, { name: 'Tik Tok', value: 800, }, ] const CircleChartWithLegendKit = (props) => ( <div> <CircleChart chartData={dataWithTitle} id="with-title-example" title="Active Users on Social Media" /> </div> ) export default CircleChartWithLegendKit
import React from 'react' import { CircleChart } from 'playbook-ui' const dataFirst = [ { name: 'Bugs', value: 8, }, { name: 'Chores', value: 1, }, { name: 'Stories', value: 12, }, ] const dataSecond = [ { name: 'Queued', value: 7, }, { name: 'In Progress', value: 6, }, { name: 'Validation', value: 3, }, { name: 'Done', value: 6, }, ] const dataThird = [ { name: '1 Point Tickets', value: 2, }, { name: '3 Point Tickets', value: 5, }, { name: '5 Point Tickets', value: 6, }, { name: '8 Point Tickets', value: 3, }, { name: '13 Point Tickets', value: 1, }, ] const dataFourth = [ { name: 'Facebook', value: 2498, }, { name: 'YouTube', value: 2000, }, { name: 'WhatsApp', value: 2000, }, { name: 'Facebook Messenger', value: 1300, }, { name: 'WeChat', value: 1165, }, { name: 'Instagram', value: 1000, }, { name: 'Tik Tok', value: 800, }, ] const CircleChartInnerSizes = (props) => ( <div> <CircleChart chartData={dataFirst} id="with-innersize-sm" innerSize="sm" /> <CircleChart chartData={dataSecond} id="with-innersize-md" innerSize="md" /> <CircleChart chartData={dataThird} id="with-innersize-lg" innerSize="lg" /> <CircleChart chartData={dataFourth} className="poop" id="with-innersize-none " innerSize="none" /> </div> ) export default CircleChartInnerSizes
A custom tooltip format can be specified. The desired format can be passed as a string
of custom HTML to the tooltipHtml
prop.
{point.name}
and {point.y}
are useful values that can be referenced for each point in the graph.
import React from 'react' import { CircleChart } from 'playbook-ui' const data = [ { name: 'Waiting for Calls', value: 41, }, { name: 'On Call', value: 49, }, { name: 'After Call', value: 10, }, ] const CircleChartCustomTooltip = (props) => ( <div> <CircleChart chartData={data} id="circle-chart-default" tooltipHtml= '<p>Custom tooltip for {point.name} <br/>with value: {point.y}</p>' /> </div> ) export default CircleChartCustomTooltip
import React from 'react' import { LineGraph } from 'playbook-ui' 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 LineGraphDefault = (props) => ( <div> <LineGraph axisTitle="Number of Employees" chartData={data} id="line-default" subTitle="Source: thesolarfoundation.com" title="Solar Employment Growth by Sector, 2010-2016" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']} yAxisMin={0} /> </div> ) export default LineGraphDefault
You don't need to use the Line Graph Kit to apply Playbook styles to your Highcharts line graph. Just import lineGraphTheme.ts and merge it with your graph options—Playbook’s styling will apply automatically.
import React from 'react' import { lineGraphTheme } from 'playbook-ui' import Highcharts from "highcharts" import HighchartsReact from "highcharts-react-official" 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 baseOptions = { 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 LineGraphPbStyles = () => { const options = Highcharts.merge({}, lineGraphTheme, baseOptions) return( <div> <HighchartsReact highcharts={Highcharts} options={options} /> </div> ) } export default LineGraphPbStyles
import React from 'react' import { LineGraph } from 'playbook-ui' const data = [{ name: 'Number of Installations', data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], }] const LineGraphLegend = (props) => ( <div> <LineGraph axisTitle="Number of Employees" chartData={data} id="line-test-2" legend title="Line Graph with Legend" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug']} yAxisMin={0} /> </div> ) export default LineGraphLegend
align
Type: String | Values: left | center | right (defaults to center)
verticalAlign
Type: String | Values: top | middle | bottom (defaults middle)
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 alignmnet. Negative x moves it to the left, positive x moves it to the right
y
offsets the legend relative to its vertical alignmnet. Negative y moves it up, positive y moves it down.
import React from 'react' import { LineGraph, Title } from 'playbook-ui' 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 LineGraphLegendPosition = (props) => ( <div> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="align | verticalAlign" /> <LineGraph align='right' axisTitle="Number of Employees" chartData={data} id="legend-position-line" legend title="Alignment of Legend" verticalAlign="top" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug']} yAxisMin={0} /> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="layout" /> <LineGraph axisTitle="Number of Employees" chartData={data} id="legend-position-line-1" layout="vertical" legend title="Layout of Legend" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug']} yAxisMin={0} /> <Title paddingBottom="sm" paddingTop="sm" size={4} tag="h4" text="x | y" /> <LineGraph axisTitle="Number of Employees" chartData={data} id="legend-position-line-2" layout="vertical" legend title="Offset of Legend" x={100} xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug']} y={10} yAxisMin={0} /> </div> ) export default LineGraphLegendPosition
import React from 'react' import { LineGraph } from 'playbook-ui' const data = [{ name: 'Number of Installations', data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], }] const LineGraphLegendNonclickable = (props) => ( <div> <LineGraph axisTitle="Number of Employees" chartData={data} id="line-test-3" legend title="Line Graph with Legend Non Clickable" toggleLegendClick={false} xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug']} /> </div> ) export default LineGraphLegendNonclickable
import React from 'react' import { LineGraph } from 'playbook-ui' const data = [{ name: 'Number of Installations', data: [43934, 52503, 57177, 69658, 97031, 119931, 137133, 154175], }] const LineGraphDefault = (props) => ( <div> <LineGraph axisTitle="Number of Employees" chartData={data} height="300px" id="line-fixed-height" title="Fixed Height (300px)" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']} yAxisMin={0} /> <br /> <br /> <LineGraph axisTitle="Number of Employees" chartData={data} height="50%" id="line-percentage-height" title="Percentage Height (50%)" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']} yAxisMin={0} /> </div> ) export default LineGraphDefault
Custom data colors allow for color customization to match the needs of business requirements.
Pass the prop colors
and use desired values data-1 | data-2 | data-3 | data-4 | data-5 | data-6 | data-7 | data-8
in an array. Hex colors are also available eg: #CA0095
import React from 'react' import { LineGraph } from 'playbook-ui' 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 LineGraphColors = (props) => ( <div> <LineGraph axisTitle="Number of Employees" chartData={data} colors={['data-4', 'data-5', 'data-6', 'data-7', 'data-8']} id="line-colors" title="Line Graph with Custom Data Colors" xAxisCategories={['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']} yAxisMin={0} /> </div> ) export default LineGraphColors
Points are automatically arranged by their value
size.
By default, point colors are assigned sequentially from the global data
colors. Note that data points without a value (such as parent nodes) will still take on the next available color.
import React from 'react' import { TreemapChart } from 'playbook-ui' const chartData = [ { name: "Pepperoni", parent: "Toppings", value: 600, }, { name: "Cheese", parent: "Toppings", value: 510, }, { name: "Mushroom", parent: "Toppings", value: 330, },{ name: "Onions", parent: "Toppings", value: 250, }, { name: "Olives", parent: "Toppings", value: 204, }, { name: "Pineapple", parent: "Toppings", value: 90, }, { name: "Pizza Toppings", id: "Toppings", }, ] const TreemapChartDefault = (props) => ( <div> <TreemapChart chartData={chartData} id="treemap-default" title="Favored Pizza Toppings" /> </div> ) export default TreemapChartDefault
Data can be grouped into distinct segments by specifying the relationship in the chartData
. For a point to be a parent, it needs an id
of type string
included in its object. Any other data points may then reference that id
as their parent
value to establish the tree structure.
Parents can also be passed a custom color to be applied to all of its child points.
import React from 'react' import { TreemapChart } from 'playbook-ui' const chartData = [ { name: 'Meat', id: 'Meat', color: "#0056CF", }, { name: 'Pepperoni', parent: 'Meat', value: 250, }, { name: 'Meatball', parent: 'Meat', value: 400, }, { name: "Anchovy", parent: 'Meat', value: 40, }, { name: 'Vegetarian', id: 'Vegetarian', color: "#F9BB00", }, { name: 'Onions', parent: 'Vegetarian', value: 300, }, { name: 'Pineapple', parent: 'Vegetarian', value: 90, }, { name: "Peppers", parent: 'Vegetarian', value: 80, }, { name: "Specialty", id: "Specialty", color: "#9E64E9", },{ name: "Buffalo Chicken", parent: "Specialty", value: 400, }, { name: "Supreme", parent: "Specialty", value: 150, } ] const TreemapChartGroupedData = (props) => ( <div> <TreemapChart chartData={chartData} grouped id="treemap-grouped-data" title="Grouped Toppings" /> </div> ) export default TreemapChartGroupedData
Adding the drillable
prop allows the tree to be traversed up and down by clicking into each box. Relationships are established through the chartData
, detailed in the Grouped Data section above.
import React from 'react' import { TreemapChart } from 'playbook-ui' const chartData = [ { name: "Evergreen", id: "Evergreen", color: "#0056CF", }, { name: "Pine", id: "Pine", parent: "Evergreen", value: 300, color: "#477BC4", }, { name: "Ponderosa Pine", parent: "Pine", value: 50, }, { name: "Scots Pine", parent: "Pine", value: 150, }, { name: "White Pine", parent: "Pine", value: 100, }, { name: "Douglas Fir", parent: "Evergreen", value: 150, }, { name: "Juniper", parent: "Evergreen", value: 80, }, { name: "Hemlock", parent: "Evergreen", value: 30, }, { name: "Deciduous", id: "Deciduous", color: "#F9BB00", }, { name: "Oak", parent: "Deciduous", value: 80, }, { name: "Maple", id: "Maple", parent: "Deciduous", value: 180, color: "#F7CE52", }, { name: "Red Maple", parent: "Maple", value: 80, }, { name: "Sugar Maple", parent: "Maple", value: 100, }, { name: "Beech", parent: "Deciduous", value: 50, }, { name: "Willow", parent: "Deciduous", value: 100, }, { name: "Juniper", parent: "Deciduous", value: 90, }, ] const TreemapChartDrillable = (props) => ( <div> <TreemapChart chartData={chartData} drillable grouped id="treemap-drillable" title="Drillable Grouped Tree Species" /> </div> ) export default TreemapChartDrillable
Custom data colors allow for color customization to match the needs of business requirements.
Pass the prop colors
and use desired values data-1 | data-2 | data-3 | data-4 | data-5 | data-6 | data-7 | data-8
in an array. Hex colors are also available eg: #CA0095
import React from 'react' import { TreemapChart } from 'playbook-ui' const chartData = [ { name: "Pepperoni", parent: "Toppings", value: 600, }, { name: "Cheese", parent: "Toppings", value: 510, }, { name: "Mushroom", parent: "Toppings", value: 330, },{ name: "Onions", parent: "Toppings", value: 250, }, { name: "Olives", parent: "Toppings", value: 204, }, { name: "Pineapple", parent: "Toppings", value: 90, }, { name: "Pizza Toppings", id: "Toppings", }, ] const TreemapChartColors = (props) => ( <div> <TreemapChart chartData={chartData} colors={["data-4", "data-7", "#8E6E53", "#124732"]} id="treemap-colors" title="Favored Pizza Toppings" /> </div> ) export default TreemapChartColors
A custom tooltip format can be specified. The desired format can be passed as a string
of custom HTML to the tooltipHtml
prop.
{point.name}
and {point.value}
are useful values that can be referenced for each point in the graph.
import React from 'react' import { TreemapChart } from 'playbook-ui' const chartData = [ { name: "Pepperoni", parent: "Toppings", value: 600, }, { name: "Cheese", parent: "Toppings", value: 510, }, { name: "Mushroom", parent: "Toppings", value: 330, },{ name: "Onions", parent: "Toppings", value: 250, }, { name: "Olives", parent: "Toppings", value: 204, }, { name: "Pineapple", parent: "Toppings", value: 90, }, { name: "Pizza Toppings", id: "Toppings", }, ] const TreemapChartTooltip = (props) => ( <div> <TreemapChart chartData={chartData} id="treemap-tooltip" title="Favored Pizza Toppings" tooltipHtml= '<p>Custom tooltip for {point.name} <br/>with value: {point.value}</p>' /> </div> ) export default TreemapChartTooltip