Translation support for dropdown.tsx component
This commit is contained in:
parent
fe85a1c33a
commit
0f7297aa70
6 changed files with 81 additions and 29 deletions
|
|
@ -24,6 +24,10 @@
|
||||||
"tab": "Tab",
|
"tab": "Tab",
|
||||||
"custom": "Customization",
|
"custom": "Customization",
|
||||||
"misc": "Misc"
|
"misc": "Misc"
|
||||||
|
},
|
||||||
|
"proxy": {
|
||||||
|
"title": "Proxy",
|
||||||
|
"automatic": "Automatic"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,10 @@
|
||||||
"tab": "タブ",
|
"tab": "タブ",
|
||||||
"custom": "カスタマイズ",
|
"custom": "カスタマイズ",
|
||||||
"misc": "その他"
|
"misc": "その他"
|
||||||
|
},
|
||||||
|
"proxy": {
|
||||||
|
"title": "プロキシ",
|
||||||
|
"automatic": "自動"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { HeaderRoute } from "../components/HeaderRoute";
|
import { HeaderRoute } from "../components/HeaderRoute";
|
||||||
|
|
||||||
export function Home() {
|
export function Home() {
|
||||||
const [isFocused, setIsFocused] = useState(false);
|
const [isFocused, setIsFocused] = useState(false);
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,29 @@
|
||||||
import { useState } from "preact/hooks";
|
import { useState, useEffect } from "preact/hooks";
|
||||||
|
|
||||||
const Dropdown = ({ name, options }: { name: string; options: string[] }) => {
|
interface Option {
|
||||||
|
id: string;
|
||||||
|
label: string; // Translations CAN be passed
|
||||||
|
}
|
||||||
|
|
||||||
|
const Dropdown = ({
|
||||||
|
name,
|
||||||
|
options,
|
||||||
|
storageKey
|
||||||
|
}: {
|
||||||
|
name: string;
|
||||||
|
storageKey: string;
|
||||||
|
options: Option[];
|
||||||
|
}) => {
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [choice, setChoice] = useState(
|
|
||||||
localStorage.getItem(name) || options[0]
|
const [choice, setChoice] = useState(() => {
|
||||||
);
|
return localStorage.getItem(storageKey) || options[0]?.id || "";
|
||||||
|
});
|
||||||
|
|
||||||
|
// update on localstorage change
|
||||||
|
useEffect(() => {
|
||||||
|
setChoice(localStorage.getItem(storageKey) || options[0]?.id || "");
|
||||||
|
}, [storageKey, options]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative text-center">
|
<div className="relative text-center">
|
||||||
|
|
@ -13,20 +32,22 @@ const Dropdown = ({ name, options }: { name: string; options: string[] }) => {
|
||||||
className="font-roboto flex h-14 w-56 cursor-pointer flex-col items-center justify-center rounded-2xl border border-input-border-color bg-input text-center text-xl"
|
className="font-roboto flex h-14 w-56 cursor-pointer flex-col items-center justify-center rounded-2xl border border-input-border-color bg-input text-center text-xl"
|
||||||
onClick={() => setIsOpen(!isOpen)}
|
onClick={() => setIsOpen(!isOpen)}
|
||||||
>
|
>
|
||||||
<div className="select-none">{choice}</div>
|
<div className="select-none">
|
||||||
|
{options.find((o) => o.id === choice)?.label}
|
||||||
|
</div>
|
||||||
{isOpen && (
|
{isOpen && (
|
||||||
<div className="absolute top-full w-full border">
|
<div className="absolute top-full w-full border">
|
||||||
{options.map((option: string) => (
|
{options.map((option) => (
|
||||||
<div
|
<div
|
||||||
key={option}
|
key={option.id}
|
||||||
className="hover:bg-dropdown-option-hover-color"
|
className="hover:bg-dropdown-option-hover-color"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setIsOpen(false);
|
setIsOpen(false);
|
||||||
setChoice(option);
|
setChoice(option.id);
|
||||||
localStorage.setItem(name, option);
|
localStorage.setItem(storageKey, option.id);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{option}
|
{option.label}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -37,4 +58,3 @@ const Dropdown = ({ name, options }: { name: string; options: string[] }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Dropdown;
|
export default Dropdown;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,37 @@
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { tabContentVariant, settingsPageVariant } from "./Variants";
|
import { tabContentVariant, settingsPageVariant } from "./Variants";
|
||||||
|
import Dropdown from "./Dropdown";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const Misc = ({ id, active }) => (
|
const Misc = ({ id, active }) => {
|
||||||
<motion.div
|
const { t } = useTranslation();
|
||||||
role="tabpanel"
|
const engines = [
|
||||||
id={id}
|
{ id: "automatic", label: t("settings.proxy.automatic") },
|
||||||
className="tab-content"
|
{ id: "ultraviolet", label: "Ultraviolet" },
|
||||||
variants={tabContentVariant}
|
{ id: "rammerhead", label: "Rammerhead" },
|
||||||
animate={active ? "active" : "inactive"}
|
{ id: "dynamic", label: "Dynamic" }
|
||||||
initial="inactive"
|
];
|
||||||
>
|
|
||||||
<motion.div variants={settingsPageVariant} className="content-card">
|
return (
|
||||||
<h1>Misc settings</h1>
|
<motion.div
|
||||||
|
role="tabpanel"
|
||||||
|
id={id}
|
||||||
|
className="tab-content"
|
||||||
|
variants={tabContentVariant}
|
||||||
|
animate={active ? "active" : "inactive"}
|
||||||
|
initial="inactive"
|
||||||
|
>
|
||||||
|
<motion.div
|
||||||
|
variants={settingsPageVariant}
|
||||||
|
className="content-card flex flex-row flex-wrap justify-around"
|
||||||
|
>
|
||||||
|
<Dropdown
|
||||||
|
name={t("settings.proxy.title")}
|
||||||
|
storageKey="proxy"
|
||||||
|
options={engines}
|
||||||
|
/>
|
||||||
|
</motion.div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</motion.div>
|
);
|
||||||
);
|
};
|
||||||
|
|
||||||
export default Misc;
|
export default Misc;
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,16 @@
|
||||||
import { motion } from "framer-motion";
|
import { motion } from "framer-motion";
|
||||||
import { tabContentVariant, settingsPageVariant } from "./Variants";
|
import { tabContentVariant, settingsPageVariant } from "./Variants";
|
||||||
import Dropdown from "./Dropdown";
|
import Dropdown from "./Dropdown";
|
||||||
|
import { useTranslation } from "react-i18next";
|
||||||
|
|
||||||
const Proxy = ({ id, active }) => {
|
const Proxy = ({ id, active }) => {
|
||||||
const engines = ["Automatic", "Ultraviolet", "Rammerhead", "Dynamic"];
|
const { t } = useTranslation();
|
||||||
|
const engines = [
|
||||||
|
{ id: "automatic", label: t("settings.proxy.automatic") },
|
||||||
|
{ id: "ultraviolet", label: "Ultraviolet" },
|
||||||
|
{ id: "rammerhead", label: "Rammerhead" },
|
||||||
|
{ id: "dynamic", label: "Dynamic" }
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<motion.div
|
<motion.div
|
||||||
|
|
@ -18,7 +25,7 @@ const Proxy = ({ id, active }) => {
|
||||||
variants={settingsPageVariant}
|
variants={settingsPageVariant}
|
||||||
className="content-card flex flex-row flex-wrap justify-around"
|
className="content-card flex flex-row flex-wrap justify-around"
|
||||||
>
|
>
|
||||||
<Dropdown name="Engine" options={engines} />
|
<Dropdown name={t("settings.proxy.title")} storageKey="proxy" options={engines} />
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue