multi columns layout

This commit is contained in:
Ren Amamiya 2023-05-21 08:49:08 +07:00
parent f11fe2d349
commit f73c7321d7
20 changed files with 127 additions and 199 deletions

View File

@ -92,7 +92,7 @@ export default function ChannelCreateModal() {
<PlusIcon width={12} height={12} className="text-zinc-500" />
</div>
<div>
<h5 className="text-[13px] font-semibold text-zinc-500 group-hover:text-zinc-400">
<h5 className="font-semibold text-zinc-400 group-hover:text-zinc-200">
Add a new channel
</h5>
</div>

View File

@ -32,7 +32,7 @@ export default function ChannelsListItem({ data }: { data: any }) {
<span className="text-base text-white">#</span>
</div>
<div>
<h5 className="truncate font-medium text-zinc-400">{channel?.name}</h5>
<h5 className="truncate font-medium text-zinc-200">{channel?.name}</h5>
</div>
</a>
);

View File

@ -11,7 +11,7 @@ export default function ChannelsList() {
const { data, error }: any = useSWR("channels", fetcher);
return (
<div className="flex flex-col gap-px">
<div className="flex flex-col gap-1">
{!data || error ? (
<>
<div className="inline-flex h-8 items-center gap-2 rounded-md px-2.5">

View File

@ -4,22 +4,12 @@ import Navigation from "@shared/navigation";
export function LayoutChannel({ children }: { children: React.ReactNode }) {
return (
<div className="h-screen w-screen bg-zinc-50 text-zinc-900 dark:bg-zinc-950 dark:text-white">
<div className="flex h-screen w-full flex-col">
<div
data-tauri-drag-region
className="relative h-9 shrink-0 border-b border-zinc-100 bg-white dark:border-zinc-900 dark:bg-black"
>
<AppHeader />
</div>
<div className="relative flex min-h-0 w-full flex-1">
<div className="relative flex flex-row flex-wrap shrink-0">
<MultiAccounts />
<Navigation />
</div>
<div className="w-full h-full">{children}</div>
</div>
<div className="flex w-screen h-screen">
<div className="relative flex flex-row flex-wrap shrink-0">
<MultiAccounts />
<Navigation />
</div>
<div className="w-full h-full">{children}</div>
</div>
);
}

View File

@ -44,7 +44,7 @@ export default function ChatsListItem({ pubkey }: { pubkey: string }) {
/>
</div>
<div>
<h5 className="truncate font-medium text-zinc-400 group-hover:text-white">
<h5 className="truncate font-medium text-zinc-200 group-hover:text-white">
{user.nip05 || user.name || shortenKey(pubkey)}
</h5>
</div>

View File

@ -16,7 +16,7 @@ export default function ChatsList() {
);
return (
<div className="flex flex-col gap-px">
<div className="flex flex-col gap-1">
<ChatsListSelfItem />
{!chats || error ? (
<>

View File

@ -45,7 +45,7 @@ export default function ChatsListSelfItem() {
/>
</div>
<div>
<h5 className="truncate font-medium text-zinc-400">
<h5 className="truncate font-medium text-zinc-200">
{profile?.nip05 || profile?.name || shortenKey(account.pubkey)}{" "}
<span className="text-zinc-600">(you)</span>
</h5>

View File

@ -4,22 +4,12 @@ import Navigation from "@shared/navigation";
export function LayoutChat({ children }: { children: React.ReactNode }) {
return (
<div className="h-screen w-screen bg-zinc-50 text-zinc-900 dark:bg-zinc-950 dark:text-white">
<div className="flex h-screen w-full flex-col">
<div
data-tauri-drag-region
className="relative h-9 shrink-0 border-b border-zinc-100 bg-white dark:border-zinc-900 dark:bg-black"
>
<AppHeader />
</div>
<div className="relative flex min-h-0 w-full flex-1">
<div className="relative flex flex-row flex-wrap shrink-0">
<MultiAccounts />
<Navigation />
</div>
<div className="w-full h-full">{children}</div>
</div>
<div className="flex w-screen h-screen">
<div className="relative flex flex-row flex-wrap shrink-0">
<MultiAccounts />
<Navigation />
</div>
<div className="w-full h-full">{children}</div>
</div>
);
}

View File

@ -4,22 +4,12 @@ import Navigation from "@shared/navigation";
export function LayoutNewsfeed({ children }: { children: React.ReactNode }) {
return (
<div className="h-screen w-screen bg-zinc-50 text-zinc-900 dark:bg-zinc-950 dark:text-white">
<div className="flex h-screen w-full flex-col">
<div
data-tauri-drag-region
className="relative h-9 shrink-0 border-b border-zinc-100 bg-white dark:border-zinc-900 dark:bg-black"
>
<AppHeader />
</div>
<div className="relative flex min-h-0 w-full flex-1">
<div className="relative flex flex-row flex-wrap shrink-0">
<MultiAccounts />
<Navigation />
</div>
<div className="w-full h-full">{children}</div>
</div>
<div className="flex w-screen h-screen">
<div className="relative flex flex-row flex-wrap shrink-0">
<MultiAccounts />
<Navigation />
</div>
<div className="w-full h-full">{children}</div>
</div>
);
}

View File

@ -1 +1 @@
export { LayoutNewsfeed as Layout } from "./layout";
export { LayoutSpace as Layout } from "./layout";

View File

@ -1,25 +1,14 @@
import AppHeader from "@shared/appHeader";
import MultiAccounts from "@shared/multiAccounts";
import Navigation from "@shared/navigation";
export function LayoutNewsfeed({ children }: { children: React.ReactNode }) {
export function LayoutSpace({ children }: { children: React.ReactNode }) {
return (
<div className="h-screen w-screen bg-zinc-50 text-zinc-900 dark:bg-zinc-950 dark:text-white">
<div className="flex h-screen w-full flex-col">
<div
data-tauri-drag-region
className="relative h-9 shrink-0 border-b border-zinc-100 bg-white dark:border-zinc-900 dark:bg-black"
>
<AppHeader />
</div>
<div className="relative flex min-h-0 w-full flex-1">
<div className="relative flex flex-row flex-wrap shrink-0">
<MultiAccounts />
<Navigation />
</div>
<div className="w-full h-full">{children}</div>
</div>
<div className="flex w-screen h-screen">
<div className="relative flex flex-row flex-wrap shrink-0">
<MultiAccounts />
<Navigation />
</div>
<div className="w-full h-full">{children}</div>
</div>
);
}

View File

@ -58,73 +58,76 @@ export function Page() {
}, [fetchNextPage, allRows.length, rowVirtualizer.getVirtualItems()]);
return (
<div
ref={parentRef}
className="scrollbar-hide flex h-full flex-col justify-between gap-1.5 overflow-y-auto"
style={{ contain: "strict" }}
>
<div className="pt-1.5">
{status === "loading" ? (
<div className="px-3 py-1.5">
<div className="rounded-md border border-zinc-800 bg-zinc-900 px-3 py-3 shadow-input shadow-black/20">
<NoteSkeleton />
</div>
</div>
) : status === "error" ? (
<div>{error.message}</div>
) : (
<div
className="relative w-full"
style={{
height: `${rowVirtualizer.getTotalSize()}px`,
}}
>
<div
className="absolute left-0 top-0 w-full"
style={{
transform: `translateY(${
itemsVirtualizer[0].start -
rowVirtualizer.options.scrollMargin
}px)`,
}}
>
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
const note = allRows[virtualRow.index];
if (note) {
if (note.kind === 1) {
return (
<div
key={virtualRow.index}
data-index={virtualRow.index}
ref={rowVirtualizer.measureElement}
>
<NoteBase key={note.event_id} event={note} />
</div>
);
} else {
return (
<div
key={virtualRow.index}
data-index={virtualRow.index}
ref={rowVirtualizer.measureElement}
>
<NoteQuoteRepost key={note.event_id} event={note} />
</div>
);
}
}
})}
</div>
</div>
)}
<div>
{isFetching && !isFetchingNextPage ? (
<div className="h-full w-full flex flex-nowrap overflow-x-auto">
<div className="shrink-0 w-[420px] border-r border-zinc-900">
<div className="h-11 w-full inline-flex items-center justify-center border-b border-zinc-900">
<h3 className="font-semibold text-zinc-100">Following</h3>
</div>
<div
ref={parentRef}
className="scrollbar-hide flex w-full h-full flex-col justify-between gap-1.5 overflow-y-auto"
style={{ contain: "strict" }}
>
{status === "loading" ? (
<div className="px-3 py-1.5">
<div className="rounded-md border border-zinc-800 bg-zinc-900 px-3 py-3 shadow-input shadow-black/20">
<NoteSkeleton />
</div>
</div>
) : null}
) : (
<div
className="relative w-full"
style={{
height: `${rowVirtualizer.getTotalSize()}px`,
}}
>
<div
className="absolute left-0 top-0 w-full"
style={{
transform: `translateY(${
itemsVirtualizer[0].start -
rowVirtualizer.options.scrollMargin
}px)`,
}}
>
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
const note = allRows[virtualRow.index];
if (note) {
if (note.kind === 1) {
return (
<div
key={virtualRow.index}
data-index={virtualRow.index}
ref={rowVirtualizer.measureElement}
>
<NoteBase key={note.event_id} event={note} />
</div>
);
} else {
return (
<div
key={virtualRow.index}
data-index={virtualRow.index}
ref={rowVirtualizer.measureElement}
>
<NoteQuoteRepost key={note.event_id} event={note} />
</div>
);
}
}
})}
</div>
</div>
)}
<div>
{isFetching && !isFetchingNextPage && (
<div className="px-3 py-1.5">
<div className="rounded-md border border-zinc-800 bg-zinc-900 px-3 py-3 shadow-input shadow-black/20">
<NoteSkeleton />
</div>
</div>
)}
</div>
</div>
</div>
</div>

View File

@ -1,25 +1,14 @@
import AppHeader from "@shared/appHeader";
import MultiAccounts from "@shared/multiAccounts";
import Navigation from "@shared/navigation";
export function LayoutNewsfeed({ children }: { children: React.ReactNode }) {
return (
<div className="h-screen w-screen bg-zinc-50 text-zinc-900 dark:bg-zinc-950 dark:text-white">
<div className="flex h-screen w-full flex-col">
<div
data-tauri-drag-region
className="relative h-9 shrink-0 border-b border-zinc-100 bg-white dark:border-zinc-900 dark:bg-black"
>
<AppHeader />
</div>
<div className="relative flex min-h-0 w-full flex-1">
<div className="relative flex flex-row flex-wrap shrink-0">
<MultiAccounts />
<Navigation />
</div>
<div className="w-full h-full">{children}</div>
</div>
<div className="flex w-screen h-screen">
<div className="relative flex flex-row flex-wrap shrink-0">
<MultiAccounts />
<Navigation />
</div>
<div className="w-full h-full">{children}</div>
</div>
);
}

View File

@ -36,7 +36,7 @@ export function render(pageContext: PageContextServer) {
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
</head>
<body class="cursor-default select-none overflow-hidden font-sans antialiased">
<body class="cursor-default select-none overflow-hidden font-sans antialiased bg-zinc-50 text-zinc-900 dark:bg-zinc-950 dark:text-white">
<div id="app">${dangerouslySkipEscape(pageHtml)}</div>
</body>
</html>`;

View File

@ -6,15 +6,11 @@ export default function ActiveAccount({ user }: { user: any }) {
const userData = JSON.parse(user.metadata);
return (
<button
type="button"
className="relative h-10 w-10 overflow-hidden rounded-lg"
>
<button type="button" className="relative h-11 w-11 overflow-hidden">
<Image
src={userData.picture || DEFAULT_AVATAR}
alt="user's avatar"
loading="auto"
className="h-10 w-10 object-cover"
className="h-11 w-11 rounded-md object-cover"
/>
</button>
);

View File

@ -6,11 +6,11 @@ export default function InactiveAccount({ user }: { user: any }) {
const userData = JSON.parse(user.metadata);
return (
<div className="relative h-10 w-10 shrink rounded-lg">
<div className="relative h-11 w-11 shrink rounded-md">
<Image
src={userData.picture || DEFAULT_AVATAR}
alt="user's avatar"
className="h-10 w-10 rounded-lg object-cover"
className="h-11 w-11 rounded-lg object-cover"
/>
</div>
);

View File

@ -1,7 +1,6 @@
import ArrowLeftIcon from "@icons/arrowLeft";
import ArrowRightIcon from "@icons/arrowRight";
import RefreshIcon from "@icons/refresh";
import EventCollector from "@shared/eventCollector";
import useSWR from "swr";
const fetcher = async () => {
@ -27,47 +26,33 @@ export default function AppHeader() {
return (
<div
data-tauri-drag-region
className="flex h-full w-full flex-1 items-center px-2"
className="flex h-11 w-full items-center justify-between border-b border-zinc-900 px-3 gap-2.5"
>
<div
className={`flex h-full items-center gap-2 ${
platform === "darwin" ? "pl-[68px]" : ""
}`}
>
<div className="flex gap-2.5">
<button
type="button"
onClick={() => goBack()}
className="group inline-flex h-5 w-5 items-center justify-center rounded hover:bg-zinc-900"
className="group inline-flex h-6 w-6 items-center justify-center rounded hover:bg-zinc-900"
>
<ArrowLeftIcon
width={14}
height={14}
width={16}
height={16}
className="text-zinc-500 group-hover:text-zinc-300"
/>
</button>
<button
type="button"
onClick={() => goForward()}
className="group inline-flex h-5 w-5 items-center justify-center rounded hover:bg-zinc-900"
className="group inline-flex h-6 w-6 items-center justify-center rounded hover:bg-zinc-900"
>
<ArrowRightIcon
width={14}
height={14}
className="text-zinc-500 group-hover:text-zinc-300"
/>
</button>
<button
type="button"
onClick={() => reload()}
className="group inline-flex h-5 w-5 items-center justify-center rounded hover:bg-zinc-900"
>
<RefreshIcon
width={14}
height={14}
width={16}
height={16}
className="text-zinc-500 group-hover:text-zinc-300"
/>
</button>
</div>
<EventCollector />
</div>
);
}

View File

@ -136,8 +136,8 @@ export default function EventCollector() {
);
return (
<div className="inline-flex h-6 w-6 items-center justify-center rounded text-zinc-400 hover:bg-zinc-900 hover:text-white">
<HeartBeatIcon width={14} height={14} />
<div className="inline-flex h-6 w-6 items-center justify-center rounded text-green-400 hover:bg-zinc-900 hover:text-white">
<HeartBeatIcon width={16} height={16} />
</div>
);
}

View File

@ -18,7 +18,7 @@ export default function MultiAccounts() {
const { data: activeAccount }: any = useSWR("activeAccount", fetcher);
return (
<div className="flex shrink-0 w-[68px] h-full flex-col items-center justify-between border-r border-zinc-900 pb-4 pt-3">
<div className="flex shrink-0 w-[68px] h-full flex-col items-center justify-between border-r border-zinc-900 pb-4 pt-11">
<div className="flex flex-col items-center">
<div className="flex flex-col gap-2">
<>
@ -31,7 +31,7 @@ export default function MultiAccounts() {
<div>
<button
type="button"
className="group relative flex h-10 w-10 shrink items-center justify-center rounded-lg bg-zinc-900 hover:bg-zinc-800"
className="group relative flex h-11 w-11 shrink items-center justify-center rounded-md bg-zinc-900 hover:bg-zinc-800"
>
<BellIcon
width={16}

View File

@ -1,23 +1,19 @@
import ChannelsList from "@app/channel/components/list";
import ChatsList from "@app/chat/components/list";
import ActiveLink from "@shared/activeLink";
import { ComposerModal } from "@shared/composer/modal";
import EventCollector from "@shared/eventCollector";
import MyspaceIcon from "@icons/myspace";
import { Disclosure } from "@headlessui/react";
import NavArrowDownIcon from "@icons/navArrowDown";
import ThreadsIcon from "@icons/threads";
import WorldIcon from "@icons/world";
import { Disclosure } from "@headlessui/react";
import ActiveLink from "@shared/activeLink";
import AppHeader from "@shared/appHeader";
import { ComposerModal } from "@shared/composer/modal";
export default function Navigation() {
return (
<div className="flex w-[232px] h-full flex-col gap-3 pt-1.5">
<div className="flex h-11 items-center justify-between px-3.5">
<div className="flex w-[232px] h-full flex-col gap-3 border-r border-zinc-900">
<AppHeader />
<div className="flex h-8 px-3.5">
<ComposerModal />
<EventCollector />
</div>
{/* Newsfeed */}
<div className="flex flex-col gap-0.5 px-1.5">
@ -26,10 +22,10 @@ export default function Navigation() {
Feeds
</h3>
</div>
<div className="flex flex-col text-zinc-400">
<div className="flex flex-col gap-1">
<ActiveLink
href="/app/space"
className="flex h-8 items-center gap-2.5 rounded-md px-2.5 hover:text-white"
className="flex h-8 items-center gap-2.5 rounded-md px-2.5 text-zinc-200 hover:text-white"
activeClassName="bg-zinc-900/50 hover:bg-zinc-900"
>
<span className="inline-flex h-5 w-5 items-center justify-center rounded bg-zinc-900">
@ -39,7 +35,7 @@ export default function Navigation() {
</ActiveLink>
<ActiveLink
href="/app/threads"
className="flex h-8 items-center gap-2.5 rounded-md px-2.5 hover:text-white"
className="flex h-8 items-center gap-2.5 rounded-md px-2.5 text-zinc-200 hover:text-white"
activeClassName=""
>
<span className="inline-flex h-5 w-5 items-center justify-center rounded bg-zinc-900">