From 2f76c6b42065e69e5a694f86fe13d7f5fe40f094 Mon Sep 17 00:00:00 2001 From: cloudflypeng <44285412+cloudflypeng@users.noreply.github.com> Date: Fri, 7 Jun 2024 11:01:55 +0800 Subject: [PATCH] feat: switch language on the panel (#1882) * feat: switch language on the panel move nameMap to i18n.ts add Switch Language i18n add switch language in ConnectButton.tsx close https://github.com/Crossbell-Box/xLog/issues/1881 * feat: Add auto placement option to Menu component to looks like submenu adjust dom in connectButton * feat: Add support for nested menus in Menu component --------- Co-authored-by: pengyunfei --- src/components/common/ConnectButton.tsx | 377 ++++++++++++----------- src/components/common/LanguageSwitch.tsx | 9 +- src/components/ui/Menu.tsx | 50 ++- src/i18n.ts | 6 + src/messages/ja.json | 1 + src/messages/zh-TW.json | 1 + src/messages/zh.json | 1 + 7 files changed, 254 insertions(+), 191 deletions(-) diff --git a/src/components/common/ConnectButton.tsx b/src/components/common/ConnectButton.tsx index cb5e0a8a..f60e8c75 100644 --- a/src/components/common/ConnectButton.tsx +++ b/src/components/common/ConnectButton.tsx @@ -1,6 +1,6 @@ "use client" -import { useTranslations } from "next-intl" +import { useLocale, useTranslations } from "next-intl" import React, { useEffect, useState } from "react" import { @@ -32,6 +32,7 @@ import { BellAlertIcon } from "@heroicons/react/24/solid" import { Avatar } from "~/components/ui/Avatar" import { Button, type Variant, type VariantColor } from "~/components/ui/Button" import { Menu } from "~/components/ui/Menu" +import { nameMap } from "~/i18n" import { SITE_URL } from "~/lib/env" import { getSiteLink } from "~/lib/helpers" import { cn } from "~/lib/utils" @@ -39,6 +40,8 @@ import { cn } from "~/lib/utils" type HeaderLinkType = { icon?: React.ReactNode label: string | JSX.Element + isSubmenu?: boolean + subMenu?: HeaderLinkType[] } & ( | { href: string @@ -77,6 +80,7 @@ export const ConnectButton = ({ sizeDecrease = "xs" } + const locale = useLocale() const [ssrReady, account] = useAccountState(({ ssrReady, computed }) => [ ssrReady, computed.account, @@ -95,23 +99,17 @@ export const ConnectButton = ({ const selectCharactersModal = useSelectCharactersModal() const walletMintNewCharacterModal = useWalletMintNewCharacterModal() - const showNotificationModal = useShowNotificationModal() - const { isAllRead } = useNotifications() - const [InsufficientBalance, setInsufficientBalance] = useState(false) const t = useTranslations() useEffect(() => { - if (balance) { - if ( - BigInt(balance.value.toString()) > - BigInt("1" + "0".repeat(balance.decimals - 2)) - ) { - setInsufficientBalance(false) - } else { - setInsufficientBalance(true) - } - } + if (!balance) return + + const balanceValue = + BigInt(balance.value.toString()) <= + BigInt("1" + "0".repeat(balance.decimals - 2)) + + setInsufficientBalance(balanceValue) }, [balance]) const dropdownLinks: HeaderLinkType[] = [ @@ -141,6 +139,21 @@ export const ConnectButton = ({ copyLabel() }, }, + { + icon: "i-mingcute-translate-2-line", + isSubmenu: true, + label: t("Switch Language") || "", + subMenu: Object.keys(nameMap).map((lo) => ({ + label: nameMap[lo], + onClick: () => { + document.cookie = `NEXT_LOCALE=${lo};` + window.location.reload() + }, + })), + onClick: (e) => { + e.preventDefault() + }, + }, ...(account?.type === "wallet" ? [ { @@ -217,182 +230,133 @@ export const ConnectButton = ({ href: `${SITE_URL}/dashboard/${account?.character?.handle}/editor?type=portfolio`, }, ] + // TODO: maybe test this style effect + if (!ssrReady) return
+ + if (!account) + return ( +
+ +
+ ) return ( -
- {(() => { - if (!account) { - return ( - - ) - } - return ( -
- {!hideNotification && ( - <> - {isAllRead ? ( - - ) : ( - - )} - +
+
+
+ + + {!hideName && ( + <> +
+ - {addDropdownLinks.map((link, i) => ( - } - className={`${ - size === "base" ? "pl-5 pr-6 h-11" : "pl-4 pr-5 h-9" - } whitespace-nowrap`} - {...("href" in link - ? { - type: "link", - href: link.href, - } - : { - type: "button", - onClick: link.onClick, - })} - > - {link.label} - - ))} -
- } - /> -
-
-
- - )} - - - {!hideName && ( - <> -
+ {account.character?.handle && ( + - - {account.character?.metadata?.content?.name || - getAccountDisplayName(account)} - - {account.character?.handle && ( - - {"@" + account.character?.handle || - getAccountDisplayName(account)} - - )} -
- - - )} - - } - dropdown={ -
- {dropdownLinks.map((link, i) => ( - + )} +
+ + + )} + + } + dropdown={ +
+ {dropdownLinks.map((link, i) => { + if (link.isSubmenu) { + return ( + } - className={`${ - size === "base" ? "pl-5 pr-6 h-11" : "pl-4 pr-5 h-9" - } whitespace-nowrap`} - {...("href" in link - ? { - type: "link", - href: link.href, - } - : { - type: "button", - onClick: link.onClick, - })} + icon={ + + } + dropdown={link.subMenu?.map((subLink, j) => ( + + ))} > - {link.label} - - ))} -
- } - /> -
- ) - })()} + {link.label} + + ) + } else { + return + } + })} +
+ } + /> + ) } @@ -421,3 +385,52 @@ function getAccountDisplayName(account: GeneralAccount | null) { return value.slice(0, 5) + "..." + value.slice(-4) } +// maybe we could be create a file for this component +function Notification() { + const showNotificationModal = useShowNotificationModal() + const { isAllRead } = useNotifications() + + if (isAllRead) + return ( + + ) + + return ( + + ) +} +// the all menuItem in this file +// it can just be used in this file, because it's props link is the headerLinkType +function ConnectMenuItem({ + link, + size, +}: { + link: HeaderLinkType + size: "base" | "sm" +}) { + return ( + } + className={`${ + size === "base" ? "pl-5 pr-6 h-11" : "pl-4 pr-5 h-9" + } whitespace-nowrap`} + {...("href" in link + ? { + type: "link", + href: link.href, + } + : { + type: "button", + onClick: link.onClick, + })} + > + {link.label} + + ) +} diff --git a/src/components/common/LanguageSwitch.tsx b/src/components/common/LanguageSwitch.tsx index ad0c4bb5..22086ec9 100644 --- a/src/components/common/LanguageSwitch.tsx +++ b/src/components/common/LanguageSwitch.tsx @@ -2,20 +2,13 @@ import { useLocale } from "next-intl" -import { locales } from "~/i18n" +import { locales, nameMap } from "~/i18n" import { Menu } from "../ui/Menu" export function LanguageSwitch() { const locale = useLocale() - const nameMap: Record = { - en: "English", - zh: "简体中文", - "zh-TW": "繁體中文", - ja: "日本語", - } - return ( ) { const { refs, floatingStyles } = useFloating({ placement, middleware: [ // Prevent overflowing viewport shift({ padding: 20 }), + enableAutoPlacement ? autoPlacement({ allowedPlacements }) : undefined, ], whileElementsMounted: autoUpdate, }) @@ -145,3 +156,40 @@ Menu.Item = function MenuItem({ ) } + +// TODO: Add support for nested menus +// this is a hack submenu use the div and component +// about why i'm not use the headlessui Menu.Item, because it's not support nested menu, +// and it will make the autoPlacement not work properly. +// problem that's will happen is the styles maybe not sync with the component + +Menu.SubMenu = function MenuSubMenu({ + icon, + children, + dropdown, +}: React.PropsWithChildren<{ + icon: React.ReactNode + dropdown: React.ReactNode +}>) { + return ( + + {icon} + {children} + + } + dropdown={dropdown} + /> + ) +} diff --git a/src/i18n.ts b/src/i18n.ts index 7266d7bf..a4155e8a 100644 --- a/src/i18n.ts +++ b/src/i18n.ts @@ -9,6 +9,12 @@ export const languageNames: Record<(typeof locales)[number], string> = { zh: "Chinese (Simplified)", "zh-TW": "Chinese (Traditional)", } +export const nameMap: Record = { + en: "English", + zh: "简体中文", + "zh-TW": "繁體中文", + ja: "日本語", +} export const defaultLocale = "en" export default getRequestConfig(async ({ locale }) => ({ diff --git a/src/messages/ja.json b/src/messages/ja.json index 2d747b3d..0a3743f6 100644 --- a/src/messages/ja.json +++ b/src/messages/ja.json @@ -47,6 +47,7 @@ "Dashboard": "ダッシュボード", "Copied!": "コピーしました!", "Operator Sign": "オペレーター署名", + "Switch Language": "言語を切り替える", "Switch Characters": "キャラクターを切り替える", "Upgrade to Wallet": "ウォレットにアップグレード", "Disconnect": "中断する", diff --git a/src/messages/zh-TW.json b/src/messages/zh-TW.json index b4e9ecb2..9cc77985 100644 --- a/src/messages/zh-TW.json +++ b/src/messages/zh-TW.json @@ -58,6 +58,7 @@ "Dashboard": "主控臺", "Copied!": "拷貝完成", "Operator Sign": "簽名授權", + "Switch Language": "切換語言", "Switch Characters": "切換身份", "Upgrade to Wallet": "升級為錢包認證", "Disconnect": "中斷連線", diff --git a/src/messages/zh.json b/src/messages/zh.json index 4b1d422c..31f705a6 100644 --- a/src/messages/zh.json +++ b/src/messages/zh.json @@ -57,6 +57,7 @@ "Dashboard": "仪表盘", "Copied!": "已复制!", "Operator Sign": "签名授权", + "Switch Language": "切换语言", "Switch Characters": "切换角色", "Upgrade to Wallet": "升级为钱包", "Disconnect": "断开连接",