Skip to content

Commit

Permalink
display Lang picker in a dialog on mobile
Browse files Browse the repository at this point in the history
  • Loading branch information
pettinarip committed Aug 13, 2024
1 parent 4c32eed commit ed4df19
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 84 deletions.
189 changes: 115 additions & 74 deletions src/components/LanguagePicker/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useRouter } from "next/router"
import { useTranslation } from "react-i18next"

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

import { cn } from "@/lib/utils/cn"
import { isMobile } from "@/lib/utils/isMobile"

import {
Command,
Expand All @@ -12,6 +12,7 @@ import {
CommandInput,
CommandList,
} from "../ui/command"
import { Dialog, DialogContent, DialogTrigger } from "../ui/dialog"
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover"

import MenuItem from "./MenuItem"
Expand All @@ -25,15 +26,17 @@ type LanguagePickerProps = {
children: React.ReactNode
className?: string
handleClose?: () => void
dialog?: boolean
}

const LanguagePicker = ({
children,
handleClose,
className,
dialog,
}: LanguagePickerProps) => {
const { asPath, push } = useRouter()
const { t, disclosure, languages } = useLanguagePicker(handleClose)
const { disclosure, languages } = useLanguagePicker(handleClose)
const { isOpen, setValue, onClose, onOpen } = disclosure

/**
Expand Down Expand Up @@ -63,6 +66,33 @@ const LanguagePicker = ({
eventName: "/contributing/translation-program",
})

if (dialog) {
return (
<Dialog open={isOpen} onOpenChange={setValue}>
<DialogTrigger asChild>{children}</DialogTrigger>
<DialogContent className="inset-4 flex h-auto w-auto transform-none flex-col bg-background-highlight p-0 [&>button]:hidden">
{/* Mobile Close bar */}
<MobileCloseBar handleClick={handleMobileCloseBarClick} />

<LanguagePickerMenu
languages={languages}
onSelect={handleMenuItemSelect}
onClose={() =>
onClose({
eventAction: "Translation program link (no results)",
eventName: "/contributing/translation-program",
})
}
/>

<LanguagePickerFooter
onTranslationProgramClick={handleBaseLinkClose}
/>
</DialogContent>
</Dialog>
)
}

return (
<Popover open={isOpen} onOpenChange={setValue}>
<PopoverTrigger asChild>{children}</PopoverTrigger>
Expand All @@ -73,83 +103,94 @@ const LanguagePicker = ({
className
)}
>
{/* Mobile Close bar */}
{/* avoid rendering mobile only feature on desktop */}
{isMobile() && (
<MobileCloseBar handleClick={handleMobileCloseBarClick} />
)}

<Command
className="gap-2 p-4"
filter={(value: string, search: string) => {
const item = languages.find((name) => name.localeOption === value)
<LanguagePickerMenu
languages={languages}
onSelect={handleMenuItemSelect}
onClose={() =>
onClose({
eventAction: "Translation program link (no results)",
eventName: "/contributing/translation-program",
})
}
/>

<LanguagePickerFooter onTranslationProgramClick={handleBaseLinkClose} />
</PopoverContent>
</Popover>
)
}

if (!item) return 0
const LanguagePickerMenu = ({ languages, onClose, onSelect }) => {
const { t } = useTranslation("common")

const { localeOption, sourceName, targetName, englishName } = item
return (
<Command
className="gap-2 p-4"
filter={(value: string, search: string) => {
const item = languages.find((name) => name.localeOption === value)

if (!item) return 0

const { localeOption, sourceName, targetName, englishName } = item

if (
(localeOption + sourceName + targetName + englishName)
.toLowerCase()
.includes(search.toLowerCase())
) {
return 1
}

return 0
}}
>
<div className="text-xs text-body-medium">
{t("page-languages-filter-label")}{" "}
<span className="lowercase">
({languages.length} {t("common:languages")})
</span>
</div>

<CommandInput
placeholder={t("page-languages-filter-placeholder")}
className="h-9"
kbdShortcut="\"
/>

<CommandList className="max-h-[75vh]">
<CommandEmpty className="py-0 text-left text-base">
<NoResultsCallout onClose={onClose} />
</CommandEmpty>
<CommandGroup className="p-0">
{languages.map((displayInfo) => (
<MenuItem
key={"item-" + displayInfo.localeOption}
displayInfo={displayInfo}
onSelect={onSelect}
/>
))}
</CommandGroup>
</CommandList>
</Command>
)
}

if (
(localeOption + sourceName + targetName + englishName)
.toLowerCase()
.includes(search.toLowerCase())
) {
return 1
}
const LanguagePickerFooter = ({ onTranslationProgramClick }) => {
const { t } = useTranslation("common")

return 0
}}
return (
<div className="sticky bottom-0 flex justify-center border-t-2 border-primary bg-primary-low-contrast p-3">
<p className="text-center text-xs text-body">
{t("page-languages-recruit-community")}{" "}
{/* TODO migrate once #13411 is merged */}
<BaseLink
href="/contributing/translation-program"
onClick={onTranslationProgramClick}
>
<div className="text-xs text-body-medium">
{t("page-languages-filter-label")}{" "}
<span className="lowercase">
({languages.length} {t("common:languages")})
</span>
</div>

<CommandInput
placeholder={t("page-languages-filter-placeholder")}
className="h-9"
kbdShortcut="\"
/>

<CommandList className="max-h-[75vh]">
<CommandEmpty className="py-0 text-left text-base">
<NoResultsCallout
onClose={() =>
onClose({
eventAction: "Translation program link (no results)",
eventName: "/contributing/translation-program",
})
}
/>
</CommandEmpty>
<CommandGroup className="p-0">
{languages.map((displayInfo) => (
<MenuItem
key={"item-" + displayInfo.localeOption}
displayInfo={displayInfo}
onSelect={handleMenuItemSelect}
/>
))}
</CommandGroup>
</CommandList>
</Command>

{/* Footer callout */}
<div className="sticky bottom-0 flex justify-center border-t-2 border-primary bg-primary-low-contrast p-3">
<p className="text-center text-xs text-body">
{t("page-languages-recruit-community")}{" "}
{/* TODO migrate once #13411 is merged */}
<BaseLink
href="/contributing/translation-program"
onClick={handleBaseLinkClose}
>
{t("common:learn-more")}
</BaseLink>
</p>
</div>
</PopoverContent>
</Popover>
{t("common:learn-more")}
</BaseLink>
</p>
</div>
)
}

Expand Down
1 change: 0 additions & 1 deletion src/components/LanguagePicker/useLanguagePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,6 @@ export const useLanguagePicker = (handleClose?: () => void) => {
}

return {
t,
disclosure: { isOpen, setValue, onOpen, onClose },
languages,
}
Expand Down
4 changes: 1 addition & 3 deletions src/components/Nav/Desktop/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,7 @@ const DesktopNavMenu = ({ toggleColorMode }: DesktopNavMenuProps) => {
/>

{/* Locale-picker menu */}
<LanguagePicker
// TODO w="xs"
>
<LanguagePicker>
<Button
name={DESKTOP_LANGUAGE_BUTTON_NAME}
ref={languagePickerRef}
Expand Down
5 changes: 1 addition & 4 deletions src/components/Nav/Mobile/MenuFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,7 @@ const MenuFooter = ({
<FooterItemText>{t(themeLabelKey)}</FooterItemText>
</FooterButton>

<LanguagePicker
className="fixed inset-4 h-[calc(100vh-var(--eth-sizes-8))] w-[calc(100vw-var(--eth-sizes-8))]"
handleClose={onToggle}
>
<LanguagePicker dialog handleClose={onToggle}>
<FooterButton icon={BsTranslate} name={MOBILE_LANGUAGE_BUTTON_NAME}>
<FooterItemText>{t("languages")}</FooterItemText>
</FooterButton>
Expand Down
4 changes: 2 additions & 2 deletions src/components/ui/dialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const DialogOverlay = React.forwardRef<
<DialogPrimitive.Overlay
ref={ref}
className={cn(
"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",
"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",
className
)}
{...props}
Expand All @@ -36,7 +36,7 @@ const DialogContent = React.forwardRef<
<DialogPrimitive.Content
ref={ref}
className={cn(
"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",
"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",
className
)}
{...props}
Expand Down

0 comments on commit ed4df19

Please sign in to comment.