From 052cc1a5a4668d7cb17fb273a022aa5b820d1faa Mon Sep 17 00:00:00 2001 From: Sam Nystrom Date: Wed, 13 Mar 2024 05:03:22 +0000 Subject: refactor: move styles into separate components --- src/NodeEditor.tsx | 4 +- src/components/ArrowButton.css | 9 +++ src/components/ArrowButton.tsx | 12 ++++ src/components/Button.css | 54 ++++++++++++++++ src/components/Button.tsx | 19 ++++++ src/components/ContainedList.css | 21 ++++++ src/components/ContainedList.tsx | 16 +++++ src/components/Content.css | 5 ++ src/components/Content.tsx | 16 +++++ src/components/Form.css | 8 +++ src/components/Form.tsx | 17 +++++ src/components/FormLabel.css | 8 +++ src/components/FormLabel.tsx | 16 +++++ src/components/Header.css | 21 ++++++ src/components/Header.tsx | 22 +++++++ src/components/TextInput.css | 17 +++++ src/components/TextInput.tsx | 26 ++++++++ src/components/index.ts | 8 +++ src/context.ts | 5 ++ src/index.css | 135 +-------------------------------------- src/index.tsx | 18 +++--- src/pages/Home.tsx | 16 +++-- src/pages/LogIn.tsx | 45 +++++++------ src/pages/ProjectsList.tsx | 35 +++++----- src/pages/SignUp.tsx | 61 +++++++++--------- src/pages/index.ts | 8 +-- src/pb.ts | 5 -- 27 files changed, 402 insertions(+), 225 deletions(-) create mode 100644 src/components/ArrowButton.css create mode 100644 src/components/ArrowButton.tsx create mode 100644 src/components/Button.css create mode 100644 src/components/Button.tsx create mode 100644 src/components/ContainedList.css create mode 100644 src/components/ContainedList.tsx create mode 100644 src/components/Content.css create mode 100644 src/components/Content.tsx create mode 100644 src/components/Form.css create mode 100644 src/components/Form.tsx create mode 100644 src/components/FormLabel.css create mode 100644 src/components/FormLabel.tsx create mode 100644 src/components/Header.css create mode 100644 src/components/Header.tsx create mode 100644 src/components/TextInput.css create mode 100644 src/components/TextInput.tsx create mode 100644 src/components/index.ts create mode 100644 src/context.ts delete mode 100644 src/pb.ts (limited to 'src') diff --git a/src/NodeEditor.tsx b/src/NodeEditor.tsx index 3a80825..0c0f106 100644 --- a/src/NodeEditor.tsx +++ b/src/NodeEditor.tsx @@ -56,7 +56,7 @@ interface LinkData extends LinkProps { to: { nodeId: number, socket: string }; } -export const NodeEditor = ({ user, project }) => { +const NodeEditor = ({ user, project }) => { const pb = useContext(Pb); const offsetX = useSignal(0); @@ -270,3 +270,5 @@ export const NodeEditor = ({ user, project }) => { ); }; + +export default NodeEditor; \ No newline at end of file diff --git a/src/components/ArrowButton.css b/src/components/ArrowButton.css new file mode 100644 index 0000000..a39f44a --- /dev/null +++ b/src/components/ArrowButton.css @@ -0,0 +1,9 @@ +@scope (.__ArrowButton) { + :scope { + margin-top: 1rem; + padding: 0 1rem; + background-image: url('../icons/arrow-right.svg'); + background-position: right 1rem center; + background-repeat: no-repeat; + } +} \ No newline at end of file diff --git a/src/components/ArrowButton.tsx b/src/components/ArrowButton.tsx new file mode 100644 index 0000000..ce0c898 --- /dev/null +++ b/src/components/ArrowButton.tsx @@ -0,0 +1,12 @@ +import Button, { ButtonProps } from './Button.tsx'; +import './ArrowButton.css'; + +const ArrowButton = ({ children, ...props }: ButtonProps) => { + return ( + + ); +}; + +export default ArrowButton; \ No newline at end of file diff --git a/src/components/Button.css b/src/components/Button.css new file mode 100644 index 0000000..210d131 --- /dev/null +++ b/src/components/Button.css @@ -0,0 +1,54 @@ +@scope (.__Button) { + :scope { + width: 100%; + min-width: fit-content; + height: 3rem; + padding: 0 1rem; + + /* Necessary for */ + display: flex; + align-items: center; + + font-size: 1rem; + text-align: start; + text-decoration: none; + + cursor: pointer; + + border: 1px solid var(--button-border, var(--button-base)); + background-color: var(--button-base); + color: var(--button-text); + + &:hover { + background-color: var(--button-hover); + color: var(--button-hover-text, var(--button-text)); + } + + &:focus { + outline: 2px solid var(--primary); + border-color: var(--base); + background-color: var(--button-focus, var(--button-base)); + color: var(--button-focus-text, var(--button-text)); + } + + &.primary { + --button-base: var(--primary); + --button-text: var(--text); + --button-hover: color-mix(in srgb, var(--text) 10%, var(--button-base)); + } + &.outline { + --button-base: transparent; + --button-text: var(--primary); + --button-border: var(--primary); + --button-hover: var(--primary); + --button-hover-text: var(--text); + --button-focus: var(--button-hover); + --button-focus-text: var(--button-hover-text); + } + &.ghost { + --button-base: transprent; + --button-text: var(--text); + --button-hover: var(--surface); + } + } +} \ No newline at end of file diff --git a/src/components/Button.tsx b/src/components/Button.tsx new file mode 100644 index 0000000..60f42c7 --- /dev/null +++ b/src/components/Button.tsx @@ -0,0 +1,19 @@ +import type { ComponentChildren } from 'preact'; +import './Button.css'; + +export interface ButtonProps { + children: ComponentChildren; + kind?: 'primary' | 'outline' | 'ghost'; + props: Record; +} + +const Button = ({ children, kind = 'primary', ...props }: ButtonProps) => { + const Elem = props.href ? 'a' : 'button'; + return ( + + {children} + + ); +}; + +export default Button; \ No newline at end of file diff --git a/src/components/ContainedList.css b/src/components/ContainedList.css new file mode 100644 index 0000000..97c98cc --- /dev/null +++ b/src/components/ContainedList.css @@ -0,0 +1,21 @@ +@scope (.__ContainedList) { + :scope { + list-style: none; + padding: 0; + display: flex; + flex-direction: column; + + li { + --border: 2px solid var(--surface); + border-top: var(--border); + &:last-child { + border-bottom: var(--border); + } + height: 3rem; + display: flex; + > * { + flex-grow: 1; + } + } + } +} \ No newline at end of file diff --git a/src/components/ContainedList.tsx b/src/components/ContainedList.tsx new file mode 100644 index 0000000..e514e54 --- /dev/null +++ b/src/components/ContainedList.tsx @@ -0,0 +1,16 @@ +import type { ComponentChildren } from 'preact'; +import './ContainedList.css'; + +export interface ContainedListProps { + children: ComponentChildren; +} + +const ContainedList = ({ children }: ContainedListProps) => { + return ( +
    + {children} +
+ ); +}; + +export default ContainedList; \ No newline at end of file diff --git a/src/components/Content.css b/src/components/Content.css new file mode 100644 index 0000000..ec3836b --- /dev/null +++ b/src/components/Content.css @@ -0,0 +1,5 @@ +@scope (.__Content) { + :scope { + padding: 2rem; + } +} \ No newline at end of file diff --git a/src/components/Content.tsx b/src/components/Content.tsx new file mode 100644 index 0000000..6beb82b --- /dev/null +++ b/src/components/Content.tsx @@ -0,0 +1,16 @@ +import { ComponentChildren } from 'preact'; +import './Content.css'; + +export interface ContentProps { + children: ComponentChildren; +} + +const Content = ({ children }: ContentProps) => { + return ( +
+ {children} +
+ ); +}; + +export default Content; \ No newline at end of file diff --git a/src/components/Form.css b/src/components/Form.css new file mode 100644 index 0000000..f47b737 --- /dev/null +++ b/src/components/Form.css @@ -0,0 +1,8 @@ +@scope (.__Form) { + :scope { + display: flex; + flex-direction: column; + gap: 1rem; + max-width: 26rem; + } +} \ No newline at end of file diff --git a/src/components/Form.tsx b/src/components/Form.tsx new file mode 100644 index 0000000..595e323 --- /dev/null +++ b/src/components/Form.tsx @@ -0,0 +1,17 @@ +import { ComponentChildren } from 'preact'; +import './Form.css'; + +export interface FormProps { + children: ComponentChildren; + onSubmit?: (event: SubmitEvent) => void; +} + +const Form = ({ onSubmit, children }: FormProps) => { + return ( +
+ {children} +
+ ); +}; + +export default Form; \ No newline at end of file diff --git a/src/components/FormLabel.css b/src/components/FormLabel.css new file mode 100644 index 0000000..32f9c9b --- /dev/null +++ b/src/components/FormLabel.css @@ -0,0 +1,8 @@ +@scope (.__FormLabel) { + :scope { + display: flex; + flex-direction: column; + gap: 0.5rem; + color: var(--subtext); + } +} \ No newline at end of file diff --git a/src/components/FormLabel.tsx b/src/components/FormLabel.tsx new file mode 100644 index 0000000..951bb61 --- /dev/null +++ b/src/components/FormLabel.tsx @@ -0,0 +1,16 @@ +import { ComponentChildren } from 'preact'; +import './FormLabel.css'; + +export interface FormLabelProps { + children: ComponentChildren; +} + +const FormLabel = ({ children }: FormLabelProps) => { + return ( + + ); +}; + +export default FormLabel; \ No newline at end of file diff --git a/src/components/Header.css b/src/components/Header.css new file mode 100644 index 0000000..ef1dd60 --- /dev/null +++ b/src/components/Header.css @@ -0,0 +1,21 @@ +@scope (.__Header) { + :scope { + height: 3rem; + border-bottom: 1px solid var(--overlay); + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + + > .title { + font-weight: 500; + width: fit-content; + } + + nav { + height: 100%; + display: flex; + flex-direction: row; + } + } +} \ No newline at end of file diff --git a/src/components/Header.tsx b/src/components/Header.tsx new file mode 100644 index 0000000..32fbce2 --- /dev/null +++ b/src/components/Header.tsx @@ -0,0 +1,22 @@ +import { ComponentChildren } from 'preact'; +import Button from './Button.tsx'; +import './Header.css'; + +export interface HeaderProps { + children: ComponentChildren; +} + +const Header = ({ children }: HeaderProps) => { + return ( +
+
+ +
+ +
+ ); +}; + +export default Header; \ No newline at end of file diff --git a/src/components/TextInput.css b/src/components/TextInput.css new file mode 100644 index 0000000..bb04415 --- /dev/null +++ b/src/components/TextInput.css @@ -0,0 +1,17 @@ +@scope (.__TextInput) { + :scope { + background-color: var(--surface); + color: var(--text); + height: 2.5rem; + padding: 0 0.5rem; + border: none; + border-bottom: 2px solid color-mix(in srgb, white 20%, var(--surface)); + font-size: 1rem; + + &:focus { + outline: 2px solid var(--primary); + border-bottom: none; + margin-bottom: 2px; + } + } +} \ No newline at end of file diff --git a/src/components/TextInput.tsx b/src/components/TextInput.tsx new file mode 100644 index 0000000..026b062 --- /dev/null +++ b/src/components/TextInput.tsx @@ -0,0 +1,26 @@ +import { useCallback } from 'preact/hooks'; +import type { Signal } from '@preact/signals'; +import './TextInput.css'; + +export interface TextInputProps { + signal?: Signal; + props: Record; +} + +const TextInput = ({ signal, ...props }: TextInputProps) => { + const onInputSignal = useCallback((event: InputEvent) => { + signal.value = event.target.value; + }, [signal]); + + return ( + + ); +}; + +export default TextInput; \ No newline at end of file diff --git a/src/components/index.ts b/src/components/index.ts new file mode 100644 index 0000000..1beca4d --- /dev/null +++ b/src/components/index.ts @@ -0,0 +1,8 @@ +export { default as Header } from './Header.tsx'; +export { default as TextInput } from './TextInput.tsx'; +export { default as Button } from './Button.tsx'; +export { default as ArrowButton } from './ArrowButton.tsx'; +export { default as ContainedList } from './ContainedList.tsx'; +export { default as FormLabel } from './FormLabel.tsx'; +export { default as Content } from './Content.tsx'; +export { default as Form } from './Form.tsx'; \ No newline at end of file diff --git a/src/context.ts b/src/context.ts new file mode 100644 index 0000000..2e77787 --- /dev/null +++ b/src/context.ts @@ -0,0 +1,5 @@ +import { createContext } from 'preact'; + +const Pb = createContext(); + +export { Pb }; \ No newline at end of file diff --git a/src/index.css b/src/index.css index 370f29b..51b106c 100644 --- a/src/index.css +++ b/src/index.css @@ -9,6 +9,9 @@ --subtext: #dddddd; font-family: 'Inter Variable', Helvetica, sans-serif; +} + +* { box-sizing: border-box; } @@ -18,10 +21,6 @@ body { margin: 0; } -main { - margin: 2rem; -} - h1 { margin: 0; margin-bottom: 1rem; @@ -32,23 +31,6 @@ h1, h2 { font-weight: 500; } -.container { - width: 50%; - margin: 1rem auto; -} - -.grid { - display: grid; - grid-template-columns: repeat(2, 1fr); - gap: 2rem; - grid-auto-rows: minmax(100px, auto); -} - -.row { - display: flex; - flex-direction: row; -} - hr { border: 1px solid var(--overlay); width: 100%; @@ -60,115 +42,4 @@ p { a { color: color-mix(in srgb, var(--text) 40%, var(--primary)); -} - -a.action { - color: var(--text); - text-decoration: none; - padding: 0 1rem; - height: 100%; - display: flex; - align-items: center; - - &:hover { - background-color: var(--surface); - } - - &:focus { - outline: 2px solid var(--primary); - } -} - -article { - background-color: var(--surface); - border-radius: 1rem; - padding: 1rem; -} - -ul.contained { - list-style: none; - padding: 0; - display: flex; - flex-direction: column; - - li { - --border: 2px solid var(--surface); - border-top: var(--border); - &:last-child { - border-bottom: var(--border); - } - height: 3rem; - display: flex; - > * { - flex-grow: 1; - } - } -} - -form { - display: flex; - flex-direction: column; - gap: 1rem; - max-width: 26rem; -} - -fieldset.group { - border: none; - display: flex; - flex-direction: row; - align-items: baseline; - padding: 0; - - button, input[type="submit"] { - height: calc(2.5rem + 2px); - background-image: none; - } -} - -label { - display: flex; - flex-direction: column; - gap: 0.5rem; - color: var(--subtext); -} - -input { - background-color: var(--surface); - color: var(--text); - height: 2.5rem; - padding: 0 0.5rem; - border: none; - border-bottom: 2px solid color-mix(in srgb, white 20%, var(--surface)); - font-size: 1rem; - - &:focus { - outline: 2px solid var(--primary); - border-bottom: none; - margin-bottom: 2px; - } -} - -button, input[type="submit"] { - background-color: var(--primary); - color: var(--text); - width: 100%; - height: 3rem; - font-size: 1rem; - border: 1px solid var(--primary); - cursor: pointer; - - &:focus { - border-color: var(--base); - outline: 2px solid var(--primary); - } -} - -input[type="submit"] { - margin-top: 1rem; - padding: 0 1rem; - text-align: left; - align-self: flex-end; - background-image: url('icons/arrow-right.svg'); - background-position: right 1rem center; - background-repeat: no-repeat; } \ No newline at end of file diff --git a/src/index.tsx b/src/index.tsx index bed8b66..9bcdfe9 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -2,23 +2,21 @@ import { render } from 'preact'; import { useEffect, useMemo } from 'preact/hooks'; import { Router } from 'preact-router'; import PocketBase from 'pocketbase'; -import { Pb } from './pb.ts'; +import { Pb } from './context.ts'; import { Home, SignUp, LogIn, ProjectsList } from './pages'; -import { NodeEditor } from './NodeEditor.tsx'; +import NodeEditor from './NodeEditor.tsx'; +import { Header, Button } from './components'; import './index.css'; export const App = () => { const pb = useMemo(() => new PocketBase(`/`)); return ( -
- DataNodes - -
+
+ + + +
diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 7762636..f177a75 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,8 +1,12 @@ -export const Home = () => { +import { Content } from '../components'; + +const Home = () => { return ( -
- Sign Up - Log In -
+ +

Try Now

+

Create Account

+
); -}; \ No newline at end of file +}; + +export default Home; \ No newline at end of file diff --git a/src/pages/LogIn.tsx b/src/pages/LogIn.tsx index 55b2109..7e83f98 100644 --- a/src/pages/LogIn.tsx +++ b/src/pages/LogIn.tsx @@ -1,9 +1,10 @@ import { useContext } from 'preact/hooks'; import { useSignal } from '@preact/signals'; import { route } from 'preact-router'; -import { Pb } from '../pb.ts'; +import { Pb } from '../context.ts'; +import { TextInput, ArrowButton, FormLabel, Content, Form } from '../components'; -export const LogIn = () => { +const LogIn = () => { const pb = useContext(Pb); const email = useSignal(''); @@ -18,23 +19,25 @@ export const LogIn = () => { }; return ( -
-
-

Log In

-

- Don't have an account? Sign up -

-
- - - -
-
+ +
+

Log In

+

+ Don't have an account? Sign up +

+
+ + Email + + + + Password + + + Continue +
+
); -}; \ No newline at end of file +}; + +export default LogIn; \ No newline at end of file diff --git a/src/pages/ProjectsList.tsx b/src/pages/ProjectsList.tsx index 820c457..d548aa7 100644 --- a/src/pages/ProjectsList.tsx +++ b/src/pages/ProjectsList.tsx @@ -1,9 +1,10 @@ import { useContext, useEffect } from 'preact/hooks'; import { useSignal } from '@preact/signals'; import { route } from 'preact-router'; -import { Pb } from '../pb.ts'; +import { Pb } from '../context.ts'; +import { TextInput, Button, Form, FormLabel, ContainedList, Content } from '../components'; -export const ProjectsList = ({ user }) => { +const ProjectsList = ({ user }) => { console.log(user); const pb = useContext(Pb); const projects = useSignal(null); @@ -30,22 +31,22 @@ export const ProjectsList = ({ user }) => { ); } return ( -
+

{user}'s Projects

-
-
- - -
-
-
    +
    + + Name + + + +
    + {projects.value.items.map(p => ( -
  • {p.name}
  • +
  • ))} -
-
+ + ); -}; \ No newline at end of file +}; + +export default ProjectsList; \ No newline at end of file diff --git a/src/pages/SignUp.tsx b/src/pages/SignUp.tsx index b707b7d..8bdf35b 100644 --- a/src/pages/SignUp.tsx +++ b/src/pages/SignUp.tsx @@ -1,9 +1,10 @@ import { useContext } from 'preact/hooks'; import { useSignal } from '@preact/signals'; import { route } from 'preact-router'; -import { Pb } from '../pb.ts'; +import { Pb } from '../context.ts'; +import { TextInput, ArrowButton, Form, FormLabel, Content } from '../components'; -export const SignUp = () => { +const SignUp = () => { const pb = useContext(Pb); const username = useSignal(''); @@ -26,31 +27,33 @@ export const SignUp = () => { }; return ( -
-
-

Sign Up

-

- Already have an account? Log in -

-
- - - - - -
-
+ +
+

Sign Up

+

+ Already have an account? Log in +

+
+ + Username + + + + Email + + + + Password + + + + Confirm password + + + Continue +
+
); -}; \ No newline at end of file +}; + +export default SignUp; \ No newline at end of file diff --git a/src/pages/index.ts b/src/pages/index.ts index 8b28ea6..bd162cf 100644 --- a/src/pages/index.ts +++ b/src/pages/index.ts @@ -1,4 +1,4 @@ -export { Home } from './Home.tsx'; -export { SignUp } from './SignUp.tsx'; -export { LogIn } from './LogIn.tsx'; -export { ProjectsList } from './ProjectsList.tsx'; \ No newline at end of file +export { default as Home } from './Home.tsx'; +export { default as SignUp } from './SignUp.tsx'; +export { default as LogIn } from './LogIn.tsx'; +export { default as ProjectsList } from './ProjectsList.tsx'; \ No newline at end of file diff --git a/src/pb.ts b/src/pb.ts deleted file mode 100644 index 2e77787..0000000 --- a/src/pb.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { createContext } from 'preact'; - -const Pb = createContext(); - -export { Pb }; \ No newline at end of file -- cgit v1.2.3