add button component
This commit is contained in:
12
pnpm-lock.yaml
generated
12
pnpm-lock.yaml
generated
@@ -411,8 +411,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==}
|
resolution: {integrity: sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@floating-ui/dom@1.4.0:
|
/@floating-ui/dom@1.4.1:
|
||||||
resolution: {integrity: sha512-b4F0iWffLiqb/TpP2PWVOixrZqE6ni+6VT64AmFH7sJIF3SFPLbe6/h3jQ5Cwffs+HaC9A8V0TQzCPBwVvziIA==}
|
resolution: {integrity: sha512-loCXUOLzIC3jp50RFOKXZ/kQjjz26ryr/23M+FWG9jrmAv8lRf3DUfC2AiVZ3+K316GOhB08CR+Povwz8e9mDw==}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@floating-ui/core': 1.3.1
|
'@floating-ui/core': 1.3.1
|
||||||
dev: false
|
dev: false
|
||||||
@@ -423,7 +423,7 @@ packages:
|
|||||||
react: '>=16.8.0'
|
react: '>=16.8.0'
|
||||||
react-dom: '>=16.8.0'
|
react-dom: '>=16.8.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
'@floating-ui/dom': 1.4.0
|
'@floating-ui/dom': 1.4.1
|
||||||
react: 18.2.0
|
react: 18.2.0
|
||||||
react-dom: 18.2.0(react@18.2.0)
|
react-dom: 18.2.0(react@18.2.0)
|
||||||
dev: false
|
dev: false
|
||||||
@@ -530,8 +530,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
|
resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@maverick-js/signals@5.10.5:
|
/@maverick-js/signals@5.11.0:
|
||||||
resolution: {integrity: sha512-Q9cKATEqEpXoTssZ2Lx83kjgpLYMlpE2V+LlwuudXRT/pxPAIGRxq0xnXk7B2CQlD3Zjc5xXb7a87sGWdavjfA==}
|
resolution: {integrity: sha512-SpV3TAt8/ugELL2cI4mF70paHL3dnJbM69xSq7+z2BlsKeDwMK+oVXSq+WLgYANlfwkiOhZvvfQHo6Zo0muQVw==}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@noble/curves@1.0.0:
|
/@noble/curves@1.0.0:
|
||||||
@@ -3075,7 +3075,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-p8L5V62CV6TmHAngmRAopp231oJKeH77mJja5SsKOfvzrPRoThT/Jo9U0jMRB5iMykqkvyg2J5V5Agn6FPXDWQ==}
|
resolution: {integrity: sha512-p8L5V62CV6TmHAngmRAopp231oJKeH77mJja5SsKOfvzrPRoThT/Jo9U0jMRB5iMykqkvyg2J5V5Agn6FPXDWQ==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@maverick-js/signals': 5.10.5
|
'@maverick-js/signals': 5.11.0
|
||||||
type-fest: 3.12.0
|
type-fest: 3.12.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,8 @@ import { Dialog, Transition } from "@headlessui/react";
|
|||||||
import { createChannel } from "@libs/storage";
|
import { createChannel } from "@libs/storage";
|
||||||
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
||||||
import { AvatarUploader } from "@shared/avatarUploader";
|
import { AvatarUploader } from "@shared/avatarUploader";
|
||||||
import { CancelIcon, PlusIcon } from "@shared/icons";
|
import { Button } from "@shared/button";
|
||||||
|
import { CancelIcon, LoaderIcon, PlusIcon } from "@shared/icons";
|
||||||
import { Image } from "@shared/image";
|
import { Image } from "@shared/image";
|
||||||
import { RelayContext } from "@shared/relayProvider";
|
import { RelayContext } from "@shared/relayProvider";
|
||||||
import { useActiveAccount } from "@stores/accounts";
|
import { useActiveAccount } from "@stores/accounts";
|
||||||
@@ -217,37 +218,13 @@ export function ChannelCreateModal() {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<button
|
<Button preset="large" disabled={!isDirty || !isValid}>
|
||||||
type="submit"
|
|
||||||
disabled={!isDirty || !isValid}
|
|
||||||
className="inline-flex h-11 w-full transform items-center justify-center rounded-lg bg-fuchsia-500 font-medium text-zinc-100 shadow-button active:translate-y-1 disabled:cursor-not-allowed disabled:opacity-30"
|
|
||||||
>
|
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<svg
|
<LoaderIcon className="h-4 w-4 animate-spin text-black dark:text-zinc-100" />
|
||||||
className="h-4 w-4 animate-spin text-black dark:text-zinc-100"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<title id="loading">Loading</title>
|
|
||||||
<circle
|
|
||||||
className="opacity-25"
|
|
||||||
cx="12"
|
|
||||||
cy="12"
|
|
||||||
r="10"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="4"
|
|
||||||
/>
|
|
||||||
<path
|
|
||||||
className="opacity-75"
|
|
||||||
fill="currentColor"
|
|
||||||
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
) : (
|
) : (
|
||||||
"Create channel"
|
"Create channel"
|
||||||
)}
|
)}
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
46
src/shared/button.tsx
Normal file
46
src/shared/button.tsx
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import { ReactNode } from "react";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
|
export function Button({
|
||||||
|
preset,
|
||||||
|
children,
|
||||||
|
disabled = false,
|
||||||
|
onClick = undefined,
|
||||||
|
}: {
|
||||||
|
preset: "small" | "publish" | "large";
|
||||||
|
children: ReactNode;
|
||||||
|
disabled: boolean;
|
||||||
|
onClick?: () => void;
|
||||||
|
}) {
|
||||||
|
let preClass: string;
|
||||||
|
switch (preset) {
|
||||||
|
case "small":
|
||||||
|
preClass =
|
||||||
|
"w-min h-9 px-4 bg-zinc-900 rounded-md text-sm font-medium text-zinc-100 hover:bg-fuchsia-600";
|
||||||
|
break;
|
||||||
|
case "publish":
|
||||||
|
preClass =
|
||||||
|
"w-min h-9 px-4 bg-fuchsia-500 rounded-md text-sm font-medium text-zinc-100 hover:bg-fuchsia-600";
|
||||||
|
break;
|
||||||
|
case "large":
|
||||||
|
preClass =
|
||||||
|
"h-11 w-full bg-fuchsia-500 rounded-md text-sm font-medium text-zinc-100 hover:bg-fuchsia-600";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={onClick}
|
||||||
|
disabled={disabled}
|
||||||
|
className={twMerge(
|
||||||
|
"inline-flex items-center justify-center gap-1 transform active:translate-y-1 disabled:pointer-events-none disabled:opacity-50 focus:outline-none",
|
||||||
|
preClass,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { Dialog, Transition } from "@headlessui/react";
|
import { Dialog, Transition } from "@headlessui/react";
|
||||||
|
import { Button } from "@shared/button";
|
||||||
import { Post } from "@shared/composer/types/post";
|
import { Post } from "@shared/composer/types/post";
|
||||||
import { User } from "@shared/composer/user";
|
import { User } from "@shared/composer/user";
|
||||||
import {
|
import {
|
||||||
@@ -24,14 +25,10 @@ export function Composer() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button
|
<Button onClick={() => toggle(true)} preset="small">
|
||||||
type="button"
|
|
||||||
onClick={() => toggle(true)}
|
|
||||||
className="inline-flex h-8 w-max items-center justify-center gap-1 rounded-md bg-fuchsia-500 px-2.5 text-sm font-medium text-zinc-100 shadow-button hover:bg-fuchsia-600 focus:outline-none"
|
|
||||||
>
|
|
||||||
<ComposeIcon width={14} height={14} />
|
<ComposeIcon width={14} height={14} />
|
||||||
Compose
|
Compose
|
||||||
</button>
|
</Button>
|
||||||
<Transition appear show={open} as={Fragment}>
|
<Transition appear show={open} as={Fragment}>
|
||||||
<Dialog as="div" className="relative z-10" onClose={closeModal}>
|
<Dialog as="div" className="relative z-10" onClose={closeModal}>
|
||||||
<Transition.Child
|
<Transition.Child
|
||||||
@@ -66,7 +63,7 @@ export function Composer() {
|
|||||||
className="text-zinc-500"
|
className="text-zinc-500"
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
<div className="inline-flex h-6 w-max items-center justify-center gap-0.5 rounded bg-zinc-800 pl-3 pr-1.5 text-sm font-medium text-zinc-400">
|
<div className="inline-flex h-7 w-max items-center justify-center gap-0.5 rounded bg-zinc-800 pl-3 pr-1.5 text-sm font-medium text-zinc-400">
|
||||||
New Post
|
New Post
|
||||||
<ChevronDownIcon width={14} height={14} />
|
<ChevronDownIcon width={14} height={14} />
|
||||||
</div>
|
</div>
|
||||||
@@ -83,7 +80,9 @@ export function Composer() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Post pubkey={account.pubkey} privkey={account.privkey} />
|
{account && (
|
||||||
|
<Post pubkey={account.pubkey} privkey={account.privkey} />
|
||||||
|
)}
|
||||||
</Dialog.Panel>
|
</Dialog.Panel>
|
||||||
</Transition.Child>
|
</Transition.Child>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
||||||
|
import { Button } from "@shared/button";
|
||||||
import { ImageUploader } from "@shared/composer/imageUploader";
|
import { ImageUploader } from "@shared/composer/imageUploader";
|
||||||
import { TrashIcon } from "@shared/icons";
|
import { TrashIcon } from "@shared/icons";
|
||||||
import { MentionNote } from "@shared/notes/mentions/note";
|
import { MentionNote } from "@shared/notes/mentions/note";
|
||||||
@@ -146,13 +147,9 @@ export function Post({ pubkey, privkey }: { pubkey: string; privkey: string }) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="mt-4 flex items-center justify-between">
|
<div className="mt-4 flex items-center justify-between">
|
||||||
<ImageUploader />
|
<ImageUploader />
|
||||||
<button
|
<Button onClick={() => submit} preset="publish">
|
||||||
type="button"
|
Publish
|
||||||
onClick={submit}
|
</Button>
|
||||||
className="inline-flex h-7 w-max items-center justify-center gap-1 rounded-md bg-fuchsia-500 px-3.5 text-base font-medium text-zinc-100 shadow-button hover:bg-fuchsia-600"
|
|
||||||
>
|
|
||||||
Post
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Slate>
|
</Slate>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ export function Navigation() {
|
|||||||
return (
|
return (
|
||||||
<div className="flex w-[232px] flex-col gap-3 border-r border-zinc-900">
|
<div className="flex w-[232px] flex-col gap-3 border-r border-zinc-900">
|
||||||
<AppHeader />
|
<AppHeader />
|
||||||
<div className="flex flex-col gap-3 h-full overflow-y-auto scrollbar-hide">
|
<div className="flex flex-col gap-5 h-full overflow-y-auto scrollbar-hide">
|
||||||
<div className="inlin-lflex h-8 px-3.5">
|
<div className="inlin-lflex h-8 px-3.5">
|
||||||
<Composer />
|
<Composer />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
|
||||||
|
import { Button } from "@shared/button";
|
||||||
import { Image } from "@shared/image";
|
import { Image } from "@shared/image";
|
||||||
import { RelayContext } from "@shared/relayProvider";
|
import { RelayContext } from "@shared/relayProvider";
|
||||||
import { useActiveAccount } from "@stores/accounts";
|
import { useActiveAccount } from "@stores/accounts";
|
||||||
@@ -40,18 +41,18 @@ export function NoteReplyForm({ id }: { id: string }) {
|
|||||||
name="content"
|
name="content"
|
||||||
onChange={(e) => setValue(e.target.value)}
|
onChange={(e) => setValue(e.target.value)}
|
||||||
placeholder="Reply to this thread..."
|
placeholder="Reply to this thread..."
|
||||||
className="relative h-20 w-full resize-none rounded-md px-5 py-5 text-base bg-transparent !outline-none placeholder:text-zinc-400 dark:text-zinc-100 dark:placeholder:text-zinc-500"
|
className="relative h-20 w-full resize-none rounded-md px-5 py-3 text-base bg-transparent !outline-none placeholder:text-zinc-400 dark:text-zinc-100 dark:placeholder:text-zinc-500"
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="border-t border-zinc-800 w-full py-3 px-5">
|
<div className="border-t border-zinc-800 w-full py-3 px-5">
|
||||||
<div className="flex w-full items-center justify-between">
|
<div className="flex w-full items-center justify-between">
|
||||||
<div className="inline-flex items-center gap-2">
|
<div className="inline-flex items-center gap-2">
|
||||||
<div className="relative h-8 w-8 shrink-0 rounded">
|
<div className="relative h-9 w-9 shrink-0 rounded">
|
||||||
<Image
|
<Image
|
||||||
src={user?.image || DEFAULT_AVATAR}
|
src={user?.image || DEFAULT_AVATAR}
|
||||||
alt={account.npub}
|
alt={account.npub}
|
||||||
className="h-8 w-8 rounded bg-white object-cover"
|
className="h-9 w-9 rounded-md bg-white object-cover"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -64,14 +65,13 @@ export function NoteReplyForm({ id }: { id: string }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<button
|
<Button
|
||||||
type="button"
|
|
||||||
onClick={() => submitEvent()}
|
onClick={() => submitEvent()}
|
||||||
disabled={value.length === 0 ? true : false}
|
disabled={value.length === 0 ? true : false}
|
||||||
className="inline-flex h-8 w-16 items-center justify-center rounded-md bg-fuchsia-500 px-4 text-base font-medium hover:bg-fuchsia-600 disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50"
|
preset="publish"
|
||||||
>
|
>
|
||||||
Reply
|
Reply
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user