Skip to content

Commit

Permalink
feat: custom language picker (#311)
Browse files Browse the repository at this point in the history
  • Loading branch information
bryanlundberg authored Jun 5, 2024
1 parent 304a9e5 commit 79bcfd5
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 113 deletions.
28 changes: 25 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@types/react": "18.2.21",
"@types/react-dom": "18.2.7",
"autoprefixer": "10.4.15",
"country-flag-icons": "^1.5.11",
"cube-solver": "^2.4.1",
"cubing": "^0.44.1",
"date-fns": "^2.30.0",
Expand All @@ -39,6 +40,7 @@
"recharts": "^2.8.0",
"scrambow": "^1.8.1",
"sharp": "0.32.6",
"tailwind-merge": "^2.3.0",
"tailwindcss": "^3.4.0",
"ts-deepmerge": "^7.0.0",
"typescript": "5.2.2",
Expand Down
4 changes: 2 additions & 2 deletions src/app/[locale]/solves/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export default function SolvesPage() {
onClick={() => setIsOpenMoveModal(true)}
icon={<FolderArrowDownIcon className="w-4 h-4" />}
label={t("Inputs.move-all")}
isDisabled={
disabled={
selectedCube && selectedCube.solves.session.length > 0
? false
: true
Expand All @@ -67,7 +67,7 @@ export default function SolvesPage() {
onClick={() => setIsOpenDeleteModal(true)}
icon={<TrashIcon className="w-4 h-4" />}
label={t("Inputs.trash-all")}
isDisabled={
disabled={
selectedCube && selectedCube.solves.session.length > 0
? false
: true
Expand Down
31 changes: 19 additions & 12 deletions src/components/button/Button.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
import { ButtonContainer } from "./ButtonContainer";
import { ButtonContent } from "./ButtonContent";
import { twMerge } from "tailwind-merge";

interface Button {
interface Button extends React.HTMLAttributes<HTMLButtonElement> {
className?: string;
icon?: React.ReactNode;
label: string;
onClick: () => void;
minimalistic?: boolean;
isDisabled?: boolean;
disabled?: boolean;
}

export default function Button({
className,
icon,
label,
onClick,
disabled = false,
minimalistic = true,
isDisabled = false
...props
}: Button) {
return (
<>
<ButtonContainer className={className} handleClick={onClick} isDisabled={isDisabled}>
<ButtonContent icon={icon} label={label} minimalistic={minimalistic} />
</ButtonContainer>
</>
<button
{...props}
type="button"
className={twMerge(
`min-h-9 px-3 transition duration-200 rounded-md border font-medium justify-center align-middle light:hover:bg-neutral-200 light:hover:border-neutral-400 light:text-neutral-950 light:border-neutral-200 dark:hover:bg-zinc-700 dark:hover:border-zinc-500 dark:border-zinc-800 text-md disabled:bg-zinc-900 dark:disabled:border-zinc-500 dark:disabled:bg-zinc-700 light:disabled:bg-neutral-200 light:disabled:border-neutral-300 disabled:cursor-normal`,
className
)}
disabled={disabled}
>
<div className="flex items-center justify-between gap-1">
{icon}
<div className={`${minimalistic ? "hidden" : "inline"}`}>{label}</div>
</div>
</button>
);
}
26 changes: 0 additions & 26 deletions src/components/button/ButtonContainer.tsx

This file was deleted.

16 changes: 0 additions & 16 deletions src/components/button/ButtonContent.tsx

This file was deleted.

65 changes: 47 additions & 18 deletions src/components/menu-settings/MenuSelectLanguage.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,77 @@
"use client";

import { MenuSection } from "./MenuSection";
import { useLocale, useTranslations } from "next-intl";
import { languages } from "@/lib/const/languages";
import { sort } from "fast-sort";
import { ChangeEvent } from "react";
import { useRef } from "react";
import { useRouter } from "@/navigation";
import { useSettingsModalStore } from "@/store/SettingsModalStore";
import { GlobeAltIcon } from "@heroicons/react/24/solid";
import { Button } from "../button";
import useClickOutside from "@/hooks/useClickOutside";
import useOpenClose from "@/hooks/useOpenClose";

export default function MenuSelectLanguage() {
const { isOpen, close } = useOpenClose(false);
const componentRef = useRef<HTMLDivElement | null>(null);
useClickOutside(componentRef, () => close());
const { setSettingsOpen } = useSettingsModalStore();
const t = useTranslations("Index.Settings-menu");
const router = useRouter();
const locale = useLocale();

function onSelectChange(event: ChangeEvent<HTMLSelectElement>) {
const nextLocale = event.target.value;
function onSelectChange(event: any) {
const nextLocale = event.target.id;
setSettingsOpen(false);
router.replace(`${window.location.origin}/${nextLocale}`);
}
const localeData = (locale: string) => {
const language = languages.find((item) => item.code === locale);
if (!language) return languages[0];
return language;
};

const labelData = localeData(locale)?.name.toString();
const flagIcon = localeData(locale)?.flag;
return (
<>
<MenuSection
icon={<GlobeAltIcon className="w-6 h-6" />}
title={t("locale")}
>
<div className="flex justify-between">
<div className="flex justify-between ">
<div className="ms-12">{t("language")}</div>
<div className="me-6">
<select
value={locale}
className="px-2 py-1 bg-gray-200 rounded-md outline-none w-36"
onChange={(e: any) => onSelectChange(e)}
>
{sort(languages)
.asc((u) => u.name)
.map((lang) => {
<div className="me-6 relative">
<Button
onClick={() => close()}
label={labelData}
icon={flagIcon}
className="min-w-32 max-w-40 text-black font-mono"
minimalistic={false}
/>

{/* menu options */}

{isOpen && (
<div
ref={componentRef}
className="absolute top-10 right-0 border bg-white z-10 w-full max-h-96 overflow-auto"
>
{languages.map((item) => {
return (
<option key={lang.code} value={lang.code}>
{lang.name}
</option>
<div
key={item.code}
id={item.code}
className="flex items-center gap-2 p-2 hover:bg-neutral-100 hover:cursor-pointer"
onClick={(e: any) => onSelectChange(e)}
>
{item.flag}
{item.name}
</div>
);
})}
</select>
</div>
)}
</div>
</div>
</MenuSection>
Expand Down
36 changes: 0 additions & 36 deletions src/lib/const/languages.ts

This file was deleted.

66 changes: 66 additions & 0 deletions src/lib/const/languages.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { locales } from "@/navigation";
import {
US,
ES,
FR,
DE,
JP,
CN,
RU,
IN,
PT,
IT,
KR,
NL,
SE,
TR,
PL,
VN,
FI,
UA,
CZ,
RO,
NO,
MY,
HU,
ID,
BD,
SK,
EE,
} from "country-flag-icons/react/3x2";

interface LanguageProp {
code: (typeof locales)[number];
name: string;
flag: React.ReactNode;
}

export const languages: LanguageProp[] = [
{ code: "en", name: "English", flag: <US className="w-4 h-4" /> },
{ code: "es", name: "Español", flag: <ES className="w-4 h-4" /> },
{ code: "fr", name: "Français", flag: <FR className="w-4 h-4" /> },
{ code: "de", name: "Deutsch", flag: <DE className="w-4 h-4" /> },
{ code: "ja", name: "日本語", flag: <JP className="w-4 h-4" /> },
{ code: "zh", name: "中文", flag: <CN className="w-4 h-4" /> },
{ code: "ru", name: "Русский", flag: <RU className="w-4 h-4" /> },
{ code: "hi", name: "हिन्दी", flag: <IN className="w-4 h-4" /> },
{ code: "pt", name: "Português", flag: <PT className="w-4 h-4" /> },
{ code: "it", name: "Italiano", flag: <IT className="w-4 h-4" /> },
{ code: "ko", name: "한국어", flag: <KR className="w-4 h-4" /> },
{ code: "nl", name: "Nederlands", flag: <NL className="w-4 h-4" /> },
{ code: "sv", name: "Svenska", flag: <SE className="w-4 h-4" /> },
{ code: "tr", name: "Türkçe", flag: <TR className="w-4 h-4" /> },
{ code: "pl", name: "Polski", flag: <PL className="w-4 h-4" /> },
{ code: "vi", name: "Tiếng Việt", flag: <VN className="w-4 h-4" /> },
{ code: "fi", name: "Suomi", flag: <FI className="w-4 h-4" /> },
{ code: "uk", name: "Українська", flag: <UA className="w-4 h-4" /> },
{ code: "cs", name: "Čeština", flag: <CZ className="w-4 h-4" /> },
{ code: "ro", name: "Română", flag: <RO className="w-4 h-4" /> },
{ code: "no", name: "Norsk", flag: <NO className="w-4 h-4" /> },
{ code: "ms", name: "Bahasa Melayu", flag: <MY className="w-4 h-4" /> },
{ code: "hu", name: "Magyar", flag: <HU className="w-4 h-4" /> },
{ code: "id", name: "Bahasa Indonesia", flag: <ID className="w-4 h-4" /> },
{ code: "bn", name: "বাংলা", flag: <BD className="w-4 h-4" /> },
{ code: "sk", name: "Slovenčina", flag: <SK className="w-4 h-4" /> },
{ code: "et", name: "Eesti", flag: <EE className="w-4 h-4" /> },
];

0 comments on commit 79bcfd5

Please sign in to comment.