diff --git a/package.json b/package.json index c36c914d..8322bd06 100644 --- a/package.json +++ b/package.json @@ -30,6 +30,7 @@ "eslint-plugin-solid": "^0.13.1", "postcss": "^8.4.35", "postcss-easings": "^4.0.0", + "sass": "^1.72.0", "tailwindcss": "^3.4.1", "typescript": "^5.0.2", "vite": "^5.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 39fc5109..f54dfceb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -55,6 +55,9 @@ devDependencies: postcss-easings: specifier: ^4.0.0 version: 4.0.0(postcss@8.4.35) + sass: + specifier: ^1.72.0 + version: 1.72.0 tailwindcss: specifier: ^3.4.1 version: 3.4.1 @@ -63,7 +66,7 @@ devDependencies: version: 5.4.2 vite: specifier: ^5.0.0 - version: 5.1.6 + version: 5.1.6(sass@1.72.0) vite-plugin-solid: specifier: ^2.8.0 version: 2.10.1(solid-js@1.8.15)(vite@5.1.6) @@ -2374,6 +2377,10 @@ packages: engines: {node: '>= 4'} dev: true + /immutable@4.3.5: + resolution: {integrity: sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw==} + dev: true + /import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -3127,6 +3134,16 @@ packages: is-regex: 1.1.4 dev: true + /sass@1.72.0: + resolution: {integrity: sha512-Gpczt3WA56Ly0Mn8Sl21Vj94s1axi9hDIzDFn9Ph9x3C3p4nNyvsqJoQyVXKou6cBlfFWEgRW4rT8Tb4i3XnVA==} + engines: {node: '>=14.0.0'} + hasBin: true + dependencies: + chokidar: 3.6.0 + immutable: 4.3.5 + source-map-js: 1.0.2 + dev: true + /semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -3555,13 +3572,13 @@ packages: merge-anything: 5.1.7 solid-js: 1.8.15 solid-refresh: 0.6.3(solid-js@1.8.15) - vite: 5.1.6 + vite: 5.1.6(sass@1.72.0) vitefu: 0.2.5(vite@5.1.6) transitivePeerDependencies: - supports-color dev: true - /vite@5.1.6: + /vite@5.1.6(sass@1.72.0): resolution: {integrity: sha512-yYIAZs9nVfRJ/AiOLCA91zzhjsHUgMjB+EigzFb6W2XTLO8JixBCKCjvhKZaye+NKYHCrkv3Oh50dH9EdLU2RA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true @@ -3592,6 +3609,7 @@ packages: esbuild: 0.19.12 postcss: 8.4.35 rollup: 4.13.0 + sass: 1.72.0 optionalDependencies: fsevents: 2.3.3 dev: true @@ -3604,7 +3622,7 @@ packages: vite: optional: true dependencies: - vite: 5.1.6 + vite: 5.1.6(sass@1.72.0) dev: true /which-boxed-primitive@1.0.2: diff --git a/src/globals.css b/src/globals.css index 0a8dbae9..f9ef8baf 100644 --- a/src/globals.css +++ b/src/globals.css @@ -2,7 +2,15 @@ @tailwind components; @tailwind utilities; +body { + @apply text-gray-400 text-md; +} + /* start lynith's native experience */ * { user-select: none; } *:hover { cursor: default; } -/* end lynith's native experience */ \ No newline at end of file +/* end lynith's native experience */ + +h1 { @apply text-2xl font-bold; } +h2 { @apply text-xxl font-bold; } +h3 { @apply text-xl font-bold; } diff --git a/src/ui/App.tsx b/src/ui/App.tsx index e7cf1cd5..426af9c8 100644 --- a/src/ui/App.tsx +++ b/src/ui/App.tsx @@ -3,7 +3,7 @@ import WindowFrame from './components/native/WindowFrame'; function App(props: ParentProps) { return ( -
+
{props.children}
diff --git a/src/ui/components/base/Button.module.scss b/src/ui/components/base/Button.module.scss new file mode 100644 index 00000000..891008a0 --- /dev/null +++ b/src/ui/components/base/Button.module.scss @@ -0,0 +1,16 @@ +.button { + @apply border border-white/5 + bg-component-bg hover:bg-component-bg-hover active:bg-component-bg-pressed; + + &.size--sm { + + } + + &.size-md { + @apply py-2 px-4 rounded-lg; + } + + &.size-lg { + + } +} \ No newline at end of file diff --git a/src/ui/components/base/Button.tsx b/src/ui/components/base/Button.tsx new file mode 100644 index 00000000..85e29d2a --- /dev/null +++ b/src/ui/components/base/Button.tsx @@ -0,0 +1,19 @@ +import { JSX, ParentProps, mergeProps } from 'solid-js'; +import styles from './Button.module.scss'; + +type ButtonProps = JSX.ButtonHTMLAttributes & ParentProps & { + size?: 'sm' | 'md' | 'lg', + style?: 'primary' | 'secondary' | 'danger', // TODO +}; + +function Button(props: ButtonProps) { + const merged = mergeProps({ size: 'md' }, props); + + return ( + + ); +} + +export default Button; diff --git a/src/ui/components/native/WindowFrame.tsx b/src/ui/components/native/WindowFrame.tsx index 4b8b17a6..7696d77a 100644 --- a/src/ui/components/native/WindowFrame.tsx +++ b/src/ui/components/native/WindowFrame.tsx @@ -2,18 +2,19 @@ import { Window } from '@tauri-apps/api/window'; import { MinusIcon, XCloseIcon } from '@untitled-theme/icons-solid'; import { JSX, createSignal } from 'solid-js'; import Modal from '../overlay/Modal'; +import Button from '../base/Button'; -type ButtonProps = { +type TitlebarButtonProps = { // eslint-disable-next-line @typescript-eslint/no-explicit-any icon: (any: any) => JSX.Element, onClick: (event: MouseEvent) => void, danger?: boolean, }; -function Button(props: ButtonProps) { +function TitlebarButton(props: TitlebarButtonProps) { return ( @@ -21,16 +22,25 @@ function Button(props: ButtonProps) { } function WindowFrame() { - const [isCloseModalVisible, setIsCloseModalVisible] = createSignal(false); + const [isModalVisible, setModalVisible] = createSignal(false); + + const minimize = () => Window.getCurrent().minimize(); + const quit = () => Window.getCurrent().close(); return ( -
- , + , + ]} + />
); } diff --git a/src/ui/components/overlay/Modal.tsx b/src/ui/components/overlay/Modal.tsx index ffdac828..c95b5853 100644 --- a/src/ui/components/overlay/Modal.tsx +++ b/src/ui/components/overlay/Modal.tsx @@ -1,42 +1,71 @@ import { Accessor, - ParentProps, Setter, Show, createEffect, createSignal, + ParentProps, Setter, Show, createEffect, createSignal, For, + mergeProps, + JSX, } from 'solid-js'; import { Portal } from 'solid-js/web'; +import Button from '../base/Button'; -type ModalButton = { - text: string, - class?: string, - onClick?: (event: MouseEvent) => void, -}; +type ModalButtonProps = string | JSX.Element; + +function ModalButton(button: { props: ModalButtonProps }) { + return <> + {typeof button.props === 'string' ? ( + + ) : ( + button.props + )} + ; +} type ModalProps = { title: string, visible: Accessor, setVisible: Setter, - buttons?: ModalButton[], + buttons?: ModalButtonProps[], } & ParentProps; function Modal(props: ModalProps) { + const [localVisible, setLocalVisible] = createSignal(false); const [animate, setAnimate] = createSignal('animate-fade-in'); + const merged: ModalProps = mergeProps({ buttons: ['Ok'] }, props); + + createEffect(() => { + if (props.visible()) { + setAnimate('animate-fade-in'); + setLocalVisible(true); + } else { + setAnimate('animate-fade-out'); + setTimeout(() => { + setLocalVisible(false); + }, 150); + } + }); function onBackdropClick() { - setAnimate('animate-fade-out pointer-events-none'); - setTimeout(() => { - props.setVisible(false); - setAnimate('animate-fade-in pointer-events-auto'); - }, 150); + props.setVisible(false); } return ( - +
onBackdropClick()} />
-
-

Hello World

+
+

{props.title}

+
+ {props.children} +
+
+ {{(button) => ( + + )}} +
diff --git a/tailwind.config.js b/tailwind.config.js index b435144b..7c21b6fa 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -2,15 +2,36 @@ export default { content: ['./src/**/*.{js,ts,jsx,tsx}'], theme: { + fontSize: { + // Based off 16px + sm: '0.688rem', + md: '0.875rem', + lg: '1rem', + xl: '1.25rem', + xxl: '1.5rem', + '2xl': '2rem', + }, colors: { white: '#ffffff', black: '#000000', + slate: '#9BA1A6', danger: '#E5484D', - bg: { - primary: '#11171C', - secondary: '#192026', + + gray: { + 400: '#D5DBFF', }, + + component: { + bg: { + DEFAULT: '#1A2229', + hover: '#171F25', + pressed: '#222C35', + }, + }, + + primary: '#11171C', + secondary: '#192026', }, extend: { animation: {