feat: darkmode draft version

This commit is contained in:
Tristan Yang
2023-02-06 07:35:31 +08:00
parent b4c5d5cb86
commit 07ddfbf12b
111 changed files with 885 additions and 2102 deletions
+1 -1
View File
@@ -40,7 +40,7 @@ export default function APIConfig() {
data-checked={thirdParty}
/>
<div className="w-full flex flex-col items-start gap-2">
<label htmlFor="secret" className="text-sm text-gray-500"> {t("third_app.key")}:</label>
<label htmlFor="secret" className="text-sm text-gray-500 dark:text-gray-100"> {t("third_app.key")}:</label>
<Input disabled={!thirdParty} type="password" id="secret" value={updatedSecret || data} />
</div>
<Tippy
+7 -7
View File
@@ -14,11 +14,11 @@ const APIDocument = () => {
};
return (
<section className="flex flex-col justify-start items-start gap-4">
<div className="text-gray-500 ">
<div className="text-gray-500 dark:text-gray-100">
{t("api_doc.desc")}
</div>
<div className='flex flex-col gap-2'>
<h2 className='text-gray-700 text-xl font-bold'>
<h2 className='text-gray-700 dark:text-white text-xl font-bold'>
{t("api_doc.access")}
</h2>
<a href={APIUrl} target="_blank" rel="noopener noreferrer" className='underline text-primary-600'>
@@ -26,12 +26,12 @@ const APIDocument = () => {
</a>
</div>
<div className='flex flex-col gap-2'>
<h2 className='text-gray-700 text-xl font-bold'>
<h2 className='text-gray-700 dark:text-white text-xl font-bold'>
{t("api_doc.use_method")}
</h2>
<div className=" flex flex-col gap-6">
<div className="flex flex-col gap-2">
<h3 className='text-gray-700 text-lg'>
<h3 className='text-gray-700 dark:text-white text-lg'>
👉 {t("api_doc.step_1")}
</h3>
{/* <div className="flex flex-col gap-1"> */}
@@ -39,8 +39,8 @@ const APIDocument = () => {
{/* </div> */}
</div>
<div className="flex flex-col gap-2">
<h3 className='text-gray-700 text-lg flex items-center gap-2'>
👉 {t("api_doc.step_2")} <span className='text-gray-500 text-sm'>
<h3 className='text-gray-700 dark:text-white text-lg flex items-center gap-2'>
👉 {t("api_doc.step_2")} <span className='text-gray-500 dark:text-white text-sm'>
({t("api_doc.step_2_desc")})
</span>
</h3>
@@ -53,7 +53,7 @@ const APIDocument = () => {
<img className='border border-solid rounded-md border-gray-300 shadow-lg w-[85%]' src="https://s.voce.chat/web_client/assets/img/api.doc.step2.jpg" alt="step 2" />
</div>
<div className="flex flex-col gap-2">
<h3 className='text-gray-700 text-lg flex items-center gap-2'>
<h3 className='text-gray-700 dark:text-white text-lg flex items-center gap-2'>
👉 {t("api_doc.last")}
</h3>
<img className='border border-solid rounded-md border-gray-300 shadow-lg w-[85%]' src="https://s.voce.chat/web_client/assets/img/api.doc.step3.png" alt="step 3" />
+3 -3
View File
@@ -21,7 +21,7 @@ type Props = {
// </table>;
// };
type DeleteAPIKeyProps = { uid: number, kid: number }
const tdClass = "p-1 whitespace-nowrap text-xs text-gray-500 align-middle px-1";
const tdClass = "p-1 whitespace-nowrap text-xs text-gray-500 dark:text-gray-200 align-middle px-1";
const BotAPIKeys = ({ uid }: Props) => {
const { t } = useTranslation("setting", { keyPrefix: "bot" });
const [currentUid, setCurrentUid] = useState<number | undefined>();
@@ -39,11 +39,11 @@ const BotAPIKeys = ({ uid }: Props) => {
const colWidths = ["w-20", "w-[166px]", "w-36", "w-15", "w-10"];
return (
<div className='flex flex-col gap-2 items-start'>
<div className='border-t border-solid border-b border-gray-100 py-2 w-full'>
<div className='border-t border-solid border-b border-gray-100 dark:border-gray-500 py-2 w-full'>
<table className="min-w-full table-fixed font-mono">
<thead >
<tr >
{[t("col_key_name"), t('col_key_value'), t('col_key_create_time'), t('col_key_last_used'), ""].map((title, idx) => <th key={title} scope="col" className={clsx(`text-xs text-gray-900 px-1 text-left pb-2`, colWidths[idx])}>
{[t("col_key_name"), t('col_key_value'), t('col_key_create_time'), t('col_key_last_used'), ""].map((title, idx) => <th key={title} scope="col" className={clsx(`text-xs text-gray-900 dark:text-gray-50 px-1 text-left pb-2`, colWidths[idx])}>
{title}
</th>)}
</tr>
+3 -3
View File
@@ -77,12 +77,12 @@ const CreateModal = ({ closeModal }: Props) => {
</>
}
>
<form ref={formRef} className="w-full flex flex-col gap-2 items-center" action="/">
<div className="flex flex-col gap-1 w-full">
<form ref={formRef} className="w-full flex flex-col gap-2" action="/">
<div className="flex flex-col items-start gap-1 w-full">
<label htmlFor={"name"} className="text-sm text-[#6b7280]">Name</label>
<Input name={"name"} required placeholder='Please input bot name'></Input>
</div>
<div className="flex flex-col gap-1 w-full">
<div className="flex flex-col items-start gap-1 w-full">
<label htmlFor={"webhook_url"} className="text-sm text-[#6b7280]">Webhook URL (Optional)</label>
<Input name={"webhook_url"} type="url" placeholder='Please input webhook url'></Input>
</div>
+1 -1
View File
@@ -72,7 +72,7 @@ const WebhookEdit = ({ uid }: Props) => {
evt.preventDefault();
handleEdit();
}}>
<input readOnly={!editable} required autoFocus type="url" name='webhook' defaultValue={url} className={clsx("text-sm text-gray-500 px-2 py-1", editable ? "border border-solid border-gray-200 bg-gray-50" : "bg-transparent")} />
<input readOnly={!editable} required autoFocus type="url" name='webhook' defaultValue={url} className={clsx("text-sm text-gray-500 dark:text-gray-100 px-2 py-1", editable ? "border border-solid border-gray-200 bg-gray-50" : "bg-transparent")} />
</form>
<button type='button' disabled={isUpdating} onClick={handleEdit}>
{isUpdating ? <Orbit size={16} /> : editable ?
+8 -9
View File
@@ -20,11 +20,11 @@ type TipProps = { title: string, desc: string };
const Tip = ({ title, desc }: TipProps) => {
return <div className="flex flex-col text-sm">
<h2 className="">{title}</h2>
<p className="text-gray-500">{desc}</p>
<h2 className="dark:text-white">{title}</h2>
<p className="text-gray-500 dark:text-gray-400">{desc}</p>
</div>;
};
const tdClass = "p-6 whitespace-nowrap text-sm font-medium text-gray-900 align-top";
const tdClass = "p-6 whitespace-nowrap text-sm font-medium text-gray-900 dark:text-gray-100 align-top";
type WebhookParams = { webhook?: string, uid: number };
type DeleteParams = { name: string, uid: number };
export default function BotConfig() {
@@ -65,19 +65,19 @@ export default function BotConfig() {
<Tip title={t("webhook_tip_title")} desc={t("webhook_tip_desc")} />
</div>
<div className="flex flex-col gap-1">
<h2 className='font-semibold flex gap-4 items-center'>
<h2 className='font-semibold flex gap-4 items-center dark:text-white'>
{t("manage")}
<a href="https://doc.voce.chat/bot-and-webhook" target="_blank" className="text-sm text-blue-400 underline-offset-1 underline" rel="noopener noreferrer">
🔗 {t("how_to_use")}
</a>
</h2>
<p className='text-gray-500 text-xs'>{t("manage_desc")}</p>
<p className='text-gray-500 dark:text-gray-400 text-xs'>{t("manage_desc")}</p>
</div>
<div className="w-fit overflow-hidden">
<table className="min-w-full table-auto">
<thead className="border-b bg-gray-50">
<thead className="border-b dark:border-b-gray-500 bg-gray-50 dark:bg-gray-600">
<tr>
{[t("col_avatar"), t('col_name'), t('col_api_key'), t('col_webhook'), t('col_opt')].map(title => <th key={title} scope="col" className="text-sm font-bold text-gray-900 px-6 py-4 text-left">
{[t("col_avatar"), t('col_name'), t('col_api_key'), t('col_webhook'), t('col_opt')].map(title => <th key={title} scope="col" className="text-sm font-bold text-gray-900 dark:text-gray-100 px-6 py-4 text-left">
{title}
</th>)}
</tr>
@@ -85,10 +85,9 @@ export default function BotConfig() {
<tbody>
{bots.map(bot => {
const { uid, name, avatar } = bot;
return <tr key={uid} className="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
return <tr key={uid} className="bg-white dark:bg-gray-800 border-b dark:border-b-gray-500 transition duration-300 ease-in-out hover:bg-gray-100">
<td className="px-4 py-2">
<AvatarUploader uid={uid} url={avatar} uploadImage={updateAvatar} name={name} size={56} />
</td>
<td className={`${tdClass}`}>
<div>
+1 -1
View File
@@ -13,7 +13,7 @@ const Item = ({ label, data, foldable = false, ...rest }: ItemProps) => {
const infoClass = clsx("font-bold w-full cursor-pointer", foldable ? " overflow-hidden text-ellipsis" : "whitespace-pre-wrap break-all");
if (!data) return null;
return <div className="whitespace-nowrap flex flex-col items-start justify-start text-lg">
<span className="text-sm text-gray-400">{label}</span>
<span className="text-sm text-gray-400 dark:text-white">{label}</span>
{Array.isArray(data) ? <ul className={infoClass}>
{data.map((d) => {
return <li key={d}>{d}</li>;
+6 -6
View File
@@ -61,16 +61,16 @@ export default function MyAccount() {
return (
<>
<div className="flex flex-col items-start gap-8">
<div className="p-6 flex flex-col items-center w-[512px] bg-slate-100 rounded-2xl">
<div className="p-6 flex flex-col items-center w-[512px] bg-slate-100 dark:bg-gray-800 rounded-2xl">
<AvatarUploader url={avatar} name={name} uploadImage={uploadAvatar} />
<div className="mt-2 mb-16 font-bold text-lg text-gray-800">
<div className="mt-2 mb-16 font-bold text-lg text-gray-800 dark:text-white">
{name} <span className="font-normal text-gray-500">#{uid}</span>
</div>
<div className="w-full flex justify-between mb-6">
<div className="flex flex-col text-gray-500">
<div className="flex flex-col text-gray-500 dark:text-gray-50">
<span className="text-xs uppercase font-semibold">{t("username")}</span>
<span className="text-sm ">
{name} <span className="text-gray-600"> #{uid}</span>
{name} <span className="text-gray-600 dark:text-gray-400"> #{uid}</span>
</span>
</div>
<Button data-edit="name" onClick={handleBasicEdit} className="">
@@ -78,7 +78,7 @@ export default function MyAccount() {
</Button>
</div>
<div className="w-full flex justify-between mb-6">
<div className="flex flex-col text-gray-500">
<div className="flex flex-col text-gray-500 dark:text-gray-50">
<span className="text-xs uppercase font-semibold">{t("email")}</span>
<span className="text-sm">{email}</span>
</div>
@@ -87,7 +87,7 @@ export default function MyAccount() {
</Button>
</div>
<div className="w-full flex justify-between mb-6">
<div className="flex flex-col text-gray-500">
<div className="flex flex-col text-gray-500 dark:text-gray-50">
<span className="text-xs uppercase font-semibold">{t("password")}</span>
<span className="text-sm">*********</span>
</div>
+43
View File
@@ -0,0 +1,43 @@
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import Radio from '../../../common/component/styled/Radio';
import { Theme } from '../../../types/common';
// type Props = {}
const DarkMode = () => {
const [theme, setTheme] = useState<Theme>(localStorage.theme || "auto");
const { t } = useTranslation("setting");
const handleThemeToggle = (v: Theme) => {
setTheme(v);
localStorage.theme = v;
// reset
document.documentElement.classList.remove("dark");
document.documentElement.classList.remove("light");
if (v !== "auto") {
document.documentElement.classList.add(v);
} else {
const isDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.classList.add(isDark ? "dark" : 'light');
}
};
return (
<div className="text-sm">
<p className="dark:text-gray-100 font-semibold">{t("overview.theme.title")}</p>
<p className="flex justify-between w-full text-gray-400 mb-2">
{t("overview.theme.desc")}
</p>
<Radio
options={[t("overview.theme.auto"), t("overview.theme.dark"), t("overview.theme.light")]}
values={['auto', 'dark', 'light']}
value={theme}
onChange={(v) => {
handleThemeToggle(v);
}}
/>
</div>
);
};
export default DarkMode;
+1 -2
View File
@@ -33,12 +33,11 @@ const Index = () => {
// if(!fetch)
return (
<div className="text-sm">
<p className="font-semibold">{t("overview.url.title")}</p>
<p className="dark:text-gray-100 font-semibold">{t("overview.url.title")}</p>
<p className="flex justify-between w-full text-gray-400">
{t("overview.url.desc")}
</p>
<div className="flex items-center gap-4 mt-2">
<StyledInput placeholder='frontend url' value={url} onChange={handleChange} />
<StyledButton disabled={!url || isLoading} className='' onClick={handleUpdate}> {ct("action.update")}</StyledButton>
</div>
+4 -2
View File
@@ -7,6 +7,7 @@ import useConfig from "../../../common/hook/useConfig";
import Server from './server';
import Language from './Language';
import FrontendURL from "./FrontendURL";
// import DarkMode from "./DarkMode";
import ServerVersionChecker from "../../../common/component/ServerVersionChecker";
export default function Overview() {
@@ -33,7 +34,7 @@ export default function Overview() {
{isAdmin && (
<>
<div className="text-sm">
<p className="font-semibold">{t("overview.sign_up.title")}</p>
<p className="dark:text-gray-100 font-semibold">{t("overview.sign_up.title")}</p>
<p className="flex justify-between w-full text-gray-400 mb-2">{t("overview.sign_up.desc")}</p>
<StyledRadio
options={[t("overview.sign_up.everyone"), t("overview.sign_up.invite")]}
@@ -45,7 +46,7 @@ export default function Overview() {
/>
</div>
<div className="text-sm">
<p className="font-semibold">{t("overview.guest_mode.title")}</p>
<p className="dark:text-gray-100 font-semibold">{t("overview.guest_mode.title")}</p>
<p className="flex justify-between w-full text-gray-400 mb-2">
<span className="txt">
{t("overview.guest_mode.desc")}
@@ -66,6 +67,7 @@ export default function Overview() {
</>
)}
<Language />
{/* <DarkMode /> */}
</div>
);
}
+1 -1
View File
@@ -11,7 +11,7 @@ const Index = () => {
};
return (
<div className="text-sm">
<p className="font-semibold">{t("overview.lang.title")}</p>
<p className="dark:text-gray-100 font-semibold">{t("overview.lang.title")}</p>
<p className="flex justify-between w-full text-gray-400 mb-2">
{t("overview.lang.desc")}
</p>
+3 -3
View File
@@ -72,7 +72,7 @@ const Index = () => {
</div>
{isAdmin && (
<div className="flex flex-col justify-between items-start">
<div className="text-sm text-gray-600">
<div className="text-sm text-gray-600 dark:text-gray-100">
{t("overview.upload_desc")}
</div>
</div>
@@ -80,7 +80,7 @@ const Index = () => {
</div>
<div className="flex flex-col items-start gap-6 mb-16">
<div className="w-full flex flex-col items-start gap-2">
<Label htmlFor="name">{t("overview.name")}</Label>
<Label className='dark:text-gray-100' htmlFor="name">{t("overview.name")}</Label>
<Input
disabled={!isAdmin}
data-type="name"
@@ -92,7 +92,7 @@ const Index = () => {
/>
</div>
<div className="w-full flex flex-col items-start gap-2">
<Label htmlFor="desc">{t("overview.desc")}</Label>
<Label className='dark:text-gray-100' htmlFor="desc">{t("overview.desc")}</Label>
<Textarea
disabled={!isAdmin}
data-type="description"
+12 -12
View File
@@ -5,14 +5,14 @@ import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism';
const Row = ({ paramKey, paramDefault, remarks }: { paramKey: string, paramDefault: string | number, remarks: string }) => {
return <tr className="bg-white border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium text-gray-900">
return <tr className="bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-50 border-b transition duration-300 ease-in-out hover:bg-gray-100">
<td className="px-6 py-4 whitespace-nowrap text-sm font-medium">
{paramKey}
</td>
<td className="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<td className="text-sm font-light px-6 py-4 whitespace-nowrap">
{paramDefault}
</td>
<td className="text-sm text-gray-900 font-light px-6 py-4 whitespace-nowrap">
<td className="text-sm font-light px-6 py-4 whitespace-nowrap">
{remarks}
</td>
</tr>;
@@ -22,23 +22,23 @@ export default function Widget() {
// const disableBtn = !reachLimit;
return (
<div className="flex flex-col justify-start items-start">
<div className="text-gray-600 ">
<div className="text-gray-600 dark:text-gray-100">
{t('tip')}
</div>
<label htmlFor="code" className="text-gray-500 text-sm mt-5">
<label htmlFor="code" className="text-gray-500 dark:text-white text-sm mt-5">
{t('code')}:
</label>
<SyntaxHighlighter id="code" language="html" style={vscDarkPlus} className="rounded">
{`<!-- ${t('code_comment')} -->\n<script \n data-host-id="1" \n data-close-width="48" \n data-close-height="48" \n data-open-width="380" \n data-open-height="680" \n src="${location.origin}/widget.js" \n async \n/>`}
</SyntaxHighlighter>
<div className="text-gray-500 text-sm mt-5 mb-2">
<div className="text-gray-500 dark:text-white text-sm mt-5 mb-2">
{t('config')}:
</div>
<div className="w-[700px] border border-solid border-gray-300 rounded overflow-hidden">
<div className="w-[700px] border border-solid border-gray-300 dark:border-gray-400 rounded overflow-hidden">
<table className="min-w-full table-auto">
<thead className="border-b bg-gray-50">
<thead className="border-b bg-gray-50 dark:bg-gray-500">
<tr>
{[t('param_key'), t('default_value'), t('remark')].map(title => <th key={title} scope="col" className="text-sm font-bold text-gray-900 px-6 py-4 text-left">
{[t('param_key'), t('default_value'), t('remark')].map(title => <th key={title} scope="col" className="text-sm font-bold text-gray-900 dark:text-white px-6 py-4 text-left">
{title}
</th>)}
</tr>
@@ -67,9 +67,9 @@ export default function Widget() {
}
].map(row => <Row key={row.paramKey} {...row} />)}
</tbody>
<tfoot className="border-t border-solid border-gray-200" >
<tfoot className="border-t border-solid border-gray-200 dark:border-gray-50 dark:bg-gray-500" >
<tr>
<td colSpan={3} className="text-gray-400 px-5 py-3 text-sm">
<td colSpan={3} className="text-gray-400 dark:text-white px-5 py-3 text-sm">
* All the parameters are optional, and prefixed by <i className="bg-gray-700 text-white px-1">data-</i>
</td>
</tr>
+4 -4
View File
@@ -87,7 +87,7 @@ export default function ConfigFirebase() {
/>
{<fieldset className="inputs" disabled={select !== "custom"}>
<div className="input">
<Label htmlFor="name">{t("firebase.token_url")}</Label>
<Label htmlFor="name" className="dark:text-gray-200">{t("firebase.token_url")}</Label>
<Input
data-type="token_url"
onChange={handleChange}
@@ -97,7 +97,7 @@ export default function ConfigFirebase() {
/>
</div>
<div className="input">
<Label htmlFor="desc">{t("firebase.project_id")}</Label>
<Label htmlFor="desc" className="dark:text-gray-200">{t("firebase.project_id")}</Label>
<Input
data-type="project_id"
onChange={handleChange}
@@ -107,7 +107,7 @@ export default function ConfigFirebase() {
/>
</div>
<div className="input">
<Label htmlFor="desc">{t("firebase.private_key")}</Label>
<Label htmlFor="desc" className="dark:text-gray-200">{t("firebase.private_key")}</Label>
<Textarea
rows={10}
spellCheck={false}
@@ -119,7 +119,7 @@ export default function ConfigFirebase() {
/>
</div>
<div className="input">
<Label htmlFor="desc">{t("firebase.client_email")}</Label>
<Label htmlFor="desc" className="dark:text-gray-200">{t("firebase.client_email")}</Label>
<Input
data-type="client_email"
onChange={handleChange}
+16 -18
View File
@@ -1,12 +1,11 @@
import { ChangeEvent, FC, useState } from "react";
import { useTranslation } from "react-i18next";
import Select, { Option } from "../../../../common/component/styled/Select";
import Button from "../../../../common/component/styled/Button";
import Input from "../../../../common/component/styled/Input";
import Toggle from "../../../../common/component/styled/Toggle";
import options from "./items.json";
import Styled from "./styled";
import IconMinus from "../../../../assets/icons/minus.circle.svg";
import { useTranslation } from "react-i18next";
interface Issuer {
domain: string;
@@ -32,32 +31,31 @@ const IssuerList: FC<Props> = ({ issuers = [], onChange }) => {
(!newDomain && !select?.value) ||
!select?.title ||
issuers.some((issuer) => issuer.domain === newDomain);
return (
<Styled>
<ul className="issuers">
<div className="py-4 w-full flex flex-col gap-4">
<ul className="flex flex-col gap-4">
{issuers.map(({ enable, favicon, domain }) => {
return (
<li key={domain} className="issuer">
<div className="left">
<li key={domain} className="flex items-center justify-between gap-10">
<div className="flex-1 flex items-center justify-between">
<IconMinus
className="remove"
className="cursor-pointer"
onClick={() => {
onChange(issuers.filter((issuer) => issuer.domain !== domain));
}}
/>
<div className="data">
{Boolean(favicon) && <img src={favicon} alt="logo" className="icon" />}
<div className="flex items-center justify-between gap-4">
{Boolean(favicon) && <img src={favicon} alt="logo" className="w-8 h-8" />}
<Input
readOnly
value={domain}
prefix="https://"
placeholder="Issuer Domain"
className="url"
className="w-[280px]"
/>
</div>
</div>
<div className="right">
<div className="w-14 flex justify-end">
<Toggle
data-checked={enable}
onClick={() => {
@@ -74,8 +72,8 @@ const IssuerList: FC<Props> = ({ issuers = [], onChange }) => {
);
})}
<li className="issuer add">
<div className="left">
<li className="flex items-center justify-between gap-10 cursor-pointer">
<div className="flex-1 flex items-center justify-between">
<Select
options={options.map((option) => ({
...option,
@@ -84,18 +82,18 @@ const IssuerList: FC<Props> = ({ issuers = [], onChange }) => {
current={select}
updateSelect={setSelect}
/>
<div className="data">
<div className="flex items-center justify-between gap-4">
<Input
onChange={handleNewDomain}
readOnly={!!select?.value}
value={select?.value || newDomain}
prefix="https://"
placeholder="domain.com"
className="url"
className="w-[280px]"
/>
</div>
</div>
<div className="right">
<div className="w-14 flex justify-end">
<Button
disabled={disableBtn}
onClick={() => {
@@ -119,7 +117,7 @@ const IssuerList: FC<Props> = ({ issuers = [], onChange }) => {
</li>
</ul>
{/* <IconPlus className="add" /> */}
</Styled>
</div>
);
};
@@ -1,52 +0,0 @@
import styled from "styled-components";
const Styled = styled.div`
padding: 16px 0;
width: 100%;
display: flex;
flex-direction: column;
gap: 16px;
.issuers {
display: flex;
flex-direction: column;
gap: 16px;
.issuer {
display: flex;
align-items: center;
justify-content: space-between;
gap: 40px;
.left {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
.remove {
cursor: pointer;
}
.data {
display: flex;
align-items: center;
gap: 16px;
justify-content: space-between;
> .icon {
width: 32px;
height: 32px;
}
> .url {
width: 280px;
}
}
}
.right {
width: 56px;
display: flex;
justify-content: flex-end;
}
}
}
.add {
cursor: pointer;
}
`;
export default Styled;
+12 -12
View File
@@ -77,9 +77,9 @@ export default function Logins() {
<div className="row">
<div className="title">
<div className="txt">
<Label>{t("password")}</Label>
<Label className="dark:text-gray-200">{t("password")}</Label>
</div>
<span className="desc">{t("password_desc")}</span>
<span className="desc dark:!text-gray-400" >{t("password_desc")}</span>
</div>
<Toggle
onClick={handleToggle.bind(null, { password: !password })}
@@ -91,9 +91,9 @@ export default function Logins() {
<div className="row">
<div className="title">
<div className="txt">
<Label>{t("magic_link")}</Label>
<Label className="dark:text-gray-200">{t("magic_link")}</Label>
</div>
<span className="desc">{t("magic_link_desc")}</span>
<span className="desc dark:!text-gray-400" >{t("magic_link_desc")}</span>
</div>
<Toggle
onClick={handleToggle.bind(null, { magic_link: !magic_link })}
@@ -105,10 +105,10 @@ export default function Logins() {
<div className="row">
<div className="title">
<div className="txt">
<Label>{t("google")}</Label>
<Label className="dark:text-gray-200">{t("google")}</Label>
<Tooltip link="https://doc.voce.chat/setting/third_login/login-google" />
</div>
<span className="desc">{t("google_desc")}</span>
<span className="desc dark:!text-gray-400" >{t("google_desc")}</span>
</div>
<Toggle
onClick={handleToggle.bind(null, { google: !google })}
@@ -128,10 +128,10 @@ export default function Logins() {
<div className="row">
<div className="title">
<div className="txt">
<Label>{t("github")}</Label>
<Label className="dark:text-gray-200">{t("github")}</Label>
<Tooltip link="https://doc.voce.chat/setting/third_login/login-github" />
</div>
<span className="desc">{t("github_desc")}</span>
<span className="desc dark:!text-gray-400" >{t("github_desc")}</span>
</div>
<Toggle
onClick={handleToggle.bind(null, { github: !github })}
@@ -159,10 +159,10 @@ export default function Logins() {
<div className="row">
<div className="title">
<div className="txt">
<Label>{t("metamask")}</Label>
<Label className="dark:text-gray-200">{t("metamask")}</Label>
<Tooltip link="https://doc.voce.chat/setting/third_login/login-metamask" />
</div>
<span className="desc">{t("metamask_desc")}</span>
<span className="desc dark:!text-gray-400" >{t("metamask_desc")}</span>
</div>
<Toggle
onClick={handleToggle.bind(null, { metamask: !metamask })}
@@ -174,10 +174,10 @@ export default function Logins() {
<div className="row">
<div className="title">
<div className="txt">
<Label htmlFor="desc">{t("oidc")}</Label>
<Label className="dark:text-gray-200" htmlFor="desc">{t("oidc")}</Label>
<Tooltip link="https://doc.voce.chat/setting/third_login/login-webid" />
</div>
<span className="desc">{t("oidc_desc")}</span>
<span className="desc dark:!text-gray-400" >{t("oidc_desc")}</span>
</div>
</div>
<div className="row">
+6 -6
View File
@@ -57,11 +57,11 @@ export default function ConfigSMTP() {
<StyledContainer>
<div className="inputs">
<div className="input row">
<Label>{t("enable")}</Label>
<Label className="dark:text-gray-200">{t("enable")}</Label>
<Toggle onClick={toggleEnable} data-checked={enabled}></Toggle>
</div>
<div className="input">
<Label htmlFor="name">{t("host")}</Label>
<Label className="dark:text-gray-200" htmlFor="name">{t("host")}</Label>
<Input
disabled={!enabled}
data-type="host"
@@ -72,7 +72,7 @@ export default function ConfigSMTP() {
/>
</div>
<div className="input">
<Label htmlFor="desc">{t("port")}</Label>
<Label className="dark:text-gray-200" htmlFor="desc">{t("port")}</Label>
<Input
disabled={!enabled}
type={"number"}
@@ -84,7 +84,7 @@ export default function ConfigSMTP() {
/>
</div>
<div className="input">
<Label htmlFor="desc">{t("from")}</Label>
<Label className="dark:text-gray-200" htmlFor="desc">{t("from")}</Label>
<Input
disabled={!enabled}
data-type="from"
@@ -95,7 +95,7 @@ export default function ConfigSMTP() {
/>
</div>
<div className="input">
<Label htmlFor="desc">{t("username")}</Label>
<Label className="dark:text-gray-200" htmlFor="desc">{t("username")}</Label>
<Input
disabled={!enabled}
data-type="username"
@@ -106,7 +106,7 @@ export default function ConfigSMTP() {
/>
</div>
<div className="input">
<Label htmlFor="desc">{t("password")}</Label>
<Label className="dark:text-gray-200" htmlFor="desc">{t("password")}</Label>
<Input
type={"password"}
disabled={!enabled}
+2 -2
View File
@@ -86,11 +86,11 @@ const navs = [
},
{
name: "terms",
component: "Terms & Privacy"
component: <div className="dark:text-white">Terms & Privacy</div>
},
{
name: "feedback",
component: <ul className="flex flex-col gap-2 text-lg">
component: <ul className="flex flex-col gap-2 text-lg dark:text-white">
<li>Email: <strong className="font-bold">han@privoce.com</strong></li>
<li>Wechat: <strong className="font-bold">Privoce</strong></li>
<li>GitHub:&nbsp;