refactor: mobile UX friendly

This commit is contained in:
Tristan Yang
2023-02-15 10:04:26 +08:00
parent 476ffc344d
commit 56bd1557db
28 changed files with 71 additions and 77 deletions
+2 -2
View File
@@ -136,7 +136,7 @@ function ChannelChat({ cid = 0, dropFiles = [] }: Props) {
<div className="flex items-center gap-1">
<ChannelIcon personal={!is_public} />
<span className="text-gray-800 dark:text-white">{name}</span>
<span className="ml-2 text-gray-500">{description}</span>
<span className="ml-2 text-gray-500 hidden md:block">{description}</span>
</div>
</header>
}
@@ -164,7 +164,7 @@ function ChannelChat({ cid = 0, dropFiles = [] }: Props) {
</div>
}
>
<article className="py-4.5 px-4 w-full h-full overflow-x-hidden overflow-y-auto" id={`VOCECHAT_FEED_channel_${cid}`}>
<article className="py-4.5 px-1 md:px-4 w-full h-full overflow-x-hidden overflow-y-auto" id={`VOCECHAT_FEED_channel_${cid}`}>
{hasMore ? (
<LoadMore pullUp={pullUp} pulling={pulling} />
) : (
+1 -1
View File
@@ -40,7 +40,7 @@ const SessionList: FC<Props> = () => {
}, [channelIDs, channelMessage, readChannels, readUsers, loginUid, userMessage]);
return (
<ul className="flex flex-col gap-0.5 p-2 overflow-auto h-[calc(100vh_-_56px_-_16px_-_8px)]">
<ul className="flex flex-col gap-0.5 p-2 overflow-auto h-[calc(100vh_-_56px_-_38px)]">
{sessions.map((s) => {
const { key, id, mid = 0 } = s;
return <Session key={key} id={id} mid={mid} />;
+2 -2
View File
@@ -119,7 +119,7 @@ function FavsPage() {
};
return (
<div className="h-screen flex bg-white mt-2 mr-6 mb-2.5 overflow-auto dark:bg-[#384250] rounded-2xl">
<div className="min-w-[268px] p-2 shadow-inner-[-1px_0px_0px_rgba(0,_0,_0,_0.1)]">
<div className=" md:min-w-[268px] p-2 shadow-inner-[-1px_0px_0px_rgba(0,_0,_0,_0.1)]">
<ul className="flex flex-col gap-0.5">
{Filters.map(({ icon, title, filter: f }) => {
return (
@@ -129,7 +129,7 @@ function FavsPage() {
onClick={handleFilter.bind(null, f as filter)}
>
{icon}
<span className="font-bold text-sm text-gray-600 dark:text-gray-100">{title}</span>
<span className="hidden md:block font-bold text-sm text-gray-600 dark:text-gray-100">{title}</span>
</li>
);
})}
+10 -19
View File
@@ -9,13 +9,14 @@ import usePreload from "../../common/hook/usePreload";
import Tooltip from "../../common/component/Tooltip";
import Notification from "../../common/component/Notification";
import Manifest from "../../common/component/Manifest";
import ChatIcon from "../../assets/icons/chat.svg";
import UserIcon from "../../assets/icons/user.svg";
import FavIcon from "../../assets/icons/bookmark.svg";
import FolderIcon from "../../assets/icons/folder.svg";
import { useAppSelector } from "../../app/store";
// const routes = ["/setting", "/setting/channel/:cid"];
import { isMobile } from "../../common/utils";
function HomePage() {
const { t } = useTranslation();
const isHomePath = useMatch(`/`);
@@ -42,16 +43,13 @@ function HomePage() {
const isSettingPage = pathname.startsWith("/setting");
const isChattingPage = isHomePath || pathname.startsWith("/chat");
if (isSettingPage) {
return (
<>
<Outlet />
</>
);
return <Outlet />;
}
// 有点绕
const chatNav = isChatHomePath ? "/chat" : chatPath || "/chat";
const userNav = userPath || "/users";
const linkClass = `flex items-center gap-2.5 px-3 py-2 font-semibold text-sm text-gray-600 rounded-lg hover:bg-gray-800/10`;
const mobile = isMobile();
return (
<>
<Manifest />
@@ -62,42 +60,35 @@ function HomePage() {
{loginUid && <User uid={loginUid} />}
<nav className="flex flex-col gap-1 px-3 py-6">
<NavLink
className={() => {
return `${linkClass} ${isChattingPage ? "bg-primary-400 hover:bg-primary-400" : ""}`;
}}
className={({ isActive }) => `${linkClass} ${(isActive || isChattingPage) ? "bg-primary-400 hover:bg-primary-400" : ""}`}
to={chatNav}
>
{({ isActive }) => {
return <Tooltip tip={t("chat")}>
return <Tooltip disabled={mobile} tip={t("chat")}>
<ChatIcon className={(isActive || isChattingPage) ? "fill-white" : ""} />
</Tooltip>;
}}
</NavLink>
<NavLink className={({ isActive }) => `${linkClass} ${isActive ? 'bg-primary-400 hover:bg-primary-400' : ""}`} to={userNav}>
{({ isActive }) => {
return <Tooltip tip={t("members")}>
return <Tooltip disabled={mobile} tip={t("members")}>
<UserIcon className={isActive ? "fill-white" : ""} />
</Tooltip>;
}}
</NavLink>
<NavLink className={({ isActive }) => `${linkClass} ${isActive ? 'bg-primary-400 hover:bg-primary-400' : ""}`} to={"/favs"}>
{({ isActive }) => {
return <Tooltip tip={t("favs")}>
return <Tooltip disabled={mobile} tip={t("favs")}>
<FavIcon className={isActive ? "fill-white" : ""} />
</Tooltip>;
}}
</NavLink>
<NavLink className={({ isActive }) => `${linkClass} ${isActive ? 'bg-primary-400 hover:bg-primary-400' : ""}`} to={"/files"}>
{({ isActive }) => {
return <Tooltip tip={t("files")}>
return <Tooltip disabled={mobile} tip={t("files")}>
<FolderIcon className={isActive ? "fill-white" : ""} />
</Tooltip>;
}}
</NavLink>
</nav>
<Menu />
+5 -5
View File
@@ -1,5 +1,7 @@
import { useState } from "react";
import Tippy from "@tippyjs/react";
import clsx from "clsx";
import { useTranslation } from "react-i18next";
import Avatar from "../../../common/component/Avatar";
import FilterDate, { Dates } from "./Date";
import FilterFrom from "./From";
@@ -7,11 +9,9 @@ import FilterChannel from "./Channel";
import FilterType, { FileTypes } from "./Type";
import ArrowDown from "../../../assets/icons/arrow.down.svg";
import { useAppSelector } from "../../../app/store";
import { useTranslation } from "react-i18next";
import clsx from "clsx";
const getClass = (selected: boolean) => {
return clsx(`cursor-pointer flex items-center gap-2 shadow rounded-lg py-2 px-3 text-xs text-gray-900 dark:text-gray-200`, selected ? 'text-white bg-primary-400' : 'border border-solid border-gray-300 dark:border-gray-400 ');
return clsx(`cursor-pointer flex items-center gap-1 md:gap-2 shadow rounded-lg p-1 md:py-2 md:px-3 text-xs text-gray-900 dark:text-gray-200`, selected ? 'text-white bg-primary-400' : 'border border-solid border-gray-300 dark:border-gray-400 ');
};
export default function Filter({ filter, updateFilter }) {
const { t } = useTranslation("file");
@@ -22,13 +22,13 @@ export default function Filter({ filter, updateFilter }) {
type: false
});
const toggleFilterVisible = (obj) => {
const toggleFilterVisible = (obj: any) => {
setFiltersVisible((prev) => {
return { ...prev, ...obj };
});
};
const handleUpdateFilter = (data) => {
const handleUpdateFilter = (data: any) => {
updateFilter(data);
let _key = Object.keys(data)[0];
let tmp = {
+1 -1
View File
@@ -17,7 +17,7 @@ const Search: FC<Props> = ({ value = "", updateSearchValue = null, embed = false
};
return (
<div className={clsx(`relative w-full py-1.5 px-4 shadow`, embed && "py-2 shadow-none")}>
<div className={clsx(`hidden md:block relative w-full py-1.5 px-4 shadow`, embed && "py-2 shadow-none")}>
<IconSearch className="absolute left-6 top-1/2 -translate-y-1/2" />
<input value={value} onChange={handleChange} className="bg-black/5 dark:bg-black/20 rounded-full text-sm text-gray-500 py-2.5 pl-9" placeholder={`${t("action.search")}...`} />
</div>
+1 -1
View File
@@ -18,7 +18,7 @@ export default function View({ view = "item" }: Props) {
};
const isGrid = view == "grid";
return (
<ul className={`flex border border-solid dark:border-gray-400 shadow rounded-lg box-border`}>
<ul className={`hidden md:flex border border-solid dark:border-gray-400 shadow rounded-lg box-border`}>
<li className={getClass(!isGrid)} data-view={"item"} onClick={handleChangeView}>
<IconList className={`${!isGrid ? "fill-primary-400" : ""} dark:fill-gray-400`} />
</li>
+1 -2
View File
@@ -82,9 +82,8 @@ function ResourceManagement({ fileMessages }) {
}, [view, filter]);
return (
<div className="h-screen overflow-y-scroll flex flex-col items-start my-2 mr-6 rounded-2xl bg-white dark:bg-[#384250]">
<div className="h-screen md:overflow-y-scroll flex flex-col items-start my-2 mr-6 rounded-2xl bg-white dark:bg-[#384250]">
<Search value={filter.name} updateSearchValue={handleUpdateSearch} />
<div className="divider"></div>
<div className="flex justify-between w-full px-4 py-5">
<Filter filter={filter} updateFilter={updateFilter} />
<View view={view} />
+4 -4
View File
@@ -61,12 +61,12 @@ 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-gray-100 dark:bg-gray-800 rounded-2xl">
<div className="p-6 flex flex-col items-center md:w-[512px] bg-gray-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 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="w-full flex flex-col items-start md:flex-row justify-between mb-6">
<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 ">
@@ -77,7 +77,7 @@ export default function MyAccount() {
{ct("action.edit")}
</Button>
</div>
<div className="w-full flex justify-between mb-6">
<div className="w-full flex flex-col items-start md:flex-row justify-between mb-6">
<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>
@@ -86,7 +86,7 @@ export default function MyAccount() {
{ct("action.edit")}
</Button>
</div>
<div className="w-full flex justify-between mb-6">
<div className="w-full flex flex-col items-start md:flex-row justify-between mb-6">
<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>
+1 -1
View File
@@ -15,7 +15,7 @@ const Search: FC<Props> = ({ input, updateInput }) => {
updateInput(evt.target.value);
};
return (
<div className="relative min-h-[56px] px-2 py-3 flex items-center justify-between gap-2 shadow-[rgb(0_0_0_/_10%)_0px_1px_0px] dark:border-b-gray-500">
<div className="hidden md:flex relative min-h-[56px] px-2 py-3 items-center justify-between gap-2 shadow-[rgb(0_0_0_/_10%)_0px_1px_0px] dark:border-b-gray-500">
<div className="flex items-center gap-1">
<img src={searchIcon} alt="search icon" />
<input value={input} placeholder={`${t("action.search")}...`} className="w-full text-sm bg-transparent dark:text-gray-50" onChange={handleInput} />
+4 -4
View File
@@ -25,11 +25,11 @@ function UsersPage() {
if (!users) return null;
return (
<div className="flex h-full pt-2 pr-12 pb-2.5">
<div className="rounded-l-2xl bg-white dark:bg-[#1F2A37] relative flex flex-col min-w-[268px] shadow-[inset_-1px_0px_0px_rgba(0,_0,_0,_0.1)]">
<div className="flex h-full pt-2 md:pr-12 pb-2.5">
<div className="rounded-l-2xl bg-white dark:bg-[#1F2A37] relative flex flex-col md:min-w-[268px] shadow-[inset_-1px_0px_0px_rgba(0,_0,_0,_0.1)]">
<Search input={input} updateInput={updateInput} />
<div className="px-2 py-3 overflow-scroll pb-[50px]">
<nav className="flex flex-col gap-1">
<div className="px-2 py-3 overflow-scroll">
<nav className="flex flex-col md:gap-1">
{users.map(({ uid }) => {
return (
<NavLink key={uid} className={({ isActive }) => `rounded-md hover:bg-gray-500/10 ${isActive ? "bg-gray-500/10" : ""}`} to={`/users/${uid}`}>