Skip to content

Commit

Permalink
🎉 (entity selector) sort by name or value
Browse files Browse the repository at this point in the history
  • Loading branch information
sophiamersmann committed Apr 10, 2024
1 parent 43637ac commit 74553b7
Show file tree
Hide file tree
Showing 16 changed files with 622 additions and 203 deletions.
5 changes: 2 additions & 3 deletions packages/@ourworldindata/components/src/Checkbox.scss
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

$light-stroke: #dadada;
$hover-stroke: #a4b6ca;
$active-fill: #dbe5f0;
$active-fill: #a4b6ca;

position: relative;

Expand All @@ -27,7 +27,7 @@
pointer-events: none;
border-radius: 2px;
border: 1px solid $light-stroke;
color: $dark-text;
color: #fff;

display: flex;
align-items: center;
Expand All @@ -36,7 +36,6 @@
svg {
font-size: 10px;
padding-left: 0.75px;
color: $active-text;
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/@ourworldindata/components/src/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { faCheck } from "@fortawesome/free-solid-svg-icons"

export class Checkbox extends React.Component<{
checked: boolean
onChange: React.ChangeEventHandler<HTMLInputElement>
onChange?: React.ChangeEventHandler<HTMLInputElement>
label: React.ReactNode
}> {
render(): JSX.Element {
Expand Down
4 changes: 4 additions & 0 deletions packages/@ourworldindata/core-table/src/CoreTableColumns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -928,3 +928,7 @@ export const ColumnTypeMap = {
const _ColumnTypeMap: {
[key in ColumnTypeNames]: unknown
} = ColumnTypeMap

export function isColumnWithNumberFormatting(column: CoreColumn): boolean {
return column instanceof AbstractColumnWithNumberFormatting
}
2 changes: 1 addition & 1 deletion packages/@ourworldindata/core-table/src/OwidTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ export class OwidTable extends CoreTable<OwidRow, OwidColumnDef> {
}

// Does a stable sort by time. You can refer to this table for fast time filtering.
@imemo private get sortedByTime(): this {
@imemo get sortedByTime(): this {
if (this.timeColumn.isMissing) return this
return this.sortBy([this.timeColumn.slug])
}
Expand Down
1 change: 1 addition & 0 deletions packages/@ourworldindata/core-table/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export {
ColumnTypeMap,
AbstractCoreColumn,
TimeColumn,
isColumnWithNumberFormatting,
} from "./CoreTableColumns.js"

export { OwidTable, BlankOwidTable } from "./OwidTable.js"
Expand Down
91 changes: 91 additions & 0 deletions packages/@ourworldindata/grapher/src/controls/Dropdown.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
.grapher-dropdown {
$option-checkmark: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iOSIgdmlld0JveD0iMCAwIDEyIDkiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0xMS4wMTU2IDAuOTg0Mzc1QzExLjMyMDMgMS4yNjU2MiAxMS4zMjAzIDEuNzU3ODEgMTEuMDE1NiAyLjAzOTA2TDUuMDE1NjIgOC4wMzkwNkM0LjczNDM4IDguMzQzNzUgNC4yNDIxOSA4LjM0Mzc1IDMuOTYwOTQgOC4wMzkwNkwwLjk2MDkzOCA1LjAzOTA2QzAuNjU2MjUgNC43NTc4MSAwLjY1NjI1IDQuMjY1NjIgMC45NjA5MzggMy45ODQzOEMxLjI0MjE5IDMuNjc5NjkgMS43MzQzOCAzLjY3OTY5IDIuMDE1NjIgMy45ODQzOEw0LjQ3NjU2IDYuNDQ1MzFMOS45NjA5NCAwLjk4NDM3NUMxMC4yNDIyIDAuNjc5Njg4IDEwLjczNDQgMC42Nzk2ODggMTEuMDE1NiAwLjk4NDM3NVoiIGZpbGw9IiMxRDNENjMiLz4KPC9zdmc+";
$menu-caret-up: "data:image/svg+xml;base64, PHN2ZyB3aWR0aD0iOCIgaGVpZ2h0PSI1IiB2aWV3Qm94PSIwIDAgOCA1IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMC40NjA5MzggMy43MzQzOEwzLjQzNzUgMC43MzQzNzVDMy42MDE1NiAwLjU5Mzc1IDMuNzg5MDYgMC41IDQgMC41QzQuMTg3NSAwLjUgNC4zNzUgMC41OTM3NSA0LjUxNTYyIDAuNzM0Mzc1TDcuNDkyMTkgMy43MzQzOEM3LjcwMzEyIDMuOTQ1MzEgNy43NzM0NCA0LjI3MzQ0IDcuNjU2MjUgNC41NTQ2OUM3LjUzOTA2IDQuODM1OTQgNy4yODEyNSA1IDYuOTc2NTYgNUgxQzAuNjk1MzEyIDUgMC40MTQwNjIgNC44MzU5NCAwLjI5Njg3NSA0LjU1NDY5QzAuMTc5Njg4IDQuMjczNDQgMC4yNSAzLjk0NTMxIDAuNDYwOTM4IDMuNzM0MzhaIiBmaWxsPSIjNUI1QjVCIi8+Cjwvc3ZnPg==";
$menu-caret-down: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iOCIgaGVpZ2h0PSI1IiB2aWV3Qm94PSIwIDAgOCA1IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNNy41MTU2MiAxLjI4OTA2TDQuNTM5MDYgNC4yODkwNkM0LjM3NSA0LjQyOTY5IDQuMTg3NSA0LjUgNCA0LjVDMy43ODkwNiA0LjUgMy42MDE1NiA0LjQyOTY5IDMuNDYwOTQgNC4yODkwNkwwLjQ4NDM3NSAxLjI4OTA2QzAuMjUgMS4wNzgxMiAwLjE3OTY4OCAwLjc1IDAuMjk2ODc1IDAuNDY4NzVDMC40MTQwNjIgMC4xODc1IDAuNjk1MzEyIDAgMSAwSDYuOTc2NTZDNy4yODEyNSAwIDcuNTM5MDYgMC4xODc1IDcuNjU2MjUgMC40Njg3NUM3Ljc3MzQ0IDAuNzUgNy43MjY1NiAxLjA3ODEyIDcuNTE1NjIgMS4yODkwNloiIGZpbGw9IiM1QjVCNUIiLz4KPC9zdmc+Cg==";

$medium: 400;
$lato: $sans-serif-font-stack;

$light-stroke: #e7e7e7;
$active-stroke: #a4b6ca;

$active-fill: #dbe5f0;
$hover-fill: #f2f2f2;
$selected-fill: #c7ced7;

$light-text: #858585;

font: $medium 13px/16px $lato;

// fixes a bug in Firefox where long labels would cause the dropdown to resize,
// see https://github.com/JedWatson/react-select/issues/5170
display: grid;
grid-template-columns: minmax(0, 1fr);

.control {
min-height: auto;
font: $medium 13px/16px $lato;
letter-spacing: 0.01em;
display: flex;
align-items: center;
border: 1px solid $light-stroke;
border-radius: 4px;
padding: 7px;
color: $dark-text;

&:hover {
background: $hover-fill;
cursor: pointer;
}

&:after {
content: " ";
background: url($menu-caret-down) no-repeat center;
width: 16px;
height: 16px;
}

&.active {
border-color: $active-stroke;
&:after {
background: url($menu-caret-up) no-repeat center;
}
}
}

.menu {
margin-top: 3px;
border-radius: 4px;
background: white;
box-shadow: 0px 4px 40px 0px rgba(0, 0, 0, 0.15);
z-index: $zindex-controls-popup;

.option {
padding: 8px 18px;
&:hover {
cursor: pointer;
background: $hover-fill;
}
&:active,
&.active {
color: $active-text;
background: $active-fill;
}
&.active {
position: relative;
&:hover {
background: $selected-fill;
}
&:after {
content: " ";
background: url($option-checkmark) no-repeat;
width: 12px;
height: 9px;
position: absolute;
right: 18px;
bottom: 11px;
}
}
}
}
}
26 changes: 26 additions & 0 deletions packages/@ourworldindata/grapher/src/controls/Dropdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react"
import Select, { Props } from "react-select"

export function Dropdown(props: Props): React.JSX.Element {
return (
<Select
className="grapher-dropdown"
menuPlacement="bottom"
components={{
IndicatorSeparator: null,
DropdownIndicator: null,
}}
isSearchable={false}
unstyled={true}
isMulti={false}
classNames={{
control: (state) =>
state.menuIsOpen ? "active control" : "control",
option: (state) =>
state.isSelected ? "active option" : "option",
menu: () => "menu",
}}
{...props}
/>
)
}
Original file line number Diff line number Diff line change
@@ -1,95 +1,13 @@
.map-projection-menu {
$option-checkmark: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iOSIgdmlld0JveD0iMCAwIDEyIDkiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxwYXRoIGQ9Ik0xMS4wMTU2IDAuOTg0Mzc1QzExLjMyMDMgMS4yNjU2MiAxMS4zMjAzIDEuNzU3ODEgMTEuMDE1NiAyLjAzOTA2TDUuMDE1NjIgOC4wMzkwNkM0LjczNDM4IDguMzQzNzUgNC4yNDIxOSA4LjM0Mzc1IDMuOTYwOTQgOC4wMzkwNkwwLjk2MDkzOCA1LjAzOTA2QzAuNjU2MjUgNC43NTc4MSAwLjY1NjI1IDQuMjY1NjIgMC45NjA5MzggMy45ODQzOEMxLjI0MjE5IDMuNjc5NjkgMS43MzQzOCAzLjY3OTY5IDIuMDE1NjIgMy45ODQzOEw0LjQ3NjU2IDYuNDQ1MzFMOS45NjA5NCAwLjk4NDM3NUMxMC4yNDIyIDAuNjc5Njg4IDEwLjczNDQgMC42Nzk2ODggMTEuMDE1NiAwLjk4NDM3NVoiIGZpbGw9IiMxRDNENjMiLz4KPC9zdmc+";
$menu-caret-up: "data:image/svg+xml;base64, PHN2ZyB3aWR0aD0iOCIgaGVpZ2h0PSI1IiB2aWV3Qm94PSIwIDAgOCA1IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNMC40NjA5MzggMy43MzQzOEwzLjQzNzUgMC43MzQzNzVDMy42MDE1NiAwLjU5Mzc1IDMuNzg5MDYgMC41IDQgMC41QzQuMTg3NSAwLjUgNC4zNzUgMC41OTM3NSA0LjUxNTYyIDAuNzM0Mzc1TDcuNDkyMTkgMy43MzQzOEM3LjcwMzEyIDMuOTQ1MzEgNy43NzM0NCA0LjI3MzQ0IDcuNjU2MjUgNC41NTQ2OUM3LjUzOTA2IDQuODM1OTQgNy4yODEyNSA1IDYuOTc2NTYgNUgxQzAuNjk1MzEyIDUgMC40MTQwNjIgNC44MzU5NCAwLjI5Njg3NSA0LjU1NDY5QzAuMTc5Njg4IDQuMjczNDQgMC4yNSAzLjk0NTMxIDAuNDYwOTM4IDMuNzM0MzhaIiBmaWxsPSIjNUI1QjVCIi8+Cjwvc3ZnPg==";
$menu-caret-down: "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iOCIgaGVpZ2h0PSI1IiB2aWV3Qm94PSIwIDAgOCA1IiBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgo8cGF0aCBkPSJNNy41MTU2MiAxLjI4OTA2TDQuNTM5MDYgNC4yODkwNkM0LjM3NSA0LjQyOTY5IDQuMTg3NSA0LjUgNCA0LjVDMy43ODkwNiA0LjUgMy42MDE1NiA0LjQyOTY5IDMuNDYwOTQgNC4yODkwNkwwLjQ4NDM3NSAxLjI4OTA2QzAuMjUgMS4wNzgxMiAwLjE3OTY4OCAwLjc1IDAuMjk2ODc1IDAuNDY4NzVDMC40MTQwNjIgMC4xODc1IDAuNjk1MzEyIDAgMSAwSDYuOTc2NTZDNy4yODEyNSAwIDcuNTM5MDYgMC4xODc1IDcuNjU2MjUgMC40Njg3NUM3Ljc3MzQ0IDAuNzUgNy43MjY1NiAxLjA3ODEyIDcuNTE1NjIgMS4yODkwNloiIGZpbGw9IiM1QjVCNUIiLz4KPC9zdmc+Cg==";

$medium: 400;
$lato: $sans-serif-font-stack;

$light-stroke: #e7e7e7;
$active-stroke: #a4b6ca;

$active-fill: #dbe5f0;
$hover-fill: #f2f2f2;
$selected-fill: #c7ced7;

$light-text: #858585;

font: $medium 13px/16px $lato;

.control {
min-height: auto;
min-width: 150px;
font: $medium 13px/16px $lato;
letter-spacing: 0.01em;
display: flex;
align-items: center;
border: 1px solid $light-stroke;
border-radius: 4px;
padding: 7px;
color: $dark-text;

&:hover {
background: $hover-fill;
cursor: pointer;
}

&:after {
content: " ";
background: url($menu-caret-down) no-repeat center;
width: 16px;
height: 16px;
}

&.active {
border-color: $active-stroke;
&:after {
background: url($menu-caret-up) no-repeat center;
}
}
}

.menu {
margin-top: 3px;
border-radius: 4px;
background: white;
box-shadow: 0px 4px 40px 0px rgba(0, 0, 0, 0.15);
z-index: $zindex-controls-popup;

&:before {
display: inline-block;
content: "Zoom to selection";
font: 700 12px/16px $lato;
color: $light-text;
padding: 8px 18px;
}

.option {
padding: 8px 18px;
&:hover {
cursor: pointer;
background: $hover-fill;
}
&:active,
&.active {
color: $active-text;
background: $active-fill;
}
&.active {
position: relative;
&:hover {
background: $selected-fill;
}
&:after {
content: " ";
background: url($option-checkmark) no-repeat;
width: 12px;
height: 9px;
position: absolute;
right: 18px;
bottom: 11px;
}
}
}
.menu:before {
display: inline-block;
content: "Zoom to selection";
font: 700 12px/16px $lato;
color: $light-text;
padding: 8px 18px;
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React from "react"
import Select from "react-select"
import { computed, action } from "mobx"
import { observer } from "mobx-react"
import { MapConfig } from "../mapCharts/MapConfig"
import { MapProjectionName } from "@ourworldindata/types"
import { MapProjectionLabels } from "../mapCharts/MapProjections"
import { Dropdown } from "./Dropdown"

export { AbsRelToggle } from "./settings/AbsRelToggle"
export { FacetStrategySelector } from "./settings/FacetStrategySelector"
Expand Down Expand Up @@ -40,9 +40,10 @@ export class MapProjectionMenu extends React.Component<{
return !hideMapProjectionMenu && !!(isOnMapTab && projection)
}

@action.bound onChange(selected: MapProjectionMenuItem | null): void {
@action.bound onChange(selected: unknown): void {
const { mapConfig } = this.props.manager
if (selected && mapConfig) mapConfig.projection = selected.value
if (selected && mapConfig)
mapConfig.projection = (selected as MapProjectionMenuItem).value
}

@computed get options(): MapProjectionMenuItem[] {
Expand All @@ -62,25 +63,10 @@ export class MapProjectionMenu extends React.Component<{
render(): JSX.Element | null {
return this.showMenu ? (
<div className="map-projection-menu">
<Select
<Dropdown
options={this.options}
onChange={this.onChange}
value={this.value}
menuPlacement="bottom"
components={{
IndicatorSeparator: null,
DropdownIndicator: null,
}}
isSearchable={false}
unstyled={true}
isMulti={false}
classNames={{
control: (state) =>
state.menuIsOpen ? "active control" : "control",
option: (state) =>
state.isSelected ? "active option" : "option",
menu: () => "menu",
}}
/>
</div>
) : null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react"

export class RadioButton extends React.Component<{
checked: boolean
onChange: React.ChangeEventHandler<HTMLInputElement>
onChange?: React.ChangeEventHandler<HTMLInputElement>
label: React.ReactNode
group?: string
}> {
Expand Down
1 change: 1 addition & 0 deletions packages/@ourworldindata/grapher/src/core/grapher.scss
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ $zindex-controls-drawer: 150;
@import "../../../components/src/Checkbox.scss";
@import "../closeButton/CloseButton.scss";
@import "../controls/RadioButton.scss";
@import "../controls/Dropdown.scss";

.grapher_dark {
color: $dark-text;
Expand Down
9 changes: 9 additions & 0 deletions packages/@ourworldindata/grapher/src/core/typography.scss
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,12 @@
.grapher_label-2-regular {
@include grapher_label-2-regular;
}

@mixin grapher_label-2-medium {
@include grapher_label-2-regular;
font-weight: 500;
}

.grapher_label-2-medium {
@include grapher_label-2-medium;
}
Loading

0 comments on commit 74553b7

Please sign in to comment.