Skip to content

Commit

Permalink
Merge pull request #2734 from owid/grapher-redesign-improve-static-ch…
Browse files Browse the repository at this point in the history
…arts

Grapher redesign: Improve static charts
  • Loading branch information
sophiamersmann authored Oct 11, 2023
2 parents d375bd1 + 33bd0e5 commit fa6ab25
Show file tree
Hide file tree
Showing 6 changed files with 119 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
MarkdownTextWrap,
sumTextWrapHeights,
} from "@ourworldindata/utils"
import { Header } from "../header/Header"
import { Header, StaticHeader } from "../header/Header"
import { Footer, StaticFooter } from "../footer/Footer"
import {
ChartComponentClassMap,
Expand Down Expand Up @@ -487,6 +487,16 @@ export class StaticCaptionedChart extends CaptionedChart {
})
}

@computed protected get staticHeader(): Header {
const { paddedBounds } = this
return new StaticHeader({
manager: this.manager,
maxWidth: this.maxWidth,
targetX: paddedBounds.x,
targetY: paddedBounds.y,
})
}

@computed protected get framePaddingVertical(): number {
return DEFAULT_GRAPHER_FRAME_PADDING
}
Expand All @@ -503,7 +513,7 @@ export class StaticCaptionedChart extends CaptionedChart {

@computed protected get boundsForChartArea(): Bounds {
return this.paddedBounds
.padTop(this.header.height)
.padTop(this.staticHeader.height)
.padBottom(this.staticFooter.height + this.verticalPadding)
.padTop(this.manager.isOnMapTab ? 0 : this.verticalPadding)
}
Expand Down Expand Up @@ -584,7 +594,12 @@ export class StaticCaptionedChart extends CaptionedChart {
width={width}
height={height}
/>
{this.header.renderStatic(paddedBounds.x, paddedBounds.y)}
<StaticHeader
manager={manager}
maxWidth={maxWidth}
targetX={paddedBounds.x}
targetY={paddedBounds.y}
/>
{this.renderChart()}
<StaticFooter
manager={manager}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ export class ShareMenu extends React.Component<ShareMenuProps, ShareMenuState> {
Share via&hellip;
</a>
)}
{true && (
{this.state.canWriteToClipboard && (
<a
title="Copy link to clipboard"
data-track-note="chart_share_copylink"
Expand Down
7 changes: 6 additions & 1 deletion packages/@ourworldindata/grapher/src/core/Grapher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,12 @@ export class Grapher
@observable shouldOptimizeForHorizontalSpace = false

@computed private get optimizeForHorizontalSpace(): boolean {
return this.isNarrow && this.shouldOptimizeForHorizontalSpace
return (
this.isNarrow &&
this.shouldOptimizeForHorizontalSpace &&
// in full-screen mode, we prefer padding on the sides
!this.isInFullScreenMode
)
}

/**
Expand Down
127 changes: 88 additions & 39 deletions packages/@ourworldindata/grapher/src/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
TextWrap,
DEFAULT_BOUNDS,
MarkdownTextWrap,
range,
} from "@ourworldindata/utils"
import { computed } from "mobx"
import { observer } from "mobx-react"
Expand All @@ -13,12 +14,16 @@ import {
GRAPHER_DARK_TEXT,
} from "../core/GrapherConstants"

@observer
export class Header extends React.Component<{
interface HeaderProps {
manager: HeaderManager
maxWidth?: number
}> {
@computed private get manager(): HeaderManager {
}

@observer
export class Header<
Props extends HeaderProps = HeaderProps
> extends React.Component<Props> {
@computed protected get manager(): HeaderManager {
return this.props.manager
}

Expand All @@ -38,7 +43,7 @@ export class Header extends React.Component<{
)
}

@computed private get titleText(): string {
@computed protected get titleText(): string {
return this.manager.currentTitle ?? ""
}

Expand All @@ -58,7 +63,7 @@ export class Header extends React.Component<{
})
}

@computed private get logoWidth(): number {
@computed protected get logoWidth(): number {
return this.logo ? this.logo.width : 0
}

Expand Down Expand Up @@ -122,39 +127,6 @@ export class Header extends React.Component<{
)
}

renderStatic(x: number, y: number): JSX.Element {
const { title, logo, subtitle, manager, maxWidth } = this

return (
<g className="HeaderView">
{logo &&
logo.height > 0 &&
logo.renderSVG(x + maxWidth - logo.width, y)}
<a
href={manager.canonicalUrl}
style={{
fontFamily:
"'Playfair Display', Georgia, 'Times New Roman', 'Liberation Serif', serif",
}}
target="_blank"
rel="noopener"
>
{title.render(x, y, {
fill: GRAPHER_DARK_TEXT,
fontWeight: 500,
})}
</a>
{subtitle.renderSVG(
x,
y + title.height + this.subtitleMarginTop,
{
fill: GRAPHER_DARK_TEXT,
}
)}
</g>
)
}

private renderTitle(): JSX.Element {
const { manager } = this

Expand Down Expand Up @@ -222,3 +194,80 @@ export class Header extends React.Component<{
)
}
}

interface StaticHeaderProps extends HeaderProps {
targetX: number
targetY: number
}

@observer
export class StaticHeader extends Header<StaticHeaderProps> {
@computed get title(): TextWrap {
const { logoWidth, titleText } = this

const makeTitle = (fontSize: number): TextWrap =>
new TextWrap({
text: titleText,
maxWidth: this.maxWidth - logoWidth - 24,
fontSize,
fontWeight: 500,
lineHeight: 1.2,
})

// try to fit the title into a single line if possible-- but not if it would make the text too small
const initialFontSize = 24
let title = makeTitle(initialFontSize)
const originalLineCount = title.lines.length
// decrease the initial font size by no more than 2px using 0.5px steps
const potentialFontSizes = range(
initialFontSize,
initialFontSize - 2.5,
-0.5
)
for (const fontSize of potentialFontSizes) {
title = makeTitle(fontSize)
const currentLineCount = title.lines.length
if (currentLineCount <= 1 || currentLineCount < originalLineCount)
break
}

// if decreasing the font size didn't make a difference, use the initial font size
if (title.lines.length === originalLineCount) {
return makeTitle(initialFontSize)
}

return title
}

render(): JSX.Element {
const { targetX: x, targetY: y } = this.props
const { title, logo, subtitle, manager, maxWidth } = this
return (
<g className="HeaderView">
{logo &&
logo.height > 0 &&
logo.renderSVG(x + maxWidth - logo.width, y)}
<a
href={manager.canonicalUrl}
style={{
fontFamily:
"'Playfair Display', Georgia, 'Times New Roman', 'Liberation Serif', serif",
}}
target="_blank"
rel="noopener"
>
{title.render(x, y, {
fill: GRAPHER_DARK_TEXT,
})}
</a>
{subtitle.renderSVG(
x,
y + title.height + this.subtitleMarginTop,
{
fill: GRAPHER_DARK_TEXT,
}
)}
</g>
)
}
}
5 changes: 5 additions & 0 deletions packages/@ourworldindata/grapher/src/modal/Modal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ $modal-padding: 1.5em;
width: 32px;
height: 32px;

// center icon
display: flex;
align-items: center;
justify-content: center;

&:hover {
border-color: $hover-fill;
background: $hover-fill;
Expand Down
3 changes: 1 addition & 2 deletions site/css/content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,7 @@ figure[data-explorer-src] {
.article-content {
span.add-country {
font-size: 0.9rem;
font: 400 13px/16px Lato, "Helvetica Neue", Helvetica, Arial,
"Liberation Sans", sans-serif;
font: 400 13px/16px $sans-serif-font-stack;
letter-spacing: 0.01em;
display: inline-flex;
align-items: center;
Expand Down

0 comments on commit fa6ab25

Please sign in to comment.