feat: tooltips for tool settings (#5586)

This commit is contained in:
Pedro Köhler 2025-11-25 11:13:01 -03:00 committed by GitHub
parent e0d74a6674
commit 411553ee91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 130 additions and 42 deletions

View File

@ -36,6 +36,7 @@ export type ButtonOptions = {
id: string;
type: 'range' | 'radio' | 'double-range' | 'custom' | 'checkbox' | 'select' | 'button';
name?: string;
tooltip?: string;
min?: number;
max?: number;
step?: number;

View File

@ -1,6 +1,7 @@
import React from 'react';
import Numeric from '../Numeric';
import { cn } from '../../lib/utils';
import { Tooltip, TooltipContent, TooltipTrigger } from '../Tooltip';
interface RowDoubleRangeProps {
values: [number, number];
@ -10,6 +11,7 @@ interface RowDoubleRangeProps {
step: number;
showLabel?: boolean;
label?: string;
tooltip?: string;
className?: string;
}
@ -21,8 +23,28 @@ const RowDoubleRange: React.FC<RowDoubleRangeProps> = ({
step,
showLabel = false,
label = '',
tooltip,
className,
}) => {
const renderLabel = () => {
if (!showLabel || !label) {
return null;
}
const labelNode = <Numeric.Label showValue>{label}</Numeric.Label>;
if (!tooltip) {
return labelNode;
}
return (
<Tooltip>
<TooltipTrigger asChild>{labelNode}</TooltipTrigger>
<TooltipContent side="top">{tooltip}</TooltipContent>
</Tooltip>
);
};
return (
<Numeric.Container
mode="doubleRange"
@ -33,7 +55,7 @@ const RowDoubleRange: React.FC<RowDoubleRangeProps> = ({
step={step}
className={cn('flex flex-col space-y-2', className)}
>
{showLabel && <Numeric.Label showValue>{label}</Numeric.Label>}
{renderLabel()}
<Numeric.DoubleRange showNumberInputs />
</Numeric.Container>
);

View File

@ -2,6 +2,7 @@ import React from 'react';
import { Label } from '../Label';
import { Tabs, TabsList, TabsTrigger } from '../Tabs';
import { cn } from '../../lib/utils';
import { Tooltip, TooltipContent, TooltipTrigger } from '../Tooltip';
interface RadioValue {
value: string;
@ -14,6 +15,7 @@ interface RadioOption {
value: string;
values: RadioValue[];
onChange?: (val: string) => void;
tooltip?: string;
}
interface RowSegmentedControlProps {
@ -38,7 +40,18 @@ export const RowSegmentedControl: React.FC<RowSegmentedControlProps> = ({
className={cn('flex items-center justify-between text-[13px]', className)}
key={option.id}
>
<Label className="mr-2">{option.name}</Label>
<Label className="mr-2">
{option.tooltip ? (
<Tooltip>
<TooltipTrigger asChild>
<span className="cursor-help">{option.name}</span>
</TooltipTrigger>
<TooltipContent side="top">{option.tooltip}</TooltipContent>
</Tooltip>
) : (
option.name
)}
</Label>
<div className="max-w-1/2">
<Tabs
value={option.value}

View File

@ -7,6 +7,7 @@ import { Checkbox } from '../Checkbox/Checkbox';
import { Label } from '../Label';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../Select';
import { Switch } from '../Switch';
import { Tooltip, TooltipContent, TooltipTrigger } from '../Tooltip';
const SETTING_TYPES = {
RANGE: 'range',
@ -61,13 +62,32 @@ function ToolSettings({ options }) {
);
}
const renderLabelWithTooltip = (label: React.ReactNode, tooltip?: string) => {
if (!label) {
return null;
}
if (!tooltip) {
return <span>{label}</span>;
}
return (
<Tooltip>
<TooltipTrigger asChild>
<span className="cursor-help">{label}</span>
</TooltipTrigger>
<TooltipContent side="top">{tooltip}</TooltipContent>
</Tooltip>
);
};
const renderRangeSetting = option => {
return (
<div
className="flex items-center"
key={option.id}
>
<div className="w-1/3 text-[13px]">{option.name}</div>
<div className="w-1/3 text-[13px]">{renderLabelWithTooltip(option.name, option.tooltip)}</div>
<div
className="w-2/3"
data-cy={option.id}
@ -98,15 +118,25 @@ const renderRadioSetting = option => {
function renderDoubleRangeSetting(option) {
return (
<RowDoubleRange
<div
className="flex items-center"
key={option.id}
values={option.value}
onChange={option.onChange}
minValue={option.min}
maxValue={option.max}
step={option.step}
showLabel={false}
/>
>
<div className="w-1/3 text-[13px]">
{renderLabelWithTooltip(option.name, option.tooltip)}
</div>
<div className="w-2/3">
<RowDoubleRange
values={option.value}
onChange={option.onChange}
minValue={option.min}
maxValue={option.max}
step={option.step}
showLabel={false}
tooltip={option.tooltip}
/>
</div>
</div>
);
}
@ -119,15 +149,38 @@ const renderCustomSetting = option => {
};
const renderButtonSetting = option => {
return (
const button = (
<Button
key={option.id}
variant="ghost"
variant={option.variant || 'ghost'}
className={option.className || ''}
onClick={() => option.onChange()}
>
{option.name}
</Button>
);
if (option.tooltip) {
return (
<Tooltip>
<TooltipTrigger asChild>{button}</TooltipTrigger>
<TooltipContent side="top">{option.tooltip}</TooltipContent>
</Tooltip>
);
}
return button;
};
const renderCheckboxLabel = option => {
return (
<Label
htmlFor={option.id}
className="cursor-pointer"
>
{renderLabelWithTooltip(option.name, option.tooltip)}
</Label>
);
};
const renderCheckboxSetting = option => {
@ -143,12 +196,7 @@ const renderCheckboxSetting = option => {
option.onChange?.(checked);
}}
/>
<Label
htmlFor={option.id}
className="cursor-pointer"
>
{option.name}
</Label>
{renderCheckboxLabel(option)}
</div>
);
};
@ -166,37 +214,41 @@ const renderSwitchSetting = option => {
option.onChange?.(checked);
}}
/>
<Label
htmlFor={option.id}
className="cursor-pointer"
>
{option.name}
</Label>
{renderCheckboxLabel(option)}
</div>
);
};
const renderSelectSetting = option => {
return (
<Select
<div
className="flex items-center"
key={option.id}
onValueChange={value => option.onChange?.(value)}
value={option.value}
>
<SelectTrigger className="w-full overflow-hidden">
<SelectValue />
</SelectTrigger>
<SelectContent>
{option.values.map(value => (
<SelectItem
key={value.id}
value={value.id}
>
{value.label}
</SelectItem>
))}
</SelectContent>
</Select>
<div className="w-1/3 text-[13px]">
{renderLabelWithTooltip(option.name, option.tooltip)}
</div>
<div className="w-2/3">
<Select
onValueChange={value => option.onChange?.(value)}
value={option.value}
>
<SelectTrigger className="w-full overflow-hidden">
<SelectValue />
</SelectTrigger>
<SelectContent>
{option.values.map(value => (
<SelectItem
key={value.id}
value={value.id}
>
{value.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
);
};