refactor: polish the tailwind refactor

This commit is contained in:
Tristan Yang
2023-02-09 17:50:42 +08:00
parent 0b817773a0
commit 446e9a17d9
38 changed files with 80 additions and 70 deletions
+3 -3
View File
@@ -42,11 +42,11 @@ export default function AddEntriesMenu() {
setChannelModalVisible(false);
};
const itemClass = "rounded flex items-center gap-2 text-sm font-semibold cursor-pointer px-2 py-2.5 hover:bg-gray-800/20";
const iconClass = "w-5 h-5";
const itemClass = "rounded flex items-center gap-2 text-sm font-semibold cursor-pointer px-2 py-2.5 hover:bg-gray-800/20 dark:hover:bg-gray-200/20";
const iconClass = "w-5 h-5 dark:fill-gray-300";
return (
<>
<ul className="flex flex-col rounded-xl drop-shadow p-1 select-none text-gray-500 bg-white">
<ul className="flex flex-col rounded-xl drop-shadow p-1 select-none text-gray-500 dark:text-gray-300 bg-white dark:bg-black">
{/* temp remove public channel */}
{currentUser?.is_admin && (
<li className={itemClass} onClick={handleOpenChannelModal.bind(null, false)}>
+1 -1
View File
@@ -31,7 +31,7 @@ const Avatar: FC<Props> = ({
}) => {
const [avatarSrc, setAvatarSrc] = useState("");
useEffect(() => {
if (!src) {
if (src) {
setAvatarSrc(src);
}
}, [src]);
+1 -1
View File
@@ -39,7 +39,7 @@ const Channel: FC<Props> = ({ interactive = true, id, compact = false, avatarSiz
</div>
{!compact && (
<div className="flex text-sm text-gray-500 font-semibold">
<span className="max-w-[140px] whitespace-nowrap overflow-hidden text-ellipsis">{name}</span> ({is_public ? totalMemberCount : members.length})
<span className="max-w-[140px] truncate">{name}</span> ({is_public ? totalMemberCount : members.length})
</div>
)}
</div>
+1 -1
View File
@@ -92,7 +92,7 @@ const FileBox: FC<Props> = ({
<div className="w-full p-2 flex items-center justify-between gap-2">
{icon}
<div className="flex flex-col gap-1 w-full overflow-hidden">
<span className="font-semibold text-sm text-gray-800 dark:text-gray-200 whitespace-nowrap text-ellipsis">{name}</span>
<span className="font-semibold text-sm text-gray-800 dark:text-gray-200 truncate">{name}</span>
<em className="text-xs text-gray-500 flex gap-4 not-italic">
<span className="size">{formatBytes(size)}</span>
<span className="time">{dayjs(created_at).fromNow()}</span>
@@ -23,7 +23,7 @@ const AudioMessage = ({ url, name, size, download }: Props) => {
<div className="flex gap-2 ">
<IconAudio className="w-9 h-auto" />
<div className="flex flex-col gap-1 text-sm text-gray-700">
<span title={name} className='font-bold whitespace-nowrap text-ellipsis w-[240px] overflow-hidden'>{name}</span>
<span title={name} className='font-bold w-[240px] truncate'>{name}</span>
<span>{_size}</span>
</div>
</div>
@@ -43,7 +43,7 @@ const VideoMessage = ({ url, name, size, download }: Props) => {
<div className="flex gap-2 ">
<IconVideo className="w-9 h-auto" />
<div className="flex flex-col gap-1 text-sm text-white">
<span title={name} className='font-bold whitespace-nowrap text-ellipsis w-[240px] overflow-hidden'>{name}</span>
<span title={name} className='font-bold w-[240px] truncate'>{name}</span>
<span>{_size}</span>
</div>
</div>
+3 -3
View File
@@ -156,11 +156,11 @@ const FileMessage: FC<Props> = ({
/>
);
return (
<div className={clsx(`file_message bg-slate-50 dark:bg-slate-900 border border-solid border-gray-300 dark:border-gray-500 box-border w-[370px] h-[66px] rounded-md`, sending && "opacity-90")}>
<div className="p-2 flex items-center justify-between gap-2">
<div className={clsx(`file_message bg-slate-50 dark:bg-slate-900 border border-solid border-gray-300 dark:border-gray-500 box-border w-[370px] rounded-md`, sending && "opacity-90")}>
<div className="px-2 py-3 flex items-center justify-between gap-2">
{icon}
<div className="flex flex-col gap-1 w-full overflow-hidden">
<span className="font-semibold text-sm text-gray-800 dark:text-gray-100 whitespace-nowrap text-ellipsis">{name}</span>
<span className="font-semibold text-sm text-gray-800 dark:text-gray-100 truncate">{name}</span>
<span className="whitespace-nowrap text-xs text-gray-500 dark:text-gray-300 flex gap-4">
{sending ? (
<Progress value={progress} width={"80%"} />
+1 -1
View File
@@ -44,7 +44,7 @@ const GoogleLoginInner: FC<Props> = ({ type = "login", loaded, loadError }) => {
}, [error]);
return (
<Button className=" group relative w-full bg-white dark:bg-[#384250] text-gray-600 dark:text-gray-200 !h-[46px] overflow-hidden border border-solid border-[#d0d5dd]" disabled={!loaded || isLoading}>
<Button className=" group relative w-full !bg-white dark:!bg-[#384250] !text-gray-600 dark:!text-gray-200 !h-[46px] overflow-hidden border border-solid border-[#d0d5dd]" disabled={!loaded || isLoading}>
<div className="absolute left-0 top-0 w-full flex-center gap-3 z-[998] h-10 bg-inherit">
<IconGoogle className="w-6 h-6" />
{loadError
+1 -1
View File
@@ -14,7 +14,7 @@ const renderContent = (data: MessagePayload) => {
switch (content_type) {
case ContentTypes.text:
res = (
<span className="text-ellipsis overflow-hidden break-words break-all text-gray-800 dark:text-gray-100">
<span className="truncate break-words break-all text-gray-800 dark:text-gray-100">
<LinkifyText text={content} url={false} mentionTextOnly={true} mentionPopOver={false} />
</span>
);
+1 -1
View File
@@ -41,7 +41,7 @@ export default function URLPreview({ url = "" }) {
const { title, description, ogImage } = data;
const containerClass = `flex items-center border border-solid border-gray-300 box-border rounded-md w-[380px]`;
const dotsClass = `overflow-hidden whitespace-nowrap text-ellipsis`;
const dotsClass = `truncate`;
return ogImage ? (
<a className={`${containerClass} flex-col !items-start p-3`} href={url} target="_blank" rel="noreferrer">
<h3 className={`text-base text-primary-500 w-full ${dotsClass}`}>{title}</h3>
+2 -2
View File
@@ -111,8 +111,8 @@ const Message: FC<IProps> = ({
trigger="click"
content={<Profile uid={fromUid || 0} type="card" cid={context == "user" ? 0 : contextId} />}
>
<div className="cursor-pointer" data-uid={fromUid} ref={avatarRef}>
<Avatar width={40} height={40} src={currUser?.avatar} name={currUser?.name} />
<div className="cursor-pointer w-10 h-10 flex-shrink-0" data-uid={fromUid} ref={avatarRef}>
<Avatar className="w-10 h-10 rounded-full object-cover" width={40} height={40} src={currUser?.avatar} name={currUser?.name} />
</div>
</Tippy>
<ContextMenu
+1 -1
View File
@@ -44,7 +44,7 @@ const Profile: FC<Props> = ({ uid, type = "embed", cid }) => {
const isCard = type == 'card';
const canRemoveFromServer = !isCard && canRemove;
const hasMore = email || canRemoveFromChannel || canRemoveFromServer;
const iconClass = `cursor-pointer flex flex-col items-center gap-1 rounded-lg w-32 text-primary-400 bg-gray-100 dark:bg-gray-800 text-sm pt-3.5 pb-3`;
const iconClass = `cursor-pointer flex flex-col items-center gap-1 rounded-lg w-32 text-primary-400 bg-gray-50 dark:bg-gray-800 text-sm pt-3.5 pb-3`;
const containerClass = clsx(`flex-center flex-col gap-1 z-[99] mt-20 select-none`, isCard ? "p-4 w-[280px] bg-white dark:bg-gray-800 drop-shadow rounded-md" : "w-[432px]");
return (
<div className={containerClass}>
+2 -2
View File
@@ -13,10 +13,10 @@ const SaveTip: FC<Props> = ({ saveHandler, resetHandler }) => {
const { t } = useTranslation("setting");
// const btnClass=clsx("")
return (
<div className="w-full p-2 absolute bottom-16 left-0 flex items-center justify-between text-gray-500 border border-solid border-gray-200 dark:border-gray-400 dark:bg-gray-600 shadow-md rounded-full">
<div className="w-full p-2 absolute bottom-16 left-0 flex items-center justify-between font-semibold text-gray-700 border border-solid border-gray-200 dark:border-gray-400 dark:bg-gray-600 shadow-md rounded-full">
<span className="p-2 text-sm dark:text-gray-200">{t('save_tip')}</span>
<div className="flex items-center gap-3">
<Button className="small ghost !border-none !text-gray-500 !shadow-none dark:!text-gray-100" onClick={resetHandler}>
<Button className="small ghost border_less !text-gray-700 !shadow-none dark:!text-gray-100" onClick={resetHandler}>
{t('reset')}
</Button>
<Button className="small !rounded-full" onClick={saveHandler}>
@@ -60,7 +60,7 @@ export default function UploadFileList({
<div className="flex-center w-40 h-40">
{type.startsWith("image") ? <img className="w-full h-full object-cover" src={url} alt="image" /> : getFileIcon(type, name)}
</div>
<h4 className="w-40 mt-4 mb-0.5 font-semibold text-sm text-gray-800 dark:text-gray-100 whitespace-nowrap overflow-hidden text-ellipsis">{name}</h4>
<h4 className="w-40 mt-4 mb-0.5 font-semibold text-sm text-gray-800 dark:text-gray-100 truncate">{name}</h4>
<span className="text-xs text-gray-500">{formatBytes(size)}</span>
<ul className="invisible group-hover:visible bg-inherit border border-solid border-black/10 box-border rounded-md flex items-center absolute -right-5 -top-2.5">
<li className="p-1 cursor-pointer edit" onClick={handleOpenEditModal.bind(null, idx)}>
@@ -45,12 +45,12 @@ const StyledSettingContainer: FC<PropsWithChildren<Props>> = ({
);
})}
{dangers.length ? (
<ul className="flex flex-col gap-2 mb-9">
<ul className="flex flex-col gap-2 mb-9 text-sm font-semibold text-red-500 dark:text-red-400">
{dangers.map((d) => {
if (typeof d === "boolean" || !d) return null;
const { title, handler } = d;
return (
<li key={title} onClick={handler} className="text-sm text-red-500 dark:text-red-400 rounded cursor-pointer py-1.5 px-3">
<li key={title} onClick={handler} className="rounded cursor-pointer py-1.5 px-3">
{title}
</li>
);
+1 -1
View File
@@ -44,7 +44,7 @@ const User: FC<Props> = ({
if (!curr) return null;
const online = curr.online || curr.uid == loginUid;
const containerClass = clsx(`relative flex items-center justify-start gap-2 p-2 rounded-lg select-none `, interactive && "hover:bg-gray-500/10", compact && "p-0");
const nameClass = clsx(`text-sm text-gray-500 max-w-[190px] overflow-hidden text-ellipsis font-semibold dark:text-white`);
const nameClass = clsx(`text-sm text-gray-500 max-w-[190px] truncate font-semibold dark:text-white`);
const statusClass = clsx(`absolute -bottom-0.5 -right-1.5 w-3 h-3 box-content rounded-full border-[2px] border-solid border-white dark:border-gray-300`,
online ? "bg-[#22c55e]" : "bg-[#a1a1aa]",
compact && "w-3.5 h-3.5");
+3 -1
View File
@@ -1,3 +1,4 @@
import dayjs from "dayjs";
import { FC } from "react";
import { useTranslation } from "react-i18next";
import { useGetServerVersionQuery } from "../../app/services/server";
@@ -5,11 +6,12 @@ type Props = {};
const Version: FC<Props> = () => {
const { t } = useTranslation("setting", { keyPrefix: "version" });
const { data: serverVersion } = useGetServerVersionQuery();
const ts = process.env.REACT_APP_BUILD_TIME;
return (
<div className="flex flex-col gap-3 dark:text-white">
<div className="item">{t("client_version")}: {process.env.VERSION}</div>
<div className="item">{t("server_version")}: {serverVersion}</div>
<div className="item">{t("build_time")}: {process.env.REACT_APP_BUILD_TIME}</div>
<div className="item">{t("build_time")}: {ts} {dayjs(ts).fromNow()}</div>
</div>
);
};
+2 -2
View File
@@ -12,8 +12,8 @@ const StyledButton = ({ children, className = '', ...rest }: Props) => {
const isFull = className.includes('flex');
return <button className={clsx(`text-sm text-white bg-primary-400 break-keep shadow rounded-lg box-border px-3.5 py-2.5 hover:bg-primary-500 active:bg-primary-500 disabled:bg-gray-300`,
isFull && "w-full",
isGhost && "text-primary-400 border border-primary-400 !bg-transparent",
isCancel && "!bg-transparent text-gray-800 dark:text-gray-50 border border-gray-200",
isGhost && "text-primary-400 border border-solid border-primary-400 !bg-transparent",
isCancel && "!bg-transparent text-gray-800 dark:text-gray-50 border border-solid border-gray-200",
isSmall && "!py-2",
noBorder && "!shadow-none border-none",
isMini && "!px-2.5 !py-1 !text-xs",
+5 -5
View File
@@ -38,25 +38,25 @@ const Input: FC<Props> = ({ type = "text", prefix = "", className = "", ...rest
// const noInner=!className.includes("inner");
const isPwd = type == "password";
const inputClass = clsx(`w-full bg-white dark:bg-gray-800 text-sm text-gray-800 dark:text-gray-200 p-2 outline-none disabled:text-gray-500 disabled:bg-gray-100 dark:disabled:text-gray-500 dark:disabled:bg-gray-800/50 placeholder:text-gray-400`,
// noInner && 'rounded border border-gray-200 shadow',
// noInner && 'rounded border border-solid border-gray-200 shadow',
isLarge && 'py-3',
isNone && "border-none bg-transparent shadow-none",
isPwd && "pr-[30px]"
);
return type == "password" ? (
<div className={`w-full relative flex overflow-hidden rounded border border-gray-300 dark:border-gray-400 shadow ${className}`}>
<div className={`w-full relative flex overflow-hidden rounded border border-solid border-gray-300 dark:border-gray-400 shadow-sm ${className}`}>
<input type={inputType} autoComplete={inputType == "password" ? "current-password" : "on"} className={`${inputClass} ${className}`} {...rest} />
<div className="absolute top-1/2 right-2.5 -translate-y-1/2 cursor-pointer" onClick={togglePasswordVisible}>
{inputType == "password" ? <IconEyeClose className="fill-gray-500" /> : <IconEyeOpen className="fill-gray-500" />}
</div>
</div>
) : prefix ? (
<div className={`w-full relative flex overflow-hidden rounded border border-gray-300 dark:border-gray-400 shadow ${className}`}>
<span className="px-4 py-2 text-sm text-gray-500 dark:text-gray-300 bg-gray-200 dark:bg-gray-800 border dark:border-gray-600">{prefix}</span>
<div className={`w-full relative flex overflow-hidden rounded border border-solid border-gray-300 dark:border-gray-400 shadow-sm ${className}`}>
<span className="px-4 py-2 text-sm text-gray-500 dark:text-gray-300 bg-gray-100 dark:bg-gray-800 shadow-[rgb(0_0_0_/_10%)_-1px_0px_0px_inset]">{prefix}</span>
<input className={`${inputClass} ${className}`} type={inputType} {...rest} />
</div>
) : (
<input type={inputType} className={`${inputClass} rounded border border-gray-200 dark:border-gray-400 shadow ${className}`} {...rest} />
<input type={inputType} className={`${inputClass} rounded border border-solid border-gray-200 dark:border-gray-400 shadow-sm ${className}`} {...rest} />
);
};
+1 -1
View File
@@ -43,7 +43,7 @@ const Radio: FC<Props> = ({
}}
id={`${id}-${index}`}
/>
<div className="drop-shadow px-2 py-3 border border-solid border-gray-300 dark:border-gray-400 rounded-lg w-full h-full bg-white dark:bg-gray-800 peer-checked:bg-primary-400 text-sm text-gray-500 dark:text-gray-300 peer-checked:text-white">
<div className="drop-shadow-sm px-2 py-3 border border-solid border-gray-300 dark:border-gray-400 rounded-lg w-full h-full bg-white dark:bg-gray-800 peer-checked:bg-primary-400 text-sm text-gray-500 dark:text-gray-300 peer-checked:text-white">
<label className="ml-6" htmlFor={`${id}-${index}`}>{item}</label>
</div>
<div className="absolute top-1/2 left-3 -translate-y-1/2 w-3.5 h-3.5 rounded-full border border-solid border-gray-300 peer-checked:hidden"></div>
+6 -2
View File
@@ -2,8 +2,12 @@ import { TextareaHTMLAttributes } from "react";
type Props = TextareaHTMLAttributes<HTMLTextAreaElement>
const StyledTextarea = ({ className, ...rest }: Props) => {
return <textarea className={`rounded text-sm p-2 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 resize-none w-full shadow border border-gray-200 dark:border-gray-400
disabled:bg-gray-100 dark:disabled:bg-gray-800/50 disabled:text-gray-400 dark:disabled:text-gray-500 disabled:pointer-events-none placeholder:text-gray-400 ${className}`}
return <textarea className={`rounded text-sm p-2 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 resize-none w-full shadow-sm border border-gray-200 dark:border-gray-400
disabled:bg-gray-100 dark:disabled:bg-gray-800/50
disabled:text-gray-400 dark:disabled:text-gray-500
disabled:pointer-events-none
placeholder:text-gray-400
${className}`}
{...rest}></textarea>;
};
export default StyledTextarea;