Skip to content

Commit

Permalink
feat: donate button overlay
Browse files Browse the repository at this point in the history
Signed-off-by: Innei <[email protected]>
  • Loading branch information
Innei committed Jun 19, 2023
1 parent c633964 commit 0c73ce0
Show file tree
Hide file tree
Showing 6 changed files with 114 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/components/common/ToastCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const ToastCard: FC<{
className={clsx(
'relative w-full overflow-hidden rounded-xl shadow-out-sm',
'my-4 mr-4 px-4 py-5',
'bg-base-100/90 backdrop-blur-sm',
'bg-slate-50/90 backdrop-blur-sm dark:bg-neutral-900/90',
'border border-slate-100/80 dark:border-neutral-900/80',
'space-x-4',
'flex items-center',
Expand Down
12 changes: 3 additions & 9 deletions src/components/layout/header/internal/HeaderDrawerButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import type { SVGProps } from 'react'

import { CloseIcon } from '~/components/icons/close'
import { MotionButtonBase } from '~/components/ui/button'
import { DialogOverlay } from '~/components/ui/dlalog/DialogOverlay'
import { reboundPreset } from '~/constants/spring'
import { useIsClient } from '~/hooks/common/use-is-client'
import { jotaiStore } from '~/lib/store'
Expand Down Expand Up @@ -47,14 +48,7 @@ export const HeaderDrawerButton = () => {
<AnimatePresence>
{open && (
<>
<Dialog.Overlay asChild>
<motion.div
className="fixed inset-0 z-[11] bg-slate-50/80 backdrop-blur-sm dark:bg-slate-900/80"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
</Dialog.Overlay>
<DialogOverlay />

<Dialog.Content>
<motion.dialog
Expand All @@ -65,7 +59,7 @@ export const HeaderDrawerButton = () => {
>
<Dialog.DialogClose asChild>
<MotionButtonBase
className="absolute right-4 top-4 p-4"
className="z-9 absolute right-0 top-0 p-8"
onClick={() => {
setOpen(false)
}}
Expand Down
15 changes: 15 additions & 0 deletions src/components/ui/dlalog/DialogOverlay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import * as Dialog from '@radix-ui/react-dialog'
import { motion } from 'framer-motion'

export const DialogOverlay = () => {
return (
<Dialog.Overlay asChild>
<motion.div
className="fixed inset-0 z-[11] bg-slate-50/80 backdrop-blur-sm dark:bg-slate-900/80"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
/>
</Dialog.Overlay>
)
}
4 changes: 2 additions & 2 deletions src/components/ui/fab/FABContainer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,8 @@ export const FABBase = (
className={clsxm(
'mt-2 inline-flex h-10 w-10 items-center justify-center',
'border border-accent transition-all duration-300 hover:opacity-100 focus:opacity-100 focus:outline-none',
'rounded-xl border border-zinc-400/20 bg-base-100/80 shadow-lg backdrop-blur-lg dark:border-zinc-500/30 dark:bg-zinc-800/80 dark:text-zinc-200',
'bg-base-100 shadow-lg',
'rounded-xl border border-zinc-400/20 shadow-lg backdrop-blur-lg dark:border-zinc-500/30 dark:bg-zinc-800/80 dark:text-zinc-200',
'bg-slate-50/80 shadow-lg dark:bg-neutral-900/80',

className,
)}
Expand Down
4 changes: 4 additions & 0 deletions src/components/ui/markdown/markdown.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,8 @@
hr {
@apply mx-auto w-[60px];
}

a {
@apply break-all;
}
}
104 changes: 89 additions & 15 deletions src/components/widgets/shared/DonateButton.tsx
Original file line number Diff line number Diff line change
@@ -1,44 +1,118 @@
import { DialogContent, DialogPortal, Root } from '@radix-ui/react-dialog'
import { AnimatePresence, motion } from 'framer-motion'
import { atom, useAtomValue, useSetAtom } from 'jotai'
import type { HTMLMotionProps } from 'framer-motion'

import { MotionButtonBase } from '~/components/ui/button'
import { FloatPopover } from '~/components/ui/float-popover'
import { DialogOverlay } from '~/components/ui/dlalog/DialogOverlay'
import { useIsClient } from '~/hooks/common/use-is-client'
import { useConfig } from '~/hooks/data/use-config'
import { clsxm } from '~/utils/helper'

export const DonateButton = () => {
const isClient = useIsClient()
const {
module: { donate },
} = useConfig()

const overlayOpen = useAtomValue(overlayShowAtom)

if (!isClient) return null
if (!donate || !donate.enable) return null

return (
<FloatPopover TriggerComponent={TriggerComponent} placement="left-end">
<div className="flex flex-wrap space-x-2 center">
{donate.qrcode.map((src) => (
<img
src={src}
alt="donate"
className="h-[300px] max-h-[70vh]"
key={src}
/>
))}
</div>
</FloatPopover>
<>
<DonateButtonBelow />
<Root open={overlayOpen}>
<DialogPortal forceMount>
<div>
<AnimatePresence>
{overlayOpen && (
<>
<DialogOverlay />
<DialogContent className="fixed inset-0 z-[11] flex max-h-[70vh] max-w-[80vw] flex-wrap space-x-4 overflow-auto center">
{donate.qrcode.map((src) => (
<motion.img
exit={{ opacity: 0 }}
src={src}
alt="donate"
className="h-[300px] max-h-[70vh]"
key={src}
/>
))}

<DonateButtonTop />
</DialogContent>
</>
)}
</AnimatePresence>
</div>
</DialogPortal>
</Root>
</>
)
}

const TriggerComponent = () => {
const positionAtom = atom({
x: 0,
y: 0,
})
const overlayShowAtom = atom(false)

const DonateButtonBelow = () => {
const setPosition = useSetAtom(positionAtom)
const setOverlayShow = useSetAtom(overlayShowAtom)
return (
<DonateButtonInternal
onMouseEnter={(e) => {
const $el = e.target as HTMLButtonElement
const rect = $el.getBoundingClientRect()
setPosition({
x: rect.left,
y: rect.top,
})
setOverlayShow(true)
}}
/>
)
}

const DonateButtonTop = () => {
const setOverlayShow = useSetAtom(overlayShowAtom)
const buttonPos = useAtomValue(positionAtom)
return (
<DonateButtonInternal
style={{
position: 'fixed',
left: buttonPos.x,
top: buttonPos.y,
zIndex: 999,
margin: 0,
}}
onMouseLeave={() => {
setOverlayShow(false)
}}
/>
)
}

const DonateButtonInternal: Component<HTMLMotionProps<'button'>> = ({
className,

...props
}) => {
const {
module: { donate },
} = useConfig()

if (!donate) return null
return (
<MotionButtonBase
className="flex flex-col space-y-2"
className={clsxm('flex flex-col space-y-2', className)}
onClick={() => {
window.open(donate.link, '_blank')
}}
{...props}
>
<i className="icon-[material-symbols--coffee] text-[24px] opacity-80 duration-200 hover:text-uk-brown-dark hover:opacity-100" />
</MotionButtonBase>
Expand Down

1 comment on commit 0c73ce0

@vercel
Copy link

@vercel vercel bot commented on 0c73ce0 Jun 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

springtide – ./

springtide-innei.vercel.app
springtide.vercel.app
springtide-git-main-innei.vercel.app

Please sign in to comment.