Skip to content

Commit 2d8471b

Browse files
authored
add version publisher avatar, a11y tweaks (#2274)
1 parent aff4509 commit 2d8471b

File tree

3 files changed

+54
-16
lines changed

3 files changed

+54
-16
lines changed

components/Package/TrustedBadge.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
1-
import { View } from 'react-native';
1+
import { type StyleProp, View, type ViewStyle } from 'react-native';
22

33
import { Verified } from '~/components/Icons';
44
import Tooltip from '~/components/Tooltip';
55
import tw from '~/util/tailwind';
66

7-
export default function TrustedBadge() {
7+
type Props = {
8+
style?: StyleProp<ViewStyle>;
9+
};
10+
11+
export default function TrustedBadge({ style }: Props) {
812
return (
913
<Tooltip
1014
trigger={
11-
<View role="button" aria-label="Trusted publisher">
12-
<Verified width={16} height={16} style={tw`text-success`} />
15+
<View role="button" aria-label="Trusted publisher" style={style}>
16+
<Verified style={tw`h-[15px] w-4 text-success`} />
1317
</View>
14-
}>
18+
}
19+
sideOffset={0}>
1520
Trusted publisher
1621
</Tooltip>
1722
);

components/Package/VersionBox.tsx

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
import SHA256 from 'crypto-js/sha256';
12
import { View } from 'react-native';
23

34
import { A, Caption, Label, useLayout } from '~/common/styleguide';
45
import { Dependency, Download, PackageSize } from '~/components/Icons';
56
import TrustedBadge from '~/components/Package/TrustedBadge';
7+
import UserAvatar from '~/components/Package/UserAvatar';
8+
import RelativeTime from '~/components/RelativeTime';
69
import { type NpmRegistryVersionData } from '~/types';
7-
import { getTimeSinceToday } from '~/util/datetime';
810
import { formatBytes } from '~/util/formatBytes';
911
import { formatNumberToString, pluralize } from '~/util/strings';
1012
import tw from '~/util/tailwind';
@@ -20,27 +22,34 @@ export default function VersionBox({ label, time, versionData, downloads = 0 }:
2022
const { isSmallScreen } = useLayout();
2123

2224
const urlBase = `https://www.npmjs.com/package/${versionData.name}/v/${versionData.version}`;
25+
const publisherMetadata = versionData._npmUser?.url ?? versionData._npmUser?.email;
2326

2427
return (
2528
<View
2629
style={[
27-
tw`flex-row items-center justify-between gap-0.5 rounded-xl border border-palette-gray2 px-4 py-2.5 dark:border-default`,
28-
isSmallScreen && tw`flex-col items-start justify-start gap-2`,
30+
tw`flex-row items-center justify-between gap-0.5 rounded-xl border border-palette-gray2 px-4 pb-2.5 pt-2 dark:border-default`,
31+
isSmallScreen && tw`flex-col items-start justify-start gap-x-2 gap-y-2.5`,
2932
]}>
3033
<View>
31-
<View style={tw`min-h-4 flex-row items-center gap-1`}>
34+
<View style={tw`min-h-4 flex-row flex-wrap items-center gap-1`}>
3235
{label && <Caption style={tw`tabular-nums`}>{label}</Caption>}
3336
{label && <Caption style={tw`text-secondary`}>{` • `}</Caption>}
3437
<Caption style={label && tw`tabular-nums text-secondary`}>{versionData.version}</Caption>
3538
</View>
36-
<View style={tw`min-h-4 flex-row items-center gap-1`}>
37-
<Label style={tw`font-light text-secondary`}>
38-
Released {getTimeSinceToday(time)} by {versionData._npmUser?.name}
39-
</Label>
40-
{versionData._npmUser?.trustedPublisher && <TrustedBadge />}
41-
</View>
39+
<Label style={tw`flex min-h-4 flex-wrap items-center font-light text-secondary`}>
40+
Released <RelativeTime time={time} dateOnly /> by
41+
{versionData._npmUser?.trustedPublisher && <TrustedBadge style={tw`mx-[3px]`} />}
42+
{publisherMetadata && !versionData._npmUser?.trustedPublisher && (
43+
<UserAvatar
44+
src={`https://gravatar.com/avatar/${SHA256(publisherMetadata).toString()}?d=retro`}
45+
alt={`${versionData._npmUser?.name} avatar`}
46+
style={tw`relative top-px mx-[3px] size-3.5 border border-default`}
47+
/>
48+
)}
49+
{versionData._npmUser?.name ?? 'Unknown'}
50+
</Label>
4251
</View>
43-
<View style={tw`flex-row flex-wrap gap-x-5 gap-y-1`}>
52+
<View style={tw`flex-row flex-wrap gap-x-5 gap-y-1.5`}>
4453
{versionData.dependencies && (
4554
<View style={[tw`flex-row items-center gap-2.5`, !isSmallScreen && tw`min-w-[110px]`]}>
4655
<Dependency style={tw`text-icon`} />

components/RelativeTime.tsx

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Label } from '~/common/styleguide';
2+
import Tooltip from '~/components/Tooltip';
3+
import { getTimeSinceToday } from '~/util/datetime';
4+
import tw from '~/util/tailwind';
5+
6+
type Props = {
7+
time: string;
8+
dateOnly?: boolean;
9+
};
10+
11+
export default function RelativeTime({ time, dateOnly }: Props) {
12+
return (
13+
<Tooltip
14+
trigger={<time dateTime={time}>{getTimeSinceToday(time)}</time>}
15+
sideOffset={0}
16+
delayDuration={500}>
17+
<Label style={tw`font-light text-white`}>
18+
{dateOnly
19+
? new Date(time).toLocaleDateString('en-US')
20+
: new Date(time).toLocaleString('en-US')}
21+
</Label>
22+
</Tooltip>
23+
);
24+
}

0 commit comments

Comments
 (0)