Skip to content

🎨 feat: UI Refresh for Enhanced UX #6346

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 107 commits into from
Mar 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
84b9ed3
✨ feat: Add Expand Chat functionality and improve UI components
berry-13 Feb 21, 2025
dbe2216
✨ feat: Introduce Chat Badges feature with editing capabilities and U…
berry-13 Feb 21, 2025
0beec47
✨ feat: re-implement file attachment functionality with new component…
berry-13 Feb 22, 2025
a29b6c4
✨ feat: Enhance BadgeRow component with drag-and-drop functionality a…
berry-13 Feb 22, 2025
e10020d
✨ feat: Add useChatBadges hook and enhance Badge component with anima…
berry-13 Feb 23, 2025
9aa0bfb
feat: Improve Add/Delete Badges + style and bug fixes
berry-13 Feb 23, 2025
b302d08
✨ feat: Refactor EditBadges component and optimize useChatBadges hook…
berry-13 Feb 23, 2025
3182b04
✨ feat: Add type definition for LucideIcon in EditBadges component
berry-13 Feb 23, 2025
60e7ecc
refactor: Clean up BadgeRow component by removing outdated comment an…
berry-13 Feb 23, 2025
ee3ae20
refactor: Rename app-icon class to badge-icon for consistency and imp…
berry-13 Feb 23, 2025
f061373
feat: Add Center Chat Input toggle and update related components for …
berry-13 Feb 27, 2025
e34996f
refactor: Simplify ChatView and MessagesView components for improved …
berry-13 Mar 2, 2025
45ac9bb
refactor: Improve layout and positioning of scroll button in Messages…
berry-13 Mar 2, 2025
61b9cac
refactor: Adjust scroll button position in MessagesView component for…
berry-13 Mar 2, 2025
17a623c
refactor: Remove redundant background class from Badge component for …
berry-13 Mar 4, 2025
18243a0
feat: disable chat badges
berry-13 Mar 4, 2025
17cc88f
refactor: adjust positioning of scroll button and popover for improve…
berry-13 Mar 4, 2025
7ffa31e
refactor: simplify class names in ChatForm and RemoveFile components …
berry-13 Mar 5, 2025
c789e5b
refactor: move Switcher to HeaderOptions from SidePanel
danny-avila Mar 6, 2025
57c4d42
fix(Landing): duplicate description
berry-13 Mar 7, 2025
675e885
feat: add SplitText component for animated text display and update La…
berry-13 Mar 7, 2025
88f3079
feat(Chat): add ConversationStarters component and integrate it into …
berry-13 Mar 7, 2025
eb9f2c1
feat(Chat): enhance Message component layout and styling for improved…
berry-13 Mar 7, 2025
9dff34f
feat(ControlCombobox, Select): enhance styling and add animation for …
berry-13 Mar 7, 2025
c4c9217
feat(Chat): update Header and HeaderNewChat components for improved l…
berry-13 Mar 7, 2025
4d152da
feat(Chat): add ModelDropdown (now includes both endpoint and model) …
berry-13 Mar 11, 2025
672a29d
feat(ModelDropdown): add Agent Select; removed old AgentSwitcher comp…
berry-13 Mar 11, 2025
c7d65cf
feat(ModelDropdown): add settings button for user key configuration
berry-13 Mar 11, 2025
ca45524
fix(ModelDropdown): the model dropdown wasn't opening automatically w…
berry-13 Mar 11, 2025
7fc1712
refactor(Chat): remove unused EndpointsMenu and related components to…
berry-13 Mar 12, 2025
fa315e7
feat: enhance greeting message and improve accessibility fro ModelDro…
berry-13 Mar 13, 2025
a26d368
refactor(Endpoints): add new hooks and components for endpoint manage…
berry-13 Mar 16, 2025
a338f47
feat(Endpoint): add support for modelSpecs
berry-13 Mar 16, 2025
6da699f
feat(Endpoints): add mobile support
berry-13 Mar 16, 2025
f524d0d
fix: type issues
berry-13 Mar 17, 2025
4659260
fix(modelSpec): type issue
berry-13 Mar 17, 2025
f8ce4d9
fix(EndpointMenuDropdown): double overflow scroller in mobile model list
berry-13 Mar 17, 2025
bd693d8
fix: search model on mobile
berry-13 Mar 17, 2025
98054f9
refactor: Endpoint/Model/modelSpec dropdown
berry-13 Mar 17, 2025
4d6034e
refactor: reorganize imports in Endpoint components
berry-13 Mar 17, 2025
492cd19
refactor: remove unused translation keys from English locale
berry-13 Mar 17, 2025
1181c8b
BREAKING: moving to ariakit with new CustomMenu
berry-13 Mar 21, 2025
f810848
refactor: remove unnecessary comments
berry-13 Mar 21, 2025
f213694
refactor: remove EndpointItem, ModelDropdownButton, SpecIcon, and Spe…
berry-13 Mar 21, 2025
ef652d6
🔧 fix: AI Icon bump when regenerating message
berry-13 Mar 22, 2025
7f4d6bd
wip: chat UI refactoring, fix issues
danny-avila Mar 23, 2025
bd0e048
chore: add recent update to useAutoSave
danny-avila Mar 23, 2025
22d4bc5
feat: add access control for agent permissions in useMentions hook
danny-avila Mar 24, 2025
ccf7863
refactor: streamline ModelSelector by removing unused endpoints logic
danny-avila Mar 24, 2025
dd8e009
refactor: enhance ModelSelector and context by integrating endpointsC…
danny-avila Mar 24, 2025
cdc0059
feat: update ModelSelectorContext to utilize conversation data for in…
danny-avila Mar 24, 2025
6b38bf3
feat: add selector effects for synced endpoint handling
danny-avila Mar 24, 2025
f5f1eae
feat: add guard clause for conversation endpoint in useSelectorEffect…
danny-avila Mar 24, 2025
d195a3e
fix: safely call onSelectMention and add autofocus to mention input
danny-avila Mar 24, 2025
595eced
chore: typing
danny-avila Mar 24, 2025
973bb06
refactor: ModelSelector to streamline key dialog handling and improve…
danny-avila Mar 24, 2025
d684dd8
refactor: extract SettingsButton component for cleaner endpoint item …
danny-avila Mar 24, 2025
8bdcaa5
wip: first pass, expand set api key
danny-avila Mar 24, 2025
3b2adbe
wip: first pass, expanding set key
danny-avila Mar 24, 2025
30ef4c2
refactor: update EndpointItem styles for improved layout and hover ef…
danny-avila Mar 24, 2025
a980c7c
refactor: adjust padding in EndpointItem for improved layout consistency
danny-avila Mar 24, 2025
b71a364
refactor: update preset structure in useSelectMention to include spec…
danny-avila Mar 24, 2025
b9a29ca
refactor: rename setKeyDialogOpen to onOpenChange for clarity and con…
danny-avila Mar 24, 2025
e85fc5a
feat: add SpecIcon component for dynamic model spec icons in menu, ad…
danny-avila Mar 24, 2025
9b6f2dd
refactor: update getSelectedIcon to accept additional parameters and …
danny-avila Mar 24, 2025
17cb8d5
fix: adjust padding in MessageRender for improved layout
berry-13 Mar 24, 2025
6a7dee9
refactor: remove inline style for menu width in CustomMenu component
danny-avila Mar 24, 2025
7f86800
refactor: enhance layout and styling in ModelSpecItem component for b…
danny-avila Mar 24, 2025
2271f00
refactor: update getDefaultModelSpec to accept startupConfig and impr…
danny-avila Mar 24, 2025
b52d50b
refactor: improve key management and default values in ModelSelector …
danny-avila Mar 24, 2025
c3e7d6e
refactor: adjust menu width and improve responsiveness in CustomMenu …
danny-avila Mar 24, 2025
2c8fefd
refactor: enhance focus styles and responsiveness in EndpointItem com…
danny-avila Mar 24, 2025
8bed338
refactor: improve layout and spacing in Header and ModelSelector comp…
danny-avila Mar 24, 2025
a40b9ab
refactor: adjust button styles for consistency and improved layout in…
danny-avila Mar 24, 2025
0d8a6ba
fix: initial fix of assistant names
danny-avila Mar 24, 2025
f724df6
fix: assistants handling
danny-avila Mar 24, 2025
75f7f03
chore: update version of librechat-data-provider to 0.7.75 and add 's…
danny-avila Mar 24, 2025
b0499f4
fix: improve endpoint filtering logic based on interface configuratio…
danny-avila Mar 24, 2025
f3f25a8
fix: remove unused HeaderOptions import and set spec to null in prese…
danny-avila Mar 24, 2025
a1f7c3c
fix: ensure currentExample is always an object when updating examples
danny-avila Mar 24, 2025
2d49384
fix: update interfaceConfig checks to ensure modelSelect is considere…
danny-avila Mar 24, 2025
db59fc9
fix: update model selection logic to consider interface configuration…
danny-avila Mar 24, 2025
34dd875
fix: add missing localizations
danny-avila Mar 24, 2025
f3e0709
fix: remove unused agent and assistant selection translations
danny-avila Mar 24, 2025
e482ab9
fix: implement debounced state updates for selected values in useSele…
danny-avila Mar 24, 2025
bade940
style: minor style changes related to the ModelSelector
berry-13 Mar 24, 2025
70e0b48
fix: adjust maximum height for popover and set fixed height for model…
danny-avila Mar 24, 2025
e52fc97
fix: update placeholders for model and endpoint search inputs
danny-avila Mar 24, 2025
79f8043
fix: refactor MessageRender and ContentRender components to better ma…
danny-avila Mar 25, 2025
77778cb
fix: remove convo fallback for iconURL in MessageRender and ContentRe…
danny-avila Mar 25, 2025
f77f390
fix: update handling of spec, iconURL, and modelLabel in conversation…
danny-avila Mar 25, 2025
e4956d4
fix: replace chatGptLabel with modelLabel in OpenAI settings configur…
danny-avila Mar 25, 2025
6331e0d
fix: remove console log for assistantNames in useEndpoints hook
danny-avila Mar 25, 2025
e0a4f11
refactor: add cleanInput and cleanOutput options to default conversat…
danny-avila Mar 25, 2025
1588949
chore: update bun.lockb
danny-avila Mar 25, 2025
a7da593
fix: set default value for showIconInHeader in getSelectedIcon function
danny-avila Mar 25, 2025
71ef579
refactor: enhance error handling in message processing when latest me…
danny-avila Mar 25, 2025
f3fc71f
chore: allow import/no-cycle for messages
danny-avila Mar 25, 2025
7f0a5ea
fix: adjust flex properties in BookmarkMenu for better layout
danny-avila Mar 25, 2025
e5da879
feat: support both 'prompt' and 'q' as query parameters in useQueryPa…
danny-avila Mar 25, 2025
05b95be
feat: re-enable Badges components
berry-13 Mar 25, 2025
a7e7846
refactor: disable edit badge component
berry-13 Mar 25, 2025
38d3024
chore: rename assistantMap to assistantsMap for consistency
danny-avila Mar 25, 2025
47e21d8
chore: rename assistantMap to assistantsMap for consistency in Mentio…
danny-avila Mar 25, 2025
a13aafe
feat: set staleTime for various queries to improve data freshness
danny-avila Mar 25, 2025
da118b8
feat: add spec field to tQueryParamsSchema for model specification
danny-avila Mar 25, 2025
ca331d2
feat: enhance useQueryParams to handle model specs
danny-avila Mar 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion api/app/clients/BaseClient.js
Original file line number Diff line number Diff line change
Expand Up @@ -879,13 +879,14 @@ class BaseClient {
: await getConvo(this.options.req?.user?.id, message.conversationId);

const unsetFields = {};
const exceptions = new Set(['spec', 'iconURL']);
if (existingConvo != null) {
this.fetchedConvo = true;
for (const key in existingConvo) {
if (!key) {
continue;
}
if (excludedKeys.has(key)) {
if (excludedKeys.has(key) && !exceptions.has(key)) {
continue;
}

Expand Down
Binary file modified bun.lockb
Binary file not shown.
3 changes: 2 additions & 1 deletion client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.3",
"@radix-ui/react-toast": "^1.1.5",
"@react-spring/web": "^9.7.5",
"@tanstack/react-query": "^4.28.0",
"@tanstack/react-table": "^8.11.7",
"class-variance-authority": "^0.6.0",
Expand Down Expand Up @@ -141,8 +142,8 @@
"ts-jest": "^29.2.5",
"typescript": "^5.3.3",
"vite": "^6.1.0",
"vite-plugin-node-polyfills": "^0.17.0",
"vite-plugin-compression": "^0.5.1",
"vite-plugin-node-polyfills": "^0.17.0",
"vite-plugin-pwa": "^0.21.1"
}
}
1 change: 1 addition & 0 deletions client/src/common/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ export * from './artifacts';
export * from './types';
export * from './menus';
export * from './tools';
export * from './selector';
export * from './assistants-types';
export * from './agents-types';
24 changes: 24 additions & 0 deletions client/src/common/selector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import { TModelSpec, TInterfaceConfig } from 'librechat-data-provider';

export interface Endpoint {
value: string;
label: string;
hasModels: boolean;
models?: string[];
icon: React.ReactNode;
agentNames?: Record<string, string>;
assistantNames?: Record<string, string>;
modelIcons?: Record<string, string | undefined>;
}

export interface SelectedValues {
endpoint: string | null;
model: string | null;
modelSpec: string | null;
}

export interface ModelSelectorProps {
interfaceConfig: TInterfaceConfig;
modelSpecs: TModelSpec[];
}
35 changes: 32 additions & 3 deletions client/src/common/types.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { RefObject } from 'react';
import { FileSources } from 'librechat-data-provider';
import { FileSources, EModelEndpoint } from 'librechat-data-provider';
import type { UseMutationResult } from '@tanstack/react-query';
import type * as InputNumberPrimitive from 'rc-input-number';
import type { SetterOrUpdater, RecoilState } from 'recoil';
import type { ColumnDef } from '@tanstack/react-table';
import type { SetterOrUpdater } from 'recoil';
import type * as t from 'librechat-data-provider';
import type { UseMutationResult } from '@tanstack/react-query';
import type { LucideIcon } from 'lucide-react';
import type { TranslationKeys } from '~/hooks';

Expand Down Expand Up @@ -48,6 +48,14 @@ export type AudioChunk = {
};
};

export type BadgeItem = {
id: string;
icon: React.ComponentType<any>;
label: string;
atom: RecoilState<boolean>;
isAvailable: boolean;
};

export type AssistantListItem = {
id: string;
name: string;
Expand Down Expand Up @@ -488,6 +496,27 @@ export interface ExtendedFile {
metadata?: t.TFile['metadata'];
}

export interface ExtendedEndpoint {
value: EModelEndpoint;
label: string;
hasModels: boolean;
icon: JSX.Element | null;
models?: string[];
agentNames?: Record<string, string>;
assistantNames?: Record<string, string>;
modelIcons?: Record<string, string | undefined>;
}

export interface ModelItemProps {
modelName: string;
endpoint: EModelEndpoint;
isSelected: boolean;
onSelect: () => void;
onNavigateBack: () => void;
icon?: JSX.Element;
className?: string;
}

export type ContextType = { navVisible: boolean; setNavVisible: (visible: boolean) => void };

export interface SwitcherProps {
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/Chat/AddMultiConvo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function AddMultiConvo() {
const localize = useLocalize();

const clickHandler = () => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars

const { title: _t, ...convo } = conversation ?? ({} as TConversation);
setAddedConvo({
...convo,
Expand Down Expand Up @@ -42,7 +42,7 @@ function AddMultiConvo() {
role="button"
onClick={clickHandler}
data-testid="parameters-button"
className="inline-flex size-10 items-center justify-center rounded-lg border border-border-light bg-transparent text-text-primary transition-all ease-in-out hover:bg-surface-tertiary disabled:pointer-events-none disabled:opacity-50 radix-state-open:bg-surface-tertiary"
className="inline-flex size-10 flex-shrink-0 items-center justify-center rounded-lg border border-border-light bg-transparent text-text-primary transition-all ease-in-out hover:bg-surface-tertiary disabled:pointer-events-none disabled:opacity-50 radix-state-open:bg-surface-tertiary"
>
<PlusCircle size={16} aria-label="Plus Icon" />
</TooltipAnchor>
Expand Down
37 changes: 29 additions & 8 deletions client/src/components/Chat/ChatView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { TMessage } from 'librechat-data-provider';
import type { ChatFormValues } from '~/common';
import { ChatContext, AddedChatContext, useFileMapContext, ChatFormProvider } from '~/Providers';
import { useChatHelpers, useAddedResponse, useSSE } from '~/hooks';
import ConversationStarters from './Input/ConversationStarters';
import MessagesView from './Messages/MessagesView';
import { Spinner } from '~/components/svg';
import Presentation from './Presentation';
Expand All @@ -21,6 +22,7 @@ function ChatView({ index = 0 }: { index?: number }) {
const { conversationId } = useParams();
const rootSubmission = useRecoilValue(store.submissionByIndex(index));
const addedSubmission = useRecoilValue(store.submissionByIndex(index + 1));
const centerFormOnLanding = useRecoilValue(store.centerFormOnLanding);

const fileMap = useFileMapContext();

Expand All @@ -46,27 +48,46 @@ function ChatView({ index = 0 }: { index?: number }) {
});

let content: JSX.Element | null | undefined;
const isLandingPage = !messagesTree || messagesTree.length === 0;

if (isLoading && conversationId !== 'new') {
content = (
<div className="flex h-screen items-center justify-center">
<Spinner className="opacity-0" />
<Spinner className="text-text-primary" />
</div>
);
} else if (messagesTree && messagesTree.length !== 0) {
content = <MessagesView messagesTree={messagesTree} Header={<Header />} />;
} else if (!isLandingPage) {
content = <MessagesView messagesTree={messagesTree} />;
} else {
content = <Landing Header={<Header />} />;
content = <Landing centerFormOnLanding={centerFormOnLanding} />;
}

return (
<ChatFormProvider {...methods}>
<ChatContext.Provider value={chatHelpers}>
<AddedChatContext.Provider value={addedChatHelpers}>
<Presentation>
{content}
<div className="w-full border-t-0 pl-0 pt-2 dark:border-white/20 md:w-[calc(100%-.5rem)] md:border-t-0 md:border-transparent md:pl-0 md:pt-0 md:dark:border-transparent">
<ChatForm index={index} />
<Footer />
<div className="flex h-full w-full flex-col">
{!isLoading && <Header />}

{isLandingPage ? (
<div className="flex flex-1 flex-col items-center justify-end sm:justify-center">
{content}
<div className="w-full max-w-3xl transition-all duration-200 xl:max-w-4xl">
<ChatForm index={index} />
<ConversationStarters />
<Footer />
</div>
</div>
) : (
<div className="flex h-full flex-col overflow-y-auto">
{content}
<div className="w-full">
<ChatForm index={index} />
<Footer />
</div>
</div>
)}
</div>
</Presentation>
</AddedChatContext.Provider>
Expand Down
17 changes: 0 additions & 17 deletions client/src/components/Chat/ConvoStarter.tsx

This file was deleted.

6 changes: 3 additions & 3 deletions client/src/components/Chat/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default function Footer({ className }: { className?: string }) {
<React.Fragment key={`main-content-part-${index}`}>
<ReactMarkdown
components={{
// eslint-disable-next-line @typescript-eslint/no-unused-vars

a: ({ node: _n, href, children, ...otherProps }) => {
return (
<a
Expand All @@ -70,7 +70,7 @@ export default function Footer({ className }: { className?: string }) {
</a>
);
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars

p: ({ node: _n, ...props }) => <span {...props} />,
}}
>
Expand All @@ -87,7 +87,7 @@ export default function Footer({ className }: { className?: string }) {
<div
className={
className ??
'relative flex items-center justify-center gap-2 px-2 py-2 text-center text-xs text-text-primary md:px-[60px]'
'relative hidden items-center justify-center gap-2 px-2 py-2 text-center text-xs text-text-primary sm:flex md:px-[60px]'
}
role="contentinfo"
>
Expand Down
14 changes: 6 additions & 8 deletions client/src/components/Chat/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import { useMemo } from 'react';
import { useOutletContext } from 'react-router-dom';
import { getConfigDefaults, PermissionTypes, Permissions } from 'librechat-data-provider';
import type { ContextType } from '~/common';
import { EndpointsMenu, ModelSpecsMenu, PresetsMenu, HeaderNewChat } from './Menus';
import ModelSelector from './Menus/Endpoints/ModelSelector';
import { PresetsMenu, HeaderNewChat } from './Menus';
import { useGetStartupConfig } from '~/data-provider';
import ExportAndShareMenu from './ExportAndShareMenu';
import { useMediaQuery, useHasAccess } from '~/hooks';
import HeaderOptions from './Input/HeaderOptions';
import BookmarkMenu from './Menus/BookmarkMenu';
import AddMultiConvo from './AddMultiConvo';

Expand Down Expand Up @@ -34,14 +34,12 @@ export default function Header() {
const isSmallScreen = useMediaQuery('(max-width: 768px)');

return (
<div className="sticky top-0 z-10 flex h-14 w-full items-center justify-between bg-white p-2 font-semibold dark:bg-gray-800 dark:text-white">
<div className="sticky top-0 z-10 flex h-14 w-full items-center justify-between bg-white p-2 font-semibold text-text-primary dark:bg-gray-800">
<div className="hide-scrollbar flex w-full items-center justify-between gap-2 overflow-x-auto">
<div className="flex items-center gap-2">
<div className="mx-2 flex items-center gap-2">
{!navVisible && <HeaderNewChat />}
{interfaceConfig.endpointsMenu === true && <EndpointsMenu />}
{modelSpecs.length > 0 && <ModelSpecsMenu modelSpecs={modelSpecs} />}
{<HeaderOptions interfaceConfig={interfaceConfig} />}
{interfaceConfig.presets === true && <PresetsMenu />}
{<ModelSelector interfaceConfig={interfaceConfig} modelSpecs={modelSpecs} />}
{interfaceConfig.presets === true && interfaceConfig.modelSelect && <PresetsMenu />}
{hasAccessToBookmarks === true && <BookmarkMenu />}
{hasAccessToMultiConvo === true && <AddMultiConvo />}
{isSmallScreen && (
Expand Down
6 changes: 1 addition & 5 deletions client/src/components/Chat/Input/AudioRecorder.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,12 @@ import { globalAudioId } from '~/common';
import { cn } from '~/utils';

export default function AudioRecorder({
isRTL,
disabled,
ask,
methods,
textAreaRef,
isSubmitting,
}: {
isRTL: boolean;
disabled: boolean;
ask: (data: { text: string }) => void;
methods: ReturnType<typeof useChatFormContext>;
Expand Down Expand Up @@ -90,9 +88,7 @@ export default function AudioRecorder({
onClick={isListening === true ? handleStopRecording : handleStartRecording}
disabled={disabled}
className={cn(
'absolute flex size-[35px] items-center justify-center rounded-full p-1 transition-colors hover:bg-surface-hover',
isRTL ? 'bottom-2 left-2' : 'bottom-2 right-2',
disabled ? 'cursor-not-allowed opacity-50' : 'cursor-pointer',
'flex size-9 items-center justify-center rounded-full p-1 transition-colors hover:bg-surface-hover',
)}
title={localize('com_ui_use_micrphone')}
aria-pressed={isListening}
Expand Down
Loading