mirror of
https://github.com/langgenius/dify.git
synced 2026-06-08 00:41:55 +08:00
refactor: enhance layout and scrolling behavior in various modals for improved user experience (#36210)
Co-authored-by: CodingOnStar <hanxujiang@dify.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
b41338cd08
commit
b04a3851cc
@ -2273,11 +2273,6 @@
|
||||
"count": 1
|
||||
}
|
||||
},
|
||||
"web/app/components/header/account-setting/members-page/invite-modal/index.tsx": {
|
||||
"react/set-state-in-effect": {
|
||||
"count": 3
|
||||
}
|
||||
},
|
||||
"web/app/components/header/account-setting/members-page/transfer-ownership-modal/index.tsx": {
|
||||
"erasable-syntax-only/enums": {
|
||||
"count": 1
|
||||
|
||||
@ -46,78 +46,80 @@ const CustomizeModal: FC<IShareLinkProps> = ({
|
||||
|
||||
return (
|
||||
<Dialog open={isShow} onOpenChange={open => !open && onClose()}>
|
||||
<DialogContent className="max-h-[calc(100dvh-2rem)] w-[640px] overflow-visible">
|
||||
<DialogTitle className="title-2xl-semi-bold text-text-primary">
|
||||
<DialogContent className="flex max-h-[calc(100dvh-2rem)] w-[640px] flex-col overflow-hidden!">
|
||||
<DialogTitle className="shrink-0 title-2xl-semi-bold text-text-primary">
|
||||
{t(`${prefixCustomize}.title`, { ns: 'appOverview' })}
|
||||
</DialogTitle>
|
||||
<DialogDescription className="mt-2 body-md-regular text-text-secondary">
|
||||
<DialogDescription className="mt-2 shrink-0 body-md-regular text-text-secondary">
|
||||
{t(`${prefixCustomize}.explanation`, { ns: 'appOverview' })}
|
||||
</DialogDescription>
|
||||
<DialogCloseButton />
|
||||
<div className="mt-4 w-full rounded-lg border-[0.5px] border-components-panel-border px-6 py-5">
|
||||
<Tag bordered={true} hideBg={true} className="border-text-accent-secondary text-text-accent-secondary uppercase">
|
||||
{t(`${prefixCustomize}.way`, { ns: 'appOverview' })}
|
||||
{' '}
|
||||
1
|
||||
</Tag>
|
||||
<p className="my-2 system-sm-medium text-text-secondary">{t(`${prefixCustomize}.way1.name`, { ns: 'appOverview' })}</p>
|
||||
<div className="flex py-4">
|
||||
<StepNum>1</StepNum>
|
||||
<div className="flex flex-col">
|
||||
<div className="text-text-primary">{t(`${prefixCustomize}.way1.step1`, { ns: 'appOverview' })}</div>
|
||||
<div className="mt-1 mb-2 text-xs text-text-tertiary">{t(`${prefixCustomize}.way1.step1Tip`, { ns: 'appOverview' })}</div>
|
||||
<Button render={<a href={`https://github.com/langgenius/${isChatApp ? 'webapp-conversation' : 'webapp-text-generator'}`} target="_blank" rel="noopener noreferrer" />}>
|
||||
<GithubIcon className="mr-2 text-text-secondary" />
|
||||
{t(`${prefixCustomize}.way1.step1Operation`, { ns: 'appOverview' })}
|
||||
</Button>
|
||||
<div className="mt-4 min-h-0 flex-1 overflow-y-auto overscroll-contain">
|
||||
<div className="w-full rounded-lg border-[0.5px] border-components-panel-border px-6 py-5">
|
||||
<Tag bordered={true} hideBg={true} className="border-text-accent-secondary text-text-accent-secondary uppercase">
|
||||
{t(`${prefixCustomize}.way`, { ns: 'appOverview' })}
|
||||
{' '}
|
||||
1
|
||||
</Tag>
|
||||
<p className="my-2 system-sm-medium text-text-secondary">{t(`${prefixCustomize}.way1.name`, { ns: 'appOverview' })}</p>
|
||||
<div className="flex py-4">
|
||||
<StepNum>1</StepNum>
|
||||
<div className="flex flex-col">
|
||||
<div className="text-text-primary">{t(`${prefixCustomize}.way1.step1`, { ns: 'appOverview' })}</div>
|
||||
<div className="mt-1 mb-2 text-xs text-text-tertiary">{t(`${prefixCustomize}.way1.step1Tip`, { ns: 'appOverview' })}</div>
|
||||
<Button render={<a href={`https://github.com/langgenius/${isChatApp ? 'webapp-conversation' : 'webapp-text-generator'}`} target="_blank" rel="noopener noreferrer" />}>
|
||||
<GithubIcon className="mr-2 text-text-secondary" />
|
||||
{t(`${prefixCustomize}.way1.step1Operation`, { ns: 'appOverview' })}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex pt-4">
|
||||
<StepNum>2</StepNum>
|
||||
<div className="flex flex-col">
|
||||
<div className="text-text-primary">{t(`${prefixCustomize}.way1.step2`, { ns: 'appOverview' })}</div>
|
||||
<div className="mt-1 mb-2 text-xs text-text-tertiary">{t(`${prefixCustomize}.way1.step2Tip`, { ns: 'appOverview' })}</div>
|
||||
<Button render={<a href="https://vercel.com/docs/concepts/deployments/git/vercel-for-github" target="_blank" rel="noopener noreferrer" />}>
|
||||
<div className="mr-1.5 border-t-0 border-r-[7px] border-b-12 border-l-[7px] border-solid border-text-primary border-t-transparent border-r-transparent border-l-transparent"></div>
|
||||
<span>{t(`${prefixCustomize}.way1.step2Operation`, { ns: 'appOverview' })}</span>
|
||||
</Button>
|
||||
<div className="flex pt-4">
|
||||
<StepNum>2</StepNum>
|
||||
<div className="flex flex-col">
|
||||
<div className="text-text-primary">{t(`${prefixCustomize}.way1.step2`, { ns: 'appOverview' })}</div>
|
||||
<div className="mt-1 mb-2 text-xs text-text-tertiary">{t(`${prefixCustomize}.way1.step2Tip`, { ns: 'appOverview' })}</div>
|
||||
<Button render={<a href="https://vercel.com/docs/concepts/deployments/git/vercel-for-github" target="_blank" rel="noopener noreferrer" />}>
|
||||
<div className="mr-1.5 border-t-0 border-r-[7px] border-b-12 border-l-[7px] border-solid border-text-primary border-t-transparent border-r-transparent border-l-transparent"></div>
|
||||
<span>{t(`${prefixCustomize}.way1.step2Operation`, { ns: 'appOverview' })}</span>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex py-4">
|
||||
<StepNum>3</StepNum>
|
||||
<div className="flex w-full flex-col overflow-hidden">
|
||||
<div className="text-text-primary">{t(`${prefixCustomize}.way1.step3`, { ns: 'appOverview' })}</div>
|
||||
<div className="mt-1 mb-2 text-xs text-text-tertiary">{t(`${prefixCustomize}.way1.step3Tip`, { ns: 'appOverview' })}</div>
|
||||
<pre className="box-border overflow-x-scroll rounded-lg border-[0.5px] border-components-panel-border bg-background-section px-4 py-3 text-xs font-medium text-text-secondary select-text">
|
||||
NEXT_PUBLIC_APP_ID=
|
||||
{`'${appId}'`}
|
||||
{' '}
|
||||
<br />
|
||||
NEXT_PUBLIC_APP_KEY=
|
||||
{'\'<Web API Key From Dify>\''}
|
||||
{' '}
|
||||
<br />
|
||||
NEXT_PUBLIC_API_URL=
|
||||
{`'${api_base_url}'`}
|
||||
</pre>
|
||||
<div className="flex py-4">
|
||||
<StepNum>3</StepNum>
|
||||
<div className="flex w-full flex-col overflow-hidden">
|
||||
<div className="text-text-primary">{t(`${prefixCustomize}.way1.step3`, { ns: 'appOverview' })}</div>
|
||||
<div className="mt-1 mb-2 text-xs text-text-tertiary">{t(`${prefixCustomize}.way1.step3Tip`, { ns: 'appOverview' })}</div>
|
||||
<pre className="box-border overflow-x-scroll rounded-lg border-[0.5px] border-components-panel-border bg-background-section px-4 py-3 text-xs font-medium text-text-secondary select-text">
|
||||
NEXT_PUBLIC_APP_ID=
|
||||
{`'${appId}'`}
|
||||
{' '}
|
||||
<br />
|
||||
NEXT_PUBLIC_APP_KEY=
|
||||
{'\'<Web API Key From Dify>\''}
|
||||
{' '}
|
||||
<br />
|
||||
NEXT_PUBLIC_API_URL=
|
||||
{`'${api_base_url}'`}
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className="mt-4 w-full rounded-lg border-[0.5px] border-components-panel-border px-6 py-5">
|
||||
<Tag bordered={true} hideBg={true} className="border-text-accent-secondary text-text-accent-secondary uppercase">
|
||||
{t(`${prefixCustomize}.way`, { ns: 'appOverview' })}
|
||||
{' '}
|
||||
2
|
||||
</Tag>
|
||||
<p className="my-2 system-sm-medium text-text-secondary">{t(`${prefixCustomize}.way2.name`, { ns: 'appOverview' })}</p>
|
||||
<Button
|
||||
render={<a href={apiDocLink} target="_blank" rel="noopener noreferrer" />}
|
||||
className="mt-2"
|
||||
>
|
||||
<span className="text-sm text-text-secondary">{t(`${prefixCustomize}.way2.operation`, { ns: 'appOverview' })}</span>
|
||||
<span aria-hidden="true" className="ml-1 i-heroicons-arrow-top-right-on-square h-4 w-4 shrink-0 text-text-secondary" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className="mt-4 w-full rounded-lg border-[0.5px] border-components-panel-border px-6 py-5">
|
||||
<Tag bordered={true} hideBg={true} className="border-text-accent-secondary text-text-accent-secondary uppercase">
|
||||
{t(`${prefixCustomize}.way`, { ns: 'appOverview' })}
|
||||
{' '}
|
||||
2
|
||||
</Tag>
|
||||
<p className="my-2 system-sm-medium text-text-secondary">{t(`${prefixCustomize}.way2.name`, { ns: 'appOverview' })}</p>
|
||||
<Button
|
||||
render={<a href={apiDocLink} target="_blank" rel="noopener noreferrer" />}
|
||||
className="mt-2"
|
||||
>
|
||||
<span className="text-sm text-text-secondary">{t(`${prefixCustomize}.way2.operation`, { ns: 'appOverview' })}</span>
|
||||
<span aria-hidden="true" className="ml-1 i-heroicons-arrow-top-right-on-square h-4 w-4 shrink-0 text-text-secondary" />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
@ -319,12 +319,12 @@ const Embedded = ({ siteInfo, isShow, onClose, appBaseUrl, accessToken, hiddenIn
|
||||
onClose()
|
||||
}}
|
||||
>
|
||||
<DialogContent className={cn('max-h-[calc(100dvh-2rem)] w-[640px] overflow-visible', className)}>
|
||||
<DialogTitle className="title-2xl-semi-bold text-text-primary">
|
||||
<DialogContent className={cn('flex max-h-[calc(100dvh-2rem)] w-[640px] flex-col overflow-hidden!', className)}>
|
||||
<DialogTitle className="shrink-0 title-2xl-semi-bold text-text-primary">
|
||||
{t(`${prefixEmbedded}.title`, { ns: 'appOverview' })}
|
||||
</DialogTitle>
|
||||
<DialogCloseButton />
|
||||
<div className="max-h-[calc(90vh-88px)] overflow-y-auto">
|
||||
<div className="min-h-0 flex-1 overflow-y-auto overscroll-contain">
|
||||
{isShow && (
|
||||
<EmbeddedContent
|
||||
key={`${appBaseUrl ?? ''}:${accessToken ?? ''}:${JSON.stringify(hiddenInputs ?? [])}`}
|
||||
|
||||
@ -251,9 +251,9 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
||||
return (
|
||||
<>
|
||||
<Dialog open={isShow} onOpenChange={open => !open && onHide()}>
|
||||
<DialogContent className="max-h-[calc(100dvh-2rem)] w-[520px] overflow-visible p-0">
|
||||
<DialogContent className="flex max-h-[calc(100dvh-2rem)] w-[520px] flex-col overflow-hidden! p-0!">
|
||||
{/* header */}
|
||||
<div className="pt-5 pr-5 pb-3 pl-6">
|
||||
<div className="shrink-0 pt-5 pr-5 pb-3 pl-6">
|
||||
<div className="flex items-center gap-1">
|
||||
<DialogTitle className="grow title-2xl-semi-bold text-text-primary">{t(`${prefixSettings}.title`, { ns: 'appOverview' })}</DialogTitle>
|
||||
<DialogCloseButton className="relative top-auto right-auto shrink-0" />
|
||||
@ -263,7 +263,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
||||
</div>
|
||||
</div>
|
||||
{/* form body */}
|
||||
<div className="space-y-5 px-6 py-3">
|
||||
<div className="min-h-0 flex-1 space-y-5 overflow-y-auto overscroll-contain px-6 py-3">
|
||||
{/* name & icon */}
|
||||
<div className="flex gap-4">
|
||||
<div className="grow">
|
||||
@ -474,7 +474,7 @@ const SettingsModal: FC<ISettingsModalProps> = ({
|
||||
)}
|
||||
</div>
|
||||
{/* footer */}
|
||||
<div className="flex justify-end p-6 pt-5">
|
||||
<div className="flex shrink-0 justify-end p-6 pt-5">
|
||||
<Button className="mr-2" onClick={onHide}>{t('operation.cancel', { ns: 'common' })}</Button>
|
||||
<Button variant="primary" onClick={onClickSave} loading={saveLoading}>{t('operation.save', { ns: 'common' })}</Button>
|
||||
</div>
|
||||
|
||||
@ -198,7 +198,7 @@ const CloudPlanItem: FC<CloudPlanItemProps> = ({
|
||||
>
|
||||
<DialogContent
|
||||
backdropProps={{ forceRender: true }}
|
||||
className="w-[520px] overflow-visible"
|
||||
className="w-[520px]"
|
||||
>
|
||||
<DialogCloseButton
|
||||
aria-label={t('operation.close', { ns: 'common' })}
|
||||
|
||||
@ -121,9 +121,9 @@ const AddExternalAPIModal: FC<AddExternalAPIModalProps> = ({ data, onSave, onCan
|
||||
onCancel()
|
||||
}}
|
||||
>
|
||||
<DialogContent className="w-[480px]! max-w-none! overflow-visible! rounded-2xl! border-[0.5px]! border-components-panel-border! bg-components-panel-bg! p-0! shadow-xl!">
|
||||
<div className="relative flex w-full flex-col items-start">
|
||||
<div className="flex flex-col items-start gap-2 self-stretch pt-6 pr-14 pb-3 pl-6">
|
||||
<DialogContent className="flex max-h-[calc(100dvh-2rem)] w-[480px]! max-w-none! flex-col overflow-hidden! rounded-2xl! border-[0.5px]! border-components-panel-border! bg-components-panel-bg! p-0! shadow-xl!">
|
||||
<div className="relative flex min-h-0 w-full flex-1 flex-col items-start">
|
||||
<div className="flex shrink-0 flex-col items-start gap-2 self-stretch pt-6 pr-14 pb-3 pl-6">
|
||||
<DialogTitle className="grow self-stretch title-2xl-semi-bold text-text-primary">
|
||||
{isEditMode ? t('editExternalAPIFormTitle', { ns: 'dataset' }) : t('createExternalAPI', { ns: 'dataset' })}
|
||||
</DialogTitle>
|
||||
@ -173,8 +173,8 @@ const AddExternalAPIModal: FC<AddExternalAPIModalProps> = ({ data, onSave, onCan
|
||||
<ActionButton className="absolute top-5 right-5" onClick={onCancel}>
|
||||
<RiCloseLine className="h-[18px] w-[18px] shrink-0 text-text-tertiary" />
|
||||
</ActionButton>
|
||||
<Form value={formData} onChange={handleDataChange} formSchemas={formSchemas} className="flex flex-col items-start justify-center gap-4 self-stretch px-6 py-3" />
|
||||
<div className="flex items-center justify-end gap-2 self-stretch p-6 pt-5">
|
||||
<Form value={formData} onChange={handleDataChange} formSchemas={formSchemas} className="min-h-0 w-full flex-1 overflow-y-auto px-6 py-3" />
|
||||
<div className="flex shrink-0 items-center justify-end gap-2 self-stretch p-6 pt-5">
|
||||
<Button type="button" variant="secondary" onClick={onCancel}>
|
||||
{t('externalAPIForm.cancel', { ns: 'dataset' })}
|
||||
</Button>
|
||||
@ -194,7 +194,7 @@ const AddExternalAPIModal: FC<AddExternalAPIModalProps> = ({ data, onSave, onCan
|
||||
{t('externalAPIForm.save', { ns: 'dataset' })}
|
||||
</Button>
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-1 self-stretch rounded-b-2xl border-t-[0.5px] border-divider-subtle
|
||||
<div className="flex shrink-0 items-center justify-center gap-1 self-stretch rounded-b-2xl border-t-[0.5px] border-divider-subtle
|
||||
bg-background-soft px-2 py-3 system-xs-regular text-text-tertiary"
|
||||
>
|
||||
<RiLock2Fill className="h-3 w-3 text-text-quaternary" />
|
||||
|
||||
@ -60,7 +60,7 @@ const EditWorkspaceModal = ({ onCancel }: IEditWorkspaceModalProps) => {
|
||||
onCancel()
|
||||
}}
|
||||
>
|
||||
<DialogContent backdropProps={{ forceRender: true }} className="overflow-visible">
|
||||
<DialogContent backdropProps={{ forceRender: true }}>
|
||||
<DialogCloseButton />
|
||||
|
||||
<form
|
||||
|
||||
@ -6,7 +6,7 @@ import { cn } from '@langgenius/dify-ui/cn'
|
||||
import { Dialog, DialogCloseButton, DialogContent, DialogTitle } from '@langgenius/dify-ui/dialog'
|
||||
import { toast } from '@langgenius/dify-ui/toast'
|
||||
import { useBoolean } from 'ahooks'
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { ReactMultiEmail } from 'react-multi-email'
|
||||
import { emailRegex } from '@/config'
|
||||
@ -31,16 +31,9 @@ const InviteModal = ({
|
||||
const licenseLimit = useProviderContextSelector(s => s.licenseLimit)
|
||||
const refreshLicenseLimit = useProviderContextSelector(s => s.refreshLicenseLimit)
|
||||
const [emails, setEmails] = useState<string[]>([])
|
||||
const [isLimited, setIsLimited] = useState(false)
|
||||
const [isLimitExceeded, setIsLimitExceeded] = useState(false)
|
||||
const [usedSize, setUsedSize] = useState(licenseLimit.workspace_members.size ?? 0)
|
||||
useEffect(() => {
|
||||
const limited = licenseLimit.workspace_members.limit > 0
|
||||
const used = emails.length + licenseLimit.workspace_members.size
|
||||
setIsLimited(limited)
|
||||
setUsedSize(used)
|
||||
setIsLimitExceeded(limited && (used > licenseLimit.workspace_members.limit))
|
||||
}, [licenseLimit, emails])
|
||||
const isLimited = licenseLimit.workspace_members.limit > 0
|
||||
const usedSize = emails.length + licenseLimit.workspace_members.size
|
||||
const isLimitExceeded = isLimited && (usedSize > licenseLimit.workspace_members.limit)
|
||||
|
||||
const locale = useLocale()
|
||||
const [role, setRole] = useState<RoleKey>('normal')
|
||||
@ -85,7 +78,7 @@ const InviteModal = ({
|
||||
>
|
||||
<DialogContent
|
||||
backdropProps={{ forceRender: true }}
|
||||
className="w-[400px] overflow-visible px-8 py-6"
|
||||
className="w-[400px] px-8 py-6"
|
||||
>
|
||||
<DialogCloseButton className="top-6 right-8" />
|
||||
<div className="mb-2 pr-8">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user