mirror of
https://github.com/khairul169/vaulterm.git
synced 2025-04-28 16:49:39 +07:00
feat: update host selection ux
This commit is contained in:
parent
b0932c39b1
commit
4f9578ffce
49
frontend/pages/hosts/components/host-actions.tsx
Normal file
49
frontend/pages/hosts/components/host-actions.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import React from "react";
|
||||
import MenuButton from "@/components/ui/menu-button";
|
||||
import { Button, GetProps } from "tamagui";
|
||||
import Icons from "@/components/ui/icons";
|
||||
|
||||
type Props = GetProps<typeof Button> & {
|
||||
onSelect?: (() => void) | null;
|
||||
onEdit?: (() => void) | null;
|
||||
};
|
||||
|
||||
const HostActions = ({ onSelect, onEdit, ...props }: Props) => {
|
||||
if (!onSelect && !onEdit) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<MenuButton
|
||||
placement="bottom-end"
|
||||
trigger={
|
||||
<Button
|
||||
circular
|
||||
bg="$colorTransparent"
|
||||
icon={<Icons name="dots-vertical" size={20} />}
|
||||
{...props}
|
||||
/>
|
||||
}
|
||||
>
|
||||
{onSelect != null && (
|
||||
<MenuButton.Item
|
||||
onPress={onSelect}
|
||||
icon={<Icons name="cursor-pointer" size={16} />}
|
||||
>
|
||||
Select
|
||||
</MenuButton.Item>
|
||||
)}
|
||||
|
||||
{onEdit != null && (
|
||||
<MenuButton.Item
|
||||
onPress={onEdit}
|
||||
icon={<Icons name="pencil" size={16} />}
|
||||
>
|
||||
Edit
|
||||
</MenuButton.Item>
|
||||
)}
|
||||
</MenuButton>
|
||||
);
|
||||
};
|
||||
|
||||
export default HostActions;
|
@ -10,16 +10,9 @@ type HostItemProps = {
|
||||
selected?: boolean;
|
||||
onMultiTap: () => void;
|
||||
onTap?: () => void;
|
||||
onEdit?: (() => void) | null;
|
||||
};
|
||||
|
||||
const HostItem = ({
|
||||
host,
|
||||
selected,
|
||||
onMultiTap,
|
||||
onTap,
|
||||
onEdit,
|
||||
}: HostItemProps) => {
|
||||
const HostItem = ({ host, selected, onMultiTap, onTap }: HostItemProps) => {
|
||||
return (
|
||||
<MultiTapPressable
|
||||
cursor="pointer"
|
||||
@ -64,23 +57,6 @@ const HostItem = ({
|
||||
{host.host}
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
{onEdit != null && (
|
||||
<Button
|
||||
circular
|
||||
opacity={0}
|
||||
$sm={{ opacity: 1 }}
|
||||
$group-hover={{ opacity: 1 }}
|
||||
animation="quick"
|
||||
animateOnly={["opacity"]}
|
||||
onPress={(e) => {
|
||||
e.stopPropagation();
|
||||
onEdit();
|
||||
}}
|
||||
>
|
||||
<Icons name="pencil" size={16} />
|
||||
</Button>
|
||||
)}
|
||||
</XStack>
|
||||
</Card>
|
||||
</MultiTapPressable>
|
||||
|
@ -7,6 +7,7 @@ import { hostFormModal } from "./form";
|
||||
import { GridLayout } from "@/components/ui/grid-view";
|
||||
import HostItem from "./host-item";
|
||||
import { useHosts } from "../hooks/query";
|
||||
import HostActions from "./host-actions";
|
||||
|
||||
type HostsListProps = {
|
||||
allowEdit?: boolean;
|
||||
@ -115,7 +116,7 @@ const HostList = ({
|
||||
<ItemList
|
||||
data={groups}
|
||||
selected={selected}
|
||||
onTap={onSelectedChange ? onSelect : undefined}
|
||||
onTap={selected.length > 0 ? onSelect : undefined}
|
||||
onMultiTap={(group) => onParentIdChange?.(group.id)}
|
||||
onEdit={allowEdit ? onEdit : undefined}
|
||||
/>
|
||||
@ -132,9 +133,10 @@ const HostList = ({
|
||||
<ItemList
|
||||
data={hosts}
|
||||
selected={selected}
|
||||
onTap={onSelectedChange ? onSelect : undefined}
|
||||
onTap={selected.length > 0 ? onSelect : undefined}
|
||||
onMultiTap={onOpenTerminal}
|
||||
onEdit={allowEdit ? onEdit : undefined}
|
||||
onSelect={onSelectedChange ? onSelect : undefined}
|
||||
/>
|
||||
</ScrollView>
|
||||
)}
|
||||
@ -148,6 +150,7 @@ type ItemListProps = {
|
||||
onTap?: (host: any) => void;
|
||||
onMultiTap?: (host: any) => void;
|
||||
onEdit?: (host: any) => void;
|
||||
onSelect?: (host: any) => void;
|
||||
};
|
||||
|
||||
const ItemList = ({
|
||||
@ -156,6 +159,7 @@ const ItemList = ({
|
||||
onTap,
|
||||
onMultiTap,
|
||||
onEdit,
|
||||
onSelect,
|
||||
}: ItemListProps) => (
|
||||
<GridLayout
|
||||
data={data}
|
||||
@ -163,13 +167,21 @@ const ItemList = ({
|
||||
padding="$2"
|
||||
gap="$2.5"
|
||||
renderItem={(host: any) => (
|
||||
<HostItem
|
||||
host={host}
|
||||
selected={selected?.includes(host.id)}
|
||||
onTap={onEdit ? () => onTap?.(host) : undefined}
|
||||
onMultiTap={() => onMultiTap?.(host)}
|
||||
onEdit={onEdit ? () => onEdit?.(host) : undefined}
|
||||
/>
|
||||
<View position="relative" h="100%">
|
||||
<HostItem
|
||||
host={host}
|
||||
selected={selected?.includes(host.id)}
|
||||
onTap={() => onTap?.(host)}
|
||||
onMultiTap={() => onMultiTap?.(host)}
|
||||
/>
|
||||
<HostActions
|
||||
position="absolute"
|
||||
top="$2"
|
||||
right="$2"
|
||||
onSelect={onSelect ? () => onSelect?.(host) : undefined}
|
||||
onEdit={onEdit ? () => onEdit?.(host) : undefined}
|
||||
/>
|
||||
</View>
|
||||
)}
|
||||
/>
|
||||
);
|
||||
|
Loading…
x
Reference in New Issue
Block a user