Skip to content

Commit

Permalink
Merge pull request #150 from xmtp/rygine/re-org
Browse files Browse the repository at this point in the history
Reorganize React app and components
  • Loading branch information
rygine authored Jan 5, 2024
2 parents 6abf376 + 2fe2660 commit 4ba8fd8
Show file tree
Hide file tree
Showing 101 changed files with 322 additions and 655 deletions.
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@
"access": "public",
"baseBranch": "main",
"updateInternalDependencies": "patch",
"ignore": ["@xmtp/react-quickstart-example", "@xmtp/react-components"]
"ignore": ["@xmtp/react-app", "@xmtp/react-vite-example"]
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ module.exports = {
parserOptions: {
project: "./tsconfig.eslint.json",
},
ignorePatterns: ["lib/**/*"],
};
27 changes: 27 additions & 0 deletions apps/react/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# React app

![Status](https://img.shields.io/badge/Project_Status-Beta-yellow)

Use this React app as a tool to start building an app with XMTP. This basic messaging app has an intentionally unopinionated UI to help make it easier for you to build with.

The app is built using the [React XMTP client SDK](/packages/react-sdk/README.md), [React](https://react.dev/), and [RainbowKit](https://www.rainbowkit.com/).

This app is in **beta** status and ready to serve as a reference for you to start building with.

However, we do not recommend using beta software in production apps.

To keep up with the latest React app developments, see the [Issues tab](https://github.com/xmtp/xmtp-web/issues) in this repo.

To learn more about XMTP and get answers to frequently asked questions, see the [XMTP documentation](https://xmtp.org/docs).

### Limitations

This React app isn't a complete solution. For example, the list of conversations doesn't update when new messages arrive in existing conversations.

## Useful commands

- `yarn clean`: Removes `node_modules` and `.turbo` folders
- `yarn format`: Runs prettier format and write changes
- `yarn format:check`: Runs prettier format check
- `yarn lint`: Runs ESLint
- `yarn typecheck`: Runs `tsc`
40 changes: 40 additions & 0 deletions apps/react/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"name": "@xmtp/react-app",
"private": true,
"version": "0.0.0",
"type": "module",
"module": "src/index.ts",
"exports": {
".": "./src/index.ts",
"./styles.css": "./src/styles/index.css"
},
"scripts": {
"clean": "rm -rf .turbo && rm -rf node_modules",
"lint": "eslint . --ignore-path ../../.gitignore",
"format:base": "prettier --ignore-path ../../.gitignore",
"format:check": "yarn format:base -c .",
"format": "yarn format:base -w .",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@heroicons/react": "^2.0.18",
"@rainbow-me/rainbowkit": "^1.3.0",
"@xmtp/content-type-reaction": "^1.1.3",
"@xmtp/content-type-read-receipt": "^1.1.5",
"@xmtp/content-type-remote-attachment": "^1.1.4",
"@xmtp/content-type-reply": "^1.1.5",
"@xmtp/react-sdk": "workspace:*",
"date-fns": "^3.0.6",
"react": "^18.2.0",
"react-18-blockies": "^1.0.6",
"wagmi": "^1.4.7"
},
"devDependencies": {
"@types/react": "^18.2.38",
"@xmtp/tsconfig": "workspace:*",
"eslint": "^8.54.0",
"eslint-config-xmtp-web": "workspace:*",
"prettier": "^3.1.1",
"typescript": "^5.3.2"
}
}
File renamed without changes
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { useClient } from "@xmtp/react-sdk";
import { ContentRouter } from "./ContentRouter";
import { useWallet } from "../hooks/useWallet";

const App = () => {
export const App = () => {
const { address } = useWallet();
const { disconnect } = useClient();

Expand All @@ -20,5 +20,3 @@ const App = () => {
</div>
);
};

export default App;
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { CachedConversation } from "@xmtp/react-sdk";
import { useLastMessage, useConsent } from "@xmtp/react-sdk";
import { ConversationPreview } from "@xmtp/react-components";
import { ConversationPreview } from "../controllers/ConversationPreview";

type ConversationCardProps = {
conversation: CachedConversation;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useConversations, useStreamConversations } from "@xmtp/react-sdk";
import type { CachedConversation } from "@xmtp/react-sdk";
import { ChatBubbleLeftIcon } from "@heroicons/react/24/outline";
import { ConversationList } from "@xmtp/react-components";
import { ConversationList } from "./library/ConversationList";
import { Notification } from "./Notification";
import { ConversationCard } from "./ConversationCard";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
}

.InboxHeader__xmtp {
flex: 0 0 var(--sidebar-width);
flex: 0 0 28rem;
display: flex;
align-items: center;
justify-content: space-between;
Expand All @@ -33,7 +33,7 @@

.InboxConversations__list {
overflow-y: auto;
flex: 0 0 var(--sidebar-width);
flex: 0 0 28rem;
background-color: #eee;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { Messages } from "./Messages";
import { NewMessage } from "./NewMessage";
import { useWallet } from "../hooks/useWallet";
import { NoSelectedConversationNotification } from "./NoSelectedConversationNotification";
import xmtpIcon from "../assets/xmtp-icon.png";
import { Button } from "./library/Button";

export const Inbox: React.FC = () => {
const { disconnect } = useWallet();
Expand Down Expand Up @@ -49,21 +51,20 @@ export const Inbox: React.FC = () => {
<div className="Inbox">
<div className="InboxHeader">
<div className="InboxHeader__xmtp">
<img src="/xmtp-icon.png" alt="XMTP logo" width="32" />
<img src={xmtpIcon} alt="XMTP logo" width="32" />
</div>
<div className="InboxHeader__actions">
<button
className="Button"
type="button"
<Button
icon={<PlusCircleIcon width={24} />}
onClick={handleStartNewConversation}>
<PlusCircleIcon width={24} /> New message
</button>
<button
className="Button Button--secondary"
type="button"
onClick={handleDisconnect}>
<ArrowRightOnRectangleIcon width={24} /> Disconnect
</button>
New message
</Button>
<Button
secondary
onClick={handleDisconnect}
icon={<ArrowRightOnRectangleIcon width={24} />}>
Disconnect
</Button>
</div>
</div>
<div className="InboxConversations">
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,9 @@ import { ContentTypeReadReceipt } from "@xmtp/content-type-read-receipt";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { ContentTypeReaction } from "@xmtp/content-type-reaction";
import "./Messages.css";
import {
AddressInput,
Messages as MessagesList,
MessageInput,
} from "@xmtp/react-components";
import { AddressInput } from "./library/AddressInput";
import { Messages as MessagesList } from "./library/Messages";
import { MessageInput } from "./library/MessageInput";

type ConversationMessagesProps = {
conversation: CachedConversation;
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ import {
useCanMessage,
useStartConversation,
} from "@xmtp/react-sdk";
import { AddressInput, MessageInput } from "@xmtp/react-components";
import type { CachedConversation } from "@xmtp/react-sdk";
import { useCallback, useEffect, useRef, useState } from "react";
import "./NewMessage.css";
import { AddressInput } from "./library/AddressInput";
import { MessageInput } from "./library/MessageInput";

type NewMessageProps = {
onSuccess?: (conversation?: CachedConversation) => void;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChatBubbleLeftRightIcon } from "@heroicons/react/24/outline";
import { Notification } from "./Notification";
import { Button } from "./library/Button";

type NoSelectedConversationNotificationProps = {
onStartNewConversation?: VoidFunction;
Expand All @@ -10,9 +11,7 @@ export const NoSelectedConversationNotification: React.FC<
> = ({ onStartNewConversation }) => (
<Notification
cta={
<button className="Button" type="button" onClick={onStartNewConversation}>
Start new conversation
</button>
<Button onClick={onStartNewConversation}>Start new conversation</Button>
}
icon={<ChatBubbleLeftRightIcon />}
title="No conversation selected">
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useClient } from "@xmtp/react-sdk";
import { useCallback } from "react";
import { useWalletClient } from "wagmi";
import { Notification } from "./Notification";
import { Button } from "./library/Button";

type XMTPConnectButtonProps = {
label: string;
Expand All @@ -21,11 +22,7 @@ const XMTPConnectButton: React.FC<XMTPConnectButtonProps> = ({ label }) => {
});
}, [initialize, walletClient]);

return (
<button className="Button" type="button" onClick={handleConnect}>
{label}
</button>
);
return <Button onClick={handleConnect}>{label}</Button>;
};

export const XMTPConnect: React.FC = () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Avatar } from "./Avatar";
import { ShortCopySkeletonLoader } from "./SkeletonLoaders/ShortCopySkeletonLoader";
import styles from "./AddressInput.module.css";

export type AddressInputProps = {
type AddressInputProps = {
/**
* What, if any, ARIA label should be used for the text input
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { CachedMessage } from "@xmtp/react-sdk";
import { useAttachment } from "@xmtp/react-sdk";
import styles from "./Attachment.module.css";

export type AttachmentProps = {
type AttachmentProps = {
message: CachedMessage;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Blockies from "react-18-blockies";
import styles from "./Avatar.module.css";

export type AvatarProps = {
type AvatarProps = {
/**
* Are we waiting on an avatar url?
*/
Expand Down
17 changes: 17 additions & 0 deletions apps/react/src/components/library/Button.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
.wrapper {
background-color: var(--xmtp-action-color-primary);
color: white;
border: 0;
padding: 8px 12px;
border-radius: 8px;
font-weight: bold;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
}

.secondary {
background-color: var(--xmtp-action-color-secondary);
color: var(--xmtp-text-color-primary);
}
22 changes: 22 additions & 0 deletions apps/react/src/components/library/Button.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { PropsWithChildren } from "react";
import styles from "./Button.module.css";

type ButtonProps = PropsWithChildren & {
icon?: React.ReactNode;
onClick?: React.DOMAttributes<HTMLButtonElement>["onClick"];
secondary?: boolean;
};

export const Button: React.FC<ButtonProps> = ({
children,
icon,
onClick,
secondary,
}) => (
<button
className={`${styles.wrapper} ${secondary ? styles.secondary : ""}`}
type="button"
onClick={onClick}>
{icon} {children}
</button>
);
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import previewStyles from "./ConversationPreviewCard.module.css";
import { IconSkeletonLoader } from "./SkeletonLoaders/IconSkeletonLoader";
import { ShortCopySkeletonLoader } from "./SkeletonLoaders/ShortCopySkeletonLoader";

export type ConversationListProps = {
type ConversationListProps = {
/**
* What conversations should we render?
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ import type {
} from "@xmtp/react-sdk";
import { Avatar } from "./Avatar";
import styles from "./ConversationPreviewCard.module.css";
import { shortAddress } from "../helpers/shortAddress";
import { shortAddress } from "../../helpers/shortAddress";

export type ConversationPreviewCardProps = {
type ConversationPreviewCardProps = {
/**
* Conversation to preview
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { format } from "date-fns";
import styles from "./DateDivider.module.css";

export type DateDividerProps = {
type DateDividerProps = {
/**
* What date should be displayed in the divider?
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { PlusCircleIcon } from "@heroicons/react/24/outline";
import { ButtonLoader } from "./Loaders/ButtonLoader";
import styles from "./IconButton.module.css";

export type IconButtonProps = {
type IconButtonProps = {
/**
* What are the button contents?
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import styles from "./ButtonLoader.module.css";

export type ButtonLoaderProps = {
type ButtonLoaderProps = {
/**
* What color should the loader/spinner be?
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { ReplyContent } from "./ReplyContent";
import { ReactionsBar } from "./ReactionsBar";
import { ReactionsContent } from "./ReactionsContent";

export type MessageProps = {
type MessageProps = {
conversation: CachedConversation;
/**
* The message to display
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import { AttachmentContent } from "./AttachmentContent";
import styles from "./MessageContent.module.css";

export type MessageContentProps = {
type MessageContentProps = {
message: CachedMessage;
isIncoming?: boolean;
isRepliedTo?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { ArrowUpIcon } from "@heroicons/react/24/solid";
import { IconButton } from "./IconButton";
import styles from "./MessageInput.module.css";

export type MessageInputProps = {
type MessageInputProps = {
/**
* Is the CTA button disabled?
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { Message } from "./Message";
import { DateDivider } from "./DateDivider";
import styles from "./Messages.module.css";

export type MessagesProps = {
type MessagesProps = {
conversation: CachedConversation;
/**
* What's the client's wallet address?
Expand Down
Loading

0 comments on commit 4ba8fd8

Please sign in to comment.