add button component

This commit is contained in:
Ren Amamiya 2023-06-19 09:30:49 +07:00
parent 6d2e976355
commit 8baba4b1e2
7 changed files with 76 additions and 57 deletions

View File

@ -411,8 +411,8 @@ packages:
resolution: {integrity: sha512-Bu+AMaXNjrpjh41znzHqaz3r2Nr8hHuHZT6V2LBKMhyMl0FgKA62PNYbqnfgmzOhoWZj70Zecisbo4H1rotP5g==}
dev: false
/@floating-ui/dom@1.4.0:
resolution: {integrity: sha512-b4F0iWffLiqb/TpP2PWVOixrZqE6ni+6VT64AmFH7sJIF3SFPLbe6/h3jQ5Cwffs+HaC9A8V0TQzCPBwVvziIA==}
/@floating-ui/dom@1.4.1:
resolution: {integrity: sha512-loCXUOLzIC3jp50RFOKXZ/kQjjz26ryr/23M+FWG9jrmAv8lRf3DUfC2AiVZ3+K316GOhB08CR+Povwz8e9mDw==}
dependencies:
'@floating-ui/core': 1.3.1
dev: false
@ -423,7 +423,7 @@ packages:
react: '>=16.8.0'
react-dom: '>=16.8.0'
dependencies:
'@floating-ui/dom': 1.4.0
'@floating-ui/dom': 1.4.1
react: 18.2.0
react-dom: 18.2.0(react@18.2.0)
dev: false
@ -530,8 +530,8 @@ packages:
resolution: {integrity: sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==}
dev: false
/@maverick-js/signals@5.10.5:
resolution: {integrity: sha512-Q9cKATEqEpXoTssZ2Lx83kjgpLYMlpE2V+LlwuudXRT/pxPAIGRxq0xnXk7B2CQlD3Zjc5xXb7a87sGWdavjfA==}
/@maverick-js/signals@5.11.0:
resolution: {integrity: sha512-SpV3TAt8/ugELL2cI4mF70paHL3dnJbM69xSq7+z2BlsKeDwMK+oVXSq+WLgYANlfwkiOhZvvfQHo6Zo0muQVw==}
dev: false
/@noble/curves@1.0.0:
@ -3075,7 +3075,7 @@ packages:
resolution: {integrity: sha512-p8L5V62CV6TmHAngmRAopp231oJKeH77mJja5SsKOfvzrPRoThT/Jo9U0jMRB5iMykqkvyg2J5V5Agn6FPXDWQ==}
engines: {node: '>=16'}
dependencies:
'@maverick-js/signals': 5.10.5
'@maverick-js/signals': 5.11.0
type-fest: 3.12.0
dev: false

View File

@ -2,7 +2,8 @@ import { Dialog, Transition } from "@headlessui/react";
import { createChannel } from "@libs/storage";
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
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 { RelayContext } from "@shared/relayProvider";
import { useActiveAccount } from "@stores/accounts";
@ -217,37 +218,13 @@ export function ChannelCreateModal() {
</div>
</div>
<div>
<button
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"
>
<Button preset="large" disabled={!isDirty || !isValid}>
{loading ? (
<svg
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>
<LoaderIcon className="h-4 w-4 animate-spin text-black dark:text-zinc-100" />
) : (
"Create channel"
)}
</button>
</Button>
</div>
</form>
</div>

46
src/shared/button.tsx Normal file
View 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>
);
}

View File

@ -1,4 +1,5 @@
import { Dialog, Transition } from "@headlessui/react";
import { Button } from "@shared/button";
import { Post } from "@shared/composer/types/post";
import { User } from "@shared/composer/user";
import {
@ -24,14 +25,10 @@ export function Composer() {
return (
<>
<button
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"
>
<Button onClick={() => toggle(true)} preset="small">
<ComposeIcon width={14} height={14} />
Compose
</button>
</Button>
<Transition appear show={open} as={Fragment}>
<Dialog as="div" className="relative z-10" onClose={closeModal}>
<Transition.Child
@ -66,7 +63,7 @@ export function Composer() {
className="text-zinc-500"
/>
</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
<ChevronDownIcon width={14} height={14} />
</div>
@ -83,7 +80,9 @@ export function Composer() {
/>
</div>
</div>
{account && (
<Post pubkey={account.pubkey} privkey={account.privkey} />
)}
</Dialog.Panel>
</Transition.Child>
</div>

View File

@ -1,4 +1,5 @@
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { Button } from "@shared/button";
import { ImageUploader } from "@shared/composer/imageUploader";
import { TrashIcon } from "@shared/icons";
import { MentionNote } from "@shared/notes/mentions/note";
@ -146,13 +147,9 @@ export function Post({ pubkey, privkey }: { pubkey: string; privkey: string }) {
</div>
<div className="mt-4 flex items-center justify-between">
<ImageUploader />
<button
type="button"
onClick={submit}
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>
<Button onClick={() => submit} preset="publish">
Publish
</Button>
</div>
</div>
</Slate>

View File

@ -13,7 +13,7 @@ export function Navigation() {
return (
<div className="flex w-[232px] flex-col gap-3 border-r border-zinc-900">
<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">
<Composer />
</div>

View File

@ -1,4 +1,5 @@
import { NDKEvent, NDKPrivateKeySigner } from "@nostr-dev-kit/ndk";
import { Button } from "@shared/button";
import { Image } from "@shared/image";
import { RelayContext } from "@shared/relayProvider";
import { useActiveAccount } from "@stores/accounts";
@ -40,18 +41,18 @@ export function NoteReplyForm({ id }: { id: string }) {
name="content"
onChange={(e) => setValue(e.target.value)}
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}
/>
</div>
<div className="border-t border-zinc-800 w-full py-3 px-5">
<div className="flex w-full items-center justify-between">
<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
src={user?.image || DEFAULT_AVATAR}
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>
@ -64,14 +65,13 @@ export function NoteReplyForm({ id }: { id: string }) {
</div>
</div>
<div className="flex items-center gap-2">
<button
type="button"
<Button
onClick={() => submitEvent()}
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
</button>
</Button>
</div>
</div>
</div>