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

✨ (static charts) make charts mobile-friendly #2977

Merged
merged 25 commits into from
Jan 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
7fbbc23
:sparkles: (grapher) adjust text colour of mobile static charts
sophiamersmann Dec 13, 2023
65da7a6
:lipstick: (grapher) use base font size for static charts
sophiamersmann Dec 13, 2023
b88367b
:sparkles: (static-chart) adjust typography and colour for mobile
sophiamersmann Dec 14, 2023
ba5b198
:lipstick: (grapher) decrease font size of tick labels
sophiamersmann Dec 14, 2023
2eda45a
:sparkles: (static-chart) increase footer font size
sophiamersmann Dec 14, 2023
adc52a0
:sparkles: (static-chart) decraese logo size
sophiamersmann Dec 14, 2023
4f10cc0
:sparkles: (static-chart) increase grid line with on mobile
sophiamersmann Dec 14, 2023
5614276
:sparkles: (static-chart) increase grid line width on mobile
sophiamersmann Dec 14, 2023
00e2c37
:sparkles: (grapher) use halo effect for labels in discrete bar charts
sophiamersmann Dec 14, 2023
64746c1
:lipstick: (static-chart) increase footer font size
sophiamersmann Dec 14, 2023
6b9e9e6
:lipstick: (grapher) use a shared opacity for areas
sophiamersmann Dec 14, 2023
b1d13fd
:sparkles: (slope) hide vertical axis for small static charts
sophiamersmann Dec 14, 2023
e0361f8
:lipstick: (static-chart) hide markers, increase line width
sophiamersmann Dec 14, 2023
f355a29
:sparkles: (static-chart) use thicker stroke for all axis lines
sophiamersmann Dec 14, 2023
2c6175f
:sparkles: (static-chart) decrease font size for long footer text
sophiamersmann Dec 15, 2023
69cd8f4
:sparkles: (static-chart) apply mobile optimizations more often
sophiamersmann Dec 15, 2023
7476778
:lipstick: make eslint happy
sophiamersmann Dec 15, 2023
6c3137e
:lipstick: (grapher) rely on default
sophiamersmann Dec 15, 2023
fbf8a29
:sparkles: (static-map) increase stroke width on mobile
sophiamersmann Dec 15, 2023
4f7027a
:lipstick: (chart-admin) remove extra space on the bottom of the figure
sophiamersmann Dec 15, 2023
35c5e01
:lipstick: (slope) reduce line thickness a little in static version
sophiamersmann Dec 15, 2023
c20a65d
:bug: (static-chart) prevent details to be cut off
sophiamersmann Dec 18, 2023
a86c2f5
:lipstick: (static-chart) render logo at default size on mobile
sophiamersmann Dec 18, 2023
a8dd60e
:lipstick: (grapher) slightly reduce area opacity
sophiamersmann Dec 18, 2023
f59fec2
:bug: (static-chart) use correct details font-size for charts with id…
sophiamersmann Dec 18, 2023
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
4 changes: 4 additions & 0 deletions adminSiteClient/admin.scss
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,10 @@ $nav-height: 45px;
border-bottom: 1px solid #ccc;
}
}

figure[data-grapher-src] {
line-height: 0; // remove extra space on the bottom
}
}

.list-group {
Expand Down
4 changes: 2 additions & 2 deletions packages/@ourworldindata/grapher/src/axis/Axis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,7 @@ abstract class AbstractAxis {
}

@computed get tickFontSize(): number {
return 0.9 * this.fontSize
return 0.75 * this.fontSize
}

@computed protected get baseTicks(): Tickmark[] {
Expand Down Expand Up @@ -434,7 +434,7 @@ abstract class AbstractAxis {
}

@computed get labelFontSize(): number {
return 0.7 * this.fontSize
return 0.75 * this.fontSize
}

@computed get labelTextWrap(): TextWrap | undefined {
Expand Down
61 changes: 47 additions & 14 deletions packages/@ourworldindata/grapher/src/axis/AxisViews.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from "@ourworldindata/utils"
import { VerticalAxis, HorizontalAxis, DualAxis } from "./Axis"
import classNames from "classnames"
import { ScaleType } from "../core/GrapherConstants"
import { GRAPHER_DARK_TEXT, ScaleType } from "../core/GrapherConstants"

const dasharrayFromFontSize = (fontSize: number): string => {
const dashLength = Math.round((fontSize / 16) * 3)
Expand All @@ -28,9 +28,10 @@ const SOLID_TICK_COLOR = "#999"
export class VerticalAxisGridLines extends React.Component<{
verticalAxis: VerticalAxis
bounds: Bounds
strokeWidth?: number
}> {
render(): JSX.Element {
const { bounds, verticalAxis } = this.props
const { bounds, verticalAxis, strokeWidth } = this.props
const axis = verticalAxis.clone()
axis.range = bounds.yRange()

Expand All @@ -51,6 +52,7 @@ export class VerticalAxisGridLines extends React.Component<{
x2={bounds.right.toFixed(2)}
y2={axis.place(t.value)}
stroke={color}
strokeWidth={strokeWidth}
strokeDasharray={
t.solid
? undefined
Expand All @@ -70,13 +72,14 @@ export class VerticalAxisGridLines extends React.Component<{
export class HorizontalAxisGridLines extends React.Component<{
horizontalAxis: HorizontalAxis
bounds?: Bounds
strokeWidth?: number
}> {
@computed get bounds(): Bounds {
return this.props.bounds ?? DEFAULT_BOUNDS
}

render(): JSX.Element {
const { horizontalAxis } = this.props
const { horizontalAxis, strokeWidth } = this.props
const { bounds } = this
const axis = horizontalAxis.clone()
axis.range = bounds.xRange()
Expand All @@ -98,6 +101,7 @@ export class HorizontalAxisGridLines extends React.Component<{
x2={axis.place(t.value)}
y2={bounds.top.toFixed(2)}
stroke={color}
strokeWidth={strokeWidth}
strokeDasharray={
t.solid
? undefined
Expand All @@ -117,9 +121,10 @@ export class HorizontalAxisGridLines extends React.Component<{
export class HorizontalAxisZeroLine extends React.Component<{
horizontalAxis: HorizontalAxis
bounds: Bounds
strokeWidth?: number
}> {
render(): JSX.Element {
const { bounds, horizontalAxis } = this.props
const { bounds, horizontalAxis, strokeWidth } = this.props
const axis = horizontalAxis.clone()
axis.range = bounds.xRange()

Expand All @@ -137,6 +142,7 @@ export class HorizontalAxisZeroLine extends React.Component<{
x2={axis.place(0)}
y2={bounds.top.toFixed(2)}
stroke={SOLID_TICK_COLOR}
strokeWidth={strokeWidth}
/>
</g>
)
Expand All @@ -147,32 +153,40 @@ interface DualAxisViewProps {
dualAxis: DualAxis
highlightValue?: { x: number; y: number }
showTickMarks?: boolean
labelColor?: string
tickColor?: string
lineWidth?: number
}

@observer
export class DualAxisComponent extends React.Component<DualAxisViewProps> {
render(): JSX.Element {
const { dualAxis, showTickMarks } = this.props
const { dualAxis, showTickMarks, labelColor, tickColor, lineWidth } =
this.props
const { bounds, horizontalAxis, verticalAxis, innerBounds } = dualAxis

const verticalGridlines = verticalAxis.hideGridlines ? null : (
<VerticalAxisGridLines
verticalAxis={verticalAxis}
bounds={innerBounds}
strokeWidth={lineWidth}
/>
)

const horizontalGridlines = horizontalAxis.hideGridlines ? null : (
<HorizontalAxisGridLines
horizontalAxis={horizontalAxis}
bounds={innerBounds}
strokeWidth={lineWidth}
/>
)

const verticalAxisComponent = verticalAxis.hideAxis ? null : (
<VerticalAxisComponent
bounds={bounds}
verticalAxis={verticalAxis}
labelColor={labelColor}
tickColor={tickColor}
/>
)

Expand All @@ -182,6 +196,9 @@ export class DualAxisComponent extends React.Component<DualAxisViewProps> {
axis={horizontalAxis}
showTickMarks={showTickMarks}
preferredAxisPosition={innerBounds.bottom}
labelColor={labelColor}
tickColor={tickColor}
tickMarkWidth={lineWidth}
/>
)

Expand All @@ -200,11 +217,12 @@ export class DualAxisComponent extends React.Component<DualAxisViewProps> {
export class VerticalAxisComponent extends React.Component<{
bounds: Bounds
verticalAxis: VerticalAxis
labelColor?: string
tickColor?: string
}> {
render(): JSX.Element {
const { bounds, verticalAxis } = this.props
const { bounds, verticalAxis, labelColor, tickColor } = this.props
const { tickLabels, labelTextWrap } = verticalAxis
const textColor = "#666"

return (
<g className="VerticalAxis">
Expand All @@ -214,6 +232,7 @@ export class VerticalAxisComponent extends React.Component<{
bounds.left,
{
transform: "rotate(-90)",
fill: labelColor || GRAPHER_DARK_TEXT,
}
)}
{tickLabels.map((label, i) => {
Expand All @@ -231,7 +250,7 @@ export class VerticalAxisComponent extends React.Component<{
textAnchor={textAnchorFromAlign(
xAlign ?? HorizontalAlign.right
)}
fill={textColor}
fill={tickColor || GRAPHER_DARK_TEXT}
fontSize={verticalAxis.tickFontSize}
>
{formattedValue}
Expand All @@ -248,6 +267,9 @@ export class HorizontalAxisComponent extends React.Component<{
axis: HorizontalAxis
showTickMarks?: boolean
preferredAxisPosition?: number
labelColor?: string
tickColor?: string
tickMarkWidth?: number
}> {
@computed get scaleType(): ScaleType {
return this.props.axis.scaleType
Expand All @@ -266,11 +288,17 @@ export class HorizontalAxisComponent extends React.Component<{
}

render(): JSX.Element {
const { bounds, axis, showTickMarks, preferredAxisPosition } =
this.props
const {
bounds,
axis,
showTickMarks,
preferredAxisPosition,
labelColor,
tickColor,
tickMarkWidth,
} = this.props
const { tickLabels, labelTextWrap: label, labelOffset, orient } = axis
const horizontalAxisLabelsOnTop = orient === Position.top
const textColor = "#666"
const labelYPosition = horizontalAxisLabelsOnTop
? bounds.top
: bounds.bottom - (label?.height ?? 0)
Expand All @@ -286,6 +314,7 @@ export class HorizontalAxisComponent extends React.Component<{
axis.place(label.value)
)}
color={SOLID_TICK_COLOR}
width={tickMarkWidth}
/>
) : undefined

Expand All @@ -297,7 +326,8 @@ export class HorizontalAxisComponent extends React.Component<{
{label &&
label.render(
axis.rangeCenter - label.width / 2,
labelYPosition
labelYPosition,
{ fill: labelColor || GRAPHER_DARK_TEXT }
)}
{tickMarks}
{tickLabels.map((label, i) => {
Expand All @@ -307,7 +337,7 @@ export class HorizontalAxisComponent extends React.Component<{
key={i}
x={x}
y={tickLabelYPlacement}
fill={textColor}
fill={tickColor || GRAPHER_DARK_TEXT}
textAnchor={textAnchorFromAlign(
xAlign ?? HorizontalAlign.center
)}
Expand All @@ -326,9 +356,11 @@ export class AxisTickMarks extends React.Component<{
tickMarkTopPosition: number
tickMarkXPositions: number[]
color: string
width?: number
}> {
render(): JSX.Element[] {
const { tickMarkTopPosition, tickMarkXPositions, color } = this.props
const { tickMarkTopPosition, tickMarkXPositions, color, width } =
this.props
const tickSize = 5
const tickBottom = tickMarkTopPosition + tickSize
return tickMarkXPositions.map((tickMarkPosition, index) => {
Expand All @@ -340,6 +372,7 @@ export class AxisTickMarks extends React.Component<{
x2={tickMarkPosition}
y2={tickBottom}
stroke={color}
strokeWidth={width}
/>
)
})
Expand Down
55 changes: 37 additions & 18 deletions packages/@ourworldindata/grapher/src/barCharts/DiscreteBarChart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ import {
BASE_FONT_SIZE,
SeriesStrategy,
FacetStrategy,
GRAPHER_DARK_TEXT,
GRAPHER_AXIS_LINE_WIDTH_THICK,
GRAPHER_AXIS_LINE_WIDTH_DEFAULT,
GRAPHER_AREA_OPACITY_DEFAULT,
} from "../core/GrapherConstants"
import {
HorizontalAxisComponent,
Expand Down Expand Up @@ -67,6 +71,7 @@ import {
import { CategoricalBin, ColorScaleBin } from "../color/ColorScaleBin"
import { HorizontalNumericColorLegend } from "../horizontalColorLegend/HorizontalColorLegends"
import { BaseType, Selection } from "d3"
import { getElementWithHalo } from "../scatterCharts/Halos.js"

const labelToTextPadding = 10
const labelToBarPadding = 5
Expand Down Expand Up @@ -393,6 +398,7 @@ export class DiscreteBarChart
)

const {
manager,
series,
boundsWithoutColorLegend,
yAxis,
Expand All @@ -403,6 +409,10 @@ export class DiscreteBarChart

let yOffset = innerBounds.top + barHeight / 2 + barSpacing / 2

const axisLineWidth = manager.isStaticAndSmall
? GRAPHER_AXIS_LINE_WIDTH_THICK
: GRAPHER_AXIS_LINE_WIDTH_DEFAULT

return (
<g ref={this.base} className="DiscreteBarChart">
<rect
Expand All @@ -421,11 +431,14 @@ export class DiscreteBarChart
bounds={boundsWithoutColorLegend}
axis={yAxis}
preferredAxisPosition={innerBounds.bottom}
labelColor={manager.secondaryColorInStaticCharts}
tickMarkWidth={axisLineWidth}
/>
)}
<HorizontalAxisGridLines
horizontalAxis={yAxis}
bounds={innerBounds}
strokeWidth={axisLineWidth}
/>
{series.map((series) => {
// Todo: add a "placedSeries" getter to get the transformed series, then just loop over the placedSeries and render a bar for each
Expand Down Expand Up @@ -471,26 +484,31 @@ export class DiscreteBarChart
width={barWidth}
height={barHeight}
fill={barColor}
opacity={0.85}
opacity={GRAPHER_AREA_OPACITY_DEFAULT}
style={{ transition: "height 200ms ease" }}
/>
<text
x={0}
y={0}
transform={`translate(${
yAxis.place(series.value) +
(isNegative
? -labelToBarPadding
: labelToBarPadding)
}, 0)`}
fill="#666"
dominantBaseline="middle"
textAnchor={isNegative ? "end" : "start"}
{...this.valueLabelStyle}
>
{label.valueString}
<tspan fill="#999">{label.timeString}</tspan>
</text>
{getElementWithHalo(
series.seriesName + "-label",
<text
x={0}
y={0}
transform={`translate(${
yAxis.place(series.value) +
(isNegative
? -labelToBarPadding
: labelToBarPadding)
}, 0)`}
fill={GRAPHER_DARK_TEXT}
dominantBaseline="middle"
textAnchor={isNegative ? "end" : "start"}
{...this.valueLabelStyle}
>
{label.valueString}
<tspan fill="#999">
{label.timeString}
</tspan>
</text>
)}
</g>
)

Expand All @@ -502,6 +520,7 @@ export class DiscreteBarChart
<HorizontalAxisZeroLine
horizontalAxis={yAxis}
bounds={innerBounds}
strokeWidth={axisLineWidth}
/>
)}
</g>
Expand Down
4 changes: 4 additions & 0 deletions packages/@ourworldindata/grapher/src/chart/ChartManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,8 @@ export interface ChartManager {
disableIntroAnimation?: boolean

missingDataStrategy?: MissingDataStrategy

isNarrow?: boolean
isStaticAndSmall?: boolean
secondaryColorInStaticCharts?: string
}
Loading
Loading