refactor: migrate dialogs & tooltips from reach-ui (#2314)

This commit is contained in:
Aman Harwara
2023-04-21 01:51:22 +05:30
committed by GitHub
parent 5a02003458
commit 9996dac00a
62 changed files with 387 additions and 563 deletions

View File

@@ -0,0 +1,35 @@
import { Dialog, DialogStoreProps, useDialogStore } from '@ariakit/react'
import { classNames } from '@standardnotes/snjs'
import { ReactNode } from 'react'
const AlertDialog = ({
children,
closeDialog,
className,
...props
}: { children: ReactNode; closeDialog: () => void; className?: string } & Partial<DialogStoreProps>) => {
const dialog = useDialogStore({
open: true,
...props,
})
return (
<Dialog store={dialog} role="alertdialog" className="h-full w-full" backdropProps={{ className: '!z-modal' }}>
<div
className="absolute z-0 h-full w-full bg-passive-5 opacity-0 md:opacity-75"
role="presentation"
onClick={closeDialog}
/>
<div
className={classNames(
'absolute top-1/2 left-1/2 z-[1] max-w-[600px] -translate-x-1/2 -translate-y-1/2 rounded border border-border bg-default px-6 py-5 shadow-xl',
className,
)}
>
{children}
</div>
</Dialog>
)
}
export default AlertDialog

View File

@@ -4,7 +4,6 @@ import { Component } from 'react'
import ApplicationView from '@/Components/ApplicationView/ApplicationView'
import { WebOrDesktopDevice } from '@/Application/Device/WebOrDesktopDevice'
import { ApplicationGroupEvent, ApplicationGroupEventData, DeinitSource } from '@standardnotes/snjs'
import { DialogContent, DialogOverlay } from '@reach/dialog'
import { getPlatformString, isDesktopApplication } from '@/Utils'
import DeallocateHandler from '../DeallocateHandler/DeallocateHandler'
@@ -23,6 +22,20 @@ type State = {
deviceDestroyed?: boolean
}
const renderDialog = (message: string) => {
return (
<div className="flex h-full w-full items-center justify-center bg-passive-5" role="alert">
<div
className={
'challenge-modal shadow-overlay-light relative flex max-w-125 flex-col items-center rounded border border-solid border-border bg-default p-6'
}
>
<div className="text-base lg:text-xs">{message}</div>
</div>
</div>
)
}
class ApplicationGroupView extends Component<Props, State> {
applicationObserverRemover?: () => void
private group?: ApplicationGroup
@@ -83,21 +96,6 @@ class ApplicationGroupView extends Component<Props, State> {
}
override render() {
const renderDialog = (message: string) => {
return (
<DialogOverlay className={'sn-component challenge-modal-overlay'}>
<DialogContent
aria-label="Switching workspace"
className={
'challenge-modal shadow-overlay-light relative flex flex-col items-center rounded border border-solid border-border bg-default p-8'
}
>
<div className="text-base lg:text-xs">{message}</div>
</DialogContent>
</DialogOverlay>
)
}
if (this.state.deviceDestroyed) {
const message = `Secure memory has destroyed this application instance. ${
isDesktopApplication()

View File

@@ -2,7 +2,7 @@ import { FunctionComponent } from 'react'
const DotOrgNotice: FunctionComponent = () => {
return (
<div className="z-modal flex h-30 w-full w-full items-center bg-danger text-center text-info-contrast">
<div className="z-modal flex h-30 w-full items-center bg-danger text-center text-info-contrast">
<div className="w-full text-center text-xl font-bold">
app.standardnotes.org is no longer maintained. Please switch to{' '}
<a className="underline" href="https://app.standardnotes.com">

View File

@@ -71,7 +71,6 @@ const ChallengeModal: FunctionComponent<Props> = ({
const [isSubmitting, setIsSubmitting] = useState(false)
const [isProcessing, setIsProcessing] = useState(false)
const [, setProcessingPrompts] = useState<ChallengePrompt[]>([])
const [bypassModalFocusLock, setBypassModalFocusLock] = useState(false)
const shouldShowForgotPasscode = [ChallengeReason.ApplicationUnlock, ChallengeReason.Migration].includes(
challenge.reason,
@@ -238,23 +237,17 @@ const ChallengeModal: FunctionComponent<Props> = ({
})
return (
<ModalOverlay
isOpen={true}
className={`sn-component p-0 ${isFullScreenBlocker ? 'bg-passive-5' : ''}`}
onDismiss={cancelChallenge}
dangerouslyBypassFocusLock={bypassModalFocusLock}
key={challenge.id}
ref={setModalElement}
>
<ModalOverlay isOpen={true} key={challenge.id} ref={setModalElement}>
<Modal
title="Authenticate"
close={cancelChallenge}
className={{
content: classNames(
'challenge-modal relative m-0 flex h-full w-full flex-col items-center rounded border-solid border-border bg-default p-0 md:h-auto md:!w-auto md:border',
'sn-component challenge-modal relative m-0 flex h-full w-full flex-col items-center rounded border-solid border-border bg-default p-0 md:h-auto md:!w-max md:border',
!isMobileScreen && 'shadow-overlay-light',
isMobileOverlay && 'shadow-overlay-light border border-solid border-border',
),
backdrop: isFullScreenBlocker ? 'bg-passive-5' : '',
}}
customHeader={<></>}
customFooter={<></>}
@@ -319,7 +312,6 @@ const ChallengeModal: FunctionComponent<Props> = ({
<Button
className="flex min-w-76 items-center justify-center"
onClick={() => {
setBypassModalFocusLock(true)
application.alertService
.confirm(
'If you forgot your local passcode, your only option is to clear your local data from this device and sign back in to your account.',
@@ -333,9 +325,6 @@ const ChallengeModal: FunctionComponent<Props> = ({
}
})
.catch(console.error)
.finally(() => {
setBypassModalFocusLock(false)
})
}}
>
<Icon type="help" className="mr-2 text-neutral" />

View File

@@ -223,7 +223,7 @@ const ChangeEditorMenu: FunctionComponent<ChangeEditorMenuProps> = ({
)
})}
</Menu>
<ModalOverlay isOpen={showSuperImporter} onDismiss={closeSuperNoteImporter}>
<ModalOverlay isOpen={showSuperImporter}>
{note && (
<SuperNoteImporter
note={note}

View File

@@ -180,7 +180,7 @@ const ChangeMultipleMenu = ({ application, notes, setDisableClickOutside }: Prop
</Fragment>
))}
</Menu>
<ModalOverlay isOpen={showSuperImporter} onDismiss={closeCurrentSuperNoteImporter}>
<ModalOverlay isOpen={showSuperImporter}>
{confirmationQueue[0] && (
<SuperNoteImporter
note={confirmationQueue[0]}

View File

@@ -1,11 +1,11 @@
import { observer } from 'mobx-react-lite'
import { ViewControllerManager } from '@Controllers/ViewControllerManager'
import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
import { useCallback, useRef } from 'react'
import { STRING_DELETE_ACCOUNT_CONFIRMATION } from '@/Constants/Strings'
import Button from '@/Components/Button/Button'
import { WebApplication } from '@/Application/Application'
import Icon from '../Icon/Icon'
import AlertDialog from '../AlertDialog/AlertDialog'
type Props = {
viewControllerManager: ViewControllerManager
@@ -25,37 +25,26 @@ const ConfirmDeleteAccountModal = ({ application, viewControllerManager }: Props
}, [application.user, closeDialog])
return (
<AlertDialog onDismiss={closeDialog} leastDestructiveRef={cancelRef} className="max-w-[600px] p-0">
<div className="sk-modal-content">
<div className="sn-component">
<div className="sk-panel">
<div className="sk-panel-content">
<div className="sk-panel-section">
<AlertDialogLabel className="flex items-center justify-between text-lg font-bold">
Delete account?
<button className="rounded p-1 font-bold hover:bg-contrast" onClick={closeDialog}>
<Icon type="close" />
</button>
</AlertDialogLabel>
<AlertDialogDescription className="sk-panel-row">
<div>
<p className="text-base text-foreground lg:text-sm">{STRING_DELETE_ACCOUNT_CONFIRMATION}</p>
</div>
</AlertDialogDescription>
<div className="my-1 mt-4 flex justify-end gap-2">
<Button ref={cancelRef} onClick={closeDialog}>
Cancel
</Button>
<Button primary colorStyle="danger" onClick={confirm}>
Delete my account for good
</Button>
</div>
</div>
</div>
</div>
<AlertDialog closeDialog={closeDialog}>
<div className="flex items-center justify-between text-lg font-bold">
Delete account?
<button className="rounded p-1 font-bold hover:bg-contrast" onClick={closeDialog}>
<Icon type="close" />
</button>
</div>
<div className="sk-panel-row">
<div>
<p className="text-base text-foreground lg:text-sm">{STRING_DELETE_ACCOUNT_CONFIRMATION}</p>
</div>
</div>
<div className="mt-4 flex justify-end gap-2">
<Button ref={cancelRef} onClick={closeDialog}>
Cancel
</Button>
<Button primary colorStyle="danger" onClick={confirm}>
Delete my account for good
</Button>
</div>
</AlertDialog>
)
}

View File

@@ -1,5 +1,4 @@
import { FunctionComponent, useCallback, useEffect, useRef, useState } from 'react'
import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
import { STRING_SIGN_OUT_CONFIRMATION } from '@/Constants/Strings'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
@@ -8,6 +7,7 @@ import { ApplicationGroup } from '@/Application/ApplicationGroup'
import { isDesktopApplication } from '@/Utils'
import Button from '@/Components/Button/Button'
import Icon from '../Icon/Icon'
import AlertDialog from '../AlertDialog/AlertDialog'
type Props = {
application: WebApplication
@@ -42,75 +42,65 @@ const ConfirmSignoutModal: FunctionComponent<Props> = ({ application, viewContro
}, [application, closeDialog, deleteLocalBackups])
return (
<AlertDialog onDismiss={closeDialog} leastDestructiveRef={cancelRef} className="max-w-[600px] p-0">
<div className="sk-modal-content">
<div className="sn-component">
<div className="sk-panel">
<div className="sk-panel-content">
<div className="sk-panel-section">
<AlertDialogLabel className="flex items-center justify-between text-lg font-bold">
Sign out workspace?
<button className="rounded p-1 font-bold hover:bg-contrast" onClick={closeDialog}>
<Icon type="close" />
</button>
</AlertDialogLabel>
<AlertDialogDescription className="sk-panel-row">
<div>
<p className="text-base text-foreground lg:text-sm">{STRING_SIGN_OUT_CONFIRMATION}</p>
{showWorkspaceWarning && (
<>
<br />
<p className="text-base text-foreground lg:text-sm">
<strong>Note: </strong>
Because you have other workspaces signed in, this sign out may leave logs and other metadata
of your session on this device. For a more robust sign out that performs a hard clear of all
app-related data, use the <i>Sign out all workspaces</i> option under <i>Switch workspace</i>.
</p>
</>
)}
</div>
</AlertDialogDescription>
{localBackupsCount > 0 && (
<div className="flex">
<div className="sk-panel-row"></div>
<label className="flex items-center">
<input
type="checkbox"
checked={deleteLocalBackups}
onChange={(event) => {
setDeleteLocalBackups((event.target as HTMLInputElement).checked)
}}
/>
<span className="ml-2">
Delete {localBackupsCount} local backup file
{localBackupsCount > 1 ? 's' : ''}
</span>
</label>
<button
className="sk-a ml-1.5 cursor-pointer rounded p-0 capitalize"
onClick={() => {
application.desktopDevice?.viewlocalBackups()
}}
>
View backup files
</button>
</div>
)}
<div className="my-1 mt-4 flex justify-end gap-2">
<Button ref={cancelRef} onClick={closeDialog}>
Cancel
</Button>
<Button primary colorStyle="danger" onClick={confirm}>
{application.hasAccount() ? 'Sign Out' : 'Delete Workspace'}
</Button>
</div>
</div>
</div>
</div>
<AlertDialog closeDialog={closeDialog}>
<div className="flex items-center justify-between text-lg font-bold">
Sign out workspace?
<button className="rounded p-1 font-bold hover:bg-contrast" onClick={closeDialog}>
<Icon type="close" />
</button>
</div>
<div className="sk-panel-row">
<div>
<p className="text-base text-foreground lg:text-sm">{STRING_SIGN_OUT_CONFIRMATION}</p>
{showWorkspaceWarning && (
<>
<br />
<p className="text-base text-foreground lg:text-sm">
<strong>Note: </strong>
Because you have other workspaces signed in, this sign out may leave logs and other metadata of your
session on this device. For a more robust sign out that performs a hard clear of all app-related data,
use the <i>Sign out all workspaces</i> option under <i>Switch workspace</i>.
</p>
</>
)}
</div>
</div>
{localBackupsCount > 0 && (
<div className="flex">
<div className="sk-panel-row"></div>
<label className="flex items-center">
<input
type="checkbox"
checked={deleteLocalBackups}
onChange={(event) => {
setDeleteLocalBackups((event.target as HTMLInputElement).checked)
}}
/>
<span className="ml-2">
Delete {localBackupsCount} local backup file
{localBackupsCount > 1 ? 's' : ''}
</span>
</label>
<button
className="sk-a ml-1.5 cursor-pointer rounded p-0 capitalize"
onClick={() => {
application.desktopDevice?.viewlocalBackups()
}}
>
View backup files
</button>
</div>
)}
<div className="mt-4 flex justify-end gap-2">
<Button ref={cancelRef} onClick={closeDialog}>
Cancel
</Button>
<Button primary colorStyle="danger" onClick={confirm}>
{application.hasAccount() ? 'Sign Out' : 'Delete Workspace'}
</Button>
</div>
</AlertDialog>
)
}

View File

@@ -106,10 +106,10 @@ const AddItemMenuButton = ({
</MenuItem>
</Menu>
</Popover>
<ModalOverlay isOpen={captureType === 'photo'} onDismiss={closeCaptureModal}>
<ModalOverlay isOpen={captureType === 'photo'}>
<PhotoCaptureModal filesController={filesController} close={closeCaptureModal} />
</ModalOverlay>
<ModalOverlay isOpen={captureType === 'video'} onDismiss={closeCaptureModal}>
<ModalOverlay isOpen={captureType === 'video'}>
<VideoCaptureModal filesController={filesController} close={closeCaptureModal} />
</ModalOverlay>
</>

View File

@@ -1,12 +1,12 @@
import { ListboxArrow, ListboxInput, ListboxList, ListboxPopover } from '@reach/listbox'
import '@reach/listbox/styles.css'
import { VisuallyHidden } from '@reach/visually-hidden'
import { FunctionComponent } from 'react'
import Icon from '@/Components/Icon/Icon'
import { DropdownItem } from './DropdownItem'
import StyledListboxButton from './StyledListboxButton'
import StyledListboxOption from './StyledListboxOption'
import { classNames } from '@standardnotes/snjs'
import { VisuallyHidden } from '@ariakit/react'
type DropdownProps = {
id: string

View File

@@ -285,13 +285,7 @@ FilePreviewModal.displayName = 'FilePreviewModal'
const FilePreviewModalWrapper: FunctionComponent<Props> = ({ application, viewControllerManager }) => {
return (
<ModalOverlay
className="sn-component p-0"
aria-label="File preview modal"
isOpen={viewControllerManager.filePreviewModalController.isOpen}
onDismiss={viewControllerManager.filePreviewModalController.dismiss}
dangerouslyBypassScrollLock
>
<ModalOverlay aria-label="File preview modal" isOpen={viewControllerManager.filePreviewModalController.isOpen}>
<FilePreviewModal application={application} viewControllerManager={viewControllerManager} />
</ModalOverlay>
)

View File

@@ -33,7 +33,7 @@ const ImportModal = ({ importModalController }: { importModalController: ImportM
)
return (
<ModalOverlay isOpen={isVisible} onDismiss={close}>
<ModalOverlay isOpen={isVisible}>
<Modal title="Import" close={close} actions={modalActions}>
<div className="px-4 py-4">
{!files.length && <ImportModalInitialPage setFiles={setFiles} />}

View File

@@ -1,6 +1,5 @@
import { useMediaQuery, MutuallyExclusiveMediaQueryBreakpoints } from '@/Hooks/useMediaQuery'
import { isIOS } from '@/Utils'
import { DialogContent } from '@reach/dialog'
import { classNames } from '@standardnotes/snjs'
import { ReactNode, useMemo, useRef, useState } from 'react'
import Button from '../Button/Button'
@@ -26,6 +25,7 @@ type Props = {
className?: {
content?: string
description?: string
backdrop?: string
}
customHeader?: ReactNode
disableCustomHeader?: boolean
@@ -95,13 +95,17 @@ const Modal = ({
return (
<>
<ModalAndroidBackHandler close={close} />
<DialogContent
tabIndex={0}
<div
className={classNames('absolute z-0 h-full w-full bg-passive-5 opacity-0 md:opacity-75', className?.backdrop)}
role="presentation"
onClick={close}
/>
<div
className={classNames(
'm-0 flex h-full w-full flex-col border-solid border-border bg-default p-0 md:h-auto md:max-h-[85vh] md:w-160 md:rounded md:border md:shadow-main',
className.content,
'absolute z-[1] m-0 flex h-full w-full flex-col border-solid border-border bg-default p-0 md:h-auto md:max-h-[85vh] md:w-160 md:rounded md:border md:shadow-main',
'md:left-1/2 md:top-1/2 md:-translate-x-1/2 md:-translate-y-1/2 md:transform',
className?.content,
)}
aria-label={title}
>
{customHeader && !disableCustomHeader ? (
customHeader
@@ -218,7 +222,7 @@ const Modal = ({
))}
</div>
)}
</DialogContent>
</div>
</>
)
}

View File

@@ -1,35 +1,37 @@
import { mergeRefs } from '@/Hooks/mergeRefs'
import { DialogOverlay, DialogOverlayProps } from '@reach/dialog'
import { classNames } from '@standardnotes/snjs'
import { Dialog, useDialogStore } from '@ariakit/react'
import { ForwardedRef, forwardRef, ReactNode } from 'react'
import { useModalAnimation } from '../Modal/useModalAnimation'
type Props = {
isOpen: boolean
onDismiss?: () => void
children: ReactNode
className?: string
} & DialogOverlayProps
}
const ModalOverlay = forwardRef(
({ isOpen, onDismiss, children, className, ...props }: Props, ref: ForwardedRef<HTMLDivElement>) => {
const [isMounted, setElement] = useModalAnimation(isOpen)
const ModalOverlay = forwardRef(({ isOpen, children, ...props }: Props, ref: ForwardedRef<HTMLDivElement>) => {
const [isMounted, setElement] = useModalAnimation(isOpen)
const dialog = useDialogStore({
open: isMounted,
})
if (!isMounted) {
return null
}
if (!isMounted) {
return null
}
return (
<DialogOverlay
className={classNames('p-0 md:px-0 md:opacity-100', className)}
onDismiss={onDismiss}
ref={mergeRefs([setElement, ref])}
{...props}
>
{children}
</DialogOverlay>
)
},
)
return (
<Dialog
tabIndex={0}
className="h-full w-full"
backdropProps={{
className: '!z-modal',
}}
ref={mergeRefs([setElement, ref])}
store={dialog}
{...props}
>
{children}
</Dialog>
)
})
export default ModalOverlay

View File

@@ -395,7 +395,7 @@ const NotesOptions = ({
</>
) : null}
<ModalOverlay isOpen={showExportSuperModal} onDismiss={closeSuperExportModal}>
<ModalOverlay isOpen={showExportSuperModal}>
<SuperExportModal exportNotes={downloadSelectedItems} close={closeSuperExportModal} />
</ModalOverlay>
</>

View File

@@ -1,10 +1,10 @@
import { useCallback, useRef } from 'react'
import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
import { WebApplication } from '@/Application/Application'
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { observer } from 'mobx-react-lite'
import Button from '@/Components/Button/Button'
import Icon from '../Icon/Icon'
import AlertDialog from '../AlertDialog/AlertDialog'
type Props = {
application: WebApplication
@@ -27,37 +27,26 @@ const ConfirmOtherSessionsSignOut = observer(({ application, viewControllerManag
}, [application, closeDialog])
return (
<AlertDialog onDismiss={closeDialog} leastDestructiveRef={cancelRef} className="max-w-[600px] p-0">
<div className="sk-modal-content">
<div className="sn-component">
<div className="sk-panel">
<div className="sk-panel-content">
<div className="sk-panel-section">
<AlertDialogLabel className="flex items-center justify-between text-lg font-bold capitalize">
End all other sessions?
<button className="rounded p-1 font-bold hover:bg-contrast" onClick={closeDialog}>
<Icon type="close" />
</button>
</AlertDialogLabel>
<AlertDialogDescription className="sk-panel-row">
<p className="text-base text-foreground lg:text-sm">
This action will sign out all other devices signed into your account, and remove your data from
those devices when they next regain connection to the internet. You may sign back in on those
devices at any time.
</p>
</AlertDialogDescription>
<div className="my-1 mt-4 flex justify-end gap-2">
<Button ref={cancelRef} onClick={closeDialog}>
Cancel
</Button>
<Button primary colorStyle="danger" onClick={confirm}>
End Sessions
</Button>
</div>
</div>
</div>
</div>
</div>
<AlertDialog closeDialog={closeDialog}>
<div className="flex items-center justify-between text-lg font-bold capitalize">
End all other sessions?
<button className="rounded p-1 font-bold hover:bg-contrast" onClick={closeDialog}>
<Icon type="close" />
</button>
</div>
<div className="sk-panel-row">
<p className="text-base text-foreground lg:text-sm">
This action will sign out all other devices signed into your account, and remove your data from those devices
when they next regain connection to the internet. You may sign back in on those devices at any time.
</p>
</div>
<div className="mt-4 flex justify-end gap-2">
<Button ref={cancelRef} onClick={closeDialog}>
Cancel
</Button>
<Button primary colorStyle="danger" onClick={confirm}>
End Sessions
</Button>
</div>
</AlertDialog>
)

View File

@@ -1,4 +1,3 @@
import { VisuallyHidden } from '@reach/visually-hidden'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback, useMemo } from 'react'
import Icon from '@/Components/Icon/Icon'
@@ -6,6 +5,7 @@ import { NotesController } from '@/Controllers/NotesController/NotesController'
import { classNames } from '@standardnotes/utils'
import { keyboardStringForShortcut, PIN_NOTE_COMMAND } from '@standardnotes/ui-services'
import { useCommandService } from '../CommandProvider'
import { VisuallyHidden } from '@ariakit/react'
type Props = {
className?: string

View File

@@ -58,12 +58,12 @@ const Credentials: FunctionComponent<Props> = ({ application }: Props) => {
Current password was set on <span className="font-bold">{passwordCreatedOn}</span>
</Text>
<Button className="mt-3 min-w-20" label="Change password" onClick={presentPasswordWizard} />
<ModalOverlay isOpen={isChangeEmailDialogOpen} onDismiss={closeChangeEmailDialog}>
<ModalOverlay isOpen={isChangeEmailDialogOpen}>
<ChangeEmail onCloseDialog={closeChangeEmailDialog} application={application} />
</ModalOverlay>
</PreferencesSegment>
</PreferencesGroup>
<ModalOverlay isOpen={shouldShowPasswordWizard} onDismiss={dismissPasswordWizard}>
<ModalOverlay isOpen={shouldShowPasswordWizard}>
<PasswordWizard application={application} dismissModal={dismissPasswordWizard} />
</ModalOverlay>
</>

View File

@@ -48,7 +48,7 @@ const SubscriptionSharing: FunctionComponent<Props> = ({ application, viewContro
{!subscriptionState.allInvitationsUsed && (
<Button className="min-w-20" label="Invite" onClick={() => setIsInviteDialogOpen(true)} />
)}
<ModalOverlay isOpen={isInviteDialogOpen} onDismiss={closeInviteDialog}>
<ModalOverlay isOpen={isInviteDialogOpen}>
<Invite
onCloseDialog={closeInviteDialog}
application={application}

View File

@@ -89,13 +89,10 @@ const SmartViews = ({ application, featuresController }: Props) => {
)}
</PreferencesSegment>
</PreferencesGroup>
<ModalOverlay isOpen={!!editSmartViewModalController.view} onDismiss={editSmartViewModalController.closeDialog}>
<ModalOverlay isOpen={!!editSmartViewModalController.view}>
<EditSmartViewModal controller={editSmartViewModalController} platform={application.platform} />
</ModalOverlay>
<ModalOverlay
isOpen={addSmartViewModalController.isAddingSmartView}
onDismiss={addSmartViewModalController.closeModal}
>
<ModalOverlay isOpen={addSmartViewModalController.isAddingSmartView}>
<AddSmartViewModal controller={addSmartViewModalController} platform={application.platform} />
</ModalOverlay>
</>

View File

@@ -115,7 +115,7 @@ const TwoFactorAuthView: FunctionComponent<Props> = ({ auth, application }) => {
</PreferencesSegment>
)}
</PreferencesGroup>
<ModalOverlay isOpen={shouldShowActivationModal} onDismiss={closeActivationModal}>
<ModalOverlay isOpen={shouldShowActivationModal}>
<Modal title={activationModalTitle} close={closeActivationModal} actions={activationModalActions}>
{shouldShowActivationModal && <TwoFactorActivationView activation={auth.status} />}
</Modal>

View File

@@ -20,11 +20,7 @@ const PreferencesViewWrapper: FunctionComponent<PreferencesViewWrapperProps> = (
}, [commandService, viewControllerManager])
return (
<ModalOverlay
isOpen={viewControllerManager.preferencesController.isOpen}
onDismiss={viewControllerManager.preferencesController.closePreferences}
className="p-0"
>
<ModalOverlay isOpen={viewControllerManager.preferencesController.isOpen}>
<PreferencesView
closePreferences={() => viewControllerManager.preferencesController.closePreferences()}
application={application}

View File

@@ -1,4 +1,4 @@
import { AlertDialog } from '@reach/alert-dialog'
import AlertDialog from '../AlertDialog/AlertDialog'
import { FunctionComponent, useRef } from 'react'
import { WebApplication } from '@/Application/Application'
import { PremiumFeatureModalType } from './PremiumFeatureModalType'
@@ -30,9 +30,9 @@ const PremiumFeaturesModal: FunctionComponent<Props> = ({
}
return (
<AlertDialog leastDestructiveRef={ctaButtonRef} className="p-0">
<AlertDialog closeDialog={onClose} className="!max-w-89">
<div tabIndex={-1} className="sn-component bg-default">
<div tabIndex={0} className="max-w-89 rounded bg-default p-4 shadow-main">
<div tabIndex={0}>
{type === PremiumFeatureModalType.UpgradePrompt && (
<UpgradePrompt
featureName={featureName}

View File

@@ -1,5 +1,4 @@
import Icon from '@/Components/Icon/Icon'
import { AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
export const SuccessPrompt = ({
ctaRef,
@@ -10,7 +9,7 @@ export const SuccessPrompt = ({
}) => {
return (
<>
<AlertDialogLabel>
<div>
<div className="flex justify-end p-1">
<button
className="flex cursor-pointer border-0 bg-transparent p-0"
@@ -27,11 +26,9 @@ export const SuccessPrompt = ({
<Icon className={'h-24 w-24 px-7 py-2 text-[50px]'} size={'custom'} type={'🎉'} />
</div>
<div className="mb-1 text-center text-lg font-bold">Your purchase was successful!</div>
</AlertDialogLabel>
</div>
<AlertDialogDescription className="mb-2 px-4.5 text-center text-sm text-passive-1">
Enjoy your new powered up experience.
</AlertDialogDescription>
<div className="mb-2 px-4.5 text-center text-sm text-passive-1">Enjoy your new powered up experience.</div>
<div className="p-4">
<button

View File

@@ -1,4 +1,3 @@
import { AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
import { useCallback } from 'react'
import { WebApplication } from '@/Application/Application'
import { openSubscriptionDashboard } from '@/Utils/ManageSubscription'
@@ -29,7 +28,7 @@ export const UpgradePrompt = ({
return (
<>
<AlertDialogLabel>
<div>
<div className="flex justify-end p-1">
<button
className="flex cursor-pointer border-0 bg-transparent p-0"
@@ -46,8 +45,8 @@ export const UpgradePrompt = ({
<Icon className={`h-12 w-12 ${PremiumFeatureIconClass}`} size={'custom'} type={PremiumFeatureIconName} />
</div>
<div className="mb-1 text-center text-lg font-bold">Enable Advanced Features</div>
</AlertDialogLabel>
<AlertDialogDescription className="mb-2 px-4.5 text-center text-sm text-passive-1">
</div>
<div className="mb-2 px-4.5 text-center text-sm text-passive-1">
{featureName && (
<span>
To take advantage of <span className="font-semibold">{featureName}</span> and other advanced features,
@@ -74,7 +73,7 @@ export const UpgradePrompt = ({
</ul>
</div>
)}
</AlertDialogDescription>
</div>
<div className="p-4">
<button

View File

@@ -1,6 +1,6 @@
import { getPlatformString } from '@/Utils'
import { classNames } from '@standardnotes/utils'
import { DialogOverlay, DialogContent } from '@reach/dialog'
import { Dialog, useDialogStore } from '@ariakit/react'
import { ForwardedRef, forwardRef, ReactNode } from 'react'
type Props = {
@@ -9,23 +9,36 @@ type Props = {
}
const HistoryModalDialog = forwardRef(({ children, onDismiss }: Props, ref: ForwardedRef<HTMLDivElement>) => {
const dialog = useDialogStore({
open: true,
})
return (
<DialogOverlay
className={`sn-component ${getPlatformString()}`}
onDismiss={onDismiss}
<Dialog
store={dialog}
aria-label="Note revision history"
ref={ref}
backdropProps={{
className: '!z-modal',
}}
className="h-full w-full"
>
<DialogContent
aria-label="Note revision history"
<div
className="absolute z-0 h-full w-full bg-passive-5 opacity-0 md:opacity-75"
role="presentation"
onClick={onDismiss}
/>
<div
className={classNames(
'my-0 flex h-full w-full flex-col rounded-md bg-[color:var(--modal-background-color)]',
'absolute z-[1] my-0 flex h-full w-full flex-col rounded-md bg-[color:var(--modal-background-color)]',
'p-0 pt-safe-top pb-safe-bottom shadow-lg md:max-h-[90%] md:w-[90%] md:max-w-[90%]',
'md:left-1/2 md:top-1/2 md:-translate-x-1/2 md:-translate-y-1/2 md:transform',
getPlatformString(),
)}
>
<div className="flex h-full flex-col overflow-hidden bg-default">{children}</div>
</DialogContent>
</DialogOverlay>
{children}
</div>
</Dialog>
)
})

View File

@@ -1,8 +1,6 @@
import { ViewControllerManager } from '@/Controllers/ViewControllerManager'
import { SNApplication, SessionStrings, UuidString, SessionListEntry, isErrorResponse } from '@standardnotes/snjs'
import { FunctionComponent, useState, useEffect, useRef, useMemo, useCallback } from 'react'
import { Alert } from '@reach/alert'
import { AlertDialog, AlertDialogDescription, AlertDialogLabel } from '@reach/alert-dialog'
import { WebApplication } from '@/Application/Application'
import { observer } from 'mobx-react-lite'
import Spinner from '@/Components/Spinner/Spinner'
@@ -10,6 +8,7 @@ import Button from '@/Components/Button/Button'
import Icon from '../Icon/Icon'
import Modal, { ModalAction } from '../Modal/Modal'
import ModalOverlay from '../Modal/ModalOverlay'
import AlertDialog from '../AlertDialog/AlertDialog'
type Session = SessionListEntry & {
revoking?: true
@@ -126,7 +125,14 @@ const SessionsModalContent: FunctionComponent<{
return (
<>
<Modal title="Active Sessions" close={close} actions={sessionModalActions}>
<Modal
title="Active Sessions"
close={close}
actions={sessionModalActions}
className={{
content: 'sessions-modal',
}}
>
<div className="px-4 py-4">
{refreshing ? (
<div className="flex items-center gap-2">
@@ -135,7 +141,11 @@ const SessionsModalContent: FunctionComponent<{
</div>
) : (
<>
{errorMessage && <Alert className="sk-p bold">{errorMessage}</Alert>}
{errorMessage && (
<div role="alert" className="sk-p bold">
{errorMessage}
</div>
)}
{sessions.length > 0 && (
<ul>
{sessions.map((session) => (
@@ -166,43 +176,30 @@ const SessionsModalContent: FunctionComponent<{
</div>
</Modal>
{confirmRevokingSessionUuid && (
<AlertDialog onDismiss={closeRevokeConfirmationDialog} leastDestructiveRef={cancelRevokeRef} className="p-0">
<div className="sk-modal-content">
<div className="sn-component">
<div className="sk-panel">
<div className="sk-panel-content">
<div className="sk-panel-section">
<AlertDialogLabel className="flex items-center justify-between text-lg font-bold">
{SessionStrings.RevokeTitle}
<button
className="rounded p-1 font-bold hover:bg-contrast"
onClick={closeRevokeConfirmationDialog}
>
<Icon type="close" />
</button>
</AlertDialogLabel>
<AlertDialogDescription className="sk-panel-row">
<p className="text-base text-foreground lg:text-sm">{SessionStrings.RevokeText}</p>
</AlertDialogDescription>
<div className="my-1 mt-4 flex justify-end gap-2">
<Button ref={cancelRevokeRef} onClick={closeRevokeSessionAlert}>
<span>{SessionStrings.RevokeCancelButton}</span>
</Button>
<Button
primary
colorStyle="danger"
onClick={() => {
closeRevokeSessionAlert()
revokeSession(confirmRevokingSessionUuid).catch(console.error)
}}
>
<span>{SessionStrings.RevokeConfirmButton}</span>
</Button>
</div>
</div>
</div>
</div>
</div>
<AlertDialog closeDialog={closeRevokeConfirmationDialog}>
<div className="flex items-center justify-between text-lg font-bold">
{SessionStrings.RevokeTitle}
<button className="rounded p-1 font-bold hover:bg-contrast" onClick={closeRevokeConfirmationDialog}>
<Icon type="close" />
</button>
</div>
<div className="sk-panel-row">
<p className="text-base text-foreground lg:text-sm">{SessionStrings.RevokeText}</p>
</div>
<div className="mt-4 flex justify-end gap-2">
<Button ref={cancelRevokeRef} onClick={closeRevokeSessionAlert}>
<span>{SessionStrings.RevokeCancelButton}</span>
</Button>
<Button
primary
colorStyle="danger"
onClick={() => {
closeRevokeSessionAlert()
revokeSession(confirmRevokingSessionUuid).catch(console.error)
}}
>
<span>{SessionStrings.RevokeConfirmButton}</span>
</Button>
</div>
</AlertDialog>
)}
@@ -215,11 +212,7 @@ const SessionsModal: FunctionComponent<{
application: WebApplication
}> = ({ viewControllerManager, application }) => {
return (
<ModalOverlay
isOpen={viewControllerManager.isSessionsModalVisible}
onDismiss={viewControllerManager.closeSessionsModal}
className="sessions-modal"
>
<ModalOverlay isOpen={viewControllerManager.isSessionsModalVisible}>
<SessionsModalContent application={application} viewControllerManager={viewControllerManager} />
</ModalOverlay>
)

View File

@@ -1,14 +1,27 @@
import { Tooltip } from '@reach/tooltip'
import styled from 'styled-components'
import { classNames } from '@standardnotes/snjs'
import { ReactNode } from 'react'
import { Tooltip, TooltipAnchor, useTooltipStore } from '@ariakit/react'
import { Slot } from '@radix-ui/react-slot'
export default styled(Tooltip)`
&[data-reach-tooltip] {
border-radius: 0.25rem;
font-size: 0.875rem;
padding: 0.375rem 0.75rem;
background-color: var(--sn-stylekit-contrast-background-color);
color: var(--sn-stylekit-foreground-color);
border-color: var(--sn-stylekit-border-color);
z-index: var(--z-index-tooltip);
}
`
const StyledTooltip = ({ children, className, label }: { children: ReactNode; className?: string; label: string }) => {
const tooltip = useTooltipStore()
return (
<>
<TooltipAnchor store={tooltip} as={Slot}>
{children}
</TooltipAnchor>
<Tooltip
store={tooltip}
className={classNames(
'z-tooltip rounded border border-border bg-contrast py-1.5 px-3 text-sm text-foreground shadow',
className,
)}
>
{label}
</Tooltip>
</>
)
}
export default StyledTooltip

View File

@@ -208,7 +208,7 @@ export const SuperEditor: FunctionComponent<Props> = ({
</BlocksEditorComposer>
</FilesControllerProvider>
</LinkingControllerProvider>
<ModalOverlay isOpen={showMarkdownPreview} onDismiss={closeMarkdownPreview}>
<ModalOverlay isOpen={showMarkdownPreview}>
<SuperNoteMarkdownPreview note={note.current} closeDialog={closeMarkdownPreview} />
</ModalOverlay>
</ErrorBoundary>

View File

@@ -1,7 +1,6 @@
import Icon from '@/Components/Icon/Icon'
import { FeaturesController } from '@/Controllers/FeaturesController'
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
import '@reach/tooltip/styles.css'
import { SmartView, SystemViewId, isSystemView } from '@standardnotes/snjs'
import { observer } from 'mobx-react-lite'
import {

View File

@@ -54,13 +54,10 @@ const SmartViewsSection: FunctionComponent<Props> = ({ application, navigationCo
featuresController={featuresController}
setEditingSmartView={editSmartViewModalController.setView}
/>
<ModalOverlay isOpen={!!editSmartViewModalController.view} onDismiss={editSmartViewModalController.closeDialog}>
<ModalOverlay isOpen={!!editSmartViewModalController.view}>
<EditSmartViewModal controller={editSmartViewModalController} platform={application.platform} />
</ModalOverlay>
<ModalOverlay
isOpen={addSmartViewModalController.isAddingSmartView}
onDismiss={addSmartViewModalController.closeModal}
>
<ModalOverlay isOpen={addSmartViewModalController.isAddingSmartView}>
<AddSmartViewModal controller={addSmartViewModalController} platform={application.platform} />
</ModalOverlay>
</section>

View File

@@ -3,7 +3,6 @@ import { FOCUSABLE_BUT_NOT_TABBABLE, TAG_FOLDERS_FEATURE_NAME } from '@/Constant
import { KeyboardKey } from '@standardnotes/ui-services'
import { FeaturesController } from '@/Controllers/FeaturesController'
import { NavigationController } from '@/Controllers/Navigation/NavigationController'
import '@reach/tooltip/styles.css'
import { IconType, SNTag } from '@standardnotes/snjs'
import { computed } from 'mobx'
import { observer } from 'mobx-react-lite'

View File

@@ -1,9 +1,9 @@
import { TAG_FOLDERS_FEATURE_NAME, TAG_FOLDERS_FEATURE_TOOLTIP } from '@/Constants/Constants'
import { usePremiumModal } from '@/Hooks/usePremiumModal'
import { FeaturesController } from '@/Controllers/FeaturesController'
import { Tooltip } from '@reach/tooltip'
import { observer } from 'mobx-react-lite'
import { FunctionComponent, useCallback } from 'react'
import StyledTooltip from '../StyledTooltip/StyledTooltip'
type Props = {
features: FeaturesController
@@ -38,11 +38,11 @@ const TagsSectionTitle: FunctionComponent<Props> = ({ features, hasMigration, on
<>
<div className="title text-base md:text-sm">
<span className="font-bold">Tags</span>
<Tooltip label={TAG_FOLDERS_FEATURE_TOOLTIP}>
<StyledTooltip label={TAG_FOLDERS_FEATURE_TOOLTIP}>
<label className="ml-1 cursor-pointer font-bold text-passive-2" onClick={showPremiumAlert}>
Folders
</label>
</Tooltip>
</StyledTooltip>
</div>
</>
)

View File

@@ -1,7 +1,6 @@
//= require_tree ./app
// css
import '@reach/dialog/styles.css'
import '../stylesheets/index.css.scss'
// entry point