From fd0140f64ead9dcff34598ed77274c50da85a7d0 Mon Sep 17 00:00:00 2001 From: Shawn Allen Date: Wed, 19 Sep 2018 23:16:26 -0700 Subject: [PATCH 01/13] rename DonutChart.js -> Donut.js --- src/{DonutChart.js => Donut.js} | 0 src/__tests__/{DonutChart.js => Donut.js} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/{DonutChart.js => Donut.js} (100%) rename src/__tests__/{DonutChart.js => Donut.js} (100%) diff --git a/src/DonutChart.js b/src/Donut.js similarity index 100% rename from src/DonutChart.js rename to src/Donut.js diff --git a/src/__tests__/DonutChart.js b/src/__tests__/Donut.js similarity index 100% rename from src/__tests__/DonutChart.js rename to src/__tests__/Donut.js From f0cce628aa428a725c8448cabcd9ba4e85c06aa9 Mon Sep 17 00:00:00 2001 From: Shawn Allen Date: Wed, 19 Sep 2018 23:17:49 -0700 Subject: [PATCH 02/13] update docs references --- pages/components/docs/DonutChart.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/pages/components/docs/DonutChart.md b/pages/components/docs/DonutChart.md index 765d56b8270..01f0828d4a1 100644 --- a/pages/components/docs/DonutChart.md +++ b/pages/components/docs/DonutChart.md @@ -1,18 +1,18 @@ -# DonutChart +# Donut ## Default example ```.jsx - - - - - - + + + + + + ``` ## System props -DonutChart components get `space` system props. Read our [System Props](/system-props) doc page for a full list of available props. +Donut components get `space` system props. Read our [System Props](/system-props) doc page for a full list of available props. ## Component props @@ -21,4 +21,4 @@ DonutChart components get `space` system props. Read our [System Props](/system- | data | Object | Use the keys `error`, `pending`, and `success` to set values used to generate slices in the chart | | size | Number | Used to set the width and height of the component -export const meta = {displayName: 'DonutChart'} +export const meta = {displayName: 'Donut'} From c7d82115fe6def8139b8166338af13a5a78f0e42 Mon Sep 17 00:00:00 2001 From: Shawn Allen Date: Wed, 19 Sep 2018 23:19:49 -0700 Subject: [PATCH 03/13] move DonutSlice -> Donut.Slice --- .../docs/{DonutChart.md => Donut.md} | 0 src/Donut.js | 48 +++++++++++++--- src/__tests__/Donut.js | 56 +++++++++++++------ .../{DonutChart.js.snap => Donut.js.snap} | 6 +- 4 files changed, 82 insertions(+), 28 deletions(-) rename pages/components/docs/{DonutChart.md => Donut.md} (100%) rename src/__tests__/__snapshots__/{DonutChart.js.snap => Donut.js.snap} (88%) diff --git a/pages/components/docs/DonutChart.md b/pages/components/docs/Donut.md similarity index 100% rename from pages/components/docs/DonutChart.md rename to pages/components/docs/Donut.md diff --git a/src/Donut.js b/src/Donut.js index 3933d85071d..27d2ade0cab 100644 --- a/src/Donut.js +++ b/src/Donut.js @@ -1,10 +1,13 @@ import React from 'react' import PropTypes from 'prop-types' import {arc as Arc, pie as Pie} from 'd3-shape' -import DonutSlice from './DonutSlice' -import {withSystemProps} from './system-props' +import {themeGet} from 'styled-system' +import {withSystemProps, withDefaultTheme} from './system-props' -function DonutChart(props) { +const defaultColor = '#666' +const getStateColors = themeGet('colors.state', {}) + +function Donut(props) { const {className, data, children = mapData(data), size} = props const radius = size / 2 @@ -31,18 +34,47 @@ function DonutChart(props) { } function mapData(data) { - return Object.keys(data).map(key => ) + return Object.keys(data).map(key => ) } -DonutChart.defaultProps = { +Donut.defaultProps = { size: 30 } -DonutChart.propTypes = { - // require elements, not mixed content: , , etc. +Donut.propTypes = { + // require elements, not mixed content: <Slice>, <title>, etc. children: PropTypes.oneOfType([PropTypes.element, PropTypes.arrayOf(PropTypes.element)]), data: PropTypes.objectOf(PropTypes.number), size: PropTypes.number } -export default withSystemProps(DonutChart, ['space']) +const Slice = withDefaultTheme(props => { + const {children, d, fill, state, value} = props + const stateColors = getStateColors(props) + const color = fill || stateColors[state] || stateColors.unknown || defaultColor + return ( + <path d={d} fill={color} data-value={value}> + {children} + </path> + ) +}) + +Slice.propTypes = { + // <title> is really the only thing that should be acceptable here + children: PropTypes.shape({type: 'title'}), + d: PropTypes.string, + fill: PropTypes.string, + state: PropTypes.string, + /* eslint-disable react/no-unused-prop-types */ + theme: PropTypes.shape({ + colors: PropTypes.shape({ + state: PropTypes.objectOf(PropTypes.string) + }) + }), + /* eslint-enable */ + value: PropTypes.number +} + +Donut.Slice = Slice + +export default withSystemProps(Donut, ['space']) diff --git a/src/__tests__/Donut.js b/src/__tests__/Donut.js index d98af748820..dba4615f81f 100644 --- a/src/__tests__/Donut.js +++ b/src/__tests__/Donut.js @@ -1,16 +1,17 @@ import React from 'react' -import DonutChart from '../DonutChart' -import DonutSlice from '../DonutSlice' +import Donut from '../Donut' import theme, {colors} from '../theme' -import {render} from '../utils/testing' +import {render, renderWithTheme} from '../utils/testing' -describe('DonutChart', () => { +const {state} = colors + +describe('Donut', () => { it('is a system component', () => { - expect(DonutChart.systemComponent).toEqual(true) + expect(Donut.systemComponent).toEqual(true) }) it('renders the data prop', () => { - const donut = render(<DonutChart data={{error: 1}} />) + const donut = render(<Donut data={{error: 1}} />) expect(donut).toMatchSnapshot() expect(donut.type).toEqual('svg') @@ -27,12 +28,12 @@ describe('DonutChart', () => { // expect(slice.props.fill).toEqual(colors.state.error) }) - it('renders DonutSlice children', () => { + it('renders Donut.Slice children', () => { const donut = render( - <DonutChart> - <DonutSlice state="success" value={1} /> - <DonutSlice state="failure" value={1} /> - </DonutChart> + <Donut> + <Donut.Slice state="success" value={1} /> + <Donut.Slice state="failure" value={1} /> + </Donut> ) expect(donut).toMatchSnapshot() expect(donut.children).toHaveLength(1) @@ -43,21 +44,42 @@ describe('DonutChart', () => { expect(slices[1].props.fill).toEqual(colors.state.failure) }) - it('renders a single DonutSlice child', () => { + it('renders a single Donut.Slice child', () => { const donut = render( - <DonutChart> - <DonutSlice state="success" value={1} /> - </DonutChart> + <Donut> + <Donut.Slice state="success" value={1} /> + </Donut> ) expect(donut).toMatchSnapshot() expect(donut.type).toEqual('svg') }) it('respects margin utility prop', () => { - expect(render(<DonutChart m={4} data={{error: 1}} />)).toHaveStyleRule('margin', `${theme.space[4]}px`) + expect(render(<Donut m={4} data={{error: 1}} />)).toHaveStyleRule('margin', `${theme.space[4]}px`) }) it('respects padding utility prop', () => { - expect(render(<DonutChart p={4} data={{error: 1}} />)).toHaveStyleRule('padding', `${theme.space[4]}px`) + expect(render(<Donut p={4} data={{error: 1}} />)).toHaveStyleRule('padding', `${theme.space[4]}px`) + }) + + describe('Donut.Slice', () => { + it('renders known states as colors', () => { + expect(render(<Donut.Slice state="error" />).props.fill).toEqual(state.error) + expect(render(<Donut.Slice state="pending" />).props.fill).toEqual(state.pending) + expect(render(<Donut.Slice state="success" />).props.fill).toEqual(state.success) + expect(render(<Donut.Slice state="unknown" />).props.fill).toEqual(state.unknown) + }) + + it('renders unknown states with theme.colors.state.unknown', () => { + expect(render(<Donut.Slice state="xyz" />).props.fill).toEqual(state.unknown) + }) + + it('renders the fallback color when no state color is found in the theme', () => { + expect(render(<Donut.Slice state="error" theme={{}} />).props.fill).toEqual('#666') + }) + + it('respects the fill attribute', () => { + expect(render(<Donut.Slice fill="pink" />).props.fill).toEqual('pink') + }) }) }) diff --git a/src/__tests__/__snapshots__/DonutChart.js.snap b/src/__tests__/__snapshots__/Donut.js.snap similarity index 88% rename from src/__tests__/__snapshots__/DonutChart.js.snap rename to src/__tests__/__snapshots__/Donut.js.snap index 4f8a874a51e..bc430a1166e 100644 --- a/src/__tests__/__snapshots__/DonutChart.js.snap +++ b/src/__tests__/__snapshots__/Donut.js.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`DonutChart renders DonutSlice children 1`] = ` +exports[`Donut renders Donut.Slice children 1`] = ` <svg className="emotion-0" height={30} @@ -23,7 +23,7 @@ exports[`DonutChart renders DonutSlice children 1`] = ` </svg> `; -exports[`DonutChart renders a single DonutSlice child 1`] = ` +exports[`Donut renders a single Donut.Slice child 1`] = ` <svg className="emotion-0" height={30} @@ -41,7 +41,7 @@ exports[`DonutChart renders a single DonutSlice child 1`] = ` </svg> `; -exports[`DonutChart renders the data prop 1`] = ` +exports[`Donut renders the data prop 1`] = ` <svg className="emotion-0" height={30} From bcd58f35bbecd0366948d7bc8d1dc81944c15fc2 Mon Sep 17 00:00:00 2001 From: Shawn Allen <shawn.allen@github.com> Date: Wed, 19 Sep 2018 23:20:03 -0700 Subject: [PATCH 04/13] export Donut only --- src/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index be157317c3f..d426d955369 100644 --- a/src/index.js +++ b/src/index.js @@ -23,8 +23,7 @@ export {default as CircleBadge} from './CircleBadge' export {default as Details} from './Details' export {default as Dropdown} from './Dropdown' -export {default as DonutChart} from './DonutChart' -export {default as DonutSlice} from './DonutSlice' +export {default as Donut} from './Donut' export {default as FilterList} from './FilterList' export {default as FilterListItem} from './FilterListItem' export {default as FlexContainer} from './FlexContainer' From 29e9b1b0cb064ad3604a5a8cb4c07cb47eeaf38d Mon Sep 17 00:00:00 2001 From: Shawn Allen <shawn.allen@github.com> Date: Wed, 19 Sep 2018 23:20:18 -0700 Subject: [PATCH 05/13] import {Donut} only --- pages/components/docs/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pages/components/docs/index.js b/pages/components/docs/index.js index 4ebd0349e05..d9b43b40c11 100644 --- a/pages/components/docs/index.js +++ b/pages/components/docs/index.js @@ -7,7 +7,7 @@ export {meta as CircleBadge} from './CircleBadge.md' export {meta as CircleOcticon} from './CircleOcticon.md' export {meta as CounterLabel} from './CounterLabel.md' export {meta as Details} from './Details.md' -export {meta as DonutChart} from './DonutChart.md' +export {meta as Donut} from './Donut.md' export {meta as Dropdown} from './Dropdown.md' export {meta as FilterList} from './FilterList.md' export {meta as Flash} from './Flash.md' From 2e3af10172161f067cc5cba71e2b9f7638ebcfd7 Mon Sep 17 00:00:00 2001 From: Shawn Allen <shawn.allen@github.com> Date: Wed, 19 Sep 2018 23:21:02 -0700 Subject: [PATCH 06/13] update testProps for Donut --- src/__tests__/UtilitySystemProps.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/UtilitySystemProps.js b/src/__tests__/UtilitySystemProps.js index 10fad9e11c0..e322e9f148f 100644 --- a/src/__tests__/UtilitySystemProps.js +++ b/src/__tests__/UtilitySystemProps.js @@ -6,7 +6,7 @@ import {renderStyles} from '../utils/testing' const testProps = { OcticonButton: {icon: X, label: 'button'}, - DonutChart: {data: {pending: 1}}, + Donut: {data: {pending: 1}}, MergeStatus: {state: 'ready'} } From 5f33164d66cd67d6a84970ad23025713e91f884c Mon Sep 17 00:00:00 2001 From: Shawn Allen <shawn.allen@github.com> Date: Thu, 20 Sep 2018 09:08:18 -0700 Subject: [PATCH 07/13] nix DonutSlice tests --- src/__tests__/DonutSlice.js | 27 --------------------------- 1 file changed, 27 deletions(-) delete mode 100644 src/__tests__/DonutSlice.js diff --git a/src/__tests__/DonutSlice.js b/src/__tests__/DonutSlice.js deleted file mode 100644 index 46ee60e4607..00000000000 --- a/src/__tests__/DonutSlice.js +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react' -import DonutSlice from '../DonutSlice' -import {colors} from '../theme' -import {renderWithTheme as render} from '../utils/testing' - -const {state} = colors - -describe('DonutSlice', () => { - it('renders known states as colors', () => { - expect(render(<DonutSlice state="error" />).props.fill).toEqual(state.error) - expect(render(<DonutSlice state="pending" />).props.fill).toEqual(state.pending) - expect(render(<DonutSlice state="success" />).props.fill).toEqual(state.success) - expect(render(<DonutSlice state="unknown" />).props.fill).toEqual(state.unknown) - }) - - it('renders unknown states with theme.colors.state.unknown', () => { - expect(render(<DonutSlice state="xyz" />).props.fill).toEqual(state.unknown) - }) - - it('renders the fallback color when no state color is found in the theme', () => { - expect(render(<DonutSlice state="error" theme={{}} />).props.fill).toEqual('#666') - }) - - it('respects the fill attribute', () => { - expect(render(<DonutSlice fill="pink" />).props.fill).toEqual('pink') - }) -}) From 45ca22a54eb820aebe7c703349879e5610226ca7 Mon Sep 17 00:00:00 2001 From: Shawn Allen <shawn.allen@github.com> Date: Thu, 20 Sep 2018 09:18:17 -0700 Subject: [PATCH 08/13] lint --- src/__tests__/Donut.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/__tests__/Donut.js b/src/__tests__/Donut.js index dba4615f81f..e93731bea87 100644 --- a/src/__tests__/Donut.js +++ b/src/__tests__/Donut.js @@ -1,7 +1,7 @@ import React from 'react' import Donut from '../Donut' import theme, {colors} from '../theme' -import {render, renderWithTheme} from '../utils/testing' +import {render} from '../utils/testing' const {state} = colors From 5fbdb02d4df490c2e43285c319e00adfd0e80ec6 Mon Sep 17 00:00:00 2001 From: Shawn Allen <shawn.allen@github.com> Date: Thu, 20 Sep 2018 09:18:23 -0700 Subject: [PATCH 09/13] remove DonutSlice component --- src/DonutSlice.js | 36 ------------------------------------ 1 file changed, 36 deletions(-) delete mode 100644 src/DonutSlice.js diff --git a/src/DonutSlice.js b/src/DonutSlice.js deleted file mode 100644 index a06b6a5c0c8..00000000000 --- a/src/DonutSlice.js +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react' -import PropTypes from 'prop-types' -import {themeGet} from 'styled-system' -import {withDefaultTheme} from './system-props' - -const defaultColor = '#666' -const getStateColors = themeGet('colors.state', {}) - -function DonutSlice(props) { - const {children, d, fill, state, value} = props - const stateColors = getStateColors(props) - const color = fill || stateColors[state] || stateColors.unknown || defaultColor - return ( - <path d={d} fill={color} data-value={value}> - {children} - </path> - ) -} - -DonutSlice.propTypes = { - // <title> is really the only thing that should be acceptable here - children: PropTypes.shape({type: 'title'}), - d: PropTypes.string, - fill: PropTypes.string, - state: PropTypes.string, - /* eslint-disable react/no-unused-prop-types */ - theme: PropTypes.shape({ - colors: PropTypes.shape({ - state: PropTypes.objectOf(PropTypes.string) - }) - }), - /* eslint-enable */ - value: PropTypes.number -} - -export default withDefaultTheme(DonutSlice) From 0a557e79bbe0297ab13d14eaa4929969a22cc6ba Mon Sep 17 00:00:00 2001 From: Shawn Allen <shawn.allen@github.com> Date: Thu, 20 Sep 2018 16:42:11 -0700 Subject: [PATCH 10/13] update Donut docs --- pages/components/docs/Donut.md | 35 ++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/pages/components/docs/Donut.md b/pages/components/docs/Donut.md index 01f0828d4a1..3f15650a2d0 100644 --- a/pages/components/docs/Donut.md +++ b/pages/components/docs/Donut.md @@ -1,15 +1,15 @@ # Donut +The Donut component is a circular chart that shows the relative share of commit status states for a pull request. + +## The `data` prop +The `data` prop is the simplest way to define the share of states. It takes an object literal with states as keys and the number of statuses with that state as values. Slices are always rendered clockwise in descending order by size. -## Default example ```.jsx -<Donut mr={1} data={{error: 2, pending: 3, success: 5}} /> -<Donut mr={1}> - <Donut.Slice value={1} state="pending" /> - <Donut.Slice value={1} state="success" /> - <Donut.Slice value={1} state="error" /> -</Donut> +<Donut data={{error: 2, pending: 3, success: 5}} /> ``` +When using the `data` prop, the fill of each slice comes from the corresponding value in the theme's `colors.state` object. In other words, if `theme.colors.state.error = "red"`, then the `error` slice will get `fill="red"`. You can customize the slice colors by either passing a custom `theme` prop or using the `Donut.Slice` component described below. + ## System props Donut components get `space` system props. Read our [System Props](/system-props) doc page for a full list of available props. @@ -19,6 +19,25 @@ Donut components get `space` system props. Read our [System Props](/system-props | Prop name | Type | Description | | :- | :- | :- | | data | Object | Use the keys `error`, `pending`, and `success` to set values used to generate slices in the chart | -| size | Number | Used to set the width and height of the component +| size | Number | Used to set the width and height of the component | + +# Donut.Slice +If you need to customize the color of your slices, you can use the `Donut.Slice` component as a child of `Donut`. + +```.jsx +<Donut> + <Donut.Slice value={1} fill="pink" /> + <Donut.Slice value={1} fill="salmon" /> + <Donut.Slice value={1} fill="tomato" /> +</Donut> +``` + +## `Donut.Slice` component props + +| Prop name | Type | Description | +| :- | :- | :- | +| state | String | The commit status state which this slice represents | +| value | Number | The number of statuses with this slice's state | +| fill | String | The fill color of the slice, which overrides the color determined by the `state` prop | export const meta = {displayName: 'Donut'} From 8f5969226447a4aef43cd511cfe21a3652097f1a Mon Sep 17 00:00:00 2001 From: Shawn Allen <shawn.allen@github.com> Date: Thu, 20 Sep 2018 16:42:19 -0700 Subject: [PATCH 11/13] update package-lock version --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9641706e486..a8451a93bb1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { - "name": "primer-react", - "version": "2.0.3-beta", + "name": "@primer/components", + "version": "2.0.4-beta", "lockfileVersion": 1, "requires": true, "dependencies": { From 14e72aa4bb4086cb343c96424cf3a5da6cecefd8 Mon Sep 17 00:00:00 2001 From: Shawn Allen <shawn.allen@github.com> Date: Thu, 27 Sep 2018 12:56:12 -0700 Subject: [PATCH 12/13] =?UTF-8?q?fix=20bad=20merge=20=F0=9F=A4=A6=E2=80=8D?= =?UTF-8?q?=E2=99=82=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/__tests__/UtilitySystemProps.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/__tests__/UtilitySystemProps.js b/src/__tests__/UtilitySystemProps.js index f8002c08dcf..7c04fdc7301 100644 --- a/src/__tests__/UtilitySystemProps.js +++ b/src/__tests__/UtilitySystemProps.js @@ -7,7 +7,6 @@ import {renderStyles} from '../utils/testing' const testProps = { OcticonButton: {icon: X, label: 'button'}, Donut: {data: {pending: 1}}, - MergeStatus: {state: 'ready'} MergeStatus: {state: 'ready'}, Avatar: {alt: ''} } From a487638a2e8f77d9dd4473eb5ca905f5624340dd Mon Sep 17 00:00:00 2001 From: Emily <emplums@github.com> Date: Fri, 28 Sep 2018 12:02:06 -0700 Subject: [PATCH 13/13] fix test --- src/__tests__/UtilitySystemProps.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/__tests__/UtilitySystemProps.js b/src/__tests__/UtilitySystemProps.js index 5b1c02c1066..c293b3896dc 100644 --- a/src/__tests__/UtilitySystemProps.js +++ b/src/__tests__/UtilitySystemProps.js @@ -6,7 +6,8 @@ import {renderStyles} from '../utils/testing' const testProps = { OcticonButton: {icon: X, label: 'button'}, - DonutChart: {data: {pending: 1}} + Donut: {data: {pending: 1}}, + Avatar: {alt: ''} } describe('UtilitySystemProps', () => {