modal-fix, media-query-fix
This commit is contained in:
parent
1d38c12509
commit
c6ae893403
|
@ -10,10 +10,15 @@ import { email, setEmail } from './sharedLogic'
|
|||
import { useSearchParams } from '@solidjs/router'
|
||||
import styles from './AuthModal.module.scss'
|
||||
|
||||
export type ConfirmEmailSearchParams = {
|
||||
access_token?: string
|
||||
token?: string
|
||||
}
|
||||
|
||||
export const EmailConfirm = () => {
|
||||
const { t } = useLocalize()
|
||||
const { hideModal } = useUI()
|
||||
const [, changeSearchParams] = useSearchParams()
|
||||
const [, changeSearchParams] = useSearchParams<ConfirmEmailSearchParams>()
|
||||
const { session, authError } = useSession()
|
||||
const [emailConfirmed, setEmailConfirmed] = createSignal(false)
|
||||
|
||||
|
|
|
@ -2,8 +2,7 @@ import { clsx } from 'clsx'
|
|||
import { Component, Show, createEffect, createMemo } from 'solid-js'
|
||||
import { Dynamic } from 'solid-js/web'
|
||||
|
||||
import { useUI } from '~/context/ui'
|
||||
import type { AuthModalMode } from '~/context/ui'
|
||||
import { AuthModalSource, useUI } from '~/context/ui'
|
||||
import { useLocalize } from '../../../context/localize'
|
||||
import { isMobile } from '../../../utils/media-query'
|
||||
import { ChangePasswordForm } from './ChangePasswordForm'
|
||||
|
@ -15,11 +14,24 @@ import { SendResetLinkForm } from './SendResetLinkForm'
|
|||
|
||||
import { useSearchParams } from '@solidjs/router'
|
||||
import styles from './AuthModal.module.scss'
|
||||
import { AuthModalSearchParams } from './types'
|
||||
|
||||
export type AuthModalMode =
|
||||
| 'login'
|
||||
| 'register'
|
||||
| 'confirm-email'
|
||||
| 'send-confirm-email'
|
||||
| 'send-reset-link'
|
||||
| 'change-password'
|
||||
|
||||
export type AuthModalSearchParams = {
|
||||
mode: AuthModalMode
|
||||
source?: AuthModalSource
|
||||
token?: string
|
||||
}
|
||||
|
||||
const AUTH_MODAL_MODES: Record<AuthModalMode, Component> = {
|
||||
login: LoginForm,
|
||||
register: RegisterForm,
|
||||
'login': LoginForm,
|
||||
'register': RegisterForm,
|
||||
'send-reset-link': SendResetLinkForm,
|
||||
'confirm-email': EmailConfirm,
|
||||
'send-confirm-email': SendEmailConfirm,
|
||||
|
|
|
@ -1,17 +0,0 @@
|
|||
import { AuthModalMode, AuthModalSource } from '~/context/ui'
|
||||
|
||||
export type AuthModalSearchParams = {
|
||||
mode: AuthModalMode
|
||||
source?: AuthModalSource
|
||||
token?: string
|
||||
}
|
||||
|
||||
export type ConfirmEmailSearchParams = {
|
||||
access_token?: string
|
||||
token?: string
|
||||
}
|
||||
|
||||
export type CreateChatSearchParams = {
|
||||
id: number
|
||||
}
|
||||
export type { AuthModalSource }
|
|
@ -155,8 +155,7 @@ export const Header = (props: Props) => {
|
|||
const loc = useLocation()
|
||||
const handleToggleMenuByLink = (event: MouseEvent, route: string) => {
|
||||
event.preventDefault()
|
||||
console.debug(route)
|
||||
console.debug(loc.pathname)
|
||||
console.debug(loc.pathname, route)
|
||||
if (!fixed()) return
|
||||
if (loc.pathname.startsWith(route) || loc.pathname.startsWith(`/${route}`)) {
|
||||
toggleFixed()
|
||||
|
@ -176,7 +175,7 @@ export const Header = (props: Props) => {
|
|||
<Modal
|
||||
variant={searchParams?.source ? 'narrow' : 'wide'}
|
||||
name="auth"
|
||||
allowClose={searchParams?.source !== 'authguard'}
|
||||
hideClose={Boolean(searchParams?.source === 'authguard')}
|
||||
noPadding={true}
|
||||
>
|
||||
<AuthModal />
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import { clsx } from 'clsx'
|
||||
import type { JSX } from 'solid-js'
|
||||
import { Show, createEffect, createMemo, createSignal } from 'solid-js'
|
||||
import { Show } from 'solid-js'
|
||||
import { useUI } from '~/context/ui'
|
||||
import { isPortrait } from '~/utils/media-query'
|
||||
import { useEscKeyDownHandler } from '../../../utils/useEscKeyDownHandler'
|
||||
import { Icon } from '../../_shared/Icon'
|
||||
|
||||
import { useNavigate } from '@solidjs/router'
|
||||
import { mediaMatches } from '~/utils/media-query'
|
||||
import styles from './Modal.module.scss'
|
||||
|
||||
interface Props {
|
||||
|
@ -16,44 +14,25 @@ interface Props {
|
|||
onClose?: () => void
|
||||
noPadding?: boolean
|
||||
maxHeight?: boolean
|
||||
allowClose?: boolean
|
||||
hideClose?: boolean
|
||||
isResponsive?: boolean
|
||||
}
|
||||
|
||||
export const Modal = (props: Props) => {
|
||||
const { modal, hideModal } = useUI()
|
||||
const [visible, setVisible] = createSignal(false)
|
||||
const allowClose = createMemo(() => props.allowClose !== false)
|
||||
const [isMobileView, setIsMobileView] = createSignal(false)
|
||||
const navigate = useNavigate()
|
||||
|
||||
const handleHide = () => {
|
||||
if (modal()) {
|
||||
if (allowClose()) {
|
||||
props.onClose?.()
|
||||
} else {
|
||||
navigate('/')
|
||||
}
|
||||
}
|
||||
console.debug('[Modal.handleHide]', modal())
|
||||
modal() && props.onClose?.()
|
||||
hideModal()
|
||||
}
|
||||
|
||||
useEscKeyDownHandler(handleHide)
|
||||
|
||||
createEffect(() => {
|
||||
setVisible(modal() === props.name)
|
||||
})
|
||||
|
||||
createEffect(() => {
|
||||
if (props.isResponsive) {
|
||||
setIsMobileView(!mediaMatches.sm)
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<Show when={visible()}>
|
||||
<Show when={modal() === props.name}>
|
||||
<div
|
||||
class={clsx(styles.backdrop, [styles[`modal-${props.name}` as keyof typeof styles]], {
|
||||
[styles.isMobile]: isMobileView(),
|
||||
[styles.isMobile]: props.isResponsive && isPortrait(),
|
||||
})}
|
||||
onClick={handleHide}
|
||||
>
|
||||
|
@ -68,7 +47,7 @@ export const Modal = (props: Props) => {
|
|||
onClick={(event) => event.stopPropagation()}
|
||||
>
|
||||
<div class={styles.modalInner}>{props.children}</div>
|
||||
<Show when={!isMobileView()}>
|
||||
<Show when={!isPortrait()}>
|
||||
<div class={styles.close} onClick={handleHide}>
|
||||
<Icon name="close" class={styles.icon} />
|
||||
</div>
|
||||
|
|
|
@ -14,7 +14,7 @@ export const ShareModal = (props: Props) => {
|
|||
const { t } = useLocalize()
|
||||
const { hideModal } = useUI()
|
||||
return (
|
||||
<Modal name="share" variant="medium" allowClose={true}>
|
||||
<Modal name="share" variant="medium">
|
||||
<h2>{t('Share publication')}</h2>
|
||||
<ShareLinks
|
||||
variant="inModal"
|
||||
|
|
|
@ -23,6 +23,10 @@ type InboxContextType = {
|
|||
sendMessage?: (args: MutationCreate_MessageArgs) => void
|
||||
}
|
||||
|
||||
export type CreateChatSearchParams = {
|
||||
inbox: number
|
||||
}
|
||||
|
||||
const InboxContext = createContext<InboxContextType>({} as InboxContextType)
|
||||
|
||||
export function useInbox() {
|
||||
|
|
|
@ -70,14 +70,6 @@ export const SnackbarProvider = (props: { children: JSX.Element }) => {
|
|||
return <SnackbarContext.Provider value={value}>{props.children}</SnackbarContext.Provider>
|
||||
}
|
||||
|
||||
export type AuthModalMode =
|
||||
| 'login'
|
||||
| 'register'
|
||||
| 'confirm-email'
|
||||
| 'send-confirm-email'
|
||||
| 'send-reset-link'
|
||||
| 'change-password'
|
||||
|
||||
export type AuthModalSource =
|
||||
| 'discussions'
|
||||
| 'vote'
|
||||
|
@ -135,7 +127,7 @@ type ConfirmMessage = {
|
|||
}
|
||||
|
||||
type UIContextType = {
|
||||
modal: Accessor<string>
|
||||
modal: Accessor<ModalType|null>
|
||||
showModal: (m: ModalType, source?: AuthModalSource) => void
|
||||
hideModal: () => void
|
||||
confirmMessage: Accessor<ConfirmMessage>
|
||||
|
@ -151,7 +143,7 @@ export function useUI() {
|
|||
|
||||
export const UIProvider = (props: { children: JSX.Element }) => {
|
||||
const [, setSearchParams] = useSearchParams<Record<string, string>>()
|
||||
const [modal, setModal] = createSignal<ModalType>('')
|
||||
const [modal, setModal] = createSignal<ModalType|null>(null)
|
||||
const [confirmMessage, setConfirmMessage] = createSignal<ConfirmMessage>({} as ConfirmMessage)
|
||||
|
||||
let resolveFn: (value: boolean) => void
|
||||
|
@ -172,6 +164,7 @@ export const UIProvider = (props: { children: JSX.Element }) => {
|
|||
}
|
||||
|
||||
const showModal = (modalType: ModalType, modalSource?: AuthModalSource) => {
|
||||
console.log('[context.ui] showModal()', modalType)
|
||||
if (modalSource) {
|
||||
setSearchParams({ source: modalSource })
|
||||
}
|
||||
|
@ -179,8 +172,9 @@ export const UIProvider = (props: { children: JSX.Element }) => {
|
|||
}
|
||||
|
||||
const hideModal = () => {
|
||||
setSearchParams({}, { replace: true })
|
||||
setModal('')
|
||||
console.log('[context.ui] hideModal()', modal())
|
||||
setTimeout(() => setModal(null), 1) // NOTE: modal rerender fix
|
||||
setSearchParams({source: undefined, m: undefined, mode: undefined})
|
||||
}
|
||||
|
||||
const [searchParams] = useSearchParams()
|
||||
|
@ -190,12 +184,14 @@ export const UIProvider = (props: { children: JSX.Element }) => {
|
|||
[modal, () => searchParams?.m || ''],
|
||||
([m1, m2]) => {
|
||||
const m = m1 || m2 || ''
|
||||
setModal((_) => m as ModalType)
|
||||
console.log('[context.ui] search params change', m)
|
||||
if (m) {
|
||||
showModal(m as ModalType)
|
||||
} else {
|
||||
setModal(null)
|
||||
}
|
||||
},
|
||||
{ defer: true },
|
||||
{},
|
||||
),
|
||||
)
|
||||
|
||||
|
|
|
@ -8,6 +8,9 @@ export const breakpoints = {
|
|||
xl: '1200px',
|
||||
xxl: '1400px',
|
||||
}
|
||||
export const isMobile = createMediaQuery('(max-width: 767px)')
|
||||
export const isDesktop = createMediaQuery('(min-width: 1200px)')
|
||||
export const isPortrait = createMediaQuery(`(max-width: ${breakpoints.sm})`)
|
||||
export const isMobile = createMediaQuery(`(max-width: ${breakpoints.md})`)
|
||||
export const isTablet = createMediaQuery(`(min-width: ${breakpoints.sm}, max-width: ${breakpoints.lg})`)
|
||||
export const isDesktop = createMediaQuery(`(min-width: ${breakpoints.md}, max-width: ${breakpoints.xl})`)
|
||||
export const isBig = createMediaQuery(`(min-width: ${breakpoints.xl})`)
|
||||
export const mediaMatches = createBreakpoints(breakpoints)
|
||||
|
|
Loading…
Reference in New Issue
Block a user