cetirizine

An experimental matrix client written in reactjs utilizing tailwind and storybook
git clone git://archive.git.mtrnord.blog/MTRNord/cetirizine.git
Log | Files | Refs | README | LICENSE

commit 76416bba11d4b14aa17cb1d61401f51cb7b7d4f5
parent d1f892739678db66266fb725d5463d322f0c9666
Author: MTRNord <mtrnord1@gmail.com>
Date:   Thu, 20 Apr 2023 23:16:30 +0200

Add github actions, add login bg image, move inputs to components nad some cleanup

Diffstat:
A.github/workflows/deploy.yaml | 28++++++++++++++++++++++++++++
A.github/workflows/storybook.yaml | 27+++++++++++++++++++++++++++
M.gitignore | 3++-
M.storybook/main.ts | 4++--
M.vscode/settings.json | 5++++-
Mpackage-lock.json | 22++++++++++++++++++++++
Mpackage.json | 1+
Apublic/bg.jpg | 0
Apublic/bg1.jpg | 0
Msrc/App.tsx | 1-
Msrc/app/api/reducers.ts | 5+++--
Msrc/app/protectedRoute.tsx | 2+-
Msrc/components/button/button.tsx | 6+++---
Asrc/components/input/input.stories.tsx | 61+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/components/input/input.tsx | 38++++++++++++++++++++++++++++++++++++++
Msrc/components/login/login.tsx | 13++++++-------
Asrc/documentation/README.md | 2++
Asrc/documentation/Welcome.stories.mdx | 13+++++++++++++
Msrc/index.scss | 7++++---
Msrc/pages/LoginPage.scss | 13+++++--------
Msrc/pages/LoginPage.tsx | 3+--
Mtailwind.config.js | 4+++-
22 files changed, 226 insertions(+), 32 deletions(-)

diff --git a/.github/workflows/deploy.yaml b/.github/workflows/deploy.yaml @@ -0,0 +1,27 @@ +name: Build and Publish to GitHub Pages + +on: + push: + branches: + - "main" +jobs: + deploy-storybook: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v2.3.1 + with: + persist-credentials: false + - name: Install and Build 🔧 + run: | # Install npm packages and build the Storybook files + npm install + npm run build + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@4.4.1 + with: + folder: dist # The folder that the build-storybook script generates files. + clean: true # Automatically remove deleted files from the deploy branch + clean-exclude: | + storybook/**/* +\ No newline at end of file diff --git a/.github/workflows/storybook.yaml b/.github/workflows/storybook.yaml @@ -0,0 +1,26 @@ +name: Build and Publish storybook to GitHub Pages + +on: + push: + branches: + - "main" +jobs: + deploy-storybook: + permissions: + contents: write + runs-on: ubuntu-latest + steps: + - name: Checkout 🛎️ + uses: actions/checkout@v2.3.1 + with: + persist-credentials: false + - name: Install and Build 🔧 + run: | # Install npm packages and build the Storybook files + npm install + npm run build-storybook + - name: Deploy 🚀 + uses: JamesIves/github-pages-deploy-action@4.4.1 + with: + folder: storybook-static # The folder that the build-storybook script generates files. + clean: true # Automatically remove deleted files from the deploy branch + target-folder: storybook # The folder that we serve our Storybook files from +\ No newline at end of file diff --git a/.gitignore b/.gitignore @@ -9,7 +9,8 @@ /coverage # production -/build +/dist +/storybook-static # misc .DS_Store diff --git a/.storybook/main.ts b/.storybook/main.ts @@ -1,6 +1,6 @@ import type { StorybookConfig } from '@storybook/react-vite'; const config: StorybookConfig = { - stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"], + stories: ["../src/**/*.stories.@(js|jsx|ts|tsx|mdx)"], addons: [ "@storybook/addon-links", "@storybook/addon-essentials", @@ -29,7 +29,7 @@ const config: StorybookConfig = { builder: '@storybook/builder-vite', }, docs: { - autodocs: "tag", + autodocs: true, defaultName: 'Documentation', }, staticDirs: ["../public"], diff --git a/.vscode/settings.json b/.vscode/settings.json @@ -1,3 +1,6 @@ { - "typescript.tsdk": "node_modules/typescript/lib" + "typescript.tsdk": "node_modules/typescript/lib", + "yaml.schemas": { + "https://json.schemastore.org/github-workflow.json": "file:///media/marcel/1ac60e61-e5e2-4157-9a7a-830801a3fb0b/projects/cetirizine/.github/workflows/deploy.yaml" + } } \ No newline at end of file diff --git a/package-lock.json b/package-lock.json @@ -37,6 +37,7 @@ "@storybook/react": "^7.0.6", "@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", "autoprefixer": "^10.4.14", "postcss": "^8.4.23", @@ -4733,6 +4734,18 @@ "url": "https://opencollective.com/storybook" } }, + "node_modules/@tailwindcss/forms": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.3.tgz", + "integrity": "sha512-y5mb86JUoiUgBjY/o6FJSFZSEttfb3Q5gllE4xoKjAAD+vBrnIhE4dViwUuow3va8mpH4s9jyUbUbrRGoRdc2Q==", + "dev": true, + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1" + } + }, "node_modules/@testing-library/dom": { "version": "9.2.0", "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.2.0.tgz", @@ -10368,6 +10381,15 @@ "node": ">=4" } }, + "node_modules/mini-svg-data-uri": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz", + "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==", + "dev": true, + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, "node_modules/minimatch": { "version": "5.1.6", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", diff --git a/package.json b/package.json @@ -68,6 +68,7 @@ "@storybook/react": "^7.0.6", "@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", "autoprefixer": "^10.4.14", "postcss": "^8.4.23", diff --git a/public/bg.jpg b/public/bg.jpg Binary files differ. diff --git a/public/bg1.jpg b/public/bg1.jpg Binary files differ. diff --git a/src/App.tsx b/src/App.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { BrowserRouter, Route, diff --git a/src/app/api/reducers.ts b/src/app/api/reducers.ts @@ -37,11 +37,12 @@ const initialLoginState: ApiLoginStatus = { loginPending: false, error: undefine export const apiLoginReducer = createReducer(initialLoginState, (builder) => { builder - .addCase(LOGIN_REQUEST, (state, action) => { + .addCase(LOGIN_REQUEST, (state, _) => { state.loginPending = true; state.error = undefined; }) - .addCase(LOGIN_SUCCESS, (state, action) => { + // @ts-ignore: Somehow this state is causing issues here since its written but not read. TS6133 + .addCase(LOGIN_SUCCESS, (state, _) => { state = initialLoginState; }) .addCase(LOGIN_FAILURE, (state, action) => { diff --git a/src/app/protectedRoute.tsx b/src/app/protectedRoute.tsx @@ -1,4 +1,4 @@ -import React, { ReactElement } from "react"; +import { ReactElement } from "react"; import { Navigate } from "react-router-dom"; import { useAppSelector } from "./hooks"; diff --git a/src/components/button/button.tsx b/src/components/button/button.tsx @@ -21,10 +21,10 @@ type ButtonProps = { export default function Button({ type = "button", style = "primary", onClick, children }: ButtonProps) { if (style === "secondary") { - return <button onClick={onClick} className="button bg-orange-400" type={type}>{children}</button>; + return <button onClick={onClick} className="button bg-orange-400 hover:bg-orange-500 ease-out duration-150" type={type}>{children}</button>; } else if (style === "abort") { - return <button onClick={onClick} className="button bg-red-400" type={type}>{children}</button>; + return <button onClick={onClick} className="button bg-red-400 hover:bg-red-500 ease-out duration-150" type={type}>{children}</button>; } else { - return <button onClick={onClick} className="button bg-green-400" type={type}>{children}</button>; + return <button onClick={onClick} className="button bg-green-400 hover:bg-green-500 ease-out duration-150" type={type}>{children}</button>; } } \ No newline at end of file diff --git a/src/components/input/input.stories.tsx b/src/components/input/input.stories.tsx @@ -0,0 +1,60 @@ +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'; + +const meta: Meta<typeof Input> = { + title: 'Fundamentals/Inputs/BasicInput', + tags: ['autodocs'], + component: Input, + parameters: { + badges: [BADGE.EXPERIMENTAL] + }, + argTypes: { + placeholder: { + required: true, + name: "Placeholder", + description: "The Placeholder for the input field. Shown if it is empty.", + }, + password: { + required: false, + name: "Password", + control: "boolean", + defaultValue: false, + description: "If the input field takes a password.", + }, + autoFocus: { + required: false, + name: "Auto Focus", + control: "boolean", + defaultValue: false, + description: "If the field should be focused automatically.", + }, + value: { + required: true, + name: "Value", + description: "The current value of the input.", + }, + onChange: { + description: "The onChange handler of the input field.", + required: true, + }, + } +}; + +export default meta; +type Story = StoryObj<typeof Input>; + +export const Default: Story = { + args: { + placeholder: "Placeholder", + password: false, + autoFocus: false, + value: "", + onChange: (_) => { } + }, + render: (args) => <Provider store={store}> + <Input {...args} /> + </Provider>, +}; +\ No newline at end of file diff --git a/src/components/input/input.tsx b/src/components/input/input.tsx @@ -0,0 +1,37 @@ +import { ChangeEvent } from 'react'; + +type InputProps = { + /** + * The Placeholder text + */ + placeholder: string + /** + * If it is a password input + */ + password?: boolean + /** + * If input should be autofocused + */ + autoFocus?: boolean + /** + * The value of the input field + */ + value: string + /** + * Handler for the onChange event + */ + onChange: (e: ChangeEvent<HTMLInputElement>) => void; +}; + +export default function Input({ placeholder, password = false, autoFocus = false, value, onChange }: InputProps) { + return ( + <input + className='form-input rounded-lg' + value={value} + type={password ? "password" : "text"} + autoFocus={autoFocus} + placeholder={placeholder} + onChange={onChange} + /> + ); +} +\ No newline at end of file diff --git a/src/components/login/login.tsx b/src/components/login/login.tsx @@ -5,6 +5,7 @@ import { useAppDispatch, useAppSelector } from '../../app/hooks'; import { RootState } from '../../app/store'; import Button from '../button/button'; import Header from '../header/header'; +import Input from '../input/input'; export function Login() { const loginError = useAppSelector((state: RootState) => getLoginError(state)); @@ -14,25 +15,23 @@ export function Login() { const dispatch = useAppDispatch(); return ( - <div className="flex flex-col rounded shadow p-4 bg-slate-200 gap-2"> + <div className="flex flex-col rounded-md shadow p-4 bg-white gap-2"> <Header>Login</Header> {loginError ? <h2 className='text-red-500 font-normal text-sm'>{loginError}</h2> : <></>} - <input + <Input value={homeserver} - type="text" autoFocus={true} placeholder="Homeserver" onChange={e => { setHomeserver(e.target.value); dispatch(setBaseUrl(e.target.value)) }} /> - <input + <Input value={username} - type="text" placeholder="Username" onChange={e => setUsername(e.target.value)} /> - <input + <Input value={password} - type="password" + password={true} placeholder="Password" onChange={e => setPassword(e.target.value)} /> diff --git a/src/documentation/README.md b/src/documentation/README.md @@ -0,0 +1 @@ +This folder only exists for storybook reasons +\ No newline at end of file diff --git a/src/documentation/Welcome.stories.mdx b/src/documentation/Welcome.stories.mdx @@ -0,0 +1,13 @@ +import { Meta } from "@storybook/addon-docs"; + +<Meta title="Introduction/Welcome" /> + +# About Cetirizine + +Welcome to the Cetirizine Design System! + +This storybook design system describes in depth the components used within the +Cetirizine Matrix Client. + +The Design heavily leans on the Tailwindcss Design System. However there are speciic +components for some things and Pages are also documented. diff --git a/src/index.scss b/src/index.scss @@ -1,3 +1,3 @@ -body { - background: #e0e0e0; -} +body, html { + margin: 0; +} +\ No newline at end of file diff --git a/src/pages/LoginPage.scss b/src/pages/LoginPage.scss @@ -2,11 +2,7 @@ @tailwind components; @tailwind utilities; -.LoginPage { - text-align: center; - min-height: 100vh; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} +.bg-img { + background: url("/bg1.jpg"); + background-position: 50% 0; +} +\ No newline at end of file diff --git a/src/pages/LoginPage.tsx b/src/pages/LoginPage.tsx @@ -1,10 +1,9 @@ -import React from 'react'; import './LoginPage.scss'; import { Login } from '../components/login/login'; function LoginPage() { return ( - <div className="LoginPage"> + <div className="flex flex-col items-center justify-center min-h-screen bg-img"> <Login /> </div> ); diff --git a/tailwind.config.js b/tailwind.config.js @@ -8,6 +8,8 @@ export default { theme: { extend: {}, }, - plugins: [], + plugins: [ + require('@tailwindcss/forms'), + ], }