Skip to content
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

🎉 (line+slope) support focus state #4254

Closed
wants to merge 91 commits into from
Closed
Changes from 1 commit
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
c4f2545
✨ (slope) show selected entities only
sophiamersmann Nov 20, 2024
a681846
✨ (slope) support relative mode
sophiamersmann Nov 20, 2024
018e132
✨ (slope) only allow selection using the entity selector
sophiamersmann Nov 20, 2024
33c00cc
✨ (slope) drop support for color dim and focus state
sophiamersmann Nov 20, 2024
a9d26c8
✨ (slope) support multiple y-dimensions
sophiamersmann Nov 20, 2024
9e61bc3
✨ (slope) drop non-positive values in log mode
sophiamersmann Nov 20, 2024
7d228b9
✨ (slope) use line legend instead of custom labels
sophiamersmann Nov 20, 2024
198a26f
✨ (slope) add support for entity name annotations
sophiamersmann Nov 20, 2024
d33eebd
✨ (grapher) disallow switching to a slope chart for projections
sophiamersmann Nov 20, 2024
5c9727e
✨ (slope) add tooltips
sophiamersmann Nov 20, 2024
f82ca07
✨ (slope) refactor
sophiamersmann Nov 21, 2024
f808447
🔨 (slope) remove color dimension
sophiamersmann Nov 21, 2024
e1491a3
✨ (slope) allow to hide legend
sophiamersmann Nov 21, 2024
6774410
🐛 (slope) fix start/end time selection
sophiamersmann Nov 21, 2024
3fc555a
🐛 (slope) error out when start and end time are the same
sophiamersmann Nov 21, 2024
9714ebe
🐛 (slope) fix No Data section when missing data strategy is hide
sophiamersmann Nov 22, 2024
932cc9d
🐛 (slope) fix tabs for line chart that turned into discrete bar
sophiamersmann Nov 22, 2024
940355b
🐛 (slope) fix entity selector title
sophiamersmann Nov 22, 2024
5193feb
🔨 (slope) cleanup
sophiamersmann Nov 22, 2024
d909066
🧪 (slope) fix tests
sophiamersmann Nov 22, 2024
02b2b60
✨ (slope) visual changes
sophiamersmann Nov 22, 2024
c489683
🔨 always apply transforms of the main chart type for the entity selec…
sophiamersmann Nov 27, 2024
187203d
✨ (slope) add Change in to title in relative mode
sophiamersmann Nov 27, 2024
4bdfcc1
✨ (admin) show relative toggle for slope charts
sophiamersmann Nov 27, 2024
864e6f6
🔨 migrate slope charts
sophiamersmann Nov 25, 2024
f201085
✨ (slope) improve tooltip in relative mode
sophiamersmann Nov 27, 2024
3167772
✨ (slope) improve No Data section
sophiamersmann Nov 27, 2024
b5f5b08
✨ nicer entity/column labels
sophiamersmann Nov 27, 2024
2414e5b
🔨 (slope) clean up code
sophiamersmann Nov 27, 2024
b71988d
🔨 update slope migration
sophiamersmann Nov 28, 2024
9cd9f30
🧪 (slope) add tests
sophiamersmann Nov 28, 2024
26bfa86
✨ (slope) drop entities from selector if time selection disabled
sophiamersmann Nov 28, 2024
322f4ee
🐛 (slope) fix relative value calculation
sophiamersmann Nov 28, 2024
cf81efe
🐛 (slope) hide relative toggle for log scale
sophiamersmann Nov 28, 2024
f322692
🐛 (line) use startTime for relative mode calculation
sophiamersmann Nov 28, 2024
a2a6a89
🔨 update slope migration after feedback
sophiamersmann Nov 28, 2024
06ddf6c
🔨 (slope) drop non-numeric data in any case
sophiamersmann Nov 28, 2024
1ed2a96
🐛 (slope) show correct label for relative toggle
sophiamersmann Nov 28, 2024
8f13554
🔨 use current chart instance for table for selection
sophiamersmann Nov 29, 2024
f52dac5
🐛 (slope) only drop entities if start and end time are different
sophiamersmann Nov 29, 2024
d9cdcb4
🐛 hide slope chart tab if line chart really is a bar chart
sophiamersmann Nov 29, 2024
f3b4993
✨ automatically adjust handles when switching from line to slope
sophiamersmann Nov 29, 2024
a617f44
🐛 (slope) only add entity name if necessary
sophiamersmann Nov 29, 2024
687c486
🎉 enable timeline animation for slope charts
sophiamersmann Nov 29, 2024
17e4cf9
🔨 (slope) update comments
sophiamersmann Nov 29, 2024
7e583e0
🔨 remove accidental commits
sophiamersmann Nov 29, 2024
ec245e5
🐛 merge arrays correctly
sophiamersmann Dec 2, 2024
804016f
Revert "🐛 hide slope chart tab if line chart really is a bar chart"
sophiamersmann Dec 2, 2024
0fa51bd
✨ (slope) incorporate pr feedback
sophiamersmann Dec 2, 2024
195acc1
🔨 rename line chart helpers file
sophiamersmann Dec 2, 2024
37ce3dd
🔨 (owid table) add time to owidRows
sophiamersmann Nov 27, 2024
fbef0e8
🐛 (slope) add tolerance
sophiamersmann Nov 27, 2024
da28f26
✨ (slope) incorporate pr feedback
sophiamersmann Dec 2, 2024
c3aec00
🔨 (line legend) add ability to render right-aligned legend
sophiamersmann Nov 26, 2024
ade96fe
🔨 (line legend) remove manager pattern
sophiamersmann Nov 26, 2024
fcc9698
✨ (slope) add second legend on the left
sophiamersmann Nov 26, 2024
c37ca89
✨ (slope) show value in the line legend
sophiamersmann Nov 26, 2024
8879090
✨ (slope) show value label inline
sophiamersmann Nov 26, 2024
27a2bfc
✨ (slope) only show 0% label once in relative mode
sophiamersmann Nov 29, 2024
0e51f4b
✨ (slope) increase font size, use consistent grid line color
sophiamersmann Nov 29, 2024
e0bbd06
✨ (slope) add entity annotation to tooltip
sophiamersmann Nov 29, 2024
59e6fe4
✨ (slope) render halo for entity labels
sophiamersmann Nov 29, 2024
d8da97a
✨ (slope) render values next to entity labels
sophiamersmann Dec 2, 2024
085f8c0
✨ (slope) give labels a bit more space
sophiamersmann Dec 2, 2024
70c09b4
✨ (slope) vertically align label and dot on top
sophiamersmann Dec 2, 2024
6bb9671
✨ incrase line height of labels
sophiamersmann Dec 2, 2024
e97e206
✨ (slope) consistent spacing between label and value
sophiamersmann Dec 2, 2024
df05912
✨ (slope) prevent x-label and entity labels from overlapping
sophiamersmann Dec 2, 2024
98510d3
✨ (slope) only show zero label once if all slopes start from zero
sophiamersmann Dec 2, 2024
fbc1903
✨ (slope) show entity label on the left if connector lines are needed
sophiamersmann Dec 2, 2024
49e0bdc
✨ (slope) prevent x-label and line labels to overlap
sophiamersmann Dec 2, 2024
cfea88b
✨ (slope) always show annotation in the tooltip
sophiamersmann Dec 2, 2024
6707a10
✨ (slope) hide tick marks
sophiamersmann Dec 2, 2024
7a40a76
🔨 replace slope chart icon
sophiamersmann Dec 2, 2024
175f15c
✨ (slope) use short name of entity
sophiamersmann Dec 2, 2024
ce3e37a
🔨 (slope) refactor & small adjustments
sophiamersmann Dec 3, 2024
8bac63c
🐛 fix type error
sophiamersmann Dec 3, 2024
d064416
🐛 (slope) make layout less jumpy
sophiamersmann Dec 3, 2024
84bddf9
🐛 (slope) avoid visible overlap when the slope is transparent
sophiamersmann Dec 3, 2024
daf2404
🔨 (slope) rephrase fail message
sophiamersmann Dec 3, 2024
a19a514
✨ (slope) slow down animation
sophiamersmann Dec 3, 2024
068a503
🔨 (slope) update fail message
sophiamersmann Dec 3, 2024
c889061
🐛 (slope) hide the No Data section for svg exports
sophiamersmann Dec 4, 2024
93fa1cd
🎉 (slope) support facetting
sophiamersmann Dec 2, 2024
279e527
🎉 (admin) add slope chart toggle
sophiamersmann Nov 22, 2024
c59b9a7
🎉 enable line/slope chart switching in explorers
sophiamersmann Nov 22, 2024
79865dd
🚧 (for testing) fix Multiembedder on staging
sophiamersmann Dec 2, 2024
420d4e3
🎉 (line+slope) support focus state
sophiamersmann Dec 4, 2024
aefcd40
🚧 hover & focus state enums
sophiamersmann Dec 4, 2024
d5c3083
🚧 add focused entities to selectionArray
sophiamersmann Dec 4, 2024
b26a81d
🚧 introduce InteractionArray
sophiamersmann Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
✨ (slope) add second legend on the left
sophiamersmann committed Dec 2, 2024
commit fcc9698ee9902e1239d79c64d62fea661faf650c
Original file line number Diff line number Diff line change
@@ -880,7 +880,7 @@ export class LineChart

// only pass props that are required to calculate
// the width to avoid circular dependencies
return LineLegend.width({
return LineLegend.incorrectWidth({
labelSeries: this.lineLegendSeries,
maxWidth: this.maxLineLegendWidth,
fontSize: this.fontSize,
77 changes: 49 additions & 28 deletions packages/@ourworldindata/grapher/src/lineLegend/LineLegend.tsx
Original file line number Diff line number Diff line change
@@ -31,8 +31,7 @@ const MARKER_MARGIN = 4
// Space between the label and the annotation
const ANNOTATION_PADDING = 2

const LEFT_PADDING = 35

const DEFAULT_CONNECTOR_LINE_WIDTH = 35
const DEFAULT_FONT_WEIGHT = 400

export interface LineLabelSeries extends ChartSeries {
@@ -91,7 +90,8 @@ function stackGroupVertically(
class LineLabels extends React.Component<{
series: PlacedSeries[]
uniqueKey: string
needsLines: boolean
needsConnectorLines: boolean
connectorLineWidth?: number
anchor?: "start" | "end"
isFocus?: boolean
isStatic?: boolean
@@ -107,24 +107,27 @@ class LineLabels extends React.Component<{
return this.props.anchor ?? "start"
}

@computed private get connectorLineWidth(): number {
return this.props.connectorLineWidth ?? DEFAULT_CONNECTOR_LINE_WIDTH
}

@computed private get markers(): {
series: PlacedSeries
labelText: { x: number; y: number }
connectorLine: { x1: number; x2: number }
}[] {
return this.props.series.map((series) => {
const markerMargin =
this.anchor === "start" ? MARKER_MARGIN : -MARKER_MARGIN
const leftPadding =
this.anchor === "start" ? LEFT_PADDING : -LEFT_PADDING
const direction = this.anchor === "start" ? 1 : -1
const markerMargin = direction * MARKER_MARGIN
const connectorLineWidth = direction * this.connectorLineWidth

const { x } = series.origBounds
const connectorLine = {
x1: x + markerMargin,
x2: x + leftPadding - markerMargin,
x2: x + connectorLineWidth - markerMargin,
}

const textX = this.props.needsLines
const textX = this.props.needsConnectorLines
? connectorLine.x2 + markerMargin
: x + markerMargin
const textY = series.bounds.y
@@ -200,7 +203,7 @@ class LineLabels extends React.Component<{
}

@computed private get connectorLines(): React.ReactElement | void {
if (!this.props.needsLines) return
if (!this.props.needsConnectorLines) return
return (
<g id={makeIdForHumanConsumption("connectors")}>
{this.markers.map(({ series, connectorLine }, index) => {
@@ -293,6 +296,7 @@ export interface LineLegendProps {
lineLegendAnchorX?: "start" | "end"

// presentation
connectorLineWidth?: number
fontSize?: number
fontWeight?: number

@@ -311,8 +315,18 @@ export interface LineLegendProps {
export class LineLegend extends React.Component<LineLegendProps> {
static width(props: LineLegendProps): number {
const test = new LineLegend(props)
if (test.sizedLabels.length === 0) return 0
return max(test.sizedLabels.map((d) => d.width)) ?? 0
const connectorLineWidth = test.needsLines ? test.connectorLineWidth : 0
return test.maxLabelWidth + connectorLineWidth + MARKER_MARGIN
}

/**
* Always adds the width of connector lines, which leads to an incorrect
* result if no connector lines are rendered. We sometimes can't use the
* correct width above due to circular dependencies.
*/
static incorrectWidth(props: LineLegendProps): number {
const test = new LineLegend(props)
return test.maxLabelWidth + test.connectorLineWidth + MARKER_MARGIN
}

@computed private get fontSize(): number {
@@ -331,9 +345,13 @@ export class LineLegend extends React.Component<LineLegendProps> {
return this.props.yAxis ?? new VerticalAxis(new AxisConfig())
}

@computed private get connectorLineWidth(): number {
return this.props.connectorLineWidth ?? DEFAULT_CONNECTOR_LINE_WIDTH
}

@computed.struct get sizedLabels(): SizedSeries[] {
const { fontSize, fontWeight, maxWidth } = this
const maxTextWidth = maxWidth - LEFT_PADDING
const maxTextWidth = maxWidth - this.connectorLineWidth
const maxAnnotationWidth = Math.min(maxTextWidth, 150)

return this.props.labelSeries.map((label) => {
@@ -356,12 +374,10 @@ export class LineLegend extends React.Component<LineLegendProps> {
...label,
textWrap,
annotationTextWrap,
width:
LEFT_PADDING +
Math.max(
textWrap.width,
annotationTextWrap ? annotationTextWrap.width : 0
),
width: Math.max(
textWrap.width,
annotationTextWrap ? annotationTextWrap.width : 0
),
height:
textWrap.height +
(annotationTextWrap
@@ -371,9 +387,9 @@ export class LineLegend extends React.Component<LineLegendProps> {
})
}

@computed get width(): number {
if (this.sizedLabels.length === 0) return 0
return max(this.sizedLabels.map((d) => d.width)) ?? 0
@computed private get maxLabelWidth(): number {
const { sizedLabels = [] } = this
return max(sizedLabels.map((d) => d.width)) ?? 0
}

@computed get onMouseOver(): any {
@@ -412,22 +428,25 @@ export class LineLegend extends React.Component<LineLegendProps> {
const [legendYMin, legendYMax] = legendY

return this.sizedLabels.map((label) => {
const labelHeight = label.height
const labelWidth = label.width + this.connectorLineWidth

// place vertically centered at Y value
const midY = yAxis.place(label.yValue)
const initialY = midY - label.height / 2
const origBounds = new Bounds(
legendX,
initialY,
label.width,
label.height
labelWidth,
labelHeight
)

// ensure label doesn't go beyond the top or bottom of the chart
const y = Math.min(
Math.max(initialY, legendYMin),
legendYMax - label.height
legendYMax - labelHeight
)
const bounds = new Bounds(legendX, y, label.width, label.height)
const bounds = new Bounds(legendX, y, labelWidth, labelHeight)

return {
...label,
@@ -699,7 +718,8 @@ export class LineLegend extends React.Component<LineLegendProps> {
<LineLabels
uniqueKey="background"
series={this.backgroundSeries}
needsLines={this.needsLines}
needsConnectorLines={this.needsLines}
connectorLineWidth={this.connectorLineWidth}
isFocus={false}
anchor={this.props.lineLegendAnchorX}
isStatic={this.props.isStatic}
@@ -717,7 +737,8 @@ export class LineLegend extends React.Component<LineLegendProps> {
<LineLabels
uniqueKey="focus"
series={this.focusedSeries}
needsLines={this.needsLines}
needsConnectorLines={this.needsLines}
connectorLineWidth={this.connectorLineWidth}
isFocus={true}
anchor={this.props.lineLegendAnchorX}
isStatic={this.props.isStatic}
Loading