import * as React from 'react'; import { useState } from 'react'; import styled from 'styled-components'; import { Button } from '@redocly/theme/components/Button/Button'; import { SearchDialog } from '@redocly/theme/components/Search/SearchDialog'; import { useThemeConfig, useThemeHooks } from '@redocly/theme/core/hooks'; import { ChatIcon } from '@redocly/theme/icons/ChatIcon/ChatIcon'; import { AiStarsGradientIcon } from '@redocly/theme/icons/AiStarsGradientIcon/AiStarsGradientIcon'; import { RedoclyIcon } from '@redocly/theme/icons/RedoclyIcon/RedoclyIcon'; import { SearchSessionProvider } from '@redocly/theme/core/contexts'; type AIAssistantButtonIconType = 'chat' | 'sparkles' | 'redocly'; type AIAssistantButtonType = 'button' | 'icon'; interface AIAssistantButtonConfig { hide?: boolean; inputType?: AIAssistantButtonType; inputIcon?: AIAssistantButtonIconType; } const defaultConfig: Required = { hide: false, inputType: 'button', inputIcon: 'sparkles', }; const getIcon = ( iconType: AIAssistantButtonIconType, inputType: AIAssistantButtonType = 'button', ) => { const iconSize = inputType === 'icon' ? 'var(--ai-assistant-button-icon-icon-size)' : 'var(--ai-assistant-button-text-icon-size)'; const redoclyIcon = ( ); const sparklesIcon = ( ); const chatIcon = ; switch (iconType) { case 'chat': return chatIcon; case 'sparkles': return sparklesIcon; case 'redocly': return redoclyIcon; default: return redoclyIcon; } }; export function AIAssistantButton() { const [isOpen, setIsOpen] = useState(false); const themeConfig = useThemeConfig(); const { useTranslate, useTelemetry } = useThemeHooks(); const { translate } = useTranslate(); const telemetry = useTelemetry(); const buttonConfig = { ...defaultConfig, ...(themeConfig.aiAssistant?.trigger ?? {}), }; const { hide, inputIcon, inputType } = buttonConfig; if (hide) { return null; } const icon = getIcon(inputIcon, inputType); const text = translate('aiAssistant.trigger', 'Ask AI'); const handleOpen = () => { setIsOpen(true); telemetry.sendSearchAiOpenedMessage([ { object: 'search', method: 'ai_trigger_button', }, ]); }; const handleClose = () => { setIsOpen(false); }; return ( {icon} {inputType === 'button' && text} {isOpen && } ); } const StyledAIAssistantButton = styled(Button)<{ $inputType?: AIAssistantButtonType }>` position: fixed; bottom: var(--ai-assistant-button-bottom); right: calc(var(--ai-assistant-button-right) + var(--modal-scrollbar-width, 0px)); ${({ $inputType }) => $inputType === 'icon' ? ` border-radius: var(--ai-assistant-button-border-radius-icon); width: var(--ai-assistant-button-icon-size); height: var(--ai-assistant-button-icon-size); ` : ` border-radius: var(--ai-assistant-button-border-radius-text); padding: var(--ai-assistant-button-text-padding); height: var(--ai-assistant-button-text-height); `} min-width: var(--ai-assistant-button-min-width); font-size: var(--ai-assistant-button-font-size); font-weight: var(--ai-assistant-button-font-weight); box-shadow: var(--bg-raised-shadow); z-index: var(--ai-assistant-button-z-index); display: flex; align-items: center; justify-content: center; gap: var(--ai-assistant-button-gap); background-color: var(--ai-assistant-button-bg-color) !important; transition: var(--ai-assistant-button-transition); &:hover { box-shadow: var(--ai-assistant-button-shadow-hover); transform: var(--ai-assistant-button-transform-hover); } &:active { transform: var(--bg-raised-shadow); box-shadow: var(--ai-assistant-button-shadow-active); } `;