diff --git a/.gitignore b/.gitignore index 378ea30e8..447544275 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,9 @@ nixos.qcow2 /docs/out **/.local.env +# MacOS stuff +**/.DS_store + # dream2nix .dream2nix diff --git a/pkgs/webview-ui/app/eslint.config.mjs b/pkgs/webview-ui/app/eslint.config.mjs index 858cc8fec..6b35c3e35 100644 --- a/pkgs/webview-ui/app/eslint.config.mjs +++ b/pkgs/webview-ui/app/eslint.config.mjs @@ -3,7 +3,7 @@ import tseslint from "typescript-eslint"; import tailwind from "eslint-plugin-tailwindcss"; import pluginQuery from "@tanstack/eslint-plugin-query"; -export default tseslint.config( +const config = tseslint.config( eslint.configs.recommended, ...pluginQuery.configs["flat/recommended"], ...tseslint.configs.strict, @@ -30,3 +30,5 @@ export default tseslint.config( }, }, ); + +export default config; diff --git a/pkgs/webview-ui/app/src/Form/fieldset/index.tsx b/pkgs/webview-ui/app/src/Form/fieldset/index.tsx new file mode 100644 index 000000000..fa5ee953a --- /dev/null +++ b/pkgs/webview-ui/app/src/Form/fieldset/index.tsx @@ -0,0 +1,32 @@ +import { JSX } from "solid-js"; + +import { Typography } from "@/src/components/Typography"; + +interface FieldsetProps { + legend?: string; + children: JSX.Element; + class?: string; +} + +export default function Fieldset(props: FieldsetProps) { + return ( +
+ {props.legend && ( +
+ + {props.legend} + +
+ )} +
+ {props.children} +
+
+ ); +} diff --git a/pkgs/webview-ui/app/src/Form/form/index.tsx b/pkgs/webview-ui/app/src/Form/form/index.tsx index d2e971ef5..9083335f2 100644 --- a/pkgs/webview-ui/app/src/Form/form/index.tsx +++ b/pkgs/webview-ui/app/src/Form/form/index.tsx @@ -368,10 +368,10 @@ export function ListValueDisplay( const bottomMost = () => props.idx === 0; return ( -
-
+
+
{props.children} -
+
+
+ +
), }} // Add the new item to the FieldArray diff --git a/pkgs/webview-ui/app/src/components/MachineListItem.tsx b/pkgs/webview-ui/app/src/components/MachineListItem.tsx index edfb8df1b..947e7368b 100644 --- a/pkgs/webview-ui/app/src/components/MachineListItem.tsx +++ b/pkgs/webview-ui/app/src/components/MachineListItem.tsx @@ -110,18 +110,18 @@ export const MachineListItem = (props: MachineListItemProps) => { setUpdating(false); }; return ( -
+
-
+
{name} -
+ + ); +} diff --git a/pkgs/webview-ui/app/src/components/button/css/button-dark.css b/pkgs/webview-ui/app/src/components/button/css/button-dark.css new file mode 100644 index 000000000..19f82f830 --- /dev/null +++ b/pkgs/webview-ui/app/src/components/button/css/button-dark.css @@ -0,0 +1,31 @@ +/* button DARK and states */ + +.button--dark { + @apply border border-solid border-secondary-950 bg-primary-800 text-white; + + box-shadow: inset 1px 1px theme(backgroundColor.secondary.700); + + &:disabled { + @apply disabled:bg-secondary-200 disabled:text-secondary-700 disabled:border-secondary-300; + } + + & .button__icon { + color: theme(textColor.secondary.200); + } +} + +.button--dark-hover:hover { + @apply hover:bg-secondary-900; +} + +.button--dark-focus:focus { + @apply focus:border-secondary-900; +} + +.button--dark-active:active { + @apply focus:border-secondary-900; +} + +.button--dark-active:active { + @apply active:border-secondary-900 active:shadow-inner-primary-active; +} diff --git a/pkgs/webview-ui/app/src/components/button/css/button-light.css b/pkgs/webview-ui/app/src/components/button/css/button-light.css new file mode 100644 index 000000000..aa6a114cc --- /dev/null +++ b/pkgs/webview-ui/app/src/components/button/css/button-light.css @@ -0,0 +1,37 @@ +/* button LIGHT and states */ + +.button--light { + @apply border border-solid border-secondary-400 bg-secondary-100 text-secondary-950; + + box-shadow: inset 1px 1px theme(backgroundColor.white); + + &:disabled { + @apply disabled:bg-secondary-50 disabled:text-secondary-200 disabled:border-secondary-700; + } + + & .button__icon { + color: theme(textColor.secondary.900); + } +} + +.button--light-hover:hover { + @apply hover:bg-secondary-200; +} + +.button--light-focus:focus { + @apply focus:bg-secondary-200; + + & .button__label { + color: theme(textColor.secondary.900) !important; + } +} + +.button--light-active:active { + @apply active:bg-secondary-200 border-secondary-600 active:text-secondary-900 active:shadow-inner-primary-active; + + box-shadow: inset 2px 2px theme(backgroundColor.secondary.300); + + & .button__label { + color: theme(textColor.secondary.900) !important; + } +} diff --git a/pkgs/webview-ui/app/src/components/button/css/index.css b/pkgs/webview-ui/app/src/components/button/css/index.css new file mode 100644 index 000000000..33f69a263 --- /dev/null +++ b/pkgs/webview-ui/app/src/components/button/css/index.css @@ -0,0 +1,54 @@ +@import "./button-light.css"; +@import "./button-dark.css"; + +.button { + @apply inline-flex items-center flex-shrink gap-1 justify-center p-4 font-semibold; + letter-spacing: 0.0275rem; +} + +/* button SIZES */ + +.button--default { + padding: theme(padding.2) theme(padding.4); + height: theme(height.9); + border-radius: theme(borderRadius.DEFAULT); + + &:has(> .button__icon--start):has(> .button__label) { + padding-left: theme(padding[2.5]); + } + + &:has(> .button__icon--end):has(> .button__label) { + padding-right: theme(padding[2.5]); + } +} + +.button--small { + padding: theme(padding[1.5]) theme(padding[3]); + height: theme(height.8); + border-radius: 3px; + + &:has(> .button__icon--start):has(> .button__label) { + padding-left: theme(padding.2); + } + + &:has(> .button__label):has(> .button__icon--end) { + padding-right: theme(padding.2); + } +} + +/* button group */ + +.button-group .button:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.button-group .button:first-child { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} + +.button-group .button:last-child { + border-top-left-radius: 0; + border-bottom-left-radius: 0; +} diff --git a/pkgs/webview-ui/app/src/components/button/index.tsx b/pkgs/webview-ui/app/src/components/button/index.tsx index 6c0c5209d..87756ad47 100644 --- a/pkgs/webview-ui/app/src/components/button/index.tsx +++ b/pkgs/webview-ui/app/src/components/button/index.tsx @@ -1,6 +1,8 @@ import { splitProps, type JSX } from "solid-js"; import cx from "classnames"; import { Typography } from "../Typography"; +//import './css/index.css' +import "./css/index.css"; type Variants = "dark" | "light" | "ghost"; type Size = "default" | "s"; @@ -9,50 +11,31 @@ const variantColors: ( disabled: boolean | undefined, ) => Record = (disabled) => ({ dark: cx( - "border border-solid", - "border-secondary-950 bg-primary-900 text-white", - "shadow-inner-primary", - // Hover state - // Focus state - // Active state - !disabled && "hover:border-secondary-900 hover:bg-secondary-700", - !disabled && "focus:border-secondary-900", - !disabled && - "active:border-secondary-900 active:shadow-inner-primary-active", + "button--dark", + !disabled && "button--dark-hover", // Hover state + !disabled && "button--dark-focus", // Focus state + !disabled && "button--dark-active", // Active state // Disabled "disabled:bg-secondary-200 disabled:text-secondary-700 disabled:border-secondary-300", ), light: cx( - "border border-solid", - "border-secondary-800 bg-secondary-100 text-secondary-800", - "shadow-inner-secondary", - // Hover state - // Focus state - // Active state - !disabled && "hover:bg-secondary-200 hover:text-secondary-900", - !disabled && "focus:bg-secondary-200 focus:text-secondary-900", - !disabled && - "active:bg-secondary-200 active:text-secondary-950 active:shadow-inner-secondary-active", - // Disabled - "disabled:bg-secondary-50 disabled:text-secondary-200 disabled:border-secondary-700", + "button--light", + + !disabled && "button--light-hover", // Hover state + !disabled && "button--light-focus", // Focus state + !disabled && "button--light-active", // Active state ), ghost: cx( // "shadow-inner-secondary", - // Hover state - // Focus state - // Active state - !disabled && "hover:bg-secondary-200 hover:text-secondary-900", - !disabled && "focus:bg-secondary-200 focus:text-secondary-900", - !disabled && - "active:bg-secondary-200 active:text-secondary-950 active:shadow-inner-secondary-active", - // Disabled - "disabled:bg-secondary-50 disabled:text-secondary-200 disabled:border-secondary-700", + !disabled && "hover:bg-secondary-200 hover:text-secondary-900", // Hover state + !disabled && "focus:bg-secondary-200 focus:text-secondary-900", // Focus state + !disabled && "button--light-active", // Active state ), }); const sizePaddings: Record = { - default: cx("rounded-[0.1875rem] px-4 py-2"), - s: cx("rounded-sm py-[0.375rem] px-3"), + default: cx("button--default"), + s: cx("button button--small"), //cx("rounded-sm py-[0.375rem] px-3"), }; const sizeFont: Record = { @@ -77,26 +60,38 @@ export const Button = (props: ButtonProps) => { "endIcon", "class", ]); + + const buttonInvertion = (variant: Variants) => { + return !(!variant || variant === "ghost" || variant === "light"); + }; + return ( ); }; diff --git a/pkgs/webview-ui/app/src/components/icon/index.tsx b/pkgs/webview-ui/app/src/components/icon/index.tsx index a64a9a23e..32ea5261a 100644 --- a/pkgs/webview-ui/app/src/components/icon/index.tsx +++ b/pkgs/webview-ui/app/src/components/icon/index.tsx @@ -77,6 +77,7 @@ export type IconVariant = keyof typeof icons; interface IconProps extends JSX.SvgSVGAttributes { icon: IconVariant; + size?: number; } const Icon: Component = (props) => { @@ -85,8 +86,8 @@ const Icon: Component = (props) => { const IconComponent = icons[local.icon]; return IconComponent ? ( { return ( -
+
{props.showBack && } diff --git a/pkgs/webview-ui/app/src/layout/layout.tsx b/pkgs/webview-ui/app/src/layout/layout.tsx index 85f295a94..4185f9be1 100644 --- a/pkgs/webview-ui/app/src/layout/layout.tsx +++ b/pkgs/webview-ui/app/src/layout/layout.tsx @@ -17,19 +17,11 @@ export const Layout: Component = (props) => { return (
-
-
- -
-
+
+
{props.children}
+
); diff --git a/pkgs/webview-ui/app/src/routes/machines/create.tsx b/pkgs/webview-ui/app/src/routes/machines/create.tsx index 1bda5b558..ee3b7f5ed 100644 --- a/pkgs/webview-ui/app/src/routes/machines/create.tsx +++ b/pkgs/webview-ui/app/src/routes/machines/create.tsx @@ -11,6 +11,9 @@ import { Match, Switch } from "solid-js"; import toast from "solid-toast"; import { MachineAvatar } from "./avatar"; import { DynForm } from "@/src/Form/form"; +import { Typography } from "@/src/components/Typography"; +import Fieldset from "@/src/Form/fieldset"; +import Accordion from "@/src/components/accordion"; type CreateMachineForm = OperationArgs<"create_machine">; @@ -72,44 +75,80 @@ export function CreateMachine() { <>
-
-
+
+ {(field, props) => ( <> -
+
- - )} - - {(field, props) => ( - - )} - -
- -
Deployment Settings
-
+
+ + {(field, props) => ( + <> + + + )} + + + {(field, props) => ( + + )} + +
+ +
+ + {(field, props) => ( +
+ +
+ )} +
+
+ +
{(field, props) => ( <> @@ -123,9 +162,10 @@ export function CreateMachine() { )} -
-
-
+ + + +
-
+
diff --git a/pkgs/webview-ui/app/src/routes/machines/list.tsx b/pkgs/webview-ui/app/src/routes/machines/list.tsx index 78b441a86..e5bb2eaf0 100644 --- a/pkgs/webview-ui/app/src/routes/machines/list.tsx +++ b/pkgs/webview-ui/app/src/routes/machines/list.tsx @@ -82,37 +82,31 @@ export const MachineListView: Component = () => { size="s" onClick={() => refresh()} startIcon={} - > + /> -
- - - - - - -
- +
- + startIcon={} + /> +
+ } /> diff --git a/pkgs/webview-ui/app/src/routes/modules/list.tsx b/pkgs/webview-ui/app/src/routes/modules/list.tsx index 4cfc69d10..9bf0c035f 100644 --- a/pkgs/webview-ui/app/src/routes/modules/list.tsx +++ b/pkgs/webview-ui/app/src/routes/modules/list.tsx @@ -19,9 +19,9 @@ interface CategoryProps { } const Categories = (props: CategoryProps) => { return ( - + {props.categories.map((category) => ( - {category} + {category} ))} ); @@ -32,10 +32,10 @@ interface RolesProps { } const Roles = (props: RolesProps) => { return ( -
+
- Service Typography{" "} + Service {props.roles.map((role) => ( @@ -54,9 +54,14 @@ const ModuleItem = (props: { const navigate = useNavigate(); return ( -
-
-
+
+ {/*
+
}>
  • @@ -71,20 +76,26 @@ const ModuleItem = (props: {
-
+
*/} - -
); @@ -113,38 +124,33 @@ export const ModuleList = () => { title="Modules" toolbar={ <> - - - + - - - - +
+
@@ -156,10 +162,10 @@ export const ModuleList = () => { Loading....
diff --git a/pkgs/webview-ui/app/stylelint.config.js b/pkgs/webview-ui/app/stylelint.config.js new file mode 100644 index 000000000..faf4babdd --- /dev/null +++ b/pkgs/webview-ui/app/stylelint.config.js @@ -0,0 +1,6 @@ +module.exports = { + extends: ["stylelint-config-standard", "stylelint-config-tailwindcss"], + rules: { + // You can adjust rules here + }, +}; diff --git a/pkgs/webview-ui/app/tailwind/core-plugin.ts b/pkgs/webview-ui/app/tailwind/core-plugin.ts index b40862895..9965d8935 100644 --- a/pkgs/webview-ui/app/tailwind/core-plugin.ts +++ b/pkgs/webview-ui/app/tailwind/core-plugin.ts @@ -284,7 +284,7 @@ export default plugin.withOptions( "inner-primary": "2px 2px 0px 0px var(--clr-bg-inv-acc-3, #415E63) inset", "inner-primary-active": - "0px 0px 0px 1px #FFF, 0px 0px 0px 2px var(--clr-bg-inv-acc-4, #203637), -2px -2px 0px 0px var(--clr-bg-inv-acc-1, #7B9B9F) inset", + "0px 0px 0px 1px #FFF, 0px 0px 0px 2px var(--clr-bg-inv-acc-4, #203637)", "inner-secondary": "-2px -2px 0px 0px #CEDFE2 inset, 2px 2px 0px 0px white inset", "inner-secondary-active":