avatar component
This commit is contained in:
parent
0cc108e1ac
commit
bdb2cfd710
34
web/components/avatar.tsx
Normal file
34
web/components/avatar.tsx
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import Router from 'next/router'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
|
||||||
|
export function Avatar(props: {
|
||||||
|
username?: string
|
||||||
|
avatarUrl?: string
|
||||||
|
noLink?: boolean
|
||||||
|
}) {
|
||||||
|
const { username, avatarUrl, noLink } = props
|
||||||
|
|
||||||
|
const onClick =
|
||||||
|
noLink && username
|
||||||
|
? undefined
|
||||||
|
: (e: any) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
Router.push(`/${username}`)
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
<div className="rounded-full bg-gray-400 w-10 h-10">
|
||||||
|
<img
|
||||||
|
className={clsx(
|
||||||
|
'rounded-full bg-gray-400 flex items-center justify-center',
|
||||||
|
!noLink && 'cursor-pointer',
|
||||||
|
!avatarUrl && 'hidden'
|
||||||
|
)}
|
||||||
|
src={avatarUrl}
|
||||||
|
width={40}
|
||||||
|
height={40}
|
||||||
|
onClick={onClick}
|
||||||
|
alt={username}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
|
@ -11,8 +11,9 @@ import {
|
||||||
UsersIcon,
|
UsersIcon,
|
||||||
XIcon,
|
XIcon,
|
||||||
} from '@heroicons/react/solid'
|
} from '@heroicons/react/solid'
|
||||||
|
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
|
||||||
import { OutcomeLabel } from './outcome-label'
|
import { OutcomeLabel } from './outcome-label'
|
||||||
import {
|
import {
|
||||||
contractMetrics,
|
contractMetrics,
|
||||||
|
@ -40,38 +41,8 @@ import Textarea from 'react-expanding-textarea'
|
||||||
import { outcome } from '../../common/contract'
|
import { outcome } from '../../common/contract'
|
||||||
import { fromNow } from '../lib/util/time'
|
import { fromNow } from '../lib/util/time'
|
||||||
import BetRow from './bet-row'
|
import BetRow from './bet-row'
|
||||||
import clsx from 'clsx'
|
|
||||||
import { parseTags } from '../../common/util/parse'
|
import { parseTags } from '../../common/util/parse'
|
||||||
|
import { Avatar } from './avatar'
|
||||||
export function AvatarWithIcon(props: {
|
|
||||||
username: string
|
|
||||||
avatarUrl: string
|
|
||||||
noLink?: boolean
|
|
||||||
}) {
|
|
||||||
const { username, avatarUrl, noLink } = props
|
|
||||||
|
|
||||||
const image = (
|
|
||||||
<img
|
|
||||||
className="rounded-full bg-gray-400 flex items-center justify-center"
|
|
||||||
src={avatarUrl}
|
|
||||||
width={40}
|
|
||||||
height={40}
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
|
|
||||||
if (noLink) return image
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SiteLink className="relative" href={`/${username}`}>
|
|
||||||
{image}
|
|
||||||
</SiteLink>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export function AvatarPlaceholder() {
|
|
||||||
return <div className="rounded-full bg-gray-400 w-10 h-10" />
|
|
||||||
}
|
|
||||||
|
|
||||||
function FeedComment(props: {
|
function FeedComment(props: {
|
||||||
activityItem: any
|
activityItem: any
|
||||||
|
@ -86,7 +57,7 @@ function FeedComment(props: {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<AvatarWithIcon username={person.username} avatarUrl={person.avatarUrl} />
|
<Avatar username={person.username} avatarUrl={person.avatarUrl} />
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<div>
|
<div>
|
||||||
<p className="mt-0.5 text-sm text-gray-500">
|
<p className="mt-0.5 text-sm text-gray-500">
|
||||||
|
@ -301,7 +272,7 @@ function FeedQuestion(props: { contract: Contract }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{contract.creatorAvatarUrl ? (
|
{contract.creatorAvatarUrl ? (
|
||||||
<AvatarWithIcon
|
<Avatar
|
||||||
username={contract.creatorUsername}
|
username={contract.creatorUsername}
|
||||||
avatarUrl={contract.creatorAvatarUrl}
|
avatarUrl={contract.creatorAvatarUrl}
|
||||||
/>
|
/>
|
||||||
|
@ -355,7 +326,7 @@ function FeedDescription(props: { contract: Contract }) {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{contract.creatorAvatarUrl ? (
|
{contract.creatorAvatarUrl ? (
|
||||||
<AvatarWithIcon
|
<Avatar
|
||||||
username={contract.creatorUsername}
|
username={contract.creatorUsername}
|
||||||
avatarUrl={contract.creatorAvatarUrl}
|
avatarUrl={contract.creatorAvatarUrl}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { AvatarPlaceholder, AvatarWithIcon } from './contract-feed'
|
import { Avatar } from './avatar'
|
||||||
import Textarea from 'react-expanding-textarea'
|
import Textarea from 'react-expanding-textarea'
|
||||||
import { useRef, useState } from 'react'
|
import { useRef, useState } from 'react'
|
||||||
import { Spacer } from './layout/spacer'
|
import { Spacer } from './layout/spacer'
|
||||||
|
@ -86,15 +86,7 @@ export default function FeedCreate(props: {
|
||||||
onClick={() => inputRef.current?.focus()}
|
onClick={() => inputRef.current?.focus()}
|
||||||
>
|
>
|
||||||
<div className="relative flex items-start space-x-3">
|
<div className="relative flex items-start space-x-3">
|
||||||
{user?.avatarUrl ? (
|
<Avatar username={user?.username} avatarUrl={user?.avatarUrl} noLink />
|
||||||
<AvatarWithIcon
|
|
||||||
username={user.username}
|
|
||||||
avatarUrl={user.avatarUrl}
|
|
||||||
noLink
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<AvatarPlaceholder />
|
|
||||||
)}
|
|
||||||
|
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
{/* TODO: Show focus, for accessibility */}
|
{/* TODO: Show focus, for accessibility */}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user