diff options
Diffstat (limited to 'src/components')
| -rw-r--r-- | src/components/ArrowButton.css | 9 | ||||
| -rw-r--r-- | src/components/ArrowButton.tsx | 12 | ||||
| -rw-r--r-- | src/components/Button.css | 54 | ||||
| -rw-r--r-- | src/components/Button.tsx | 19 | ||||
| -rw-r--r-- | src/components/ContainedList.css | 21 | ||||
| -rw-r--r-- | src/components/ContainedList.tsx | 16 | ||||
| -rw-r--r-- | src/components/Content.css | 5 | ||||
| -rw-r--r-- | src/components/Content.tsx | 16 | ||||
| -rw-r--r-- | src/components/Form.css | 8 | ||||
| -rw-r--r-- | src/components/Form.tsx | 17 | ||||
| -rw-r--r-- | src/components/FormLabel.css | 8 | ||||
| -rw-r--r-- | src/components/FormLabel.tsx | 16 | ||||
| -rw-r--r-- | src/components/Header.css | 21 | ||||
| -rw-r--r-- | src/components/Header.tsx | 22 | ||||
| -rw-r--r-- | src/components/TextInput.css | 17 | ||||
| -rw-r--r-- | src/components/TextInput.tsx | 26 | ||||
| -rw-r--r-- | src/components/index.ts | 8 |
17 files changed, 295 insertions, 0 deletions
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 ( + <Button {...props} class={(props.class || '') + ' __ArrowButton'}> + {children} + </Button> + ); +}; + +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 <a> */ + 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<string, any>; +} + +const Button = ({ children, kind = 'primary', ...props }: ButtonProps) => { + const Elem = props.href ? 'a' : 'button'; + return ( + <Elem {...props} class={(props.class || '') + ' __Button ' + kind}> + {children} + </Elem> + ); +}; + +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 ( + <ul class="__ContainedList"> + {children} + </ul> + ); +}; + +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 ( + <main class="__Content"> + {children} + </main> + ); +}; + +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 ( + <form class="__Form" onSubmit={onSubmit}> + {children} + </form> + ); +}; + +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 ( + <label class="__FormLabel"> + {children} + </label> + ); +}; + +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 ( + <header class="__Header"> + <div class="title"> + <Button kind="ghost" href="/">DataNodes</Button> + </div> + <nav> + {children} + </nav> + </header> + ); +}; + +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<string>; + props: Record<string, any>; +} + +const TextInput = ({ signal, ...props }: TextInputProps) => { + const onInputSignal = useCallback((event: InputEvent) => { + signal.value = event.target.value; + }, [signal]); + + return ( + <input + type="text" + {...props} + class={(props.class || '') + ' __TextInput'} + value={signal || props.value} + onInput={signal ? onInputSignal : props.onInput} + /> + ); +}; + +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 |
