diff --git a/pkgs/webview-ui/app/src/components/MachineListItem.tsx b/pkgs/webview-ui/app/src/components/MachineListItem.tsx index b00fe7923..ba8f31e8a 100644 --- a/pkgs/webview-ui/app/src/components/MachineListItem.tsx +++ b/pkgs/webview-ui/app/src/components/MachineListItem.tsx @@ -4,6 +4,7 @@ import { Menu } from "./Menu"; import { activeURI } from "../App"; import toast from "solid-toast"; import { A, useNavigate } from "@solidjs/router"; +import { RndThumbnail } from "./noiseThumbnail"; type MachineDetails = SuccessQuery<"list_inventory_machines">["data"][string]; @@ -104,15 +105,8 @@ export const MachineListItem = (props: MachineListItemProps) => { return (
  • -
    - - devices_other - +
    +
    diff --git a/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-flyout.css b/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-flyout.css index 5090c238d..56401367e 100644 --- a/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-flyout.css +++ b/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-flyout.css @@ -14,7 +14,8 @@ height: inherit; padding: theme(padding.12) theme(padding.3) theme(padding.3); - background-color: rgba(var(--clr-bg-inv-4) / 0.95); - border: 1px solid rgb(var(--clr-border-inv-4)); + background-color: var(--clr-bg-inv-4); + /* / 0.95); */ + border: 1px solid var(--clr-border-inv-4); border-radius: theme(borderRadius.lg); } diff --git a/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-header.css b/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-header.css index 39efedf1c..80d6d5bf9 100644 --- a/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-header.css +++ b/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-header.css @@ -11,7 +11,7 @@ width: 100%; height: 100%; - background: rgb(var(--clr-bg-inv-3)); + background: var(--clr-bg-inv-3); border-bottom: 1px solid var(--clr-border-inv-3); border-top-left-radius: theme(borderRadius.xl); diff --git a/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-list-item.css b/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-list-item.css index c883518fc..dfa21e989 100644 --- a/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-list-item.css +++ b/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-list-item.css @@ -17,7 +17,7 @@ } &:hover:after { - background: rgb(var(--clr-bg-inv-acc-2)); + background: var(--clr-bg-inv-acc-2); transform: scale(theme(scale.100)); transition: transform 0.24s ease-in-out; } @@ -28,7 +28,7 @@ } &:active:after { - background: rgb(var(--clr-bg-inv-acc-3)); + background: var(--clr-bg-inv-acc-3); transform: scale(theme(scale.100)); } } diff --git a/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-profile.css b/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-profile.css index 05169862f..2ddfc79b3 100644 --- a/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-profile.css +++ b/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar-profile.css @@ -6,14 +6,14 @@ width: theme(width.8); height: theme(height.8); - background: rgb(var(--clr-bg-inv-4)); + background: var(--clr-bg-inv-4); border-radius: 50%; } .sidebar__profile--flyout { - background: rgb(var(--clr-bg-def-2)); + background: var(--clr-bg-def-2); } .sidebar__profile--flyout > .sidebar__profile__character { - color: rgb(var(--clr-fg-def-1)) !important; + color: var(--clr-fg-def-1) !important; } diff --git a/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar.css b/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar.css index 649ca70df..73b7b647b 100644 --- a/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar.css +++ b/pkgs/webview-ui/app/src/components/Sidebar/css/sidebar.css @@ -10,8 +10,8 @@ .sidebar { min-width: theme(width.72); height: 100%; - background-color: rgb(var(--clr-bg-inv-2)); - border: 1px solid rgb(var(--clr-border-inv-2)); + background-color: var(--clr-bg-inv-2); + border: 1px solid var(--clr-border-inv-2); border-radius: theme(borderRadius.xl); } @@ -24,6 +24,7 @@ .sidebar__section { padding: theme(padding.2); - background-color: rgba(var(--clr-bg-inv-3) / 0.9); + /* background-color: rgba(var(--clr-bg-inv-3) / 0.9); */ + @apply bg-primary-800/90; border-radius: theme(borderRadius.md); } diff --git a/pkgs/webview-ui/app/src/components/Typography/css/typography-color.css b/pkgs/webview-ui/app/src/components/Typography/css/typography-color.css index 6f0952945..0a8d29913 100644 --- a/pkgs/webview-ui/app/src/components/Typography/css/typography-color.css +++ b/pkgs/webview-ui/app/src/components/Typography/css/typography-color.css @@ -1,23 +1,23 @@ .fnt-clr-primary { - color: (rgb(--clr-fg-def-1)); + color: var(--clr-fg-def-1); } .fnt-clr-secondary { - color: rgb(var(--clr-fg-def-2)); + color: var(--clr-fg-def-2); } .fnt-clr-tertiary { - color: rgb(var(--clr-fg-def-3)); + color: var(--clr-fg-def-3); } .fnt-clr-primary.fnt-clr--inverted { - color: rgb(var(--clr-fg-inv-1)); + color: var(--clr-fg-inv-1); } .fnt-clr-secondary.fnt-clr--inverted { - color: rgb(var(--clr-fg-inv-2)); + color: var(--clr-fg-inv-2); } .fnt-clr-tertiary.fnt-clr--inverted { - color: rgb(var(--clr-fg-inv-3)); + color: var(--clr-fg-inv-3); } diff --git a/pkgs/webview-ui/app/src/components/button/button.examples.tsx b/pkgs/webview-ui/app/src/components/button/button.examples.tsx new file mode 100644 index 000000000..ece9bd422 --- /dev/null +++ b/pkgs/webview-ui/app/src/components/button/button.examples.tsx @@ -0,0 +1,27 @@ +import { Button } from "."; +import FlashIcon from "@/icons/flash.svg"; + +export const Test = () => { +
    + + + + + +
    ; +}; diff --git a/pkgs/webview-ui/app/src/components/button/index.tsx b/pkgs/webview-ui/app/src/components/button/index.tsx new file mode 100644 index 000000000..9d179f11a --- /dev/null +++ b/pkgs/webview-ui/app/src/components/button/index.tsx @@ -0,0 +1,73 @@ +import { type JSX } from "solid-js"; +import cx from "classnames"; + +type Variants = "dark" | "light"; +type Size = "default" | "s"; + +const variantColors: Record = { + dark: cx( + "border-secondary-950 bg-primary-900 text-white", + "shadow-inner-primary", + // Hover state + // Focus state + // Active state + "hover:border-secondary-900 hover:bg-secondary-700", + "focus:border-secondary-900", + "active:border-secondary-900 active:shadow-inner-primary-active", + // Disabled + "disabled:bg-secondary-200 disabled:text-secondary-700 disabled:border-secondary-300", + ), + light: cx( + "border-secondary-800 bg-secondary-100 text-secondary-800", + "shadow-inner-secondary", + // Hover state + // Focus state + // Active state + "hover:bg-secondary-200 hover:text-secondary-900", + "focus:bg-secondary-200 focus:text-secondary-900", + "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 = { + default: cx("rounded-[0.1875rem] px-4 py-2"), + s: cx("rounded-sm py-[0.375rem] px-3"), +}; + +interface ButtonProps extends JSX.ButtonHTMLAttributes { + variant?: Variants; + size?: Size; + children: JSX.Element; + startIcon?: JSX.Element; + endIcon?: JSX.Element; +} +export const Button = (props: ButtonProps) => { + const { + children, + variant = "dark", + size = "default", + startIcon, + endIcon, + ...buttonProps + } = props; + return ( + + ); +}; diff --git a/pkgs/webview-ui/app/src/components/noiseThumbnail/index.tsx b/pkgs/webview-ui/app/src/components/noiseThumbnail/index.tsx new file mode 100644 index 000000000..77c1c4a1c --- /dev/null +++ b/pkgs/webview-ui/app/src/components/noiseThumbnail/index.tsx @@ -0,0 +1,120 @@ +import { For } from "solid-js"; + +function mulberry32(seed: number) { + return function () { + let t = (seed += 0x6d2b79f5); + t = Math.imul(t ^ (t >>> 15), 1 | t); + t ^= t + Math.imul(t ^ (t >>> 7), 61 | t); + return ((t ^ (t >>> 14)) >>> 0) / 4294967296; + }; +} + +function calculateCellColor( + x: number, + y: number, + grid: number[][], + rand: () => number, +) { + const rows = grid.length; + const cols = grid[0].length; + + // Get the values of neighboring cells + const neighbors = [ + grid[y][(x - 1 + cols) % cols], // Left + grid[y][(x + 1) % cols], // Right + grid[(y - 1 + rows) % rows][x], // Top + grid[(y + 1) % rows][x], // Bottom + ]; + + const makeValue = (threshold: number, wanted: number) => + rand() > threshold ? Math.floor(rand() * 50) : wanted; + + // Calculate the sum of neighbors + const neighborSum = neighbors.reduce((sum, val) => sum + val, 0); + // Introduce a hard cutoff for fewer intermediate values + if (neighborSum < 1) { + // Mostly dark squares + // return Math.floor(rand() * 50); // Darker square + return makeValue(0.9, Math.floor(rand() * 50)); + } else if (neighborSum >= 3) { + // Mostly bright squares + // return Math.floor(200 + rand() * 55); // Bright square + return makeValue(0.9, Math.floor(200 + rand() * 55)); + } else { + // Rare intermediate values + return makeValue(0.4, Math.floor(100 + rand() * 50)); + } +} + +function generatePatternedImage(seed: number, width = 300, height = 150) { + const rand = mulberry32(seed); + const rowSize = 1 + Math.floor((rand() * width) / 10); + const colSize = 1 + Math.floor((rand() * height) / 10); + const cols = Math.floor(width / colSize); + const rows = Math.floor(height / rowSize); + + // Initialize a 2D grid with random values (0 or 1) + const grid = Array.from({ length: rows }, () => + Array.from({ length: cols }, () => (rand() > 0.5 ? 1 : 0)), + ); + + const canvas = document.createElement("canvas"); + canvas.width = width; + canvas.height = height; + const ctx = canvas.getContext("2d"); + + if (!ctx) { + throw new Error("Could not get 2d context"); + } + + const centerX = width / 2; + const centerY = height / 2; + const totalCells = rows * cols; + for (let i = 0; i < totalCells; i++) { + // Calculate polar coordinates + const angle = (i / totalCells) * Math.PI * 2 * rand() * 360; // Increase the spiral's density + const radius = Math.sqrt(i) * rand() * 4; // Controls how tightly the spiral is packed + + // Convert polar to Cartesian coordinates + const x = Math.floor(centerX + radius * Math.cos(angle)); + const y = Math.floor(centerY + radius * Math.sin(angle)); + + // Find grid coordinates + const col = Math.floor(x / colSize); + const row = Math.floor(y / rowSize); + + // Ensure the cell is within bounds + if (col >= 0 && col < cols && row >= 0 && row < rows) { + const colorValue = calculateCellColor(col, row, grid, rand); + ctx.fillStyle = `rgb(${colorValue}, ${colorValue}, ${colorValue})`; + ctx.fillRect(x, y, colSize, rowSize); + } + } + + return canvas.toDataURL(); +} + +interface RndThumbnailProps { + name: string; + width?: number; + height?: number; +} +export const RndThumbnail = (props: RndThumbnailProps) => { + const { name } = props; + const seed = Array.from(name).reduce( + (acc, char) => acc + char.charCodeAt(0), + 0, + ); // Seed from name + const imageSrc = generatePatternedImage(seed, props.width, props.height); + return {name}; +}; + +export const RndThumbnailShow = () => { + const names = ["hsjobeki", "mic92", "lassulus", "D", "A", "D", "B", "C"]; + + return ( +
    + {(name) => } +
    + ); +}; diff --git a/pkgs/webview-ui/app/src/layout/layout.tsx b/pkgs/webview-ui/app/src/layout/layout.tsx index 8fee28058..0e6916c1e 100644 --- a/pkgs/webview-ui/app/src/layout/layout.tsx +++ b/pkgs/webview-ui/app/src/layout/layout.tsx @@ -18,7 +18,7 @@ export const Layout: Component = (props) => { }); return ( -
    +
    parseColor(value).color.join(" "); +const toRGB = (value: string) => + "rgb(" + parseColor(value).color.join(" ") + ")"; export default plugin.withOptions( (_options = {}) => - () => { + ({ addUtilities, theme }) => { + addUtilities({ + // Background colors + ".bg-def-1": { + backgroundColor: theme("colors.white"), + }, + ".bg-def-2": { + backgroundColor: theme("colors.secondary.50"), + }, + ".bg-def-3": { + backgroundColor: theme("colors.secondary.100"), + }, + ".bg-def-4": { + backgroundColor: theme("colors.secondary.200"), + }, + ".bg-def-5": { + backgroundColor: theme("colors.secondary.300"), + }, + // bg inverse + ".bg-inv-1": { + backgroundColor: theme("colors.primary.600"), + }, + ".bg-inv-2": { + backgroundColor: theme("colors.primary.700"), + }, + ".bg-inv-3": { + backgroundColor: theme("colors.primary.800"), + }, + ".bg-inv-4": { + backgroundColor: theme("colors.primary.900"), + }, + ".bg-inv-5": { + backgroundColor: theme("colors.primary.950"), + }, + // bg inverse accent + ".bg-inv-acc-1": { + backgroundColor: theme("colors.secondary.500"), + }, + ".bg-inv-acc-2": { + backgroundColor: theme("colors.secondary.600"), + }, + ".bg-inv-acc-3": { + backgroundColor: theme("colors.secondary.700"), + }, + + // Text colors + ".fg-def-1": { + color: theme("colors.secondary.950"), + }, + ".fg-def-2": { + color: theme("colors.secondary.900"), + }, + ".fg-def-3": { + color: theme("colors.secondary.700"), + }, + ".fg-def-4": { + color: theme("colors.secondary.500"), + }, + // fg inverse + ".fg-inv-1": { + color: theme("colors.white"), + }, + ".fg-inv-2": { + color: theme("colors.secondary.100"), + }, + ".fg-inv-3": { + color: theme("colors.secondary.300"), + }, + ".fg-inv-4": { + color: theme("colors.secondary.400"), + }, + + // Border colors + ".border-def-1": { + borderColor: theme("colors.secondary.50"), + }, + ".border-def-2": { + borderColor: theme("colors.secondary.100"), + }, + ".border-def-3": { + borderColor: theme("colors.secondary.200"), + }, + ".border-def-4": { + borderColor: theme("colors.secondary.300"), + }, + ".border-def-5": { + borderColor: theme("colors.secondary.400"), + }, + // border inverse + ".border-inv-1": { + borderColor: theme("colors.secondary.800"), + }, + ".border-inv-2": { + borderColor: theme("colors.secondary.900"), + }, + ".border-inv-3": { + borderColor: theme("colors.secondary.900"), + }, + ".border-inv-4": { + borderColor: theme("colors.secondary.950"), + }, + ".border-inv-5": { + borderColor: theme("colors.black"), + }, + + // Example: dark mode utilities (all elements within ) + // ".dark .bg-def-1": { + // backgroundColor: theme("colors.black"), + // }, + // ".dark .bg-def-2": { + // backgroundColor: theme("colors.primary.900"), + // }, + // ".dark .bg-def-3": { + // backgroundColor: theme("colors.primary.800"), + // }, + // ".dark .bg-def-4": { + // backgroundColor: theme("colors.primary.700"), + // }, + // ".dark .bg-def-5": { + // backgroundColor: theme("colors.primary.600"), + // }, + }); // add more base styles }, // add configuration which is merged with the final config @@ -71,6 +193,16 @@ export default plugin.withOptions( 950: toRGB("#461129"), }, }, + boxShadow: { + "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", + "inner-secondary": + "-2px -2px 0px 0px #CEDFE2 inset, 2px 2px 0px 0px white inset", + "inner-secondary-active": + "0px 0px 0px 1px white, 0px 0px 0px 2px var(--clr-bg-inv-acc-4, #203637), 2px 2px 0px 0px var(--clr-bg-inv-acc-2, #4F747A) inset", + }, }, ...typography, },