-
{t('sponsoring.form.title')}
-
{t('sponsoring.form.instructions', { authorAddress: params.instructions.authorAddress, platformAddress: params.instructions.platformAddress, authorAmount: params.instructions.authorBtc, platformAmount: params.instructions.platformBtc })}
-
-
-
-
+
+
+ {t('sponsoring.form.title')}
+ {t('sponsoring.form.instructions', { authorAddress: params.instructions.authorAddress, platformAddress: params.instructions.platformAddress, authorAmount: params.instructions.authorBtc, platformAmount: params.instructions.platformBtc })}
+
+
+
+
+
)
}
@@ -175,29 +178,24 @@ function SponsoringFormView(params: {
diff --git a/components/reviewForms/ConnectRequiredCard.tsx b/components/reviewForms/ConnectRequiredCard.tsx
index eaf8e84..0bb19e2 100644
--- a/components/reviewForms/ConnectRequiredCard.tsx
+++ b/components/reviewForms/ConnectRequiredCard.tsx
@@ -1,16 +1,14 @@
import React from 'react'
+import { Button, Card } from '@/components/ui'
import { t } from '@/lib/i18n'
export function ConnectRequiredCard(params: { message: string; onConnect: () => void }): React.ReactElement {
return (
-
+
{params.message}
-
+
+
)
}
diff --git a/components/reviewForms/ReviewFormView.tsx b/components/reviewForms/ReviewFormView.tsx
index 7e99f09..f0dca86 100644
--- a/components/reviewForms/ReviewFormView.tsx
+++ b/components/reviewForms/ReviewFormView.tsx
@@ -1,4 +1,5 @@
import React from 'react'
+import { Button, ErrorState } from '@/components/ui'
import { t } from '@/lib/i18n'
import type { ReviewFormController } from './useReviewFormController'
@@ -60,32 +61,29 @@ function ReviewFormFields(params: { ctrl: ReviewFormController }): React.ReactEl
function ReviewFormActions(params: { loading: boolean; onCancel?: (() => void) | undefined }): React.ReactElement {
return (
-
{params.loading ? t('common.loading') : t('review.form.submit')}
-
- {params.onCancel ? (
-
+ {params.onCancel && (
+
{t('common.cancel')}
-
- ) : null}
+
+ )}
)
}
function ErrorBox({ message }: { message: string }): React.ReactElement {
- return (
-
- {message}
-
- )
+ return
}
function TextInput(params: {
diff --git a/components/reviewForms/ReviewTipFormView.tsx b/components/reviewForms/ReviewTipFormView.tsx
index d1f1949..23a2e19 100644
--- a/components/reviewForms/ReviewTipFormView.tsx
+++ b/components/reviewForms/ReviewTipFormView.tsx
@@ -1,4 +1,5 @@
import React from 'react'
+import { Button, ErrorState } from '@/components/ui'
import { t } from '@/lib/i18n'
import type { ReviewTipFormController } from './useReviewTipFormController'
@@ -57,30 +58,27 @@ function ReviewTipFormActions(params: {
}): React.ReactElement {
return (
-
{params.loading ? t('common.loading') : t('reviewTip.form.submit', { amount: params.amount })}
-
- {params.onCancel ? (
-
+ {params.onCancel && (
+
{t('common.cancel')}
-
- ) : null}
+
+ )}
)
}
function ErrorBox({ message }: { message: string }): React.ReactElement {
- return (
-
- {message}
-
- )
+ return
}
diff --git a/components/ui/MobileMenu.tsx b/components/ui/MobileMenu.tsx
index 5e0f93e..5cb7708 100644
--- a/components/ui/MobileMenu.tsx
+++ b/components/ui/MobileMenu.tsx
@@ -69,7 +69,6 @@ export function MobileMenu({ children, 'aria-label': ariaLabel }: MobileMenuProp
/>
{isOpen && (
setIsOpen(false)}
ariaLabel={ariaLabel ?? 'Mobile menu'}
>
@@ -102,44 +101,64 @@ function MobileMenuButton({
)
}
-function MobileMenuDrawer({
- isOpen,
+function MobileMenuOverlay({ onClose }: { onClose: () => void }): React.ReactElement {
+ return (
+
+ )
+}
+
+function MobileMenuContent({
+ onClose,
+ ariaLabel,
+ children,
+}: {
+ onClose: () => void
+ ariaLabel: string
+ children: ReactNode
+}): React.ReactElement {
+ return (
+
+ )
+}
+
+function MobileMenuDrawer({
onClose,
ariaLabel,
children,
}: {
- isOpen: boolean
onClose: () => void
ariaLabel: string
children: ReactNode
}): React.ReactElement {
return (
<>
-
-
+
+
+ {children}
+
>
)
}
diff --git a/components/ui/Modal.tsx b/components/ui/Modal.tsx
index 5822ccf..c1db0a0 100644
--- a/components/ui/Modal.tsx
+++ b/components/ui/Modal.tsx
@@ -43,7 +43,7 @@ function ModalHeader({
showCloseButton,
onClose,
}: {
- title?: string
+ title?: string | undefined
showCloseButton: boolean
onClose: () => void
}): React.ReactElement | null {
@@ -58,32 +58,28 @@ function ModalHeader({
)
}
-export function Modal({
- children,
- isOpen,
- onClose,
- title,
- size = 'medium',
- showCloseButton = true,
- 'aria-label': ariaLabel,
-}: ModalProps): React.ReactElement | null {
- const modalRef = useRef(null)
+function useModalFocus(modalRef: React.RefObject, isOpen: boolean): void {
const previousFocusRef = useRef(null)
useEffect(() => {
if (isOpen) {
- previousFocusRef.current = document.activeElement as HTMLElement
+ const { activeElement } = document
+ if (activeElement instanceof HTMLElement) {
+ previousFocusRef.current = activeElement
+ }
const firstFocusable = modalRef.current?.querySelector(
'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
- ) as HTMLElement | null
- if (firstFocusable) {
+ )
+ if (firstFocusable instanceof HTMLElement) {
firstFocusable.focus()
}
} else {
previousFocusRef.current?.focus()
}
- }, [isOpen])
+ }, [isOpen, modalRef])
+}
+function useModalKeyboard(isOpen: boolean, onClose: () => void): void {
useEffect(() => {
const handleEscape = (e: KeyboardEvent): void => {
if (e.key === 'Escape' && isOpen) {
@@ -101,13 +97,17 @@ export function Modal({
document.body.style.overflow = ''
}
}, [isOpen, onClose])
+}
- if (!isOpen) {
- return null
- }
-
- const sizeClasses = getSizeClasses(size)
-
+function ModalOverlay({
+ onClose,
+ ariaLabel,
+ children,
+}: {
+ onClose: () => void
+ ariaLabel: string | undefined
+ children: ReactNode
+}): React.ReactElement {
return (
-
e.stopPropagation()}
- >
-
- {children}
-
+ {children}
)
}
+
+function ModalContent({
+ modalRef,
+ sizeClasses,
+ title,
+ showCloseButton,
+ onClose,
+ children,
+}: {
+ modalRef: React.RefObject
+ sizeClasses: string
+ title?: string | undefined
+ showCloseButton: boolean
+ onClose: () => void
+ children: ReactNode
+}): React.ReactElement {
+ return (
+ e.stopPropagation()}
+ >
+
+ {children}
+
+ )
+}
+
+export function Modal({
+ children,
+ isOpen,
+ onClose,
+ title,
+ size = 'medium',
+ showCloseButton = true,
+ 'aria-label': ariaLabel,
+}: ModalProps): React.ReactElement | null {
+ const modalRef = useRef(null)
+ useModalFocus(modalRef, isOpen)
+ useModalKeyboard(isOpen, onClose)
+
+ if (!isOpen) {
+ return null
+ }
+
+ const sizeClasses = getSizeClasses(size)
+
+ return (
+
+
+ {children}
+
+
+ )
+}