Skip to content

Commit f955684

Browse files
committed
feat: Optimize dialogs
1 parent 9bd8919 commit f955684

File tree

5 files changed

+131
-79
lines changed

5 files changed

+131
-79
lines changed

src/components/ActionsModal.tsx

Lines changed: 27 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,9 @@
11
import React from 'react'
22
import { useTranslation } from 'react-i18next'
3-
import { useMediaQuery } from 'usehooks-ts'
43

4+
import { useResponsiveDialog } from '@/components/ResponsiveDialog'
55
import { Button } from '@/components/ui/button'
6-
import {
7-
Dialog,
8-
DialogContent,
9-
DialogHeader,
10-
DialogTitle,
11-
} from '@/components/ui/dialog'
12-
import {
13-
Drawer,
14-
DrawerClose,
15-
DrawerContent,
16-
DrawerFooter,
17-
DrawerHeader,
18-
DrawerTitle,
19-
} from '@/components/ui/drawer'
6+
import type { Dialog } from '@/components/ui/dialog'
207
import { BottomSafeArea } from '@/components/VerticalSafeArea'
218

229
export type Action = {
@@ -36,49 +23,39 @@ const ActionsModal = ({
3623
...props
3724
}: ActionsModalProps): JSX.Element => {
3825
const { t } = useTranslation()
39-
const isDesktop = useMediaQuery('(min-width: 768px)')
40-
41-
if (isDesktop) {
42-
return (
43-
<Dialog {...props}>
44-
<DialogContent>
45-
<DialogHeader>
46-
<DialogTitle>{title}</DialogTitle>
47-
</DialogHeader>
48-
49-
<div className="space-y-5">
50-
{actions.map((action) => (
51-
<Button stretch key={action.id} onClick={action.onClick}>
52-
{t(action.title)}
53-
</Button>
54-
))}
55-
</div>
56-
</DialogContent>
57-
</Dialog>
58-
)
59-
}
26+
const {
27+
Dialog,
28+
DialogContent,
29+
DialogHeader,
30+
DialogTitle,
31+
DialogFooter,
32+
DialogClose,
33+
} = useResponsiveDialog()
6034

6135
return (
62-
<Drawer {...props}>
63-
<DrawerContent className="select-none">
64-
<DrawerHeader>
65-
<DrawerTitle>{title}</DrawerTitle>
66-
</DrawerHeader>
67-
<DrawerFooter>
36+
<Dialog {...props}>
37+
<DialogContent className="select-none">
38+
<DialogHeader>
39+
<DialogTitle>{title}</DialogTitle>
40+
</DialogHeader>
41+
42+
<div className="space-y-4">
6843
{actions.map((action) => (
6944
<Button stretch key={action.id} onClick={action.onClick}>
7045
{t(action.title)}
7146
</Button>
7247
))}
73-
<DrawerClose>
74-
<Button className="w-full" variant="outline">
75-
{t('common.close')}
76-
</Button>
77-
</DrawerClose>
78-
</DrawerFooter>
48+
</div>
49+
50+
<DialogFooter className="flex md:hidden">
51+
<DialogClose asChild>
52+
<Button variant="outline">{t('common.close')}</Button>
53+
</DialogClose>
54+
</DialogFooter>
55+
7956
<BottomSafeArea />
80-
</DrawerContent>
81-
</Drawer>
57+
</DialogContent>
58+
</Dialog>
8259
)
8360
}
8461

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import tw from 'twin.macro'
2+
import { useMediaQuery } from 'usehooks-ts'
3+
4+
import {
5+
Dialog,
6+
DialogClose,
7+
DialogContent,
8+
DialogDescription,
9+
DialogHeader,
10+
DialogFooter,
11+
DialogTitle,
12+
DialogTrigger,
13+
} from '@/components/ui/dialog'
14+
import {
15+
Drawer,
16+
DrawerClose,
17+
DrawerContent,
18+
DrawerDescription,
19+
DrawerFooter,
20+
DrawerHeader,
21+
DrawerTitle,
22+
DrawerTrigger,
23+
} from '@/components/ui/drawer'
24+
25+
const CustomDrawerContent = tw(DrawerContent)`px-6`
26+
const CustomDrawerFooter = tw(DrawerFooter)`px-0`
27+
const CustomDrawerHeader = tw(DrawerHeader)`px-0`
28+
29+
export const useResponsiveDialog = () => {
30+
const isDesktop = useMediaQuery('(min-width: 768px)')
31+
32+
return isDesktop
33+
? ({
34+
Dialog,
35+
DialogClose,
36+
DialogContent,
37+
DialogDescription,
38+
DialogFooter,
39+
DialogHeader,
40+
DialogTitle,
41+
DialogTrigger,
42+
} as const)
43+
: ({
44+
Dialog: Drawer,
45+
DialogClose: DrawerClose,
46+
DialogContent: CustomDrawerContent,
47+
DialogDescription: DrawerDescription,
48+
DialogFooter: CustomDrawerFooter,
49+
DialogHeader: CustomDrawerHeader,
50+
DialogTitle: DrawerTitle,
51+
DialogTrigger: DrawerTrigger,
52+
} as const)
53+
}

src/pages/Devices/components/DeviceSettingsModal.tsx

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,9 @@ import { zodResolver } from '@hookform/resolvers/zod'
66
import { to } from 'await-to-js'
77
import { mutate } from 'swr'
88

9+
import { useResponsiveDialog } from '@/components/ResponsiveDialog'
910
import { Button } from '@/components/ui/button'
10-
import { Checkbox } from '@/components/ui/checkbox'
11-
import {
12-
Dialog,
13-
DialogContent,
14-
DialogFooter,
15-
DialogHeader,
16-
DialogTitle,
17-
} from '@/components/ui/dialog'
11+
import type { Dialog } from '@/components/ui/dialog'
1812
import {
1913
Form,
2014
FormControl,
@@ -47,6 +41,15 @@ const DeviceSettingsModal = ({
4741
...props
4842
}: DeviceSettingsModalProps): JSX.Element => {
4943
const { t } = useTranslation()
44+
const {
45+
Dialog,
46+
DialogContent,
47+
DialogHeader,
48+
DialogTitle,
49+
DialogFooter,
50+
DialogClose,
51+
} = useResponsiveDialog()
52+
5053
const DeviceSettingsSchema = useDeviceSettingsSchema()
5154

5255
const form = useForm<FormData>({
@@ -176,7 +179,7 @@ const DeviceSettingsModal = ({
176179
control={form.control}
177180
name="shouldHandledBySurge"
178181
render={({ field }) => (
179-
<FormItem className="flex flex-row items-center space-x-3 space-y-0">
182+
<FormItem className="flex flex-row items-center space-x-3 space-y-0 py-2">
180183
<FormControl>
181184
<Switch
182185
disabled={isLoading}
@@ -190,6 +193,9 @@ const DeviceSettingsModal = ({
190193
/>
191194

192195
<DialogFooter>
196+
<DialogClose asChild>
197+
<Button variant="outline">{t('common.cancel')}</Button>
198+
</DialogClose>
193199
<Button
194200
isLoading={isLoading}
195201
type="submit"

src/pages/Scripting/Evaluate/index.tsx

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,33 @@ import CodeContent from '@/components/CodeContent'
77
import CodeMirrorLoading from '@/components/CodeMirrorLoading'
88
import FixedFullscreenContainer from '@/components/FixedFullscreenContainer'
99
import PageTitle from '@/components/PageTitle'
10+
import { useResponsiveDialog } from '@/components/ResponsiveDialog'
1011
import { Button } from '@/components/ui/button'
11-
import {
12-
Dialog,
13-
DialogContent,
14-
DialogFooter,
15-
DialogHeader,
16-
DialogTitle,
17-
} from '@/components/ui/dialog'
1812
import { Input } from '@/components/ui/input'
1913
import { Label } from '@/components/ui/label'
14+
import { BottomSafeArea } from '@/components/VerticalSafeArea'
2015
import { EvaluateResult } from '@/types'
2116
import fetcher from '@/utils/fetcher'
2217

2318
const CodeMirror = lazy(() => import('@/components/CodeMirror'))
2419

2520
export const Component: React.FC = () => {
2621
const { t } = useTranslation()
22+
23+
const {
24+
Dialog,
25+
DialogContent,
26+
DialogHeader,
27+
DialogTitle,
28+
DialogFooter,
29+
DialogClose,
30+
} = useResponsiveDialog()
31+
2732
const [code, setCode] = useState<string>(() =>
2833
t('scripting.editor_placeholder'),
2934
)
3035
const [isLoading, setIsLoading] = useState(false)
31-
const [result, setResult] = useState<string>()
36+
const [result, setResult] = useState<string | undefined>()
3237
const [timeout, setTimeoutValue] = useState<number>(5)
3338

3439
const evaluate = useCallback(() => {
@@ -133,8 +138,12 @@ export const Component: React.FC = () => {
133138
<CodeContent content={result} />
134139
</div>
135140
<DialogFooter>
136-
<Button onClick={() => setResult('')}>{t('common.close')}</Button>
141+
<DialogClose asChild>
142+
<Button variant="default">{t('common.close')}</Button>
143+
</DialogClose>
137144
</DialogFooter>
145+
146+
<BottomSafeArea />
138147
</DialogContent>
139148
</Dialog>
140149
</FixedFullscreenContainer>

src/pages/Scripting/index.tsx

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,29 @@ import CodeContent from '@/components/CodeContent'
1010
import HorizontalSafeArea from '@/components/HorizontalSafeArea'
1111
import { ListCell } from '@/components/ListCell'
1212
import PageTitle from '@/components/PageTitle'
13+
import { useResponsiveDialog } from '@/components/ResponsiveDialog'
1314
import { Button } from '@/components/ui/button'
1415
import { ButtonGroup } from '@/components/ui/button-group'
15-
import {
16-
Dialog,
17-
DialogContent,
18-
DialogFooter,
19-
DialogHeader,
20-
DialogTitle,
21-
} from '@/components/ui/dialog'
16+
import { BottomSafeArea } from '@/components/VerticalSafeArea'
2217
import { EvaluateResult, Scriptings } from '@/types'
2318
import fetcher from '@/utils/fetcher'
2419
import withProfile from '@/utils/with-profile'
2520

2621
const ComponentBase: React.FC = () => {
2722
const { t } = useTranslation()
2823
const navigate = useNavigate()
24+
25+
const {
26+
Dialog,
27+
DialogContent,
28+
DialogHeader,
29+
DialogTitle,
30+
DialogFooter,
31+
DialogClose,
32+
} = useResponsiveDialog()
33+
2934
const { data: scripting } = useSWR<Scriptings>('/scripting', fetcher)
30-
const [evaluateResult, setEvaluateResult] = useState<string>()
35+
const [evaluateResult, setEvaluateResult] = useState<string | undefined>()
3136
const [isLoading, setIsLoading] = useState<number>()
3237

3338
const filteredList = useMemo(() => {
@@ -143,10 +148,12 @@ const ComponentBase: React.FC = () => {
143148
<CodeContent content={evaluateResult} />
144149
</div>
145150
<DialogFooter>
146-
<Button onClick={() => setEvaluateResult(undefined)}>
147-
{t('common.close')}
148-
</Button>
151+
<DialogClose asChild>
152+
<Button variant="default">{t('common.close')}</Button>
153+
</DialogClose>
149154
</DialogFooter>
155+
156+
<BottomSafeArea />
150157
</DialogContent>
151158
</Dialog>
152159
</>

0 commit comments

Comments
 (0)