mirror of
https://github.com/RealKai42/qwerty-learner.git
synced 2026-04-05 06:19:08 +08:00
feat: add author button
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
"@floating-ui/react": "^0.20.1",
|
||||
"@headlessui/react": "^1.7.13",
|
||||
"@headlessui/tailwindcss": "^0.1.2",
|
||||
"@radix-ui/react-avatar": "^1.0.4",
|
||||
"@radix-ui/react-dialog": "^1.0.5",
|
||||
"@radix-ui/react-progress": "^1.0.2",
|
||||
"@radix-ui/react-radio-group": "^1.1.2",
|
||||
|
||||
BIN
src/assets/kai.jpg
Normal file
BIN
src/assets/kai.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
31
src/components/ui/avatar.tsx
Normal file
31
src/components/ui/avatar.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
/* eslint-disable react/prop-types */
|
||||
import { cn } from '@/utils/ui'
|
||||
import * as AvatarPrimitive from '@radix-ui/react-avatar'
|
||||
import * as React from 'react'
|
||||
|
||||
const Avatar = React.forwardRef<React.ElementRef<typeof AvatarPrimitive.Root>, React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>>(
|
||||
({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Root ref={ref} className={cn('relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full', className)} {...props} />
|
||||
),
|
||||
)
|
||||
Avatar.displayName = AvatarPrimitive.Root.displayName
|
||||
|
||||
const AvatarImage = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Image>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
|
||||
>(({ className, ...props }, ref) => <AvatarPrimitive.Image ref={ref} className={cn('aspect-square h-full w-full', className)} {...props} />)
|
||||
AvatarImage.displayName = AvatarPrimitive.Image.displayName
|
||||
|
||||
const AvatarFallback = React.forwardRef<
|
||||
React.ElementRef<typeof AvatarPrimitive.Fallback>,
|
||||
React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<AvatarPrimitive.Fallback
|
||||
ref={ref}
|
||||
className={cn('flex h-full w-full items-center justify-center rounded-full bg-slate-100 dark:bg-slate-800', className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
|
||||
|
||||
export { Avatar, AvatarImage, AvatarFallback }
|
||||
21
src/pages/Typing/components/ResultScreen/AuthorButton.tsx
Normal file
21
src/pages/Typing/components/ResultScreen/AuthorButton.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import kai from '@/assets/kai.jpg'
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
|
||||
export const AuthorButton = () => {
|
||||
return (
|
||||
<TooltipProvider delayDuration={100}>
|
||||
<Tooltip defaultOpen>
|
||||
<TooltipTrigger>
|
||||
<Avatar className="h-8 w-8 shadow-lg" onClick={() => window.open('https://kaiyi.cool', '_blank')}>
|
||||
<AvatarImage src={kai} alt="Kai Homepage" />
|
||||
<AvatarFallback>Kai</AvatarFallback>
|
||||
</Avatar>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent className="cursor-pointer" onClick={() => window.open('https://kaiyi.cool', '_blank')}>
|
||||
<p>点击了解作者和更多作品 ❤️</p>
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
)
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { TypingContext, TypingStateActionType } from '../../store'
|
||||
import ShareButton from '../ShareButton'
|
||||
import { AuthorButton } from './AuthorButton'
|
||||
import ConclusionBar from './ConclusionBar'
|
||||
import RemarkRing from './RemarkRing'
|
||||
import WordChip from './WordChip'
|
||||
@@ -240,7 +241,8 @@ const ResultScreen = () => {
|
||||
<ConclusionBar mistakeLevel={mistakeLevel} mistakeCount={wrongWords.length} />
|
||||
</div>
|
||||
</div>
|
||||
<div className="ml-2 flex flex-col items-center justify-end gap-3.5 text-xl">
|
||||
<div className="ml-2 flex flex-col items-center justify-end gap-3 text-xl">
|
||||
<AuthorButton />
|
||||
{!isReviewMode && (
|
||||
<>
|
||||
<ShareButton />
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
import SharePicDialog from './SharePicDialog'
|
||||
import { recordShareAction } from '@/utils'
|
||||
import { flip, offset, shift, useFloating, useHover, useInteractions, useRole } from '@floating-ui/react'
|
||||
import { useCallback, useMemo, useState } from 'react'
|
||||
import IconShare2 from '~icons/tabler/share-2'
|
||||
|
||||
export default function ShareButton() {
|
||||
const [isShowSharePanel, setIsShowSharePanel] = useState(false)
|
||||
|
||||
const [showTranslation, setShowTranslation] = useState(true)
|
||||
const { x, y, strategy, refs, context } = useFloating({
|
||||
open: showTranslation,
|
||||
onOpenChange: setShowTranslation,
|
||||
middleware: [offset(11), shift(), flip()],
|
||||
placement: 'top-start',
|
||||
})
|
||||
const hover = useHover(context)
|
||||
const role = useRole(context, { role: 'tooltip' })
|
||||
const { getReferenceProps, getFloatingProps } = useInteractions([hover, role])
|
||||
|
||||
const randomChoose = useMemo(
|
||||
() => ({
|
||||
picRandom: Math.random(),
|
||||
@@ -36,31 +24,13 @@ export default function ShareButton() {
|
||||
{isShowSharePanel && <SharePicDialog showState={isShowSharePanel} setShowState={setIsShowSharePanel} randomChoose={randomChoose} />}
|
||||
|
||||
<button
|
||||
ref={refs.setReference}
|
||||
type="button"
|
||||
{...getReferenceProps()}
|
||||
className="cursor-pointer text-xl text-indigo-400"
|
||||
className="cursor-pointer text-xl text-gray-500 hover:text-indigo-400"
|
||||
onClick={onClickShare}
|
||||
title="分享你的成绩给朋友"
|
||||
>
|
||||
<IconShare2 />
|
||||
</button>
|
||||
|
||||
{showTranslation && (
|
||||
<div
|
||||
ref={refs.setFloating}
|
||||
className="tooltip z-10"
|
||||
style={{
|
||||
position: strategy,
|
||||
top: y ?? 0,
|
||||
left: x ?? 0,
|
||||
width: 'max-content',
|
||||
}}
|
||||
{...getFloatingProps()}
|
||||
>
|
||||
✨ 分享你的成绩给朋友
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
11
yarn.lock
11
yarn.lock
@@ -1503,6 +1503,17 @@
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-primitive" "1.0.3"
|
||||
|
||||
"@radix-ui/react-avatar@^1.0.4":
|
||||
version "1.0.4"
|
||||
resolved "https://registry.npmmirror.com/@radix-ui/react-avatar/-/react-avatar-1.0.4.tgz#de9a5349d9e3de7bbe990334c4d2011acbbb9623"
|
||||
integrity sha512-kVK2K7ZD3wwj3qhle0ElXhOjbezIgyl2hVvgwfIdexL3rN6zJmy5AqqIf+D31lxVppdzV8CjAfZ6PklkmInZLw==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.13.10"
|
||||
"@radix-ui/react-context" "1.0.1"
|
||||
"@radix-ui/react-primitive" "1.0.3"
|
||||
"@radix-ui/react-use-callback-ref" "1.0.1"
|
||||
"@radix-ui/react-use-layout-effect" "1.0.1"
|
||||
|
||||
"@radix-ui/react-collection@1.0.2":
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmmirror.com/@radix-ui/react-collection/-/react-collection-1.0.2.tgz"
|
||||
|
||||
Reference in New Issue
Block a user