Merge pull request 'fix(clan-app): Misc ui styling fixes' (#3451) from amunsen/clan-core:ui-fixes into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3451
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -16,6 +16,9 @@ nixos.qcow2
|
|||||||
/docs/out
|
/docs/out
|
||||||
**/.local.env
|
**/.local.env
|
||||||
|
|
||||||
|
# MacOS stuff
|
||||||
|
**/.DS_store
|
||||||
|
|
||||||
# dream2nix
|
# dream2nix
|
||||||
.dream2nix
|
.dream2nix
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import tseslint from "typescript-eslint";
|
|||||||
import tailwind from "eslint-plugin-tailwindcss";
|
import tailwind from "eslint-plugin-tailwindcss";
|
||||||
import pluginQuery from "@tanstack/eslint-plugin-query";
|
import pluginQuery from "@tanstack/eslint-plugin-query";
|
||||||
|
|
||||||
export default tseslint.config(
|
const config = tseslint.config(
|
||||||
eslint.configs.recommended,
|
eslint.configs.recommended,
|
||||||
...pluginQuery.configs["flat/recommended"],
|
...pluginQuery.configs["flat/recommended"],
|
||||||
...tseslint.configs.strict,
|
...tseslint.configs.strict,
|
||||||
@@ -30,3 +30,5 @@ export default tseslint.config(
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
export default config;
|
||||||
|
|||||||
32
pkgs/webview-ui/app/src/Form/fieldset/index.tsx
Normal file
32
pkgs/webview-ui/app/src/Form/fieldset/index.tsx
Normal file
@@ -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 (
|
||||||
|
<fieldset class="flex flex-col gap-y-2.5">
|
||||||
|
{props.legend && (
|
||||||
|
<div class="px-2">
|
||||||
|
<Typography
|
||||||
|
hierarchy="body"
|
||||||
|
tag="p"
|
||||||
|
size="s"
|
||||||
|
color="primary"
|
||||||
|
weight="medium"
|
||||||
|
>
|
||||||
|
{props.legend}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div class="flex flex-col gap-y-3 rounded-md border border-secondary-200 bg-secondary-50 p-5">
|
||||||
|
{props.children}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -368,10 +368,10 @@ export function ListValueDisplay<T extends FieldValues, R extends ResponseData>(
|
|||||||
const bottomMost = () => props.idx === 0;
|
const bottomMost = () => props.idx === 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="w-full border-l-4 border-gray-300">
|
<div class="w-full border-b border-secondary-200 px-2 pb-4">
|
||||||
<div class="flex w-full items-end gap-2 px-4">
|
<div class="flex w-full items-center gap-2">
|
||||||
{props.children}
|
{props.children}
|
||||||
<div class="ml-4 min-w-fit pb-4">
|
<div class="ml-4 min-w-fit">
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="s"
|
size="s"
|
||||||
@@ -541,7 +541,6 @@ export function ArrayFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
)}
|
)}
|
||||||
</Field>
|
</Field>
|
||||||
</Match>
|
</Match>
|
||||||
|
|
||||||
<Match
|
<Match
|
||||||
when={
|
when={
|
||||||
itemsSchema().type === "string" ||
|
itemsSchema().type === "string" ||
|
||||||
@@ -629,9 +628,11 @@ export function ArrayFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
</ListValueDisplay>
|
</ListValueDisplay>
|
||||||
)}
|
)}
|
||||||
</For>
|
</For>
|
||||||
<span class=" font-bold text-error-700">
|
<Show when={fieldArray.error}>
|
||||||
{fieldArray.error}
|
<span class="font-bold text-error-700">
|
||||||
</span>
|
{fieldArray.error}
|
||||||
|
</span>
|
||||||
|
</Show>
|
||||||
|
|
||||||
{/* Add new item */}
|
{/* Add new item */}
|
||||||
<DynForm
|
<DynForm
|
||||||
@@ -651,14 +652,16 @@ export function ArrayFields<T extends FieldValues, R extends ResponseData>(
|
|||||||
// Button for adding new items
|
// Button for adding new items
|
||||||
components={{
|
components={{
|
||||||
before: (
|
before: (
|
||||||
<Button
|
<div class="flex w-full justify-end pb-2">
|
||||||
variant="ghost"
|
<Button
|
||||||
type="submit"
|
variant="ghost"
|
||||||
endIcon={<Icon icon={"Plus"} />}
|
type="submit"
|
||||||
class="capitalize"
|
endIcon={<Icon size={14} icon={"Plus"} />}
|
||||||
>
|
class="capitalize"
|
||||||
Add {itemsSchema().title}
|
>
|
||||||
</Button>
|
Add {itemsSchema().title}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
),
|
),
|
||||||
}}
|
}}
|
||||||
// Add the new item to the FieldArray
|
// Add the new item to the FieldArray
|
||||||
|
|||||||
@@ -110,18 +110,18 @@ export const MachineListItem = (props: MachineListItemProps) => {
|
|||||||
setUpdating(false);
|
setUpdating(false);
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<div class="border rounded-lg border-def-2 p-3 m-2 w-64">
|
<div class="m-2 w-64 rounded-lg border p-3 border-def-2">
|
||||||
<figure class="h-fit rounded-xl border bg-def-2 border-def-5">
|
<figure class="h-fit rounded-xl border bg-def-2 border-def-5">
|
||||||
<RndThumbnail name={name} width={220} height={120} />
|
<RndThumbnail name={name} width={220} height={120} />
|
||||||
</figure>
|
</figure>
|
||||||
<div class="flex-row justify-between gap-4 pt-2 px-2">
|
<div class="flex-row justify-between gap-4 px-2 pt-2">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<A href={`/machines/${name}`}>
|
<A href={`/machines/${name}`}>
|
||||||
<Typography hierarchy="title" size="m" weight="bold">
|
<Typography hierarchy="title" size="m" weight="bold">
|
||||||
{name}
|
{name}
|
||||||
</Typography>
|
</Typography>
|
||||||
</A>
|
</A>
|
||||||
<div class="text-slate-600 flex justify-between">
|
<div class="flex justify-between text-slate-600">
|
||||||
<div class="flex flex-nowrap">
|
<div class="flex flex-nowrap">
|
||||||
<span class="h-4">
|
<span class="h-4">
|
||||||
<Icon icon="Flash" class="h-4" font-size="inherit" />
|
<Icon icon="Flash" class="h-4" font-size="inherit" />
|
||||||
@@ -138,7 +138,7 @@ export const MachineListItem = (props: MachineListItemProps) => {
|
|||||||
popoverid={`menu-${props.name}`}
|
popoverid={`menu-${props.name}`}
|
||||||
label={<Icon icon={"More"} />}
|
label={<Icon icon={"More"} />}
|
||||||
>
|
>
|
||||||
<ul class="z-[1] w-64 p-2 shadow bg-white ">
|
<ul class="z-[1] w-64 bg-white p-2 shadow ">
|
||||||
<li>
|
<li>
|
||||||
<Button
|
<Button
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { A } from "@solidjs/router";
|
import { A } from "@solidjs/router";
|
||||||
|
|
||||||
import { Typography } from "@/src/components/Typography";
|
import { Typography } from "@/src/components/Typography";
|
||||||
|
import "./css/sidebar.css";
|
||||||
|
|
||||||
interface SidebarListItem {
|
interface SidebarListItem {
|
||||||
title: string;
|
title: string;
|
||||||
@@ -11,13 +11,13 @@ export const SidebarListItem = (props: SidebarListItem) => {
|
|||||||
const { title, href } = props;
|
const { title, href } = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li class="sidebar__list__item">
|
<li class="">
|
||||||
<A class="sidebar__list__link" href={href}>
|
<A class="sidebar__list__link" href={href}>
|
||||||
<Typography
|
<Typography
|
||||||
class="sidebar__list__content"
|
class="sidebar__list__content"
|
||||||
tag="span"
|
tag="span"
|
||||||
hierarchy="body"
|
hierarchy="body"
|
||||||
size="s"
|
size="xs"
|
||||||
weight="normal"
|
weight="normal"
|
||||||
color="primary"
|
color="primary"
|
||||||
inverted={true}
|
inverted={true}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
.sidebar__list__item {
|
.sidebar__list__link {
|
||||||
position: relative;
|
position: relative;
|
||||||
cursor: theme(cursor.pointer);
|
cursor: theme(cursor.pointer);
|
||||||
|
|
||||||
@@ -19,12 +19,12 @@
|
|||||||
&:hover:after {
|
&:hover:after {
|
||||||
background: var(--clr-bg-inv-acc-2);
|
background: var(--clr-bg-inv-acc-2);
|
||||||
transform: scale(theme(scale.100));
|
transform: scale(theme(scale.100));
|
||||||
transition: transform 0.24s ease-in-out;
|
transition: transform 0.32s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
transform: scale(0.99);
|
transform: scale(0.99);
|
||||||
transition: transform 0.08s ease-in-out;
|
transition: transform 0.12s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active:after {
|
&:active:after {
|
||||||
@@ -37,7 +37,13 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
z-index: 20;
|
z-index: 20;
|
||||||
display: block;
|
display: block;
|
||||||
padding: theme(padding.3);
|
padding: theme(padding.2) theme(padding.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.sidebar__list__link.active {
|
||||||
|
&:after {
|
||||||
|
background: var(--clr-bg-inv-acc-3);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__list__content {
|
.sidebar__list__content {
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
@apply bg-inv-2 h-full border border-solid border-inv-2 min-w-72 rounded-xl;
|
@apply bg-inv-2 h-full border border-solid border-inv-2 min-w-72 rounded-xl;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__body {
|
.sidebar__body {
|
||||||
@@ -19,9 +21,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.sidebar__section {
|
.sidebar__section {
|
||||||
padding: theme(padding.2);
|
|
||||||
/* background-color: rgba(var(--clr-bg-inv-3) / 0.9); */
|
|
||||||
@apply bg-primary-800/90;
|
@apply bg-primary-800/90;
|
||||||
|
|
||||||
|
padding: theme(padding.2);
|
||||||
border-radius: theme(borderRadius.md);
|
border-radius: theme(borderRadius.md);
|
||||||
|
|
||||||
::marker {
|
::marker {
|
||||||
|
|||||||
@@ -19,20 +19,22 @@ export const SidebarSection = (props: {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<details class="sidebar__section accordeon" open>
|
<details class="sidebar__section accordeon" open>
|
||||||
<summary class="accordeon__header">
|
<summary style="display: contents;">
|
||||||
<Typography
|
<div class="accordeon__header">
|
||||||
class="inline-flex w-full gap-2 uppercase"
|
<Typography
|
||||||
tag="p"
|
class="inline-flex w-full gap-2 uppercase !tracking-wider"
|
||||||
hierarchy="body"
|
tag="p"
|
||||||
size="xs"
|
hierarchy="body"
|
||||||
weight="normal"
|
size="xxs"
|
||||||
color="tertiary"
|
weight="normal"
|
||||||
inverted={true}
|
color="tertiary"
|
||||||
>
|
inverted={true}
|
||||||
<Icon icon={props.icon} />
|
>
|
||||||
{title}
|
<Icon class="opacity-90" icon={props.icon} size={13} />
|
||||||
<Icon icon="CaretDown" class="ml-auto" />
|
{title}
|
||||||
</Typography>
|
<Icon icon="CaretDown" class="ml-auto" size={10} />
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
</summary>
|
</summary>
|
||||||
<div class="accordeon__body">{children}</div>
|
<div class="accordeon__body">{children}</div>
|
||||||
</details>
|
</details>
|
||||||
@@ -60,7 +62,7 @@ export const Sidebar = (props: RouteSectionProps) => {
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="sidebar opacity-95">
|
<div class="sidebar">
|
||||||
<Show
|
<Show
|
||||||
when={query.data}
|
when={query.data}
|
||||||
fallback={<SidebarHeader clanName={"Untitled"} />}
|
fallback={<SidebarHeader clanName={"Untitled"} />}
|
||||||
@@ -81,7 +83,7 @@ export const Sidebar = (props: RouteSectionProps) => {
|
|||||||
title={route.label}
|
title={route.label}
|
||||||
icon={route.icon || "Paperclip"}
|
icon={route.icon || "Paperclip"}
|
||||||
>
|
>
|
||||||
<ul>
|
<ul class="flex flex-col gap-y-0.5">
|
||||||
<For each={children().filter((r) => !r.hidden)}>
|
<For each={children().filter((r) => !r.hidden)}>
|
||||||
{(child) => (
|
{(child) => (
|
||||||
<SidebarListItem
|
<SidebarListItem
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.fnt-body-xxs {
|
.fnt-body-xxs {
|
||||||
font-size: 0.6875rem;
|
font-size: 0.75rem;
|
||||||
line-height: 132%;
|
line-height: 132%;
|
||||||
letter-spacing: 0.00688rem;
|
letter-spacing: 0.00688rem;
|
||||||
}
|
}
|
||||||
|
|||||||
10
pkgs/webview-ui/app/src/components/accordion/accordion.css
Normal file
10
pkgs/webview-ui/app/src/components/accordion/accordion.css
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.accordion {
|
||||||
|
@apply flex flex-col gap-y-5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion__title {
|
||||||
|
@apply flex h-5 cursor-pointer items-center justify-end gap-x-0.5 px-1 font-medium;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion__body {
|
||||||
|
}
|
||||||
45
pkgs/webview-ui/app/src/components/accordion/index.tsx
Normal file
45
pkgs/webview-ui/app/src/components/accordion/index.tsx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
import { createSignal, JSX, Show } from "solid-js";
|
||||||
|
import Icon from "../icon";
|
||||||
|
import { Button } from "../button";
|
||||||
|
import cx from "classnames";
|
||||||
|
import "./accordion.css";
|
||||||
|
|
||||||
|
interface AccordionProps {
|
||||||
|
title: string;
|
||||||
|
children: JSX.Element;
|
||||||
|
class?: string;
|
||||||
|
initiallyOpen?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Accordion(props: AccordionProps) {
|
||||||
|
const [isOpen, setIsOpen] = createSignal(props.initiallyOpen ?? false);
|
||||||
|
return (
|
||||||
|
<div class={cx(`accordion`, props.class)} tabindex="0">
|
||||||
|
<div onClick={() => setIsOpen(!isOpen())} class="accordion__title">
|
||||||
|
<Show
|
||||||
|
when={isOpen()}
|
||||||
|
fallback={
|
||||||
|
<Button
|
||||||
|
endIcon={<Icon size={12} icon={"CaretDown"} />}
|
||||||
|
variant="light"
|
||||||
|
size="s"
|
||||||
|
>
|
||||||
|
{props.title}
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
endIcon={<Icon size={12} icon={"CaretUp"} />}
|
||||||
|
variant="dark"
|
||||||
|
size="s"
|
||||||
|
>
|
||||||
|
{props.title}
|
||||||
|
</Button>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
<Show when={isOpen()}>
|
||||||
|
<div class="accordion__body">{props.children}</div>
|
||||||
|
</Show>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
54
pkgs/webview-ui/app/src/components/button/css/index.css
Normal file
54
pkgs/webview-ui/app/src/components/button/css/index.css
Normal file
@@ -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;
|
||||||
|
}
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
import { splitProps, type JSX } from "solid-js";
|
import { splitProps, type JSX } from "solid-js";
|
||||||
import cx from "classnames";
|
import cx from "classnames";
|
||||||
import { Typography } from "../Typography";
|
import { Typography } from "../Typography";
|
||||||
|
//import './css/index.css'
|
||||||
|
import "./css/index.css";
|
||||||
|
|
||||||
type Variants = "dark" | "light" | "ghost";
|
type Variants = "dark" | "light" | "ghost";
|
||||||
type Size = "default" | "s";
|
type Size = "default" | "s";
|
||||||
@@ -9,50 +11,31 @@ const variantColors: (
|
|||||||
disabled: boolean | undefined,
|
disabled: boolean | undefined,
|
||||||
) => Record<Variants, string> = (disabled) => ({
|
) => Record<Variants, string> = (disabled) => ({
|
||||||
dark: cx(
|
dark: cx(
|
||||||
"border border-solid",
|
"button--dark",
|
||||||
"border-secondary-950 bg-primary-900 text-white",
|
!disabled && "button--dark-hover", // Hover state
|
||||||
"shadow-inner-primary",
|
!disabled && "button--dark-focus", // Focus state
|
||||||
// Hover state
|
!disabled && "button--dark-active", // Active 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",
|
|
||||||
// Disabled
|
// Disabled
|
||||||
"disabled:bg-secondary-200 disabled:text-secondary-700 disabled:border-secondary-300",
|
"disabled:bg-secondary-200 disabled:text-secondary-700 disabled:border-secondary-300",
|
||||||
),
|
),
|
||||||
light: cx(
|
light: cx(
|
||||||
"border border-solid",
|
"button--light",
|
||||||
"border-secondary-800 bg-secondary-100 text-secondary-800",
|
|
||||||
"shadow-inner-secondary",
|
!disabled && "button--light-hover", // Hover state
|
||||||
// Hover state
|
!disabled && "button--light-focus", // Focus state
|
||||||
// Focus state
|
!disabled && "button--light-active", // Active 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",
|
|
||||||
),
|
),
|
||||||
ghost: cx(
|
ghost: cx(
|
||||||
// "shadow-inner-secondary",
|
// "shadow-inner-secondary",
|
||||||
// Hover state
|
!disabled && "hover:bg-secondary-200 hover:text-secondary-900", // Hover state
|
||||||
// Focus state
|
!disabled && "focus:bg-secondary-200 focus:text-secondary-900", // Focus state
|
||||||
// Active state
|
!disabled && "button--light-active", // 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",
|
|
||||||
),
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
const sizePaddings: Record<Size, string> = {
|
const sizePaddings: Record<Size, string> = {
|
||||||
default: cx("rounded-[0.1875rem] px-4 py-2"),
|
default: cx("button--default"),
|
||||||
s: cx("rounded-sm py-[0.375rem] px-3"),
|
s: cx("button button--small"), //cx("rounded-sm py-[0.375rem] px-3"),
|
||||||
};
|
};
|
||||||
|
|
||||||
const sizeFont: Record<Size, string> = {
|
const sizeFont: Record<Size, string> = {
|
||||||
@@ -77,26 +60,38 @@ export const Button = (props: ButtonProps) => {
|
|||||||
"endIcon",
|
"endIcon",
|
||||||
"class",
|
"class",
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const buttonInvertion = (variant: Variants) => {
|
||||||
|
return !(!variant || variant === "ghost" || variant === "light");
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<button
|
<button
|
||||||
class={cx(
|
class={cx(
|
||||||
local.class,
|
local.class,
|
||||||
// Layout
|
"button", // default button class
|
||||||
"inline-flex items-center flex-shrink gap-2 justify-center",
|
variantColors(props.disabled)[local.variant || "dark"], // button appereance
|
||||||
// Styles
|
sizePaddings[local.size || "default"], // button size
|
||||||
"p-4",
|
|
||||||
sizePaddings[local.size || "default"],
|
|
||||||
// Colors
|
|
||||||
variantColors(props.disabled)[local.variant || "dark"],
|
|
||||||
//Font
|
|
||||||
"leading-none font-semibold",
|
|
||||||
sizeFont[local.size || "default"],
|
|
||||||
)}
|
)}
|
||||||
{...other}
|
{...other}
|
||||||
>
|
>
|
||||||
{local.startIcon && <span class="h-4">{local.startIcon}</span>}
|
{local.startIcon && (
|
||||||
{local.children && <span>{local.children}</span>}
|
<span class="button__icon--start">{local.startIcon}</span>
|
||||||
{local.endIcon && <span class="h-4">{local.endIcon}</span>}
|
)}
|
||||||
|
{local.children && (
|
||||||
|
<Typography
|
||||||
|
class="button__label"
|
||||||
|
hierarchy="label"
|
||||||
|
size={local.size || "default"}
|
||||||
|
color="inherit"
|
||||||
|
inverted={buttonInvertion(local.variant || "dark")}
|
||||||
|
weight="medium"
|
||||||
|
tag="span"
|
||||||
|
>
|
||||||
|
{local.children}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
{local.endIcon && <span class="button__icon--end">{local.endIcon}</span>}
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -77,6 +77,7 @@ export type IconVariant = keyof typeof icons;
|
|||||||
|
|
||||||
interface IconProps extends JSX.SvgSVGAttributes<SVGElement> {
|
interface IconProps extends JSX.SvgSVGAttributes<SVGElement> {
|
||||||
icon: IconVariant;
|
icon: IconVariant;
|
||||||
|
size?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Icon: Component<IconProps> = (props) => {
|
const Icon: Component<IconProps> = (props) => {
|
||||||
@@ -85,8 +86,8 @@ const Icon: Component<IconProps> = (props) => {
|
|||||||
const IconComponent = icons[local.icon];
|
const IconComponent = icons[local.icon];
|
||||||
return IconComponent ? (
|
return IconComponent ? (
|
||||||
<IconComponent
|
<IconComponent
|
||||||
width={16}
|
width={iconProps.size || 16}
|
||||||
height={16}
|
height={iconProps.size || 16}
|
||||||
viewBox="0 0 48 48"
|
viewBox="0 0 48 48"
|
||||||
// @ts-expect-error: dont know, fix this type nit later
|
// @ts-expect-error: dont know, fix this type nit later
|
||||||
ref={iconProps.ref}
|
ref={iconProps.ref}
|
||||||
|
|||||||
@@ -11,11 +11,13 @@
|
|||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
src: url(../.fonts/ArchivoSemiCondensed-Regular.woff2) format("woff2");
|
src: url(../.fonts/ArchivoSemiCondensed-Regular.woff2) format("woff2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Archivo";
|
font-family: "Archivo";
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
src: url(../.fonts/ArchivoSemiCondensed-Medium.woff2) format("woff2");
|
src: url(../.fonts/ArchivoSemiCondensed-Medium.woff2) format("woff2");
|
||||||
}
|
}
|
||||||
|
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: "Archivo";
|
font-family: "Archivo";
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
@@ -30,7 +32,7 @@
|
|||||||
|
|
||||||
:root {
|
:root {
|
||||||
--clr-bg-def-1: theme(colors.white);
|
--clr-bg-def-1: theme(colors.white);
|
||||||
--clr-bg-def-2: theme(colors.secondary.50);
|
--clr-bg-def-2: theme(colors.primary.50);
|
||||||
--clr-bg-def-3: theme(colors.secondary.100);
|
--clr-bg-def-3: theme(colors.secondary.100);
|
||||||
--clr-bg-def-4: theme(colors.secondary.200);
|
--clr-bg-def-4: theme(colors.secondary.200);
|
||||||
--clr-bg-def-5: theme(colors.secondary.300);
|
--clr-bg-def-5: theme(colors.secondary.300);
|
||||||
@@ -72,6 +74,15 @@ html {
|
|||||||
@apply font-sans;
|
@apply font-sans;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
|
||||||
|
-webkit-user-select: none;
|
||||||
|
/* Safari */
|
||||||
|
-moz-user-select: none;
|
||||||
|
/* Firefox */
|
||||||
|
-ms-user-select: none;
|
||||||
|
/* Internet Explorer/Edge */
|
||||||
|
user-select: none;
|
||||||
|
/* Standard */
|
||||||
}
|
}
|
||||||
|
|
||||||
.accordeon {
|
.accordeon {
|
||||||
@@ -81,7 +92,7 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.accordeon__header {
|
.accordeon__header {
|
||||||
padding: theme(padding.2) theme(padding[1.5]);
|
padding: theme(padding.2) theme(padding[1.5]) theme(padding.1);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,5 +101,4 @@ html {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.accordeon__body {
|
.accordeon__body {
|
||||||
padding: theme(padding.2) 0 theme(padding.1);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ interface HeaderProps {
|
|||||||
}
|
}
|
||||||
export const Header = (props: HeaderProps) => {
|
export const Header = (props: HeaderProps) => {
|
||||||
return (
|
return (
|
||||||
<div class="flex border-b px-6 py-4 border-def-3">
|
<div class="sticky top-0 z-20 flex items-center border-b bg-white/80 px-6 py-4 backdrop-blur-md border-def-3">
|
||||||
<div class="flex-none">
|
<div class="flex-none">
|
||||||
{props.showBack && <BackButton />}
|
{props.showBack && <BackButton />}
|
||||||
<span class=" lg:hidden" data-tip="Menu">
|
<span class=" lg:hidden" data-tip="Menu">
|
||||||
|
|||||||
@@ -17,19 +17,11 @@ export const Layout: Component<RouteSectionProps> = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div class="h-screen w-full p-4 bg-def-2">
|
<div class="h-screen w-full p-4 bg-def-2">
|
||||||
<div class="h-full flex">
|
<div class="flex size-full flex-row-reverse">
|
||||||
<div
|
<div class="my-2 ml-8 flex-1 overflow-x-hidden overflow-y-scroll rounded-lg border bg-def-1 border-def-3">
|
||||||
class="z-40 h-full overflow-hidden"
|
|
||||||
classList={{
|
|
||||||
hidden:
|
|
||||||
props.location.pathname === "welcome" || clanList().length === 0,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Sidebar {...props} />
|
|
||||||
</div>
|
|
||||||
<div class="w-full my-2 ml-8 overflow-x-hidden overflow-y-scroll rounded-lg border bg-def-1 border-def-3">
|
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
|
<Sidebar {...props} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -11,6 +11,9 @@ import { Match, Switch } from "solid-js";
|
|||||||
import toast from "solid-toast";
|
import toast from "solid-toast";
|
||||||
import { MachineAvatar } from "./avatar";
|
import { MachineAvatar } from "./avatar";
|
||||||
import { DynForm } from "@/src/Form/form";
|
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">;
|
type CreateMachineForm = OperationArgs<"create_machine">;
|
||||||
|
|
||||||
@@ -72,44 +75,80 @@ export function CreateMachine() {
|
|||||||
<>
|
<>
|
||||||
<Header title="Create Machine" />
|
<Header title="Create Machine" />
|
||||||
<div class="flex w-full p-4">
|
<div class="flex w-full p-4">
|
||||||
<div class="mt-4 w-full self-stretch px-2">
|
<div class="mt-4 w-full self-stretch px-8">
|
||||||
<Form onSubmit={handleSubmit} class="gap-2 flex flex-col">
|
<Form
|
||||||
|
onSubmit={handleSubmit}
|
||||||
|
class="mx-auto flex w-full max-w-2xl flex-col gap-y-6"
|
||||||
|
>
|
||||||
<Field
|
<Field
|
||||||
name="opts.machine.name"
|
name="opts.machine.name"
|
||||||
validate={[required("This field is required")]}
|
validate={[required("This field is required")]}
|
||||||
>
|
>
|
||||||
{(field, props) => (
|
{(field, props) => (
|
||||||
<>
|
<>
|
||||||
<div class="flex justify-center mb-4 pb-4 border-b">
|
<div class="mb-4 flex justify-center border-b pb-4">
|
||||||
<MachineAvatar name={field.value} />
|
<MachineAvatar name={field.value} />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<TextInput
|
|
||||||
inputProps={props}
|
|
||||||
value={`${field.value}`}
|
|
||||||
label={"name"}
|
|
||||||
error={field.error}
|
|
||||||
required
|
|
||||||
placeholder="New_machine"
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Field>
|
</Field>
|
||||||
<Field name="opts.machine.description">
|
<Fieldset legend="General">
|
||||||
{(field, props) => (
|
<Field
|
||||||
<TextInput
|
name="opts.machine.name"
|
||||||
inputProps={props}
|
validate={[required("This field is required")]}
|
||||||
value={`${field.value}`}
|
>
|
||||||
label={"description"}
|
{(field, props) => (
|
||||||
error={field.error}
|
<>
|
||||||
placeholder="My awesome machine"
|
<TextInput
|
||||||
/>
|
inputProps={props}
|
||||||
)}
|
value={`${field.value}`}
|
||||||
</Field>
|
label={"name"}
|
||||||
<div class=" " tabindex="0">
|
error={field.error}
|
||||||
<input type="checkbox" />
|
required
|
||||||
<div class=" font-medium ">Deployment Settings</div>
|
placeholder="New_machine"
|
||||||
<div class="">
|
/>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
<Field name="opts.machine.description">
|
||||||
|
{(field, props) => (
|
||||||
|
<TextInput
|
||||||
|
inputProps={props}
|
||||||
|
value={`${field.value}`}
|
||||||
|
label={"description"}
|
||||||
|
error={field.error}
|
||||||
|
placeholder="My awesome machine"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</Fieldset>
|
||||||
|
|
||||||
|
<Fieldset legend="Tags">
|
||||||
|
<Field name="opts.machine.tags" type="string[]">
|
||||||
|
{(field, props) => (
|
||||||
|
<div class="p-2">
|
||||||
|
<DynForm
|
||||||
|
initialValues={{ tags: ["all"] }}
|
||||||
|
schema={{
|
||||||
|
type: "object",
|
||||||
|
properties: {
|
||||||
|
tags: {
|
||||||
|
type: "array",
|
||||||
|
items: {
|
||||||
|
title: "Tag",
|
||||||
|
type: "string",
|
||||||
|
},
|
||||||
|
uniqueItems: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Field>
|
||||||
|
</Fieldset>
|
||||||
|
<Accordion title="Advanced">
|
||||||
|
<Fieldset>
|
||||||
<Field name="opts.machine.deploy.targetHost">
|
<Field name="opts.machine.deploy.targetHost">
|
||||||
{(field, props) => (
|
{(field, props) => (
|
||||||
<>
|
<>
|
||||||
@@ -123,9 +162,10 @@ export function CreateMachine() {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</Field>
|
</Field>
|
||||||
</div>
|
</Fieldset>
|
||||||
</div>
|
</Accordion>
|
||||||
<div class="mt-12 flex justify-end">
|
|
||||||
|
<footer class="flex justify-end gap-y-3 border-t border-secondary-200 pt-5">
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
disabled={formStore.submitting}
|
disabled={formStore.submitting}
|
||||||
@@ -141,7 +181,7 @@ export function CreateMachine() {
|
|||||||
<Match when={!formStore.submitting}>Create</Match>
|
<Match when={!formStore.submitting}>Create</Match>
|
||||||
</Switch>
|
</Switch>
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</footer>
|
||||||
</Form>
|
</Form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -82,37 +82,31 @@ export const MachineListView: Component = () => {
|
|||||||
size="s"
|
size="s"
|
||||||
onClick={() => refresh()}
|
onClick={() => refresh()}
|
||||||
startIcon={<Icon icon="Update" />}
|
startIcon={<Icon icon="Update" />}
|
||||||
></Button>
|
/>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<div class="border border-def-3">
|
<div class="button-group">
|
||||||
<span class="" data-tip="List View">
|
|
||||||
<Button
|
|
||||||
onclick={() => setView("list")}
|
|
||||||
variant={view() == "list" ? "dark" : "light"}
|
|
||||||
size="s"
|
|
||||||
startIcon={<Icon icon="List" />}
|
|
||||||
></Button>
|
|
||||||
</span>
|
|
||||||
<span class="" data-tip="Grid View">
|
|
||||||
<Button
|
|
||||||
onclick={() => setView("grid")}
|
|
||||||
variant={view() == "grid" ? "dark" : "light"}
|
|
||||||
size="s"
|
|
||||||
startIcon={<Icon icon="Grid" />}
|
|
||||||
></Button>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<span class="" data-tip="New Machine">
|
|
||||||
<Button
|
<Button
|
||||||
onClick={() => navigate("create")}
|
onclick={() => setView("list")}
|
||||||
|
variant={view() == "list" ? "dark" : "light"}
|
||||||
size="s"
|
size="s"
|
||||||
variant="light"
|
startIcon={<Icon icon="List" />}
|
||||||
startIcon={<Icon icon="Plus" />}
|
/>
|
||||||
>
|
<Button
|
||||||
New Machine
|
onclick={() => setView("grid")}
|
||||||
</Button>
|
variant={view() == "grid" ? "dark" : "light"}
|
||||||
</span>
|
size="s"
|
||||||
|
startIcon={<Icon icon="Grid" />}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Button
|
||||||
|
onClick={() => navigate("create")}
|
||||||
|
size="s"
|
||||||
|
variant="light"
|
||||||
|
startIcon={<Icon size={14} icon="Plus" />}
|
||||||
|
>
|
||||||
|
New Machine
|
||||||
|
</Button>
|
||||||
</>
|
</>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ interface CategoryProps {
|
|||||||
}
|
}
|
||||||
const Categories = (props: CategoryProps) => {
|
const Categories = (props: CategoryProps) => {
|
||||||
return (
|
return (
|
||||||
<span class="ml-6 inline-flex h-full align-middle">
|
<span class="inline-flex h-full align-middle">
|
||||||
{props.categories.map((category) => (
|
{props.categories.map((category) => (
|
||||||
<span class="">{category}</span>
|
<span class="text-sm font-normal">{category}</span>
|
||||||
))}
|
))}
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
@@ -32,10 +32,10 @@ interface RolesProps {
|
|||||||
}
|
}
|
||||||
const Roles = (props: RolesProps) => {
|
const Roles = (props: RolesProps) => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div class="flex flex-wrap items-center gap-2">
|
||||||
<span>
|
<span>
|
||||||
<Typography hierarchy="body" size="xs">
|
<Typography hierarchy="body" size="xs">
|
||||||
Service Typography{" "}
|
Service
|
||||||
</Typography>
|
</Typography>
|
||||||
</span>
|
</span>
|
||||||
{props.roles.map((role) => (
|
{props.roles.map((role) => (
|
||||||
@@ -54,9 +54,14 @@ const ModuleItem = (props: {
|
|||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div class={cx("rounded-lg shadow-md", props.class)}>
|
<div
|
||||||
<div class="text-primary-800">
|
class={cx(
|
||||||
<div class="">
|
"col-span-1 flex flex-col gap-3 border-b border-secondary-200 pb-4",
|
||||||
|
props.class,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{/* <div class="stat-figure text-primary-800">
|
||||||
|
<div class="join">
|
||||||
<Menu popoverid={`menu-${props.name}`} label={<Icon icon={"More"} />}>
|
<Menu popoverid={`menu-${props.name}`} label={<Icon icon={"More"} />}>
|
||||||
<ul class="z-[1] w-52 p-2 shadow">
|
<ul class="z-[1] w-52 p-2 shadow">
|
||||||
<li>
|
<li>
|
||||||
@@ -71,20 +76,26 @@ const ModuleItem = (props: {
|
|||||||
</ul>
|
</ul>
|
||||||
</Menu>
|
</Menu>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div> */}
|
||||||
|
|
||||||
<A href={`/modules/details/${name}`}>
|
<header class="flex flex-col gap-4">
|
||||||
<div class="underline">
|
<A href={`/modules/details/${name}`}>
|
||||||
{name}
|
<div class="">
|
||||||
<Categories categories={info.categories} />
|
<div class="flex flex-col">
|
||||||
|
<Categories categories={info.categories} />
|
||||||
|
<Typography hierarchy="title" size="m" weight="medium">
|
||||||
|
{name}
|
||||||
|
</Typography>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</A>
|
||||||
|
|
||||||
|
<div class="w-full">
|
||||||
|
<Typography hierarchy="body" size="xs">
|
||||||
|
{info.description}
|
||||||
|
</Typography>
|
||||||
</div>
|
</div>
|
||||||
</A>
|
</header>
|
||||||
|
|
||||||
<div class="w-full">
|
|
||||||
<Typography hierarchy="body" size="default">
|
|
||||||
{info.description}
|
|
||||||
</Typography>
|
|
||||||
</div>
|
|
||||||
<Roles roles={info.roles || []} />
|
<Roles roles={info.roles || []} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -113,38 +124,33 @@ export const ModuleList = () => {
|
|||||||
title="Modules"
|
title="Modules"
|
||||||
toolbar={
|
toolbar={
|
||||||
<>
|
<>
|
||||||
<span class="" data-tip="Reload">
|
<Button
|
||||||
<Button
|
variant="light"
|
||||||
variant="light"
|
size="s"
|
||||||
size="s"
|
onClick={() => refresh()}
|
||||||
onClick={() => refresh()}
|
startIcon={<Icon icon="Update" />}
|
||||||
startIcon={<Icon icon="Update" />}
|
/>
|
||||||
></Button>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<div class="border border-def-3">
|
<div class="button-group">
|
||||||
<span class="" data-tip="List View">
|
<Button
|
||||||
<Button
|
onclick={() => setView("list")}
|
||||||
onclick={() => setView("list")}
|
variant={view() == "list" ? "dark" : "light"}
|
||||||
variant={view() == "list" ? "dark" : "light"}
|
size="s"
|
||||||
size="s"
|
startIcon={<Icon icon="List" />}
|
||||||
startIcon={<Icon icon="List" />}
|
/>
|
||||||
></Button>
|
|
||||||
</span>
|
<Button
|
||||||
<span class="" data-tip="Grid View">
|
onclick={() => setView("grid")}
|
||||||
<Button
|
variant={view() == "grid" ? "dark" : "light"}
|
||||||
onclick={() => setView("grid")}
|
size="s"
|
||||||
variant={view() == "grid" ? "dark" : "light"}
|
startIcon={<Icon icon="Grid" />}
|
||||||
size="s"
|
/>
|
||||||
startIcon={<Icon icon="Grid" />}
|
|
||||||
></Button>
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
<span class="" data-tip="New Machine">
|
<span class="" data-tip="New Machine">
|
||||||
<Button
|
<Button
|
||||||
size="s"
|
size="s"
|
||||||
variant="light"
|
variant="light"
|
||||||
startIcon={<Icon icon="CaretUp" />}
|
startIcon={<Icon size={14} icon="CaretUp" />}
|
||||||
>
|
>
|
||||||
Import Module
|
Import Module
|
||||||
</Button>
|
</Button>
|
||||||
@@ -156,10 +162,10 @@ export const ModuleList = () => {
|
|||||||
<Match when={modulesQuery.isFetching}>Loading....</Match>
|
<Match when={modulesQuery.isFetching}>Loading....</Match>
|
||||||
<Match when={modulesQuery.data}>
|
<Match when={modulesQuery.data}>
|
||||||
<div
|
<div
|
||||||
class="my-4 flex flex-wrap gap-6 px-3 py-2"
|
class="grid gap-6 p-6"
|
||||||
classList={{
|
classList={{
|
||||||
"flex-col": view() === "list",
|
"grid-cols-1": view() === "list",
|
||||||
"": view() === "grid",
|
"grid-cols-2": view() === "grid",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<For each={modulesQuery.data}>
|
<For each={modulesQuery.data}>
|
||||||
|
|||||||
6
pkgs/webview-ui/app/stylelint.config.js
Normal file
6
pkgs/webview-ui/app/stylelint.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
extends: ["stylelint-config-standard", "stylelint-config-tailwindcss"],
|
||||||
|
rules: {
|
||||||
|
// You can adjust rules here
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -284,7 +284,7 @@ export default plugin.withOptions(
|
|||||||
"inner-primary":
|
"inner-primary":
|
||||||
"2px 2px 0px 0px var(--clr-bg-inv-acc-3, #415E63) inset",
|
"2px 2px 0px 0px var(--clr-bg-inv-acc-3, #415E63) inset",
|
||||||
"inner-primary-active":
|
"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":
|
"inner-secondary":
|
||||||
"-2px -2px 0px 0px #CEDFE2 inset, 2px 2px 0px 0px white inset",
|
"-2px -2px 0px 0px #CEDFE2 inset, 2px 2px 0px 0px white inset",
|
||||||
"inner-secondary-active":
|
"inner-secondary-active":
|
||||||
|
|||||||
Reference in New Issue
Block a user