Merge pull request 'ui/cubes: scene add tooltip descriptions to toolbar' (#4866) from api-modules-unify into main

Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4866
This commit is contained in:
hsjobeki
2025-08-21 16:25:11 +00:00
9 changed files with 94 additions and 87 deletions

View File

@@ -5,3 +5,14 @@
.horizontal_button { .horizontal_button {
@apply grow max-w-[18rem]; @apply grow max-w-[18rem];
} }
/* Vendored from tooltip */
.tooltipContent {
@apply z-50 px-2 py-0.5 bg-inv-4 rounded-[0.125rem] leading-none;
max-width: min(calc(100vw - 16px), 380px);
&.inverted {
@apply bg-def-2;
}
}

View File

@@ -87,7 +87,7 @@ export const HostFileInput = (props: HostFileInputProps) => {
{value() && ( {value() && (
<Tooltip placement="top"> <Tooltip placement="top">
<Tooltip.Portal> <Tooltip.Portal>
<Tooltip.Content class="tooltip-content"> <Tooltip.Content class={styles.tooltipContent}>
<Typography <Typography
hierarchy="body" hierarchy="body"
size="xs" size="xs"

View File

@@ -55,23 +55,14 @@ export const Label = (props: LabelProps) => {
<Tooltip <Tooltip
placement="top" placement="top"
inverted={props.inverted} inverted={props.inverted}
trigger={ description={props.tooltip}
>
<Icon <Icon
icon="Info" icon="Info"
color="tertiary" color="tertiary"
inverted={props.inverted} inverted={props.inverted}
size={props.size == "default" ? "0.85em" : "0.75rem"} size={props.size == "default" ? "0.85em" : "0.75rem"}
/> />
}
>
<Typography
hierarchy="body"
size="xs"
weight="medium"
inverted={!props.inverted}
>
{props.tooltip}
</Typography>
</Tooltip> </Tooltip>
)} )}
</props.labelComponent> </props.labelComponent>

View File

@@ -2,8 +2,6 @@ import { Meta, StoryObj } from "@kachurun/storybook-solid";
import { Toolbar, ToolbarProps } from "@/src/components/Toolbar/Toolbar"; import { Toolbar, ToolbarProps } from "@/src/components/Toolbar/Toolbar";
import { Divider } from "@/src/components/Divider/Divider"; import { Divider } from "@/src/components/Divider/Divider";
import { ToolbarButton } from "./ToolbarButton"; import { ToolbarButton } from "./ToolbarButton";
import { Tooltip } from "../Tooltip/Tooltip";
import { Typography } from "../Typography/Typography";
const meta: Meta<ToolbarProps> = { const meta: Meta<ToolbarProps> = {
title: "Components/Toolbar", title: "Components/Toolbar",
@@ -18,11 +16,24 @@ export const Default: Story = {
args: { args: {
children: ( children: (
<> <>
<ToolbarButton name="select" icon="Cursor" /> <ToolbarButton
<ToolbarButton name="new-machine" icon="NewMachine" /> name="select"
icon="Cursor"
description="Select my thing"
/>
<ToolbarButton
name="new-machine"
icon="NewMachine"
description="Select this thing"
/>
<Divider orientation="vertical" /> <Divider orientation="vertical" />
<ToolbarButton name="modules" icon="Modules" selected={true} /> <ToolbarButton
<ToolbarButton name="ai" icon="AI" /> name="modules"
icon="Modules"
selected={true}
description="Add service"
/>
<ToolbarButton name="ai" icon="AI" description="Call your AI Manager" />
</> </>
), ),
}, },
@@ -40,49 +51,22 @@ export const WithTooltip: Story = {
args: { args: {
children: ( children: (
<> <>
<Tooltip <ToolbarButton name="select" icon="Cursor" description="Select" />
trigger={<ToolbarButton name="select" icon="Cursor" />}
placement="top" <ToolbarButton
> name="new-machine"
<div class="mb-1 p-1 text-fg-inv-1"> icon="NewMachine"
<Typography hierarchy="label" size="s" color="inherit"> description="Select"
Select an object />
</Typography>
</div> <ToolbarButton
</Tooltip> name="modules"
<Divider orientation="vertical" /> icon="Modules"
<Tooltip selected={true}
trigger={<ToolbarButton name="new-machine" icon="NewMachine" />} description="Select"
placement="top" />
>
<div class="mb-1 p-1 text-fg-inv-1"> <ToolbarButton name="ai" icon="AI" description="Select" />
<Typography hierarchy="label" size="s" color="inherit">
Create a new machine
</Typography>
</div>
</Tooltip>
<Tooltip
trigger={
<ToolbarButton name="modules" icon="Modules" selected={true} />
}
placement="top"
>
<div class="mb-1 p-1 text-fg-inv-1">
<Typography hierarchy="label" size="s" color="inherit">
Manage Services
</Typography>
</div>
</Tooltip>
<Tooltip
trigger={<ToolbarButton name="ai" icon="AI" />}
placement="top"
>
<div class="mb-1 p-1 text-fg-inv-1">
<Typography hierarchy="label" size="s" color="inherit">
Chat with AI
</Typography>
</div>
</Tooltip>
</> </>
), ),
}, },

View File

@@ -3,15 +3,18 @@ import cx from "classnames";
import { Button } from "@kobalte/core/button"; import { Button } from "@kobalte/core/button";
import Icon, { IconVariant } from "@/src/components/Icon/Icon"; import Icon, { IconVariant } from "@/src/components/Icon/Icon";
import type { JSX } from "solid-js"; import type { JSX } from "solid-js";
import { Tooltip } from "../Tooltip/Tooltip";
export interface ToolbarButtonProps export interface ToolbarButtonProps
extends JSX.ButtonHTMLAttributes<HTMLButtonElement> { extends JSX.ButtonHTMLAttributes<HTMLButtonElement> {
icon: IconVariant; icon: IconVariant;
description: JSX.Element;
selected?: boolean; selected?: boolean;
} }
export const ToolbarButton = (props: ToolbarButtonProps) => { export const ToolbarButton = (props: ToolbarButtonProps) => {
return ( return (
<Tooltip description={props.description} gutter={10} placement="top">
<Button <Button
class={cx(styles.toolbar_button, { class={cx(styles.toolbar_button, {
[styles["selected"]]: props.selected, [styles["selected"]]: props.selected,
@@ -20,5 +23,6 @@ export const ToolbarButton = (props: ToolbarButtonProps) => {
> >
<Icon icon={props.icon} inverted={!props.selected} /> <Icon icon={props.icon} inverted={!props.selected} />
</Button> </Button>
</Tooltip>
); );
}; };

View File

@@ -1,4 +1,4 @@
div.tooltip-content { .tooltipContent {
@apply z-50 px-2 py-0.5 bg-inv-4 rounded-[0.125rem] leading-none; @apply z-50 px-2 py-0.5 bg-inv-4 rounded-[0.125rem] leading-none;
max-width: min(calc(100vw - 16px), 380px); max-width: min(calc(100vw - 16px), 380px);

View File

@@ -1,31 +1,40 @@
import "./Tooltip.css";
import { import {
Tooltip as KTooltip, Tooltip as KTooltip,
TooltipRootProps as KTooltipRootProps, TooltipRootProps as KTooltipRootProps,
} from "@kobalte/core/tooltip"; } from "@kobalte/core/tooltip";
import cx from "classnames"; import cx from "classnames";
import { JSX } from "solid-js"; import { JSX } from "solid-js";
import styles from "./Tooltip.module.css";
import { Typography } from "../Typography/Typography";
export interface TooltipProps extends KTooltipRootProps { export interface TooltipProps extends KTooltipRootProps {
inverted?: boolean; inverted?: boolean;
trigger: JSX.Element;
children: JSX.Element; children: JSX.Element;
description: JSX.Element;
animation?: "bounce"; animation?: "bounce";
} }
export const Tooltip = (props: TooltipProps) => { export const Tooltip = (props: TooltipProps) => {
return ( return (
<KTooltip {...props}> <KTooltip {...props}>
<KTooltip.Trigger>{props.trigger}</KTooltip.Trigger> <KTooltip.Trigger>{props.children}</KTooltip.Trigger>
<KTooltip.Portal> <KTooltip.Portal>
<KTooltip.Content <KTooltip.Content
class={cx("tooltip-content", { class={cx(styles.tooltipContent, {
inverted: props.inverted, [styles.inverted]: props.inverted,
"animate-bounce": props.animation == "bounce", "animate-bounce": props.animation == "bounce",
})} })}
> >
{props.placement == "bottom" && <KTooltip.Arrow />} {props.placement == "bottom" && <KTooltip.Arrow />}
{props.children} <Typography
hierarchy="body"
size="s"
weight="medium"
color="primary"
inverted={!props.inverted}
>
{props.description}
</Typography>
{props.placement == "top" && <KTooltip.Arrow />} {props.placement == "top" && <KTooltip.Arrow />}
</KTooltip.Content> </KTooltip.Content>
</KTooltip.Portal> </KTooltip.Portal>

View File

@@ -1,14 +1,15 @@
import { Tooltip } from "@/src/components/Tooltip/Tooltip"; import { Tooltip } from "@/src/components/Tooltip/Tooltip";
import { Typography } from "@/src/components/Typography/Typography";
import "./Creating.css"; import "./Creating.css";
export const Creating = () => ( export const Creating = () => (
<div class="creating"> <div class="creating">
<Tooltip open={true} placement="top" trigger={<div />}> <Tooltip
<Typography hierarchy="body" size="xs" weight="medium" inverted={true}> open={true}
Your Clan is being created placement="top"
</Typography> description={"Your Clan is being created"}
>
<div></div>
</Tooltip> </Tooltip>
<div class="scene"> <div class="scene">

View File

@@ -530,12 +530,14 @@ export function CubeScene(props: {
<div class="toolbar-container"> <div class="toolbar-container">
<Toolbar> <Toolbar>
<ToolbarButton <ToolbarButton
description="Select machine"
name="Select" name="Select"
icon="Cursor" icon="Cursor"
onClick={() => setWorldMode("view")} onClick={() => setWorldMode("view")}
selected={worldMode() === "view"} selected={worldMode() === "view"}
/> />
<ToolbarButton <ToolbarButton
description="Create new machine"
name="new-machine" name="new-machine"
icon="NewMachine" icon="NewMachine"
disabled={positionMode() === "circle"} disabled={positionMode() === "circle"}
@@ -544,6 +546,7 @@ export function CubeScene(props: {
/> />
<Divider orientation="vertical" /> <Divider orientation="vertical" />
<ToolbarButton <ToolbarButton
description="Add new Service"
name="modules" name="modules"
icon="Modules" icon="Modules"
onClick={() => { onClick={() => {
@@ -558,7 +561,11 @@ export function CubeScene(props: {
renderLoop.requestRender(); renderLoop.requestRender();
}} }}
/> />
<ToolbarButton name="delete" icon="Trash" /> {/* <ToolbarButton
description="Delete Machine"
name="delete"
icon="Trash"
/> */}
</Toolbar> </Toolbar>
</div> </div>
</> </>