Skip to content

Commit

Permalink
refactor(tabs): allow overriding button props
Browse files Browse the repository at this point in the history
especially necessary for analytics tracking, so we can consistently recognize clicks inside the button padding
  • Loading branch information
marcelgerber committed Oct 17, 2024
1 parent 67f056e commit d35eb9f
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 34 deletions.
26 changes: 14 additions & 12 deletions packages/@ourworldindata/grapher/src/controls/ContentSwitchers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { faTable, faEarthAmericas } from "@fortawesome/free-solid-svg-icons"
import { ChartTypeName, GrapherTabOption } from "@ourworldindata/types"
import { chartIcons } from "./ChartIcons"
import { Bounds, capitalize } from "@ourworldindata/utils"
import { Tabs } from "../tabs/Tabs.js"
import { TabLabel, Tabs } from "../tabs/Tabs.js"

export interface ContentSwitchersManager {
availableTabs?: GrapherTabOption[]
Expand Down Expand Up @@ -91,17 +91,19 @@ export class ContentSwitchers extends React.Component<{
}
}

@computed private get tabLabels(): React.ReactElement[] {
return this.availableTabs.map((tab) => (
<span
key={tab}
data-track-note={"chart_click_" + tab}
aria-label={tab}
>
{this.tabIcon(tab)}
{this.showTabLabels && <span className="label">{tab}</span>}
</span>
))
@computed private get tabLabels(): TabLabel[] {
return this.availableTabs.map((tab) => ({
element: (
<span key={tab}>
{this.tabIcon(tab)}
{this.showTabLabels && <span className="label">{tab}</span>}
</span>
),
buttonProps: {
"data-track-note": "chart_click_" + tab,
"aria-label": tab,
},
}))
}

render(): React.ReactElement {
Expand Down
32 changes: 16 additions & 16 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, { ReactElement } from "react"
import React from "react"
import cx from "classnames"
import { action, computed } from "mobx"
import { observer } from "mobx-react"
Expand All @@ -36,7 +36,7 @@ import { CoreColumn } from "@ourworldindata/core-table"
import { Modal } from "./Modal"
import { SourcesKeyDataTable } from "./SourcesKeyDataTable"
import { SourcesDescriptions } from "./SourcesDescriptions"
import { Tabs } from "../tabs/Tabs"
import { TabLabel, Tabs } from "../tabs/Tabs"
import { ExpandableTabs } from "../tabs/ExpandableTabs"
import { LoadingIndicator } from "../loadingIndicator/LoadingIndicator"
import { isContinentsVariableId } from "../core/GrapherConstants"
Expand Down Expand Up @@ -113,20 +113,22 @@ export class SourcesModal extends React.Component<
return this.manager.columnsWithSourcesExtensive
}

@computed private get tabLabels(): ReactElement[] {
@computed private get tabLabels(): TabLabel[] {
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>
)
return {
element: (
<React.Fragment key={column.slug}>
{column.titlePublicOrDisplayName.title}
{attribution && (
<span className="attribution">{attribution}</span>
)}
</React.Fragment>
),
}
})
}

Expand Down Expand Up @@ -214,20 +216,18 @@ export class SourcesModal extends React.Component<
}

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

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

return visibleLabels
Expand Down
8 changes: 4 additions & 4 deletions packages/@ourworldindata/grapher/src/tabs/ExpandableTabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@ import React, { useState } from "react"
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome/index.js"
import { faPlus, faMinus } from "@fortawesome/free-solid-svg-icons"
import cx from "classnames"
import { Tabs } from "./Tabs"
import { TabLabel, Tabs } from "./Tabs"

export const ExpandableTabs = ({
labels,
activeIndex,
setActiveIndex,
isExpandedDefault = false,
getVisibleLabels = (labels: React.ReactElement[]) => labels.slice(0, 3),
getVisibleLabels = (labels: TabLabel[]) => labels.slice(0, 3),
maxTabWidth = 240,
}: {
labels: React.ReactElement[]
labels: TabLabel[]
activeIndex: number
setActiveIndex: (index: number) => void
isExpandedDefault?: boolean
getVisibleLabels?: (tabLabels: React.ReactElement[]) => React.ReactElement[]
getVisibleLabels?: (tabLabels: TabLabel[]) => TabLabel[]
maxTabWidth?: number | null // if null, don't clip labels
}) => {
const [isExpanded, setExpanded] = useState(isExpandedDefault)
Expand Down
10 changes: 8 additions & 2 deletions packages/@ourworldindata/grapher/src/tabs/Tabs.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
import React, { useRef } from "react"
import cx from "classnames"

export interface TabLabel {
element: React.ReactElement
buttonProps?: React.ButtonHTMLAttributes<HTMLButtonElement>
}

export const Tabs = ({
labels,
activeIndex,
Expand All @@ -11,7 +16,7 @@ export const Tabs = ({
extraClassNames,
variant = "default",
}: {
labels: React.ReactElement[]
labels: TabLabel[]
activeIndex: number
setActiveIndex: (label: number) => void
horizontalScroll?: boolean
Expand Down Expand Up @@ -83,8 +88,9 @@ export const Tabs = ({
aria-selected={isActive}
onClick={() => setActiveIndex(index)}
onKeyDown={handleKeyDown}
{...label.buttonProps}
>
{label}
{label.element}
</button>
)
})}
Expand Down

0 comments on commit d35eb9f

Please sign in to comment.