commit 211ceccb9f5bbaea5ef2f4083bfc48f02245f75b
parent bc2f4589e5403a06408d1256b0c4603d7aad98b1
Author: MTRNord <mtrnord1@gmail.com>
Date: Fri, 21 Apr 2023 21:34:19 +0200
feat: Add avatar component and cleanup stories
Diffstat:
11 files changed, 364 insertions(+), 68 deletions(-)
diff --git a/package-lock.json b/package-lock.json
@@ -41,7 +41,7 @@
"@storybook/react-vite": "^7.0.6",
"@storybook/testing-library": "^0.0.14-next.2",
"@tailwindcss/forms": "^0.5.3",
- "@vitejs/plugin-react": "^4.0.0-beta.0",
+ "@vitejs/plugin-react-swc": "^3.3.0",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.23",
"postcss-loader": "^7.2.4",
@@ -4973,6 +4973,200 @@
"url": "https://opencollective.com/storybook"
}
},
+ "node_modules/@swc/core": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.53.tgz",
+ "integrity": "sha512-OM5nCfKDZXr1HjxD072Jlx5463tPX7xeY7NDSRE3X4KFlkRDFdyMWAyV3pet1oouOfUNrzzoVTAR4XSU8ytO6Q==",
+ "dev": true,
+ "hasInstallScript": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/swc"
+ },
+ "optionalDependencies": {
+ "@swc/core-darwin-arm64": "1.3.53",
+ "@swc/core-darwin-x64": "1.3.53",
+ "@swc/core-linux-arm-gnueabihf": "1.3.53",
+ "@swc/core-linux-arm64-gnu": "1.3.53",
+ "@swc/core-linux-arm64-musl": "1.3.53",
+ "@swc/core-linux-x64-gnu": "1.3.53",
+ "@swc/core-linux-x64-musl": "1.3.53",
+ "@swc/core-win32-arm64-msvc": "1.3.53",
+ "@swc/core-win32-ia32-msvc": "1.3.53",
+ "@swc/core-win32-x64-msvc": "1.3.53"
+ },
+ "peerDependencies": {
+ "@swc/helpers": "^0.5.0"
+ },
+ "peerDependenciesMeta": {
+ "@swc/helpers": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@swc/core-darwin-arm64": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.53.tgz",
+ "integrity": "sha512-JvWwV/duzdQ60iwWYceDhDk75LmdrLoPC7myX3Src3gl/bJtETMq7uHS9uY8m0GQOqbct7XGR3q5Ff21YxkSzg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-darwin-x64": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.53.tgz",
+ "integrity": "sha512-UuIGZtCfUPJM2Q01bRIFzmucOMg8UZ+mY3kh5xB8kl/VrLltBlraSWGjjJzYmUeUxiF8+CtMfeSYav5QfU2v3g==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm-gnueabihf": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.53.tgz",
+ "integrity": "sha512-LupAjTErteyLmowYIfiQeTz3uVh7/SPYv/EuG1PYrajNoUYomt7WA0rQUoyglF9VtwVyNqxptWEO5So32ApTHA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-gnu": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.53.tgz",
+ "integrity": "sha512-kREfZdiJH/O8GtJJ22wVN9DVzz/+CPAkw5Mn5te2KQg0xJHMWaESU5XeYMWvtwyOQVmb31b6zCGFy3pnBWWfGw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-arm64-musl": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.53.tgz",
+ "integrity": "sha512-VeAgomBr6BVuBRjZjRHmvp5gKp1nZgbbd441ca1AvsPd2c+ZyhyHLxTWeHOzBDa/vYnmi9BCwx3QJzFqbAFPVw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-gnu": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.53.tgz",
+ "integrity": "sha512-LFX5+QpQkESPkmx860C40pIiYf1utEqoA+WDtmKnUz3DucYvw3eGlXCBdyklP7UBWwJktKIcPlIqr7yROY5VlQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-linux-x64-musl": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.53.tgz",
+ "integrity": "sha512-O0lbJgeaM0VEsG8wFYvpF+Iuf0IENv+LnXHoygkAsv67sVW54+gFxav2sEdkftD5qYe9ku4tmtTVYRZlFgC84Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-arm64-msvc": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.53.tgz",
+ "integrity": "sha512-7PgvPl0aNLaFZSK+rIi4DB1g0aW2qOsTIJQSJGRszsCP8pze/traXymyuSG2I3y9Hx7Z+bP5ycJydyAgCw88WA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-ia32-msvc": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.53.tgz",
+ "integrity": "sha512-T+OacGm69t8+1mt1sHlwhREiFiFgSeIGL3h11FIs8o2zKnOr5z2H9myzR432X8WuHGVQAOCMvDu53LCMBD0ZzQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@swc/core-win32-x64-msvc": {
+ "version": "1.3.53",
+ "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.53.tgz",
+ "integrity": "sha512-uV1/GhROJ/SXzj+f+kKcVtR2GuAiggvbqepzZS46+G47okf6229hr2T1fjmiwYyA75w9R3Bj/wil4UhodohOLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=10"
+ }
+ },
"node_modules/@tailwindcss/forms": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz",
@@ -5626,22 +5820,16 @@
"integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA==",
"dev": true
},
- "node_modules/@vitejs/plugin-react": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.0.0.tgz",
- "integrity": "sha512-HX0XzMjL3hhOYm+0s95pb0Z7F8O81G7joUHgfDd/9J/ZZf5k4xX6QAMFkKsHFxaHlf6X7GD7+XuaZ66ULiJuhQ==",
+ "node_modules/@vitejs/plugin-react-swc": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.3.0.tgz",
+ "integrity": "sha512-Ycg+n2eyCOTpn/wRy+evVo859+hw7qCj9iaX5CMny6x1fx1Uoq0xBG+a98lFtwLNGfGEnpI0F26YigRuxCRkwg==",
"dev": true,
"dependencies": {
- "@babel/core": "^7.21.4",
- "@babel/plugin-transform-react-jsx-self": "^7.21.0",
- "@babel/plugin-transform-react-jsx-source": "^7.19.6",
- "react-refresh": "^0.14.0"
- },
- "engines": {
- "node": "^14.18.0 || >=16.0.0"
+ "@swc/core": "^1.3.42"
},
"peerDependencies": {
- "vite": "^4.2.0"
+ "vite": "^4"
}
},
"node_modules/@webassemblyjs/ast": {
diff --git a/package.json b/package.json
@@ -72,7 +72,7 @@
"@storybook/react-vite": "^7.0.6",
"@storybook/testing-library": "^0.0.14-next.2",
"@tailwindcss/forms": "^0.5.3",
- "@vitejs/plugin-react": "^4.0.0-beta.0",
+ "@vitejs/plugin-react-swc": "^3.3.0",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.23",
"postcss-loader": "^7.2.4",
diff --git a/src/components/avatar/avatar.stories.tsx b/src/components/avatar/avatar.stories.tsx
@@ -0,0 +1,95 @@
+import { Meta, StoryObj } from '@storybook/react';
+import Avatar from './avatar';
+import { BADGE } from '@geometricpanda/storybook-addon-badges';
+
+const meta: Meta<typeof Avatar> = {
+ title: 'Chat/Avatar',
+ tags: ['autodocs'],
+ component: Avatar,
+ parameters: {
+ badges: [BADGE.EXPERIMENTAL]
+ },
+ argTypes: {
+ avatarUrl: {
+ required: false,
+ name: "Avatar URL",
+ description: "The URL of the avatar image",
+ },
+ userID: {
+ required: true,
+ name: "User ID",
+ description: "The DISPLAY name of the User",
+ },
+ dm: {
+ required: false,
+ defaultValue: false,
+ control: "boolean",
+ name: "DM",
+ description: "Wether the Avatar is used for a DM",
+ },
+ online: {
+ required: false,
+ defaultValue: false,
+ control: "boolean",
+ name: "Online",
+ description: "Wether the user is online. Only used if dm is true",
+ },
+ }
+};
+
+export default meta;
+type Story = StoryObj<typeof Avatar>;
+
+export const Fallback: Story = {
+ args: {
+ userID: "test",
+ dm: false,
+ online: false,
+ avatarUrl: ""
+ }
+};
+
+export const Image: Story = {
+ args: {
+ userID: "test",
+ avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg",
+ dm: false,
+ online: false,
+ }
+};
+
+export const DMOffline: Story = {
+ args: {
+ userID: "test",
+ avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg",
+ dm: true,
+ online: false,
+ }
+};
+
+export const DMOnline: Story = {
+ args: {
+ userID: "test",
+ avatarUrl: "https://randomuser.me/api/portraits/men/62.jpg",
+ dm: true,
+ online: true,
+ }
+};
+
+export const DMNoAvatarOffline: Story = {
+ args: {
+ userID: "test",
+ avatarUrl: "",
+ dm: true,
+ online: false,
+ }
+};
+
+export const DMNoAvatarOnline: Story = {
+ args: {
+ userID: "test",
+ avatarUrl: "",
+ dm: true,
+ online: true,
+ }
+};
+\ No newline at end of file
diff --git a/src/components/avatar/avatar.tsx b/src/components/avatar/avatar.tsx
@@ -0,0 +1,51 @@
+type AvatarProps = {
+ /**
+ * The URL of the Avatar image
+ */
+ avatarUrl?: string
+ /**
+ * The displayname of the avatar user
+ */
+ userID: string
+ /**
+ * Wether it is a DM or not
+ */
+ dm: boolean
+ /**
+ * Wether the user is online. Only used if dm is true.
+ */
+ online: boolean
+};
+
+export default function Avatar({ avatarUrl, userID, dm = false, online = false }: AvatarProps) {
+ if (avatarUrl) {
+ return (
+ <div className="flex relative w-12 h-12 justify-center items-center m-1 mr-2 text-xl rounded-full text-white">
+ <img className="rounded-full" alt={userID} src={avatarUrl} />
+ {
+ dm ?
+ (
+ online ?
+ <div className="bg-green-500 rounded-full w-3 h-3 absolute bottom-[2px] right-[2px]"></div> :
+ <div className="bg-red-500 rounded-full w-3 h-3 absolute bottom-[2px] right-[2px]"></div>
+ ) :
+ <></>
+ }
+ </div>
+ );
+ }
+ return (
+ <div className="flex relative w-12 h-12 bg-orange-500 justify-center items-center m-1 mr-2 text-xl rounded-full text-white">
+ {userID[0].toUpperCase()}
+ {
+ dm ?
+ (
+ online ?
+ <div className="bg-green-500 rounded-full w-3 h-3 absolute bottom-[2px] right-[2px]"></div> :
+ <div className="bg-red-500 rounded-full w-3 h-3 absolute bottom-[2px] right-[2px]"></div>
+ ) :
+ <></>
+ }
+ </div>
+ );
+}
+\ No newline at end of file
diff --git a/src/components/button/button.stories.tsx b/src/components/button/button.stories.tsx
@@ -1,6 +1,4 @@
import { Meta, StoryObj } from '@storybook/react';
-import { Provider } from 'react-redux';
-import { store } from '../../app/store';
import Button from './button';
import { BADGE } from '@geometricpanda/storybook-addon-badges';
@@ -45,9 +43,6 @@ export const Default: Story = {
type: 'button',
style: 'primary',
},
- render: (args) => <Provider store={store}>
- <Button {...args} />
- </Provider>,
};
export const Submit: Story = {
@@ -56,9 +51,6 @@ export const Submit: Story = {
type: 'submit',
style: 'primary',
},
- render: (args) => <Provider store={store}>
- <Button {...args} />
- </Provider>,
};
export const Reset: Story = {
@@ -67,9 +59,6 @@ export const Reset: Story = {
type: 'reset',
style: 'primary',
},
- render: (args) => <Provider store={store}>
- <Button {...args} />
- </Provider>,
};
export const DefaultSecondary: Story = {
@@ -78,9 +67,6 @@ export const DefaultSecondary: Story = {
type: 'button',
style: 'secondary',
},
- render: (args) => <Provider store={store}>
- <Button {...args} />
- </Provider>,
};
export const SubmitSecondary: Story = {
@@ -89,9 +75,6 @@ export const SubmitSecondary: Story = {
type: 'submit',
style: 'secondary',
},
- render: (args) => <Provider store={store}>
- <Button {...args} />
- </Provider>,
};
export const ResetSecondary: Story = {
@@ -100,9 +83,6 @@ export const ResetSecondary: Story = {
type: 'reset',
style: 'secondary',
},
- render: (args) => <Provider store={store}>
- <Button {...args} />
- </Provider>,
};
export const Abort: Story = {
@@ -111,7 +91,4 @@ export const Abort: Story = {
type: 'button',
style: 'abort',
},
- render: (args) => <Provider store={store}>
- <Button {...args} />
- </Provider>,
};
\ No newline at end of file
diff --git a/src/components/header/header.stories.tsx b/src/components/header/header.stories.tsx
@@ -1,6 +1,4 @@
import { Meta, StoryObj } from '@storybook/react';
-import { Provider } from 'react-redux';
-import { store } from '../../app/store';
import Header from './header';
import { BADGE } from '@geometricpanda/storybook-addon-badges';
@@ -27,7 +25,4 @@ export const Default: Story = {
args: {
children: 'Header',
},
- render: (args) => <Provider store={store}>
- <Header {...args} />
- </Provider>,
};
\ No newline at end of file
diff --git a/src/components/input/basic/input.stories.tsx b/src/components/input/basic/input.stories.tsx
@@ -1,6 +1,4 @@
import { Meta, StoryObj } from '@storybook/react';
-import { Provider } from 'react-redux';
-import { store } from '../../../app/store';
import Input from './input';
import { BADGE } from '@geometricpanda/storybook-addon-badges';
@@ -53,8 +51,5 @@ export const Default: Story = {
autoFocus: false,
value: "",
onChange: (_) => { }
- },
- render: (args) => <Provider store={store}>
- <Input {...args} />
- </Provider>,
+ }
};
\ No newline at end of file
diff --git a/src/components/input/chat/input.stories.tsx b/src/components/input/chat/input.stories.tsx
@@ -1,10 +1,9 @@
import { Meta, StoryObj } from '@storybook/react';
-import { Provider } from 'react-redux';
-import { store } from '../../../app/store';
import ChatInput from './input';
import { BADGE } from '@geometricpanda/storybook-addon-badges';
-import { $getRoot, EditorState } from 'lexical';
+import { $getRoot, EditorState, LexicalEditor } from 'lexical';
import { TRANSFORMERS, $convertToMarkdownString } from "@lexical/markdown";
+import { $generateHtmlFromNodes } from "@lexical/html";
const meta: Meta<typeof ChatInput> = {
title: 'Chat/Input',
@@ -35,19 +34,19 @@ type Story = StoryObj<typeof ChatInput>;
export const Default: Story = {
args: {
- onChange: (editorState: EditorState) => {
+ onChange: (editorState: EditorState, editor: LexicalEditor) => {
editorState.read(() => {
// Read the contents of the EditorState here.
const root = $getRoot();
// make it markdown
const markdown = $convertToMarkdownString(TRANSFORMERS, root);
+ const html = $generateHtmlFromNodes(editor, null);
console.log(markdown);
+ console.log(html);
});
},
- onError: (error) => { console.error(error); }
- },
- render: (args) => <Provider store={store}>
- <ChatInput {...args} />
- </Provider>,
+ onError: (error) => { console.error(error); },
+ namespace: "Editor"
+ }
};
\ No newline at end of file
diff --git a/src/components/input/chat/input.tsx b/src/components/input/chat/input.tsx
@@ -38,7 +38,7 @@ type ChatInputProps = {
};
function Placeholder() {
- return <div className="editor-placeholder">Enter some rich text...</div>;
+ return <div className="editor-placeholder" id="editor-placeholder">Enter message...</div>;
}
export default function ChatInput({ namespace, onChange, onError }: ChatInputProps) {
@@ -66,7 +66,7 @@ export default function ChatInput({ namespace, onChange, onError }: ChatInputPro
<ToolbarPlugin />
<div className="editor-inner">
<RichTextPlugin
- contentEditable={<ContentEditable className="editor-input" />}
+ contentEditable={<ContentEditable className="editor-input" aria-labelledby='editor-placeholder' />}
placeholder={<Placeholder />}
ErrorBoundary={LexicalErrorBoundary}
/>
diff --git a/src/pages/LoginPage.stories.tsx b/src/pages/LoginPage.stories.tsx
@@ -1,6 +1,4 @@
import { Meta, StoryObj } from '@storybook/react';
-import { Provider } from 'react-redux';
-import { store } from '../app/store';
import LoginPage from './LoginPage';
const meta: Meta<typeof LoginPage> = {
@@ -12,8 +10,4 @@ const meta: Meta<typeof LoginPage> = {
export default meta;
type Story = StoryObj<typeof LoginPage>;
-export const Default: Story = {
- render: () => <Provider store={store}>
- <LoginPage />
- </Provider>,
-};
-\ No newline at end of file
+export const Default: Story = {};
+\ No newline at end of file
diff --git a/vite.config.ts b/vite.config.ts
@@ -1,5 +1,5 @@
import { defineConfig, splitVendorChunkPlugin } from 'vite'
-import react from '@vitejs/plugin-react'
+import react from "@vitejs/plugin-react-swc";
// https://vitejs.dev/config/
export default defineConfig({