made tip jar thingy

This commit is contained in:
ingawei 2022-10-12 22:33:25 -07:00
parent 4381911dbd
commit c72d6c5df5
4 changed files with 132 additions and 71 deletions

View File

@ -82,3 +82,39 @@ export function Button(props: {
</button> </button>
) )
} }
export function IconButton(props: {
className?: string
onClick?: MouseEventHandler<any> | undefined
children?: ReactNode
size?: SizeType
type?: 'button' | 'reset' | 'submit'
disabled?: boolean
loading?: boolean
}) {
const {
children,
className,
onClick,
size = 'md',
type = 'button',
disabled = false,
loading,
} = props
return (
<button
type={type}
className={clsx(
'inline-flex items-center justify-center transition-colors disabled:cursor-not-allowed',
sizeClasses[size],
'disabled:text-greyscale-2 text-greyscale-6 hover:text-indigo-600',
className
)}
disabled={disabled || loading}
onClick={onClick}
>
{children}
</button>
)
}

View File

@ -1,11 +1,9 @@
import clsx from 'clsx' import clsx from 'clsx'
import { HeartIcon } from '@heroicons/react/outline'
import { Button } from 'web/components/button'
import { formatMoney, shortFormatNumber } from 'common/util/format' import { formatMoney, shortFormatNumber } from 'common/util/format'
import { Col } from 'web/components/layout/col' import { Col } from 'web/components/layout/col'
import { Tooltip } from '../tooltip' import { Tooltip } from '../tooltip'
import TipJar from 'web/public/custom-components/tipJar' import TipJar from 'web/public/custom-components/tipJar'
import { useState } from 'react'
export function TipButton(props: { export function TipButton(props: {
tipAmount: number tipAmount: number
@ -20,6 +18,8 @@ export function TipButton(props: {
const tipDisplay = shortFormatNumber(Math.ceil(totalTipped / 10)) const tipDisplay = shortFormatNumber(Math.ceil(totalTipped / 10))
const [hover, setHover] = useState(false)
return ( return (
<Tooltip <Tooltip
text={ text={
@ -31,35 +31,39 @@ export function TipButton(props: {
noTap noTap
noFade noFade
> >
<Button <button
size={'sm'}
className={clsx(
'max-w-xs self-center',
isCompact && 'px-0 py-0',
disabled && 'hover:bg-inherit'
)}
color={'gray-white'}
onClick={onClick} onClick={onClick}
disabled={disabled} disabled={disabled}
className={clsx(
'text-greyscale-6 transition-transform hover:text-indigo-600 disabled:cursor-not-allowed',
!disabled ? 'hover:rotate-12' : ''
)}
onMouseOver={() => setHover(true)}
onMouseLeave={() => setHover(false)}
> >
<Col <Col className={clsx('relative', disabled ? 'opacity-30' : '')}>
className={ <TipJar
'relative items-center transition-transform hover:rotate-12 sm:flex-row' size={16}
} color={hover || userTipped ? '#4f46e5' : '#66667C'}
> fill={userTipped ? '#4f46e5' : 'none'}
<TipJar /> />
<div <div
className={clsx( className={clsx(
'bg-greyscale-5 absolute rounded-full text-white', ' absolute top-[3px] text-[0.5rem]',
tipDisplay.length > 2 userTipped ? 'text-white' : '',
? 'text-[0.4rem] sm:text-[0.5rem]' tipDisplay.length === 1
: 'text-[0.5rem]' ? 'left-[6px]'
: tipDisplay.length === 2
? 'left-[3.5px]'
: tipDisplay.length > 2
? 'left-[3px] top-[5px] text-[0.35rem]'
: ''
)} )}
> >
{totalTipped > 0 ? tipDisplay : ''} {totalTipped > 0 ? tipDisplay : ''}
</div> </div>
</Col> </Col>
</Button> </button>
</Tooltip> </Tooltip>
) )
} }

View File

@ -24,7 +24,7 @@ import { UserLink } from 'web/components/user-link'
import { CommentInput } from '../comment-input' import { CommentInput } from '../comment-input'
import { AwardBountyButton } from 'web/components/award-bounty-button' import { AwardBountyButton } from 'web/components/award-bounty-button'
import { ReplyIcon } from '@heroicons/react/solid' import { ReplyIcon } from '@heroicons/react/solid'
import { Button } from '../button' import { IconButton } from '../button'
import { ReplyToggle } from '../comments/reply-toggle' import { ReplyToggle } from '../comments/reply-toggle'
export type ReplyTo = { id: string; username: string } export type ReplyTo = { id: string; username: string }
@ -154,36 +154,50 @@ export function ParentFeedComment(props: {
numComments={numComments} numComments={numComments}
onClick={onSeeReplyClick} onClick={onSeeReplyClick}
/> />
<Row className="grow justify-end gap-2"> <CommentActions
{onReplyClick && ( onReplyClick={onReplyClick}
<Button comment={comment}
size={'sm'} showTip={showTip}
className={clsx( myTip={myTip}
'hover:bg-greyscale-2 mt-0 mb-1 max-w-xs px-0 py-0' totalTip={totalTip}
)} contract={contract}
color={'gray-white'} />
onClick={() => onReplyClick(comment)}
>
<ReplyIcon className="h-5 w-5" />
</Button>
)}
{showTip && (
<Tipper
comment={comment}
myTip={myTip ?? 0}
totalTip={totalTip ?? 0}
/>
)}
{(contract.openCommentBounties ?? 0) > 0 && (
<AwardBountyButton comment={comment} contract={contract} />
)}
</Row>
</Row> </Row>
</Col> </Col>
</Row> </Row>
) )
} }
export function CommentActions(props: {
onReplyClick?: (comment: ContractComment) => void
comment: ContractComment
showTip?: boolean
myTip?: number
totalTip?: number
contract: Contract
}) {
const { onReplyClick, comment, showTip, myTip, totalTip, contract } = props
return (
<Row className="grow justify-end gap-2">
{onReplyClick && (
<IconButton
size={'xs'}
className={clsx('mt-0 mb-1 max-w-xs')}
onClick={() => onReplyClick(comment)}
>
<ReplyIcon className="h-4 w-4" />
</IconButton>
)}
{showTip && (
<Tipper comment={comment} myTip={myTip ?? 0} totalTip={totalTip ?? 0} />
)}
{(contract.openCommentBounties ?? 0) > 0 && (
<AwardBountyButton comment={comment} contract={contract} />
)}
</Row>
)
}
export const FeedComment = memo(function FeedComment(props: { export const FeedComment = memo(function FeedComment(props: {
contract: Contract contract: Contract
comment: ContractComment comment: ContractComment
@ -233,30 +247,14 @@ export const FeedComment = memo(function FeedComment(props: {
content={content || text} content={content || text}
smallImage smallImage
/> />
<Row className="grow justify-end gap-2"> <CommentActions
{onReplyClick && ( onReplyClick={onReplyClick}
<Button comment={comment}
size={'sm'} showTip={showTip}
className={clsx( myTip={myTip}
'hover:bg-greyscale-2 mt-0 mb-1 max-w-xs px-0 py-0' totalTip={totalTip}
)} contract={contract}
color={'gray-white'} />
onClick={() => onReplyClick(comment)}
>
<ReplyIcon className="h-5 w-5" />
</Button>
)}
{showTip && (
<Tipper
comment={comment}
myTip={myTip ?? 0}
totalTip={totalTip ?? 0}
/>
)}
{(contract.openCommentBounties ?? 0) > 0 && (
<AwardBountyButton comment={comment} contract={contract} />
)}
</Row>
</Col> </Col>
</Row> </Row>
) )

View File

@ -0,0 +1,23 @@
export default function TipJar({
size = 18,
color = '#66667C',
strokeWidth = 1.5,
fill = 'none',
}) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 18 18"
width={size}
height={size}
fill={fill}
stroke={color}
strokeWidth={strokeWidth}
opacity={50}
>
<path d="M15.5,8.1v5.8c0,1.43-1.16,2.6-2.6,2.6H5.1c-1.44,0-2.6-1.16-2.6-2.6v-5.8c0-1.04,.89-3.25,1.5-4.1h0v-2c0-.55,.45-1,1-1H13c.55,0,1,.45,1,1v2h0c.61,.85,1.5,3.06,1.5,4.1Z" />
<line x1="4" y1="4" x2="9" y2="4" />
<line x1="11.26" y1="4" x2="14" y2="4" />
</svg>
)
}