mirror of https://github.com/buster-so/buster.git
Update AppSegmented.tsx
This commit is contained in:
parent
dbe8b79ce7
commit
eda759798e
|
@ -1,7 +1,10 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { Magnifier, Sparkle2 } from '@/components/ui/icons';
|
import { Magnifier, Sparkle2 } from '@/components/ui/icons';
|
||||||
import Atom from '@/components/ui/icons/NucleoIconOutlined/atom';
|
import Atom from '@/components/ui/icons/NucleoIconOutlined/atom';
|
||||||
|
import { Popover } from '@/components/ui/popover';
|
||||||
import { AppSegmented, type AppSegmentedProps } from '@/components/ui/segmented';
|
import { AppSegmented, type AppSegmentedProps } from '@/components/ui/segmented';
|
||||||
|
import { Text } from '@/components/ui/typography';
|
||||||
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
export type BusterChatInputMode = 'auto' | 'research' | 'deep-research';
|
export type BusterChatInputMode = 'auto' | 'research' | 'deep-research';
|
||||||
|
|
||||||
|
@ -14,12 +17,6 @@ type BusterChatInputButtons = {
|
||||||
onModeChange: (mode: BusterChatInputMode) => void;
|
onModeChange: (mode: BusterChatInputMode) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const modesOptions: AppSegmentedProps<BusterChatInputMode>['options'] = [
|
|
||||||
{ icon: <Sparkle2 />, value: 'auto' },
|
|
||||||
{ icon: <Magnifier />, value: 'research' },
|
|
||||||
{ icon: <Atom />, value: 'deep-research' },
|
|
||||||
];
|
|
||||||
|
|
||||||
export const BusterChatInputButtons = ({
|
export const BusterChatInputButtons = ({
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onStop,
|
onStop,
|
||||||
|
@ -34,3 +31,94 @@ export const BusterChatInputButtons = ({
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ModePopoverContent = ({
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
icon,
|
||||||
|
iconText,
|
||||||
|
content,
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
|
icon: React.ReactNode;
|
||||||
|
iconText: string;
|
||||||
|
content: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) => {
|
||||||
|
const classes = 'px-3';
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
trigger="hover"
|
||||||
|
side="bottom"
|
||||||
|
sideOffset={10}
|
||||||
|
className="p-0"
|
||||||
|
content={
|
||||||
|
<div className={cn('flex flex-col space-y-3 max-w-[210px] py-3')}>
|
||||||
|
<div className={cn('flex flex-col space-y-1', classes)}>
|
||||||
|
<Text>{title}</Text>
|
||||||
|
<Text variant="secondary">{description}</Text>
|
||||||
|
</div>
|
||||||
|
<div className="border-t" />
|
||||||
|
<div className={cn('flex flex-col space-y-1', classes)}>
|
||||||
|
<div className="flex items-center gap-1 bg-item-select rounded px-1 h-4.5 w-fit text-sm text-gray-dark">
|
||||||
|
{icon}
|
||||||
|
<Text variant={'secondary'} size={'sm'}>
|
||||||
|
{iconText}
|
||||||
|
</Text>
|
||||||
|
</div>
|
||||||
|
<Text variant="secondary">{content}</Text>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Popover>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const modesOptions: AppSegmentedProps<BusterChatInputMode>['options'] = [
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<ModePopoverContent
|
||||||
|
title="Auto"
|
||||||
|
description="Decides how long to think"
|
||||||
|
icon={<Sparkle2 />}
|
||||||
|
iconText="Auto Mode"
|
||||||
|
content={`Dynamically pick between “Research” and “Deep Research”`}
|
||||||
|
>
|
||||||
|
<Sparkle2 />
|
||||||
|
</ModePopoverContent>
|
||||||
|
),
|
||||||
|
value: 'auto' as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<ModePopoverContent
|
||||||
|
title="Research"
|
||||||
|
description="Responds in 1-3 minutes"
|
||||||
|
icon={<Magnifier />}
|
||||||
|
iconText="Research Mode"
|
||||||
|
content={`In-depth exploration for ad-hoc charts, dashboards, or reports`}
|
||||||
|
>
|
||||||
|
<Magnifier />
|
||||||
|
</ModePopoverContent>
|
||||||
|
),
|
||||||
|
value: 'research' as const,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: (
|
||||||
|
<ModePopoverContent
|
||||||
|
title="Deep Research"
|
||||||
|
description="Responds in 3-8 minutes"
|
||||||
|
icon={<Atom />}
|
||||||
|
iconText="Deep Research Mode"
|
||||||
|
content={`Generate robust reports with extremely thorough analysis`}
|
||||||
|
>
|
||||||
|
<Atom />
|
||||||
|
</ModePopoverContent>
|
||||||
|
),
|
||||||
|
value: 'deep-research' as const,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
|
@ -11,7 +11,6 @@ import * as React from 'react';
|
||||||
import { useEffect, useLayoutEffect, useState, useTransition } from 'react';
|
import { useEffect, useLayoutEffect, useState, useTransition } from 'react';
|
||||||
import { useIsBlockerEnabled } from '@/context/Routes/blocker-store';
|
import { useIsBlockerEnabled } from '@/context/Routes/blocker-store';
|
||||||
import { useDebounce } from '@/hooks/useDebounce';
|
import { useDebounce } from '@/hooks/useDebounce';
|
||||||
import { useMount } from '@/hooks/useMount';
|
|
||||||
import { useSize } from '@/hooks/useSize';
|
import { useSize } from '@/hooks/useSize';
|
||||||
import { cn } from '@/lib/classMerge';
|
import { cn } from '@/lib/classMerge';
|
||||||
import type { ILinkProps } from '@/types/routes';
|
import type { ILinkProps } from '@/types/routes';
|
||||||
|
@ -77,7 +76,7 @@ const triggerVariants = cva(
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
size: {
|
size: {
|
||||||
default: 'px-2 flex-row',
|
default: 'flex-row min-w-6',
|
||||||
medium: 'px-3 flex-row',
|
medium: 'px-3 flex-row',
|
||||||
large: 'px-3 flex-col',
|
large: 'px-3 flex-col',
|
||||||
},
|
},
|
||||||
|
@ -302,6 +301,24 @@ function SegmentedTriggerComponent<
|
||||||
<div {...commonProps}>{linkContent}</div>
|
<div {...commonProps}>{linkContent}</div>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Determine padding based on size, icon, and label presence
|
||||||
|
const getPaddingClass = () => {
|
||||||
|
if (size === 'default') {
|
||||||
|
// If there's an icon but no label, use p-0
|
||||||
|
if (icon && !label) {
|
||||||
|
return 'p-0';
|
||||||
|
}
|
||||||
|
// If there's a label, use p-2
|
||||||
|
if (label) {
|
||||||
|
return 'p-2';
|
||||||
|
}
|
||||||
|
// Default fallback for edge cases
|
||||||
|
return 'p-2';
|
||||||
|
}
|
||||||
|
// For other sizes, no additional padding (they have their own px-3)
|
||||||
|
return '';
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip title={tooltip || ''} sideOffset={10} delayDuration={150}>
|
<Tooltip title={tooltip || ''} sideOffset={10} delayDuration={150}>
|
||||||
<Tabs.Trigger
|
<Tabs.Trigger
|
||||||
|
@ -318,7 +335,8 @@ function SegmentedTriggerComponent<
|
||||||
block,
|
block,
|
||||||
disabled,
|
disabled,
|
||||||
selected: selectedValue === value,
|
selected: selectedValue === value,
|
||||||
})
|
}),
|
||||||
|
getPaddingClass()
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{linkDiv}
|
{linkDiv}
|
||||||
|
|
Loading…
Reference in New Issue