Skip to content

Commit

Permalink
✨ (grapher) add short attribution to tab labels
Browse files Browse the repository at this point in the history
  • Loading branch information
sophiamersmann committed Oct 9, 2024
1 parent 581a378 commit ff3fac6
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 26 deletions.
11 changes: 11 additions & 0 deletions packages/@ourworldindata/grapher/src/modal/SourcesModal.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
$tab-padding: 16px;
$tab-font-size: 13px;
$tab-gap: 8px;
$tab-secondary-margin: 8px;

$border: $gray-20;

Expand Down Expand Up @@ -64,6 +65,16 @@
font-size: $tab-font-size;
padding: 8px $tab-padding;
margin-right: $tab-gap;

.attribution {
color: $gray-60;
display: inline-block;
margin-left: $tab-secondary-margin;
}

&[aria-selected="true"] .attribution {
color: $blue-50;
}
}

.source {
Expand Down
69 changes: 48 additions & 21 deletions packages/@ourworldindata/grapher/src/modal/SourcesModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
CLOSE_BUTTON_WIDTH,
CloseButton,
} from "@ourworldindata/components"
import React from "react"
import React, { ReactElement } from "react"
import cx from "classnames"
import { action, computed } from "mobx"
import { observer } from "mobx-react"
Expand All @@ -46,6 +46,7 @@ const MAX_CONTENT_WIDTH = 640
const TAB_PADDING = 16
const TAB_FONT_SIZE = 13
const TAB_GAP = 8
const TAB_SECONDARY_MARGIN = 8

export interface SourcesModalManager {
isReady?: boolean
Expand Down Expand Up @@ -112,10 +113,32 @@ export class SourcesModal extends React.Component<
return this.manager.columnsWithSourcesExtensive
}

@computed private get tabLabels(): string[] {
return this.columns.map(
(column) => column.titlePublicOrDisplayName.title
)
@computed private get tabLabels(): ReactElement[] {
return this.columns.map((column) => {
const attribution = joinTitleFragments(
column.titlePublicOrDisplayName.attributionShort,
column.titlePublicOrDisplayName.titleVariant
)
return (
<React.Fragment key={column.slug}>
{column.titlePublicOrDisplayName.title}
{attribution && (
<span className="attribution">{attribution}</span>
)}
</React.Fragment>
)
})
}

@computed private get tabLabelWidths(): number[] {
return this.columns.map((column) => {
const title = `${column.titlePublicOrDisplayName.title}`
const fragments = joinTitleFragments(
column.titlePublicOrDisplayName.attributionShort,
column.titlePublicOrDisplayName.titleVariant
)
return measureTabWidth(title, fragments) + TAB_GAP
})
}

private renderSource(
Expand Down Expand Up @@ -162,12 +185,8 @@ export class SourcesModal extends React.Component<
this.modalBounds.width - 2 * this.modalPadding - 10 // wiggle room
)

const labelWidths = this.tabLabels.map(
(label) => measureTabWidth(label) + TAB_GAP
)

// check if all tab labels fit into a single line
if (sum(labelWidths) <= maxWidth) {
if (sum(this.tabLabelWidths) <= maxWidth) {
return (
<Tabs
labels={this.tabLabels}
Expand All @@ -178,8 +197,8 @@ export class SourcesModal extends React.Component<
)
}

const clippedLabelWidths = this.tabLabels.map(
(label) => Math.min(measureTabWidth(label), maxTabWidth) + TAB_GAP
const clippedLabelWidths = this.tabLabelWidths.map((labelWidth) =>
Math.min(labelWidth, maxTabWidth + TAB_GAP)
)

// check if all tab labels fit into a single line when they are clipped
Expand All @@ -195,18 +214,20 @@ export class SourcesModal extends React.Component<
}

// compute the subset of tabs that fit into a single line
const getVisibleLabels = (labels: string[]) => {
const getVisibleLabels = (
labels: React.ReactElement[]
): React.ReactElement[] => {
// take width of the "Show more" button into account
let width =
measureTabWidth("Show more") +
13 + // icon width
6 // icon padding

const visibleLabels: string[] = []
const visibleLabels: React.ReactElement[] = []
for (const [label, labelWidth] of zip(labels, clippedLabelWidths)) {
width += labelWidth as number
if (width > maxWidth) break
visibleLabels.push(label as string)
visibleLabels.push(label as React.ReactElement)
}

return visibleLabels
Expand Down Expand Up @@ -493,10 +514,16 @@ export class Source extends React.Component<{
}
}

const measureTabWidth = (label: string): number => {
return (
2 * TAB_PADDING +
Bounds.forText(label, { fontSize: TAB_FONT_SIZE }).width +
2 // border
)
const measureTabWidth = (label: string, secondary?: string): number => {
const getWidth = (text: string) =>
Bounds.forText(text, { fontSize: TAB_FONT_SIZE }).width

const labelWidth = getWidth(label)
const secondaryTextWidth = secondary
? getWidth(secondary) + TAB_SECONDARY_MARGIN
: 0
const padding = 2 * TAB_PADDING
const borderWidth = 2

return labelWidth + secondaryTextWidth + padding + borderWidth
}
6 changes: 3 additions & 3 deletions packages/@ourworldindata/grapher/src/tabs/ExpandableTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ export const ExpandableTabs = ({
activeIndex,
setActiveIndex,
isExpandedDefault = false,
getVisibleLabels = (labels: string[]) => labels.slice(0, 3),
getVisibleLabels = (labels: React.ReactElement[]) => labels.slice(0, 3),
maxTabWidth = 240,
}: {
labels: string[]
labels: React.ReactElement[]
activeIndex: number
setActiveIndex: (index: number) => void
isExpandedDefault?: boolean
getVisibleLabels?: (tabLabels: string[]) => string[]
getVisibleLabels?: (tabLabels: React.ReactElement[]) => React.ReactElement[]
maxTabWidth?: number | null // if null, don't clip labels
}) => {
const [isExpanded, setExpanded] = useState(isExpandedDefault)
Expand Down
4 changes: 2 additions & 2 deletions packages/@ourworldindata/grapher/src/tabs/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const Tabs = ({
maxTabWidth = 240,
slot,
}: {
labels: string[]
labels: React.ReactElement[]
activeIndex: number
setActiveIndex: (label: number) => void
horizontalScroll?: boolean
Expand Down Expand Up @@ -68,7 +68,7 @@ export const Tabs = ({
const isActive = index === activeIndex
return (
<button
key={label}
key={index}
className="Tabs__tab"
style={style}
type="button"
Expand Down

0 comments on commit ff3fac6

Please sign in to comment.