Jazz up the chart tooltips with avatars

This commit is contained in:
Marshall Polaris 2022-09-28 20:47:09 -07:00
parent 9fe3c24bae
commit 5e3fe64683
4 changed files with 29 additions and 13 deletions

View File

@ -8,13 +8,14 @@ export function Avatar(props: {
username?: string username?: string
avatarUrl?: string avatarUrl?: string
noLink?: boolean noLink?: boolean
size?: number | 'xs' | 'sm' size?: number | 'xxs' | 'xs' | 'sm'
className?: string className?: string
}) { }) {
const { username, noLink, size, className } = props const { username, noLink, size, className } = props
const [avatarUrl, setAvatarUrl] = useState(props.avatarUrl) const [avatarUrl, setAvatarUrl] = useState(props.avatarUrl)
useEffect(() => setAvatarUrl(props.avatarUrl), [props.avatarUrl]) useEffect(() => setAvatarUrl(props.avatarUrl), [props.avatarUrl])
const s = size == 'xs' ? 6 : size === 'sm' ? 8 : size || 10 const s =
size == 'xxs' ? 4 : size == 'xs' ? 6 : size === 'sm' ? 8 : size || 10
const sizeInPx = s * 4 const sizeInPx = s * 4
const onClick = const onClick =

View File

@ -20,6 +20,8 @@ import {
SingleValueHistoryChart, SingleValueHistoryChart,
} from '../generic-charts' } from '../generic-charts'
import { useElementWidth } from 'web/hooks/use-element-width' import { useElementWidth } from 'web/hooks/use-element-width'
import { Row } from 'web/components/layout/row'
import { Avatar } from 'web/components/avatar'
const getBetPoints = (bets: Bet[]) => { const getBetPoints = (bets: Bet[]) => {
return sortBy(bets, (b) => b.createdTime).map((b) => ({ return sortBy(bets, (b) => b.createdTime).map((b) => ({
@ -30,12 +32,14 @@ const getBetPoints = (bets: Bet[]) => {
} }
const BinaryChartTooltip = (props: SingleValueHistoryTooltipProps<Bet>) => { const BinaryChartTooltip = (props: SingleValueHistoryTooltipProps<Bet>) => {
const { x, y, xScale } = props const { x, y, xScale, datum } = props
const [start, end] = xScale.domain() const [start, end] = xScale.domain()
return ( return (
<span className="text-sm"> <Row className="items-center gap-2 text-sm">
<strong>{formatPct(y)}</strong> {formatDateInRange(x, start, end)} {datum && <Avatar size="xs" avatarUrl={datum.userAvatarUrl} />}
</span> <strong>{formatPct(y)}</strong>
<span>{formatDateInRange(x, start, end)}</span>
</Row>
) )
} }

View File

@ -23,6 +23,8 @@ import {
MultiValueHistoryTooltipProps, MultiValueHistoryTooltipProps,
} from '../generic-charts' } from '../generic-charts'
import { useElementWidth } from 'web/hooks/use-element-width' import { useElementWidth } from 'web/hooks/use-element-width'
import { Row } from 'web/components/layout/row'
import { Avatar } from 'web/components/avatar'
// thanks to https://observablehq.com/@jonhelfman/optimal-orders-for-choosing-categorical-colors // thanks to https://observablehq.com/@jonhelfman/optimal-orders-for-choosing-categorical-colors
const CATEGORY_COLORS = [ const CATEGORY_COLORS = [
@ -160,7 +162,7 @@ export const ChoiceContractChart = (props: {
const ChoiceTooltip = useMemo( const ChoiceTooltip = useMemo(
() => (props: MultiValueHistoryTooltipProps<Bet>) => { () => (props: MultiValueHistoryTooltipProps<Bet>) => {
const { x, y, xScale } = props const { x, y, xScale, datum } = props
const [start, end] = xScale.domain() const [start, end] = xScale.domain()
const legendItems = sortBy( const legendItems = sortBy(
y.map((p, i) => ({ y.map((p, i) => ({
@ -173,7 +175,10 @@ export const ChoiceContractChart = (props: {
).slice(0, 10) ).slice(0, 10)
return ( return (
<div> <div>
<p>{formatDateInRange(x, start, end)}</p> <Row className="items-center gap-2">
{datum && <Avatar size="xxs" avatarUrl={datum.userAvatarUrl} />}
<span>{formatDateInRange(x, start, end)}</span>
</Row>
<Legend className="max-w-xs text-sm" items={legendItems} /> <Legend className="max-w-xs text-sm" items={legendItems} />
</div> </div>
) )

View File

@ -21,6 +21,8 @@ import {
SingleValueHistoryTooltipProps, SingleValueHistoryTooltipProps,
} from '../generic-charts' } from '../generic-charts'
import { useElementWidth } from 'web/hooks/use-element-width' import { useElementWidth } from 'web/hooks/use-element-width'
import { Row } from 'web/components/layout/row'
import { Avatar } from 'web/components/avatar'
// mqp: note that we have an idiosyncratic version of 'log scale' // mqp: note that we have an idiosyncratic version of 'log scale'
// contracts. the values are stored "linearly" and can include zero. // contracts. the values are stored "linearly" and can include zero.
@ -41,13 +43,17 @@ const getBetPoints = (bets: Bet[], scaleP: (p: number) => number) => {
})) }))
} }
const PseudoNumericChartTooltip = (props: SingleValueHistoryTooltipProps) => { const PseudoNumericChartTooltip = (
const { x, y, xScale } = props props: SingleValueHistoryTooltipProps<Bet>
) => {
const { x, y, xScale, datum } = props
const [start, end] = xScale.domain() const [start, end] = xScale.domain()
return ( return (
<span className="text-sm"> <Row className="items-center gap-2 text-sm">
<strong>{formatLargeNumber(y)}</strong> {formatDateInRange(x, start, end)} {datum && <Avatar size="xs" avatarUrl={datum.userAvatarUrl} />}
</span> <strong>{formatLargeNumber(y)}</strong>
<span>{formatDateInRange(x, start, end)}</span>
</Row>
) )
} }