mirror of
https://github.com/luminous-devs/lume.git
synced 2024-09-19 11:43:30 +00:00
multi columns layout
This commit is contained in:
parent
f11fe2d349
commit
f73c7321d7
@ -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>
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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">
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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 ? (
|
||||
<>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
export { LayoutNewsfeed as Layout } from "./layout";
|
||||
export { LayoutSpace as Layout } from "./layout";
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>`;
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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>
|
||||
);
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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}
|
||||
|
@ -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">
|
||||
|
Loading…
Reference in New Issue
Block a user