From eec7c66ab6254bc0f29932205f87705853ab79f2 Mon Sep 17 00:00:00 2001
From: Pablo Pettinari
Date: Sat, 27 Jul 2024 11:09:43 +0200
Subject: [PATCH 01/13] initial lang picker migration and refactor to shadcn
---
package.json | 2 +
src/components/LanguagePicker/MenuItem.tsx | 115 +++-----
.../LanguagePicker/MobileCloseBar.tsx | 16 +-
.../LanguagePicker/NoResultsCallout.tsx | 43 ++-
src/components/LanguagePicker/ProgressBar.tsx | 3 +
src/components/LanguagePicker/index.tsx | 271 ++++++------------
.../LanguagePicker/useLanguagePicker.tsx | 38 +--
src/components/Nav/Desktop/index.tsx | 59 +---
src/components/Nav/Mobile/MenuFooter.tsx | 28 +-
src/components/ui/command.tsx | 157 ++++++++++
src/components/ui/dialog.tsx | 120 ++++++++
src/components/ui/popover.tsx | 2 +-
src/hooks/useDisclosure.ts | 4 +-
tailwind.config.ts | 15 +
yarn.lock | 30 +-
15 files changed, 515 insertions(+), 388 deletions(-)
create mode 100644 src/components/ui/command.tsx
create mode 100644 src/components/ui/dialog.tsx
diff --git a/package.json b/package.json
index 2d3be73046e..7b52e5db518 100644
--- a/package.json
+++ b/package.json
@@ -35,6 +35,7 @@
"@emotion/styled": "^11.11.0",
"@hookform/resolvers": "^3.8.0",
"@radix-ui/react-accordion": "^1.2.0",
+ "@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-navigation-menu": "^1.2.0",
"@radix-ui/react-popover": "^1.1.1",
"@radix-ui/react-slot": "^1.1.0",
@@ -43,6 +44,7 @@
"chartjs-plugin-datalabels": "^2.2.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
+ "cmdk": "^1.0.0",
"embla-carousel-react": "^7.0.0",
"ethereum-blockies-base64": "^1.0.2",
"framer-motion": "^10.13.0",
diff --git a/src/components/LanguagePicker/MenuItem.tsx b/src/components/LanguagePicker/MenuItem.tsx
index c9f7a99e455..3e2116eec28 100644
--- a/src/components/LanguagePicker/MenuItem.tsx
+++ b/src/components/LanguagePicker/MenuItem.tsx
@@ -1,28 +1,22 @@
+import { ComponentPropsWithoutRef } from "react"
import { useRouter } from "next/router"
import { useTranslation } from "next-i18next"
import { BsCheck } from "react-icons/bs"
-import {
- Badge,
- Box,
- Flex,
- forwardRef,
- Icon,
- MenuItem as ChakraMenuItem,
- type MenuItemProps as ChakraMenuItemProps,
- Text,
-} from "@chakra-ui/react"
+import { Badge } from "@chakra-ui/react"
import type { LocaleDisplayInfo } from "@/lib/types"
-import { BaseLink } from "@/components/Link"
+import { cn } from "@/lib/utils/cn"
+
+import { CommandItem } from "../ui/command"
import ProgressBar from "./ProgressBar"
-type ItemProps = ChakraMenuItemProps & {
+type ItemProps = ComponentPropsWithoutRef & {
displayInfo: LocaleDisplayInfo
}
-const MenuItem = forwardRef(({ displayInfo, ...props }: ItemProps, ref) => {
+const MenuItem = ({ displayInfo, ...props }: ItemProps) => {
const {
localeOption,
sourceName,
@@ -32,7 +26,7 @@ const MenuItem = forwardRef(({ displayInfo, ...props }: ItemProps, ref) => {
isBrowserDefault,
} = displayInfo
const { t } = useTranslation("common")
- const { asPath, locale } = useRouter()
+ const { locale } = useRouter()
const isCurrent = localeOption === locale
const getProgressInfo = (approvalProgress: number, wordsApproved: number) => {
@@ -48,51 +42,37 @@ const MenuItem = forwardRef(({ displayInfo, ...props }: ItemProps, ref) => {
const { progress, words } = getProgressInfo(approvalProgress, wordsApproved)
return (
- {
- e.target.scrollIntoView({ block: "nearest" })
- }}
- scrollMarginY="8"
- _hover={{
- bg: "primary.lowContrast",
- textDecoration: "none",
- "p.language-name": { color: "primary.base" },
- }}
- _focus={{ bg: "primary.lowContrast" }}
- sx={{
- p: {
- textDecoration: "none",
- overflow: "hidden",
- textOverflow: "ellipsis",
- whiteSpace: "nowrap",
- },
- }}
- href={asPath}
- locale={localeOption}
+
-
-
-
-
+
+
+
{targetName}
-
+
+ {/* TODO */}
{isBrowserDefault && (
{
{t("page-languages-browser-default")}
)}
-
-
- {sourceName}
-
-
+
+
{sourceName}
+
{isCurrent && (
-
+
)}
-
-
+
+
{progress} {t("page-languages-translated")} • {words}{" "}
{t("page-languages-words")}
-
+
-
+
)
-})
+}
export default MenuItem
diff --git a/src/components/LanguagePicker/MobileCloseBar.tsx b/src/components/LanguagePicker/MobileCloseBar.tsx
index c54bba831ef..6238aadfed2 100644
--- a/src/components/LanguagePicker/MobileCloseBar.tsx
+++ b/src/components/LanguagePicker/MobileCloseBar.tsx
@@ -1,8 +1,7 @@
import { MouseEventHandler } from "react"
import { useTranslation } from "next-i18next"
-import { Flex } from "@chakra-ui/react"
-import { Button } from "@/components/Buttons"
+import { Button } from "../../../tailwind/ui/buttons/Button"
type MobileCloseBarProps = {
handleClick: MouseEventHandler
@@ -12,17 +11,10 @@ export const MobileCloseBar = ({ handleClick }: MobileCloseBarProps) => {
const { t } = useTranslation()
return (
-
-
)
diff --git a/src/components/Nav/Mobile/MenuFooter.tsx b/src/components/Nav/Mobile/MenuFooter.tsx
index da537b82d81..acbe645064f 100644
--- a/src/components/Nav/Mobile/MenuFooter.tsx
+++ b/src/components/Nav/Mobile/MenuFooter.tsx
@@ -1,12 +1,7 @@
import { useTranslation } from "next-i18next"
import { BsTranslate } from "react-icons/bs"
import { MdBrightness2, MdSearch, MdWbSunny } from "react-icons/md"
-import {
- DrawerFooter,
- Grid,
- MenuButton,
- useColorModeValue,
-} from "@chakra-ui/react"
+import { DrawerFooter, Grid, useColorModeValue } from "@chakra-ui/react"
import LanguagePicker from "@/components/LanguagePicker"
@@ -57,26 +52,13 @@ const MenuFooter = ({
{t(themeLabelKey)}
-
+ {/* TODO migrate once #13449 is merged */}
+
{t("languages")}
-
+
diff --git a/src/components/ui/command.tsx b/src/components/ui/command.tsx
new file mode 100644
index 00000000000..5e165866111
--- /dev/null
+++ b/src/components/ui/command.tsx
@@ -0,0 +1,157 @@
+import * as React from "react"
+import { Command as CommandPrimitive } from "cmdk"
+import { Search } from "lucide-react"
+import { type DialogProps } from "@radix-ui/react-dialog"
+
+import { Dialog, DialogContent } from "@/components/ui/dialog"
+
+import { cn } from "@/lib/utils/cn"
+
+const Command = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+Command.displayName = CommandPrimitive.displayName
+
+interface CommandDialogProps extends DialogProps {}
+
+const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
+ return (
+
+ )
+}
+
+const CommandInput = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+
+))
+
+CommandInput.displayName = CommandPrimitive.Input.displayName
+
+const CommandList = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+
+CommandList.displayName = CommandPrimitive.List.displayName
+
+const CommandEmpty = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+
+CommandEmpty.displayName = CommandPrimitive.Empty.displayName
+
+const CommandGroup = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+
+CommandGroup.displayName = CommandPrimitive.Group.displayName
+
+const CommandSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+CommandSeparator.displayName = CommandPrimitive.Separator.displayName
+
+const CommandItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+
+CommandItem.displayName = CommandPrimitive.Item.displayName
+
+const CommandShortcut = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => {
+ return (
+
+ )
+}
+CommandShortcut.displayName = "CommandShortcut"
+
+export {
+ Command,
+ CommandDialog,
+ CommandEmpty,
+ CommandGroup,
+ CommandInput,
+ CommandItem,
+ CommandList,
+ CommandSeparator,
+ CommandShortcut,
+}
diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx
new file mode 100644
index 00000000000..947ea462c0b
--- /dev/null
+++ b/src/components/ui/dialog.tsx
@@ -0,0 +1,120 @@
+import * as React from "react"
+import { X } from "lucide-react"
+import * as DialogPrimitive from "@radix-ui/react-dialog"
+
+import { cn } from "@/lib/utils/cn"
+
+const Dialog = DialogPrimitive.Root
+
+const DialogTrigger = DialogPrimitive.Trigger
+
+const DialogPortal = DialogPrimitive.Portal
+
+const DialogClose = DialogPrimitive.Close
+
+const DialogOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogOverlay.displayName = DialogPrimitive.Overlay.displayName
+
+const DialogContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+ {children}
+
+
+ Close
+
+
+
+))
+DialogContent.displayName = DialogPrimitive.Content.displayName
+
+const DialogHeader = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+DialogHeader.displayName = "DialogHeader"
+
+const DialogFooter = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+DialogFooter.displayName = "DialogFooter"
+
+const DialogTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogTitle.displayName = DialogPrimitive.Title.displayName
+
+const DialogDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DialogDescription.displayName = DialogPrimitive.Description.displayName
+
+export {
+ Dialog,
+ DialogClose,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogOverlay,
+ DialogPortal,
+ DialogTitle,
+ DialogTrigger,
+}
diff --git a/src/components/ui/popover.tsx b/src/components/ui/popover.tsx
index ee8322f3345..e83b7de3107 100644
--- a/src/components/ui/popover.tsx
+++ b/src/components/ui/popover.tsx
@@ -17,7 +17,7 @@ const PopoverContent = React.forwardRef<
align={align}
sideOffset={sideOffset}
className={cn(
- "bg-popover text-popover-foreground z-50 w-72 rounded-md border p-4 shadow-md outline-none 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
+ "text-popover-foreground z-popover w-72 rounded-md border bg-background p-4 shadow-md outline-none 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-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className
)}
{...props}
diff --git a/src/hooks/useDisclosure.ts b/src/hooks/useDisclosure.ts
index 2bb5612be23..f5a8ce11d1b 100644
--- a/src/hooks/useDisclosure.ts
+++ b/src/hooks/useDisclosure.ts
@@ -5,13 +5,15 @@ import { useBoolean } from "usehooks-ts"
* modal, dropdown, or any other component that can be opened and closed.
*/
function useDisclosure(defaultValue = false) {
- const { value, setTrue, setFalse, toggle } = useBoolean(defaultValue)
+ const { value, setTrue, setFalse, toggle, setValue } =
+ useBoolean(defaultValue)
return {
isOpen: value,
onOpen: setTrue,
onClose: setFalse,
onToggle: toggle,
+ setValue,
}
}
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 5e6cb29630a..5e8ffb5ddd9 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -37,6 +37,21 @@ const config = {
sm: "1.5",
base: "1.6",
},
+ zIndex: {
+ hide: "-1",
+ auto: "auto",
+ base: "0",
+ docked: "10",
+ dropdown: "1000",
+ sticky: "1100",
+ banner: "1200",
+ overlay: "1300",
+ modal: "1400",
+ popover: "1500",
+ skipLink: "1600",
+ toast: "1700",
+ tooltip: "1800",
+ },
colors: {
primary: {
DEFAULT: "var(--primary)",
diff --git a/yarn.lock b/yarn.lock
index 4790756573b..93346cef5a5 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3837,7 +3837,7 @@
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8"
integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==
-"@radix-ui/react-dialog@^1.0.5":
+"@radix-ui/react-dialog@1.0.5", "@radix-ui/react-dialog@^1.0.5":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300"
integrity sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==
@@ -3858,6 +3858,26 @@
aria-hidden "^1.1.1"
react-remove-scroll "2.5.5"
+"@radix-ui/react-dialog@^1.1.1":
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz#4906507f7b4ad31e22d7dad69d9330c87c431d44"
+ integrity sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==
+ dependencies:
+ "@radix-ui/primitive" "1.1.0"
+ "@radix-ui/react-compose-refs" "1.1.0"
+ "@radix-ui/react-context" "1.1.0"
+ "@radix-ui/react-dismissable-layer" "1.1.0"
+ "@radix-ui/react-focus-guards" "1.1.0"
+ "@radix-ui/react-focus-scope" "1.1.0"
+ "@radix-ui/react-id" "1.1.0"
+ "@radix-ui/react-portal" "1.1.1"
+ "@radix-ui/react-presence" "1.1.0"
+ "@radix-ui/react-primitive" "2.0.0"
+ "@radix-ui/react-slot" "1.1.0"
+ "@radix-ui/react-use-controllable-state" "1.1.0"
+ aria-hidden "^1.1.1"
+ react-remove-scroll "2.5.7"
+
"@radix-ui/react-direction@1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc"
@@ -7037,6 +7057,14 @@ clsx@^2.1.1:
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
+cmdk@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/cmdk/-/cmdk-1.0.0.tgz#0a095fdafca3dfabed82d1db78a6262fb163ded9"
+ integrity sha512-gDzVf0a09TvoJ5jnuPvygTB77+XdOSwEmJ88L6XPFPlv7T3RxbP9jgenfylrAMD0+Le1aO0nVjQUzl2g+vjz5Q==
+ dependencies:
+ "@radix-ui/react-dialog" "1.0.5"
+ "@radix-ui/react-primitive" "1.0.3"
+
collapse-white-space@^1.0.2:
version "1.0.6"
resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287"
From 895203521c02ebb2050a6057a93e67d97a970fc6 Mon Sep 17 00:00:00 2001
From: Pablo Pettinari
Date: Sun, 28 Jul 2024 11:47:10 +0200
Subject: [PATCH 02/13] migrate progress bar
---
package.json | 1 +
src/components/LanguagePicker/ProgressBar.tsx | 21 ++++-----------
src/components/ui/progress.tsx | 26 +++++++++++++++++++
yarn.lock | 8 ++++++
4 files changed, 40 insertions(+), 16 deletions(-)
create mode 100644 src/components/ui/progress.tsx
diff --git a/package.json b/package.json
index 7b52e5db518..d2c3fab9209 100644
--- a/package.json
+++ b/package.json
@@ -38,6 +38,7 @@
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-navigation-menu": "^1.2.0",
"@radix-ui/react-popover": "^1.1.1",
+ "@radix-ui/react-progress": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@socialgouv/matomo-next": "^1.8.0",
"chart.js": "^4.4.2",
diff --git a/src/components/LanguagePicker/ProgressBar.tsx b/src/components/LanguagePicker/ProgressBar.tsx
index 1ea42523757..327ae272ba8 100644
--- a/src/components/LanguagePicker/ProgressBar.tsx
+++ b/src/components/LanguagePicker/ProgressBar.tsx
@@ -1,22 +1,11 @@
-import { Progress, ProgressProps } from "@chakra-ui/react"
+import { ComponentPropsWithoutRef } from "react"
-type ProgressBarProps = Pick
+import { Progress } from "../ui/progress"
+
+type ProgressBarProps = Pick, "value">
-{
- /* TODO migrate */
-}
const ProgressBar = ({ value }: ProgressBarProps) => (
-
+
)
export default ProgressBar
diff --git a/src/components/ui/progress.tsx b/src/components/ui/progress.tsx
new file mode 100644
index 00000000000..46c7aeca193
--- /dev/null
+++ b/src/components/ui/progress.tsx
@@ -0,0 +1,26 @@
+import * as React from "react"
+import * as ProgressPrimitive from "@radix-ui/react-progress"
+
+import { cn } from "@/lib/utils/cn"
+
+const Progress = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, value, ...props }, ref) => (
+
+
+
+))
+Progress.displayName = ProgressPrimitive.Root.displayName
+
+export { Progress }
diff --git a/yarn.lock b/yarn.lock
index 93346cef5a5..c80989d52e7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4057,6 +4057,14 @@
dependencies:
"@radix-ui/react-slot" "1.1.0"
+"@radix-ui/react-progress@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@radix-ui/react-progress/-/react-progress-1.1.0.tgz#28c267885ec154fc557ec7a66cb462787312f7e2"
+ integrity sha512-aSzvnYpP725CROcxAOEBVZZSIQVQdHgBr2QQFKySsaD14u8dNT0batuXI+AAGDdAHfXH8rbnHmjYFqVJ21KkRg==
+ dependencies:
+ "@radix-ui/react-context" "1.1.0"
+ "@radix-ui/react-primitive" "2.0.0"
+
"@radix-ui/react-slot@1.0.2", "@radix-ui/react-slot@^1.0.2":
version "1.0.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab"
From 87ddb2fc73ccd7c4ba3b1e1a09f7c23f01456767 Mon Sep 17 00:00:00 2001
From: Pablo Pettinari
Date: Sun, 28 Jul 2024 12:20:10 +0200
Subject: [PATCH 03/13] migrate badge used in language picker
---
src/components/LanguagePicker/MenuItem.tsx | 12 ++-----
src/components/ui/badge.tsx | 40 ++++++++++++++++++++++
tailwind.config.ts | 1 +
3 files changed, 44 insertions(+), 9 deletions(-)
create mode 100644 src/components/ui/badge.tsx
diff --git a/src/components/LanguagePicker/MenuItem.tsx b/src/components/LanguagePicker/MenuItem.tsx
index 3e2116eec28..fc4873ca98e 100644
--- a/src/components/LanguagePicker/MenuItem.tsx
+++ b/src/components/LanguagePicker/MenuItem.tsx
@@ -2,12 +2,12 @@ import { ComponentPropsWithoutRef } from "react"
import { useRouter } from "next/router"
import { useTranslation } from "next-i18next"
import { BsCheck } from "react-icons/bs"
-import { Badge } from "@chakra-ui/react"
import type { LocaleDisplayInfo } from "@/lib/types"
import { cn } from "@/lib/utils/cn"
+import { Badge } from "../ui/badge"
import { CommandItem } from "../ui/command"
import ProgressBar from "./ProgressBar"
@@ -75,14 +75,8 @@ const MenuItem = ({ displayInfo, ...props }: ItemProps) => {
{/* TODO */}
{isBrowserDefault && (
{t("page-languages-browser-default")}
diff --git a/src/components/ui/badge.tsx b/src/components/ui/badge.tsx
new file mode 100644
index 00000000000..5d453ef21ca
--- /dev/null
+++ b/src/components/ui/badge.tsx
@@ -0,0 +1,40 @@
+import * as React from "react"
+import { cva, type VariantProps } from "class-variance-authority"
+
+import { cn } from "@/lib/utils/cn"
+
+/**
+ * TODO: finish migration. Needs to implement the DS badge styles. Currently is
+ * only used in the LanguagePicker component.
+ */
+const badgeVariants = cva(
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
+ {
+ variants: {
+ variant: {
+ default:
+ "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
+ secondary:
+ "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
+ destructive:
+ "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
+ outline: "text-foreground",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ },
+ }
+)
+
+export interface BadgeProps
+ extends React.HTMLAttributes,
+ VariantProps {}
+
+function Badge({ className, variant, ...props }: BadgeProps) {
+ return (
+
+ )
+}
+
+export { Badge, badgeVariants }
diff --git a/tailwind.config.ts b/tailwind.config.ts
index 5e8ffb5ddd9..f53ccbc9de7 100644
--- a/tailwind.config.ts
+++ b/tailwind.config.ts
@@ -26,6 +26,7 @@ const config = {
md: ["1rem", "1.6"], // [md, base]
sm: ["0.875rem", "1.6"], // [sm, base]
xs: ["0.75rem", "1.6"], // [xs, base]
+ "2xs": ["0.625rem", "1.6"], // [2xs, base]
},
lineHeight: {
"6xs": "1.1",
From 9d11e3ad9e7544924900bd790ef3cf1da5ea5bc8 Mon Sep 17 00:00:00 2001
From: Pablo Pettinari
Date: Sun, 28 Jul 2024 12:22:53 +0200
Subject: [PATCH 04/13] add event listener for shortcut to open the language
picker
---
src/components/LanguagePicker/index.tsx | 14 ++++++++------
1 file changed, 8 insertions(+), 6 deletions(-)
diff --git a/src/components/LanguagePicker/index.tsx b/src/components/LanguagePicker/index.tsx
index c3053f9f51c..373a85117b0 100644
--- a/src/components/LanguagePicker/index.tsx
+++ b/src/components/LanguagePicker/index.tsx
@@ -19,6 +19,8 @@ import { MobileCloseBar } from "./MobileCloseBar"
import NoResultsCallout from "./NoResultsCallout"
import { useLanguagePicker } from "./useLanguagePicker"
+import { useEventListener } from "@/hooks/useEventListener"
+
type LanguagePickerProps = {
children: React.ReactNode
className?: string
@@ -38,17 +40,17 @@ const LanguagePicker = ({
// TODO: Implement this
// handleInputFocus,
} = useLanguagePicker(handleClose)
- const { isOpen, setValue, onClose } = disclosure
+ const { isOpen, setValue, onClose, onOpen } = disclosure
/**
* Adds a keydown event listener to focus filter input (\).
* @param {string} event - The keydown event.
*/
- // useEventListener("keydown", (e) => {
- // if (e.key !== "\\") return
- // e.preventDefault()
- // inputRef.current?.focus()
- // })
+ useEventListener("keydown", (e) => {
+ if (e.key !== "\\") return
+ e.preventDefault()
+ onOpen()
+ })
// onClick handlers
const handleMobileCloseBarClick = () => onClose()
From d2a6906d3ab1ac9b41beb4ba4f722d4412e8df3e Mon Sep 17 00:00:00 2001
From: Pablo Pettinari
Date: Sun, 28 Jul 2024 12:31:04 +0200
Subject: [PATCH 05/13] cleanup
---
src/components/LanguagePicker/MenuItem.tsx | 1 -
src/components/LanguagePicker/index.tsx | 8 +------
.../LanguagePicker/useLanguagePicker.tsx | 24 -------------------
3 files changed, 1 insertion(+), 32 deletions(-)
diff --git a/src/components/LanguagePicker/MenuItem.tsx b/src/components/LanguagePicker/MenuItem.tsx
index fc4873ca98e..a5acc4ef5a4 100644
--- a/src/components/LanguagePicker/MenuItem.tsx
+++ b/src/components/LanguagePicker/MenuItem.tsx
@@ -72,7 +72,6 @@ const MenuItem = ({ displayInfo, ...props }: ItemProps) => {
>
{targetName}
- {/* TODO */}
{isBrowserDefault && (
{
const { asPath, push } = useRouter()
- const {
- t,
- disclosure,
- filteredNames,
- // TODO: Implement this
- // handleInputFocus,
- } = useLanguagePicker(handleClose)
+ const { t, disclosure, filteredNames } = useLanguagePicker(handleClose)
const { isOpen, setValue, onClose, onOpen } = disclosure
/**
diff --git a/src/components/LanguagePicker/useLanguagePicker.tsx b/src/components/LanguagePicker/useLanguagePicker.tsx
index d1215b20321..3750fa23fbd 100644
--- a/src/components/LanguagePicker/useLanguagePicker.tsx
+++ b/src/components/LanguagePicker/useLanguagePicker.tsx
@@ -26,14 +26,6 @@ export const useLanguagePicker = (handleClose?: () => void) => {
const [filteredNames, setFilteredNames] = useState([])
- // Used to only send one matomo event for users who focus the filter input
- const [hasFocusedInput, setHasFocusedInput] = useState(false)
-
- // Reset if user switches languages
- useEffect(() => {
- setHasFocusedInput(false)
- }, [locale])
-
// perform all the filtering and mapping when the filter value change
useEffect(() => {
const locales = filterRealLocales(rawLocales)
@@ -187,25 +179,9 @@ export const useLanguagePicker = (handleClose?: () => void) => {
)
}
- /**
- * Send Matomo event when user focuses in the filter input.
- * Only send once per user per session per language
- * @returns void
- */
- const handleInputFocus = (): void => {
- if (hasFocusedInput) return
- trackCustomEvent({
- ...eventBase,
- eventAction: "Filter input",
- eventName: "Focused inside filter input",
- })
- setHasFocusedInput(true)
- }
-
return {
t,
disclosure: { isOpen, setValue, onOpen, onClose },
filteredNames,
- handleInputFocus,
}
}
From 9aa5d3f747fe858ffd3cd4ad47ed9b5df612b4b9 Mon Sep 17 00:00:00 2001
From: Pablo Pettinari
Date: Sun, 28 Jul 2024 19:01:48 +0200
Subject: [PATCH 06/13] refactor: move localeToDisplayInfo to its own function
+ remove useEffect for filtering
---
src/components/LanguagePicker/index.tsx | 10 +-
.../LanguagePicker/localeToDisplayInfo.ts | 95 ++++++++++++
.../LanguagePicker/useLanguagePicker.tsx | 135 ++++--------------
3 files changed, 124 insertions(+), 116 deletions(-)
create mode 100644 src/components/LanguagePicker/localeToDisplayInfo.ts
diff --git a/src/components/LanguagePicker/index.tsx b/src/components/LanguagePicker/index.tsx
index 91b482931ff..4fc9424f72b 100644
--- a/src/components/LanguagePicker/index.tsx
+++ b/src/components/LanguagePicker/index.tsx
@@ -33,7 +33,7 @@ const LanguagePicker = ({
className,
}: LanguagePickerProps) => {
const { asPath, push } = useRouter()
- const { t, disclosure, filteredNames } = useLanguagePicker(handleClose)
+ const { t, disclosure, languages } = useLanguagePicker(handleClose)
const { isOpen, setValue, onClose, onOpen } = disclosure
/**
@@ -82,9 +82,7 @@ const LanguagePicker = ({
{
- const item = filteredNames.find(
- (name) => name.localeOption === value
- )
+ const item = languages.find((name) => name.localeOption === value)
if (!item) return 0
@@ -104,7 +102,7 @@ const LanguagePicker = ({
{t("page-languages-filter-label")}{" "}
- ({filteredNames.length} {t("common:languages")})
+ ({languages.length} {t("common:languages")})
@@ -126,7 +124,7 @@ const LanguagePicker = ({
/>
- {filteredNames.map((displayInfo) => (
+ {languages.map((displayInfo) => (