Skip to content

Commit 0a16364

Browse files
committed
Lithology tags can now be clickable or links
1 parent 8d6903b commit 0a16364

File tree

3 files changed

+98
-27
lines changed

3 files changed

+98
-27
lines changed

packages/data-components/src/components/unit-details/lithology-tag.ts

Lines changed: 40 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
import h from "@macrostrat/hyper";
22
import { TagField } from "./base";
3-
import { Tag, TagSize } from "./tag";
3+
import { BaseTagProps, Tag, TagSize } from "./tag";
44
import { useMemo } from "react";
5+
import { Lithology } from "@macrostrat/api-types";
6+
import classNames from "classnames";
57

6-
interface LithologyTagProps {
7-
data: any;
8-
color?: string;
8+
interface LithologyTagProps extends Omit<BaseTagProps, "onClick" | "name"> {
9+
data: Lithology;
910
className?: string;
1011
expandOnHover?: boolean;
1112
size?: TagSize;
1213
features?: Set<LithologyTagFeature>;
13-
onClick?: (event: any) => void;
14+
onClick?: (event: any, data: Lithology) => void;
1415
}
1516

1617
export enum LithologyTagFeature {
@@ -22,8 +23,8 @@ export function LithologyTag({
2223
data,
2324
color,
2425
features,
25-
size,
26-
onClick,
26+
onClick: _onClick,
27+
...rest
2728
}: LithologyTagProps) {
2829
let proportion = null;
2930
const showProportion = features?.has(LithologyTagFeature.Proportion) ?? false;
@@ -44,22 +45,21 @@ export function LithologyTag({
4445
});
4546
}
4647

47-
const clickable = onClick != null;
48-
49-
const handleClick = (event: MouseEvent) => {
50-
if (onClick) {
51-
onClick({ event, data });
52-
}
53-
};
48+
const onClick = useMemo(() => {
49+
if (_onClick == null) return null;
50+
return (event: MouseEvent) => {
51+
_onClick(event, data);
52+
};
53+
}, [data, _onClick]);
5454

5555
return h(Tag, {
5656
prefix: atts,
5757
details: proportion,
5858
name: data.name,
59-
className: clickable ? " clickable" : "",
60-
size,
59+
className: classNames({ clickable: onClick != null }, "lithology-tag"),
6160
color: color ?? data.color,
62-
onClick: clickable ? handleClick : undefined,
61+
onClick,
62+
...rest,
6363
});
6464
}
6565

@@ -95,11 +95,17 @@ export function LithologyList({
9595
LithologyTagFeature.Attributes,
9696
]),
9797
onClickItem,
98+
getItemHref,
99+
className,
98100
}: {
99101
label?: string;
100102
lithologies: any[];
101103
features?: Set<LithologyTagFeature>;
102-
onClickItem?: (data: any) => void;
104+
// Optional function to handle click events on each item
105+
onClickItem?: (event: MouseEvent, data: Lithology) => void;
106+
// Optional function to get a link location for each item
107+
getItemHref?: (data: Lithology) => string | null | undefined;
108+
className?: string;
103109
}) {
104110
const sortedLiths = useMemo(() => {
105111
const l1 = [...lithologies];
@@ -109,7 +115,7 @@ export function LithologyList({
109115

110116
return h(
111117
TagField,
112-
{ label },
118+
{ label, className },
113119
sortedLiths.map((lith) => {
114120
let l1 = { ...lith };
115121
if (l1.prop == 0) {
@@ -119,9 +125,8 @@ export function LithologyList({
119125
return h(LithologyTag, {
120126
data: l1,
121127
features,
122-
onClick: onClickItem
123-
? (data) => onClickItem({ ...data, data: l1 })
124-
: undefined,
128+
onClick: onClickItem,
129+
href: getItemHref?.(lith),
125130
});
126131
})
127132
);
@@ -138,12 +143,21 @@ function lithologyComparison(a, b) {
138143
return dx;
139144
}
140145

141-
export function EnvironmentsList({ environments, onClickItem }) {
146+
export function EnvironmentsList({
147+
environments,
148+
onClickItem,
149+
getItemHref,
150+
label = "Environments",
151+
}) {
142152
return h(
143153
TagField,
144-
{ label: "Environments", className: "environments-list" },
145-
environments.map((lith: any) => {
146-
return h(LithologyTag, { data: lith, onClick: onClickItem });
154+
{ label, className: "environments-list" },
155+
environments.map((env: any) => {
156+
return h(LithologyTag, {
157+
data: env,
158+
onClick: onClickItem,
159+
href: getItemHref?.(env),
160+
});
147161
})
148162
);
149163
}

packages/data-components/src/components/unit-details/tag.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ export function Tag(props: BaseTagProps) {
8282
className: classNames(className, "tag"),
8383
style: buildTagStyle({ color, size, inDarkMode }),
8484
onClick,
85+
href,
8586
},
8687
[_prefix, mainTag]
8788
);

packages/data-components/src/components/unit-details/unit-details.stories.ts

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,21 @@ import {
1010
DataField as _DataField,
1111
IntervalField as _IntervalField,
1212
} from "./base";
13+
import {
14+
useAPIResult,
15+
useToaster,
16+
ToasterContext,
17+
} from "@macrostrat/ui-components";
1318

1419
export default {
1520
title: "Data components/Unit details",
1621
component: _LithologyTag,
17-
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes
22+
// More on argTypes: https://storybook.js.org/docs/react/api/argtypes,
23+
decorators: [
24+
(Story) => {
25+
return h(ToasterContext, {}, h(Story));
26+
},
27+
],
1828
} as Meta<any>;
1929

2030
export function DataField() {
@@ -114,3 +124,49 @@ export function LithologyList() {
114124
},
115125
});
116126
}
127+
128+
export function LithologyListClickable() {
129+
const toaster = useToaster();
130+
const liths = useAPIResult(
131+
"https://dev.macrostrat.org/api/v2/defs/lithologies",
132+
{
133+
lith_class: "sedimentary",
134+
},
135+
(res) => res.success.data
136+
);
137+
138+
if (liths == null) {
139+
return h("div", "Loading lithologies...");
140+
}
141+
142+
return h(_LithologyList, {
143+
lithologies: liths,
144+
onClickItem: (e, data) => {
145+
toaster.show({
146+
message: `Clicked lith ID: ${data.lith_id}`,
147+
intent: "success",
148+
});
149+
},
150+
});
151+
}
152+
153+
export function LithologyListWithLinks() {
154+
const liths = useAPIResult(
155+
"https://dev.macrostrat.org/api/v2/defs/lithologies",
156+
{
157+
lith_class: "sedimentary",
158+
},
159+
(res) => res.success.data
160+
);
161+
162+
if (liths == null) {
163+
return h("div", "Loading lithologies...");
164+
}
165+
166+
return h(_LithologyList, {
167+
lithologies: liths,
168+
getItemHref(data) {
169+
return `https://dev.macrostrat.org/lex/lithology/${data.lith_id}`;
170+
},
171+
});
172+
}

0 commit comments

Comments
 (0)