-
Notifications
You must be signed in to change notification settings - Fork 836
Charts: Simplify PieSemiCircleChart API to use children composition #45369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Changes from all commits
b08ca0d
a898fbe
0fa5155
baf39ee
21d2e47
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
Significance: minor | ||
Type: changed | ||
|
||
Charts: improve pie semi circle chart composition | ||
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -1,7 +1,6 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||
import { localPoint } from '@visx/event'; | ||||||||||||||||||||||||||||||||||||||||||||||||
import { Group } from '@visx/group'; | ||||||||||||||||||||||||||||||||||||||||||||||||
import { Pie } from '@visx/shape'; | ||||||||||||||||||||||||||||||||||||||||||||||||
import { Text } from '@visx/text'; | ||||||||||||||||||||||||||||||||||||||||||||||||
import { useTooltip, useTooltipInPortal } from '@visx/tooltip'; | ||||||||||||||||||||||||||||||||||||||||||||||||
import clsx from 'clsx'; | ||||||||||||||||||||||||||||||||||||||||||||||||
import { useCallback, useContext, useMemo } from 'react'; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -46,18 +45,9 @@ export interface PieSemiCircleChartProps extends BaseChartProps< DataPointPercen | |||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||
clockwise?: boolean; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||||||
* Label text to display above the chart | ||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||
label?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||||||
* Note text to display below the label | ||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||
note?: string; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
/** | ||||||||||||||||||||||||||||||||||||||||||||||||
* Use the children prop to render additional elements on the chart. | ||||||||||||||||||||||||||||||||||||||||||||||||
* Supports composition API with PieSemiCircleChart.SVG and PieSemiCircleChart.HTML components. | ||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] Since label/note props were removed, consider adding a short usage example in this docblock showing how to render a title/note via children (Group/Text) and via the SVG compound component to guide consumers migrating to the new API.
Suggested change
Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||||||||||||||||||||||||||||||||||||||||||||||||
*/ | ||||||||||||||||||||||||||||||||||||||||||||||||
children?: ReactNode; | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -133,8 +123,6 @@ const PieSemiCircleChartInternal: FC< PieSemiCircleChartProps > = ( { | |||||||||||||||||||||||||||||||||||||||||||||||
legendItemClassName, | ||||||||||||||||||||||||||||||||||||||||||||||||
legendShape = 'circle', | ||||||||||||||||||||||||||||||||||||||||||||||||
legendValueDisplay = 'percentage', | ||||||||||||||||||||||||||||||||||||||||||||||||
label, | ||||||||||||||||||||||||||||||||||||||||||||||||
note, | ||||||||||||||||||||||||||||||||||||||||||||||||
className, | ||||||||||||||||||||||||||||||||||||||||||||||||
children, | ||||||||||||||||||||||||||||||||||||||||||||||||
tooltipOffsetX = 0, | ||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -316,26 +304,6 @@ const PieSemiCircleChartInternal: FC< PieSemiCircleChartProps > = ( { | |||||||||||||||||||||||||||||||||||||||||||||||
} } | ||||||||||||||||||||||||||||||||||||||||||||||||
</Pie> | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
{ /* Label and note text */ } | ||||||||||||||||||||||||||||||||||||||||||||||||
<Group> | ||||||||||||||||||||||||||||||||||||||||||||||||
<Text | ||||||||||||||||||||||||||||||||||||||||||||||||
textAnchor="middle" | ||||||||||||||||||||||||||||||||||||||||||||||||
verticalAnchor="start" | ||||||||||||||||||||||||||||||||||||||||||||||||
y={ -40 } // Position above the chart with space for note | ||||||||||||||||||||||||||||||||||||||||||||||||
className={ styles.label } | ||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||
{ label } | ||||||||||||||||||||||||||||||||||||||||||||||||
</Text> | ||||||||||||||||||||||||||||||||||||||||||||||||
<Text | ||||||||||||||||||||||||||||||||||||||||||||||||
textAnchor="middle" | ||||||||||||||||||||||||||||||||||||||||||||||||
verticalAnchor="start" | ||||||||||||||||||||||||||||||||||||||||||||||||
y={ -20 } // Position between label and chart | ||||||||||||||||||||||||||||||||||||||||||||||||
className={ styles.note } | ||||||||||||||||||||||||||||||||||||||||||||||||
> | ||||||||||||||||||||||||||||||||||||||||||||||||
{ note } | ||||||||||||||||||||||||||||||||||||||||||||||||
</Text> | ||||||||||||||||||||||||||||||||||||||||||||||||
</Group> | ||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||
{ /* Render SVG children from composition API */ } | ||||||||||||||||||||||||||||||||||||||||||||||||
{ svgChildren } | ||||||||||||||||||||||||||||||||||||||||||||||||
</Group> | ||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
import { render, screen, waitFor } from '@testing-library/react'; | ||
import userEvent from '@testing-library/user-event'; | ||
import { Group } from '@visx/group'; | ||
import { Text } from '@visx/text'; | ||
import { act } from 'react'; | ||
import { GlobalChartsProvider } from '../../../providers'; | ||
import PieSemiCircleChart from '../pie-semi-circle-chart'; | ||
|
@@ -35,13 +37,23 @@ describe( 'PieSemiCircleChart', () => { | |
expect( segments ).toHaveLength( 2 ); | ||
} ); | ||
|
||
it( 'renders label and note when provided', () => { | ||
const label = 'Chart Title'; | ||
const note = 'Additional Info'; | ||
renderPieChart( { data: mockData, label, note } ); | ||
it( 'renders custom children content', () => { | ||
renderPieChart( { | ||
data: mockData, | ||
children: ( | ||
<Group> | ||
<Text textAnchor="middle" y={ -40 }> | ||
Chart Title | ||
</Text> | ||
<Text textAnchor="middle" y={ -20 }> | ||
Additional Info | ||
</Text> | ||
</Group> | ||
), | ||
} ); | ||
|
||
expect( screen.getByText( label ) ).toBeInTheDocument(); | ||
expect( screen.getByText( note ) ).toBeInTheDocument(); | ||
expect( screen.getByText( 'Chart Title' ) ).toBeInTheDocument(); | ||
expect( screen.getByText( 'Additional Info' ) ).toBeInTheDocument(); | ||
} ); | ||
|
||
it( 'shows legend when showLegend is true', () => { | ||
|
@@ -178,4 +190,89 @@ describe( 'PieSemiCircleChart', () => { | |
).toBeInTheDocument(); | ||
} ); | ||
} ); | ||
|
||
describe( 'Composition API', () => { | ||
it( 'renders children with SVG content', () => { | ||
renderPieChart( { | ||
data: mockData, | ||
children: ( | ||
<Group> | ||
<Text textAnchor="middle" y={ -40 }> | ||
Custom Title | ||
</Text> | ||
</Group> | ||
), | ||
} ); | ||
|
||
expect( screen.getByText( 'Custom Title' ) ).toBeInTheDocument(); | ||
} ); | ||
|
||
it( 'renders PieSemiCircleChart.SVG compound component', () => { | ||
render( | ||
<GlobalChartsProvider> | ||
<PieSemiCircleChart data={ mockData }> | ||
<PieSemiCircleChart.SVG> | ||
<Group> | ||
<Text textAnchor="middle" y={ -50 }> | ||
SVG Component Title | ||
</Text> | ||
</Group> | ||
</PieSemiCircleChart.SVG> | ||
</PieSemiCircleChart> | ||
</GlobalChartsProvider> | ||
); | ||
Comment on lines
+210
to
+223
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nitpick] For consistency and to reduce duplication, consider using the existing renderPieChart helper in this test (and the similar cases below) instead of directly calling render with GlobalChartsProvider. Copilot uses AI. Check for mistakes. Positive FeedbackNegative Feedback |
||
|
||
expect( screen.getByText( 'SVG Component Title' ) ).toBeInTheDocument(); | ||
} ); | ||
|
||
it( 'renders PieSemiCircleChart.HTML compound component', () => { | ||
render( | ||
<GlobalChartsProvider> | ||
<PieSemiCircleChart data={ mockData }> | ||
<PieSemiCircleChart.HTML> | ||
<div data-testid="html-content">HTML Content</div> | ||
</PieSemiCircleChart.HTML> | ||
</PieSemiCircleChart> | ||
</GlobalChartsProvider> | ||
); | ||
|
||
expect( screen.getByTestId( 'html-content' ) ).toBeInTheDocument(); | ||
expect( screen.getByText( 'HTML Content' ) ).toBeInTheDocument(); | ||
} ); | ||
|
||
it( 'renders mixed SVG and HTML compound components', () => { | ||
render( | ||
<GlobalChartsProvider> | ||
<PieSemiCircleChart data={ mockData }> | ||
<PieSemiCircleChart.SVG> | ||
<Group> | ||
<Text textAnchor="middle" y={ -50 }> | ||
SVG Title | ||
</Text> | ||
</Group> | ||
</PieSemiCircleChart.SVG> | ||
<PieSemiCircleChart.HTML> | ||
<div data-testid="footer">Chart Footer</div> | ||
</PieSemiCircleChart.HTML> | ||
</PieSemiCircleChart> | ||
</GlobalChartsProvider> | ||
); | ||
|
||
expect( screen.getByText( 'SVG Title' ) ).toBeInTheDocument(); | ||
expect( screen.getByTestId( 'footer' ) ).toBeInTheDocument(); | ||
} ); | ||
|
||
it( 'renders Legend as compound component', () => { | ||
render( | ||
<GlobalChartsProvider> | ||
<PieSemiCircleChart data={ mockData }> | ||
<PieSemiCircleChart.Legend orientation="horizontal" /> | ||
</PieSemiCircleChart> | ||
</GlobalChartsProvider> | ||
); | ||
|
||
expect( screen.getByText( 'Category A' ) ).toBeInTheDocument(); | ||
expect( screen.getByText( 'Category B' ) ).toBeInTheDocument(); | ||
} ); | ||
} ); | ||
} ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removing the label and note props is a breaking API change. Please mark this as a breaking change in the changelog (e.g., Significance: major and/or Type: breaking-change) and include a brief migration note showing how to render labels via children (Group/Text or PieSemiCircleChart.SVG).
Copilot uses AI. Check for mistakes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the semi-circle chart
label
andnote
props are currently being used by any consumers, so I don't think it needs to be a significant/major change in the changelog. I'm open to having my mind changed on this, but at this time I don't think this feedback is necessary.