Skip to content

Commit ed4df19

Browse files
committed
display Lang picker in a dialog on mobile
1 parent 4c32eed commit ed4df19

File tree

5 files changed

+119
-84
lines changed

5 files changed

+119
-84
lines changed

src/components/LanguagePicker/index.tsx

Lines changed: 115 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import { useRouter } from "next/router"
2+
import { useTranslation } from "react-i18next"
23

34
import { BaseLink } from "@/components/Link"
45

56
import { cn } from "@/lib/utils/cn"
6-
import { isMobile } from "@/lib/utils/isMobile"
77

88
import {
99
Command,
@@ -12,6 +12,7 @@ import {
1212
CommandInput,
1313
CommandList,
1414
} from "../ui/command"
15+
import { Dialog, DialogContent, DialogTrigger } from "../ui/dialog"
1516
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"
1617

1718
import MenuItem from "./MenuItem"
@@ -25,15 +26,17 @@ type LanguagePickerProps = {
2526
children: React.ReactNode
2627
className?: string
2728
handleClose?: () => void
29+
dialog?: boolean
2830
}
2931

3032
const LanguagePicker = ({
3133
children,
3234
handleClose,
3335
className,
36+
dialog,
3437
}: LanguagePickerProps) => {
3538
const { asPath, push } = useRouter()
36-
const { t, disclosure, languages } = useLanguagePicker(handleClose)
39+
const { disclosure, languages } = useLanguagePicker(handleClose)
3740
const { isOpen, setValue, onClose, onOpen } = disclosure
3841

3942
/**
@@ -63,6 +66,33 @@ const LanguagePicker = ({
6366
eventName: "/contributing/translation-program",
6467
})
6568

69+
if (dialog) {
70+
return (
71+
<Dialog open={isOpen} onOpenChange={setValue}>
72+
<DialogTrigger asChild>{children}</DialogTrigger>
73+
<DialogContent className="inset-4 flex h-auto w-auto transform-none flex-col bg-background-highlight p-0 [&>button]:hidden">
74+
{/* Mobile Close bar */}
75+
<MobileCloseBar handleClick={handleMobileCloseBarClick} />
76+
77+
<LanguagePickerMenu
78+
languages={languages}
79+
onSelect={handleMenuItemSelect}
80+
onClose={() =>
81+
onClose({
82+
eventAction: "Translation program link (no results)",
83+
eventName: "/contributing/translation-program",
84+
})
85+
}
86+
/>
87+
88+
<LanguagePickerFooter
89+
onTranslationProgramClick={handleBaseLinkClose}
90+
/>
91+
</DialogContent>
92+
</Dialog>
93+
)
94+
}
95+
6696
return (
6797
<Popover open={isOpen} onOpenChange={setValue}>
6898
<PopoverTrigger asChild>{children}</PopoverTrigger>
@@ -73,83 +103,94 @@ const LanguagePicker = ({
73103
className
74104
)}
75105
>
76-
{/* Mobile Close bar */}
77-
{/* avoid rendering mobile only feature on desktop */}
78-
{isMobile() && (
79-
<MobileCloseBar handleClick={handleMobileCloseBarClick} />
80-
)}
81-
82-
<Command
83-
className="gap-2 p-4"
84-
filter={(value: string, search: string) => {
85-
const item = languages.find((name) => name.localeOption === value)
106+
<LanguagePickerMenu
107+
languages={languages}
108+
onSelect={handleMenuItemSelect}
109+
onClose={() =>
110+
onClose({
111+
eventAction: "Translation program link (no results)",
112+
eventName: "/contributing/translation-program",
113+
})
114+
}
115+
/>
116+
117+
<LanguagePickerFooter onTranslationProgramClick={handleBaseLinkClose} />
118+
</PopoverContent>
119+
</Popover>
120+
)
121+
}
86122

87-
if (!item) return 0
123+
const LanguagePickerMenu = ({ languages, onClose, onSelect }) => {
124+
const { t } = useTranslation("common")
88125

89-
const { localeOption, sourceName, targetName, englishName } = item
126+
return (
127+
<Command
128+
className="gap-2 p-4"
129+
filter={(value: string, search: string) => {
130+
const item = languages.find((name) => name.localeOption === value)
131+
132+
if (!item) return 0
133+
134+
const { localeOption, sourceName, targetName, englishName } = item
135+
136+
if (
137+
(localeOption + sourceName + targetName + englishName)
138+
.toLowerCase()
139+
.includes(search.toLowerCase())
140+
) {
141+
return 1
142+
}
143+
144+
return 0
145+
}}
146+
>
147+
<div className="text-xs text-body-medium">
148+
{t("page-languages-filter-label")}{" "}
149+
<span className="lowercase">
150+
({languages.length} {t("common:languages")})
151+
</span>
152+
</div>
153+
154+
<CommandInput
155+
placeholder={t("page-languages-filter-placeholder")}
156+
className="h-9"
157+
kbdShortcut="\"
158+
/>
159+
160+
<CommandList className="max-h-[75vh]">
161+
<CommandEmpty className="py-0 text-left text-base">
162+
<NoResultsCallout onClose={onClose} />
163+
</CommandEmpty>
164+
<CommandGroup className="p-0">
165+
{languages.map((displayInfo) => (
166+
<MenuItem
167+
key={"item-" + displayInfo.localeOption}
168+
displayInfo={displayInfo}
169+
onSelect={onSelect}
170+
/>
171+
))}
172+
</CommandGroup>
173+
</CommandList>
174+
</Command>
175+
)
176+
}
90177

91-
if (
92-
(localeOption + sourceName + targetName + englishName)
93-
.toLowerCase()
94-
.includes(search.toLowerCase())
95-
) {
96-
return 1
97-
}
178+
const LanguagePickerFooter = ({ onTranslationProgramClick }) => {
179+
const { t } = useTranslation("common")
98180

99-
return 0
100-
}}
181+
return (
182+
<div className="sticky bottom-0 flex justify-center border-t-2 border-primary bg-primary-low-contrast p-3">
183+
<p className="text-center text-xs text-body">
184+
{t("page-languages-recruit-community")}{" "}
185+
{/* TODO migrate once #13411 is merged */}
186+
<BaseLink
187+
href="/contributing/translation-program"
188+
onClick={onTranslationProgramClick}
101189
>
102-
<div className="text-xs text-body-medium">
103-
{t("page-languages-filter-label")}{" "}
104-
<span className="lowercase">
105-
({languages.length} {t("common:languages")})
106-
</span>
107-
</div>
108-
109-
<CommandInput
110-
placeholder={t("page-languages-filter-placeholder")}
111-
className="h-9"
112-
kbdShortcut="\"
113-
/>
114-
115-
<CommandList className="max-h-[75vh]">
116-
<CommandEmpty className="py-0 text-left text-base">
117-
<NoResultsCallout
118-
onClose={() =>
119-
onClose({
120-
eventAction: "Translation program link (no results)",
121-
eventName: "/contributing/translation-program",
122-
})
123-
}
124-
/>
125-
</CommandEmpty>
126-
<CommandGroup className="p-0">
127-
{languages.map((displayInfo) => (
128-
<MenuItem
129-
key={"item-" + displayInfo.localeOption}
130-
displayInfo={displayInfo}
131-
onSelect={handleMenuItemSelect}
132-
/>
133-
))}
134-
</CommandGroup>
135-
</CommandList>
136-
</Command>
137-
138-
{/* Footer callout */}
139-
<div className="sticky bottom-0 flex justify-center border-t-2 border-primary bg-primary-low-contrast p-3">
140-
<p className="text-center text-xs text-body">
141-
{t("page-languages-recruit-community")}{" "}
142-
{/* TODO migrate once #13411 is merged */}
143-
<BaseLink
144-
href="/contributing/translation-program"
145-
onClick={handleBaseLinkClose}
146-
>
147-
{t("common:learn-more")}
148-
</BaseLink>
149-
</p>
150-
</div>
151-
</PopoverContent>
152-
</Popover>
190+
{t("common:learn-more")}
191+
</BaseLink>
192+
</p>
193+
</div>
153194
)
154195
}
155196

src/components/LanguagePicker/useLanguagePicker.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,6 @@ export const useLanguagePicker = (handleClose?: () => void) => {
9595
}
9696

9797
return {
98-
t,
9998
disclosure: { isOpen, setValue, onOpen, onClose },
10099
languages,
101100
}

src/components/Nav/Desktop/index.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,7 @@ const DesktopNavMenu = ({ toggleColorMode }: DesktopNavMenuProps) => {
6565
/>
6666

6767
{/* Locale-picker menu */}
68-
<LanguagePicker
69-
// TODO w="xs"
70-
>
68+
<LanguagePicker>
7169
<Button
7270
name={DESKTOP_LANGUAGE_BUTTON_NAME}
7371
ref={languagePickerRef}

src/components/Nav/Mobile/MenuFooter.tsx

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,7 @@ const MenuFooter = ({
4343
<FooterItemText>{t(themeLabelKey)}</FooterItemText>
4444
</FooterButton>
4545

46-
<LanguagePicker
47-
className="fixed inset-4 h-[calc(100vh-var(--eth-sizes-8))] w-[calc(100vw-var(--eth-sizes-8))]"
48-
handleClose={onToggle}
49-
>
46+
<LanguagePicker dialog handleClose={onToggle}>
5047
<FooterButton icon={BsTranslate} name={MOBILE_LANGUAGE_BUTTON_NAME}>
5148
<FooterItemText>{t("languages")}</FooterItemText>
5249
</FooterButton>

src/components/ui/dialog.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const DialogOverlay = React.forwardRef<
1919
<DialogPrimitive.Overlay
2020
ref={ref}
2121
className={cn(
22-
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
22+
"fixed inset-0 z-modal bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
2323
className
2424
)}
2525
{...props}
@@ -36,7 +36,7 @@ const DialogContent = React.forwardRef<
3636
<DialogPrimitive.Content
3737
ref={ref}
3838
className={cn(
39-
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
39+
"fixed left-[50%] top-[50%] z-modal grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
4040
className
4141
)}
4242
{...props}

0 commit comments

Comments
 (0)