diff --git a/src/ui/components/native/WindowFrame.tsx b/src/ui/components/native/WindowFrame.tsx index 93f67f01..7b307ac2 100644 --- a/src/ui/components/native/WindowFrame.tsx +++ b/src/ui/components/native/WindowFrame.tsx @@ -35,9 +35,15 @@ function WindowFrame() { }); return ( -
- minimize()} /> - setModalVisible(true)} danger /> +
+
+ {/* Empty */} +
+ +
+ minimize()} /> + setModalVisible(true)} danger /> +
; +} & Popup.PopupProps; + +function ContextMenu(props: ContextMenuProps) { + const [pos, setPos] = createSignal({ x: 0, y: 0 }); + const [ref, setRef] = createSignal(); + + createEffect(() => { + if (ref() === undefined) + return; + + const rect = ref()!.getBoundingClientRect(); + + let x = props.pos().x; + let y = props.pos().y; + + if (x + rect.width > window.innerWidth) + x = window.innerWidth - rect.width - 10; + + if (y + rect.height > window.innerHeight) + y = window.innerHeight - rect.height - 10; + + setPos({ x, y }); + }); + + return ( + +
+
+ {props.children} +
+
+
+ ); +} + +ContextMenu.Seperator = function () { + return
; +}; + +interface ContextMenuRowProps { + icon: JSX.Element; + text: string; + onClick?: (e: MouseEvent) => any; +} + +ContextMenu.Row = function (props: ContextMenuRowProps) { + return ( +
props.onClick?.(e)} + class="flex items-center gap-x-2 m-px px-1.5 py-0.5 rounded-mdlg hover:bg-gray-0.05 active:bg-gray-0.10 [&>svg]:w-[18px]" + > + {props.icon} + {props.text} +
+ ); +}; + +export default ContextMenu; diff --git a/src/ui/components/overlay/Popup.tsx b/src/ui/components/overlay/Popup.tsx index dd99191a..83fef3bb 100644 --- a/src/ui/components/overlay/Popup.tsx +++ b/src/ui/components/overlay/Popup.tsx @@ -1,13 +1,12 @@ -import type { - Accessor, - ParentProps, - Setter, -} from 'solid-js'; import { Show, createEffect, - createSignal, -} from 'solid-js'; + createSignal } from 'solid-js'; +import type { + Accessor, + JSX, + ParentProps, + Setter } from 'solid-js'; import { Portal } from 'solid-js/web'; // eslint-disable-next-line ts/no-namespace @@ -16,6 +15,7 @@ declare namespace Popup { visible: Accessor; setVisible: Setter; class?: string; + style?: JSX.CSSProperties | string; mount?: Node; } } @@ -54,7 +54,7 @@ function Popup(props: Popup.PopupProps) { return ( -
+
{props.children}
diff --git a/src/ui/pages/Home.tsx b/src/ui/pages/Home.tsx index 6c145108..be896151 100644 --- a/src/ui/pages/Home.tsx +++ b/src/ui/pages/Home.tsx @@ -2,11 +2,13 @@ import { CheckIcon, DotsVerticalIcon, Download01Icon, + EyeIcon, PlayIcon, PlusIcon, SearchMdIcon, } from '@untitled-theme/icons-solid'; -import { For, createSignal } from 'solid-js'; +import type { Accessor, Setter } from 'solid-js'; +import { For, createSignal, untrack } from 'solid-js'; import { DragDropProvider, DragDropSensors, SortableProvider, closestCenter, createSortable } from '@thisbeyond/solid-dnd'; import type { DragEventHandler, Id } from '@thisbeyond/solid-dnd'; import { useNavigate } from '@solidjs/router'; @@ -17,6 +19,7 @@ import Tag from '../components/base/Tag'; import TextField from '../components/base/TextField'; import defaultCover from '../../assets/images/default_instance_cover.jpg'; import Popup from '../components/overlay/Popup'; +import ContextMenu from '../components/overlay/ContextMenu'; // TODO: Replace this into it's own component function OneConfigLogo() { @@ -81,6 +84,40 @@ declare module 'solid-js' { } } +interface InstanceCardContextMenuProps { + pos: Accessor<{ x: number; y: number }>; + contextMenuVisible: Accessor; + setContextMenuVisible: Setter; + id: string; +} + +function InstanceCardContextMenu(props: InstanceCardContextMenuProps) { + const navigate = useNavigate(); + + return ( + + } + text="View" + onClick={() => { + navigate(`/instances/?id=${props.id}`); + }} + /> + + + + } + text="Launch" + /> + + ); +} + function InstanceCard(props: InstanceCardProps) { const navigate = useNavigate(); const [pos, setPos] = createSignal({ x: 0, y: 0 }); @@ -89,7 +126,6 @@ function InstanceCard(props: InstanceCardProps) { const id = () => props.elementId as Id; let ref!: HTMLDivElement; - // eslint-disable-next-line solid/reactivity const sortable = createSortable(id()); function didDrag() { @@ -131,51 +167,50 @@ function InstanceCard(props: InstanceCardProps) { } return ( -
openInstancePage(e)} - onMouseDown={e => onMouseDown(e)} - onMouseUp={e => onMouseUp(e)} - onContextMenu={e => openContextMenu(e)} - ref={ref} - class="relative h-[152px] group flex flex-col rounded-xl bg-component-bg hover:bg-component-bg-hover active:bg-component-bg-pressed border border-gray-0.05" - > -
-
- -
-
-
-
-

{props.name}

-

- {props.clientType} - {' '} - {props.version} - {' '} - {props.mods && `• ${props.mods} mods`} -

-
- -
- - -
-
-

hello world

- + <> +
openInstancePage(e)} + onMouseDown={e => onMouseDown(e)} + onMouseUp={e => onMouseUp(e)} + onContextMenu={e => openContextMenu(e)} + ref={ref} + class="relative h-[152px] group flex flex-col rounded-xl bg-component-bg hover:bg-component-bg-hover active:bg-component-bg-pressed border border-gray-0.05" + > +
+
+
- -
+
+
+

{props.name}

+

+ {props.clientType} + {' '} + {props.version} + {' '} + {props.mods && `• ${props.mods} mods`} +

+
+ +
+
+ + ); } diff --git a/tailwind.config.ts b/tailwind.config.ts index d09ee747..0291d530 100644 --- a/tailwind.config.ts +++ b/tailwind.config.ts @@ -88,6 +88,10 @@ const config: Config = { transparent: 'transparent', }, + borderRadius: { + mdlg: '0.438rem', + }, + animation: { 'fade-in': 'fadeIn 150ms easeOutExpo forwards', 'fade-out': 'fadeOut 150ms easeOutExpo forwards',