feat: design the ai-models tab on settings ai page (#18147)

Remove AI model selectors from the settings tab on AI settings page,
rename that tab to "More" and create a separate "Models" tab as per the
design.


https://www.figma.com/design/xt8O9mFeLl46C5InWwoMrN/Twenty?node-id=91311-278313&m=dev

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
Abdullah.
2026-02-22 15:41:26 +05:00
committed by GitHub
parent 088be4c47b
commit 0bccdedb4f
15 changed files with 260 additions and 229 deletions
@@ -13,15 +13,16 @@ import { getSettingsPath } from 'twenty-shared/utils';
import { t } from '@lingui/core/macro';
import {
H2Title,
IconCpu,
IconFileText,
IconSettings,
IconSettingsBolt,
IconSparkles,
IconTool,
} from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { Card, Section } from 'twenty-ui/layout';
import { SettingsAIMCP } from './components/SettingsAIMCP';
import { SettingsAIRouterSettings } from './components/SettingsAIRouterSettings';
import { SettingsAIModelsTab } from './components/SettingsAIModelsTab';
import { SettingsSkillsTable } from './components/SettingsSkillsTable';
import { SettingsToolsTable } from './components/SettingsToolsTable';
import { SETTINGS_AI_TABS } from './constants/SettingsAiTabs';
@@ -37,6 +38,11 @@ export const SettingsAI = () => {
);
const tabs = [
{
id: SETTINGS_AI_TABS.TABS_IDS.MODELS,
title: t`Models`,
Icon: IconCpu,
},
{
id: SETTINGS_AI_TABS.TABS_IDS.SKILLS,
title: t`Skills`,
@@ -48,15 +54,16 @@ export const SettingsAI = () => {
Icon: IconTool,
},
{
id: SETTINGS_AI_TABS.TABS_IDS.SETTINGS,
title: t`Settings`,
Icon: IconSettings,
id: SETTINGS_AI_TABS.TABS_IDS.MORE,
title: t`More`,
Icon: IconSettingsBolt,
},
];
const isModelsTab = activeTabId === SETTINGS_AI_TABS.TABS_IDS.MODELS;
const isSkillsTab = activeTabId === SETTINGS_AI_TABS.TABS_IDS.SKILLS;
const isToolsTab = activeTabId === SETTINGS_AI_TABS.TABS_IDS.TOOLS;
const isSettingsTab = activeTabId === SETTINGS_AI_TABS.TABS_IDS.SETTINGS;
const isMoreTab = activeTabId === SETTINGS_AI_TABS.TABS_IDS.MORE;
return (
<SubMenuTopBarContainer
@@ -74,11 +81,11 @@ export const SettingsAI = () => {
tabs={tabs}
componentInstanceId={SETTINGS_AI_TABS.COMPONENT_INSTANCE_ID}
/>
{isModelsTab && <SettingsAIModelsTab />}
{isSkillsTab && <SettingsSkillsTable />}
{isToolsTab && <SettingsToolsTable />}
{isSettingsTab && (
{isMoreTab && (
<>
<SettingsAIRouterSettings />
<Section>
<H2Title
title={t`System Prompt`}
@@ -0,0 +1,105 @@
import { useRecoilState } from 'recoil';
import { DEFAULT_FAST_MODEL } from '@/ai/constants/DefaultFastModel';
import { DEFAULT_SMART_MODEL } from '@/ai/constants/DefaultSmartModel';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { aiModelsState } from '@/client-config/states/aiModelsState';
import { SettingsOptionCardContentSelect } from '@/settings/components/SettingsOptions/SettingsOptionCardContentSelect';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { Select } from '@/ui/input/components/Select';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
import { t } from '@lingui/core/macro';
import { H2Title, IconBolt } from 'twenty-ui/display';
import { Card, Section } from 'twenty-ui/layout';
import { useUpdateWorkspaceMutation } from '~/generated-metadata/graphql';
import { PROVIDER_CONFIG } from '~/pages/settings/ai/constants/SettingsAiModelProviders';
const VIRTUAL_MODEL_IDS: Set<string> = new Set([
DEFAULT_SMART_MODEL,
DEFAULT_FAST_MODEL,
]);
export const SettingsAIModelsTab = () => {
const { enqueueSuccessSnackBar, enqueueErrorSnackBar } = useSnackBar();
const [currentWorkspace, setCurrentWorkspace] = useRecoilState(
currentWorkspaceState,
);
const [updateWorkspace] = useUpdateWorkspaceMutation();
const aiModels = useRecoilValueV2(aiModelsState);
const realModels = aiModels.filter(
(model) => !VIRTUAL_MODEL_IDS.has(model.modelId),
);
const currentSmartModel = currentWorkspace?.smartModel;
const defaultModelOptions = realModels
.filter((model) => !model.deprecated || model.modelId === currentSmartModel)
.map((model) => ({
value: model.modelId,
label: model.label,
Icon: PROVIDER_CONFIG[model.provider.toUpperCase()]?.Icon,
}));
const handleDefaultModelChange = async (value: string) => {
if (!currentWorkspace?.id) {
return;
}
const previousSmartModel = currentWorkspace.smartModel;
try {
setCurrentWorkspace({
...currentWorkspace,
smartModel: value,
});
await updateWorkspace({
variables: {
input: {
smartModel: value,
},
},
});
enqueueSuccessSnackBar({
message: t`Default model updated successfully`,
});
} catch {
setCurrentWorkspace({
...currentWorkspace,
smartModel: previousSmartModel,
});
enqueueErrorSnackBar({
message: t`Failed to update default model`,
});
}
};
return (
<Section>
<H2Title
title={t`Default`}
description={t`Configure your default AI model`}
/>
<Card rounded>
<SettingsOptionCardContentSelect
Icon={IconBolt}
title={t`Default Model`}
description={t`Default model for new chats and agents`}
>
<Select
dropdownId="default-model-select"
value={currentSmartModel}
onChange={handleDefaultModelChange}
options={defaultModelOptions}
selectSizeVariant="small"
/>
</SettingsOptionCardContentSelect>
</Card>
</Section>
);
};
@@ -1,220 +0,0 @@
import styled from '@emotion/styled';
import { useRecoilState } from 'recoil';
import { DEFAULT_FAST_MODEL } from '@/ai/constants/DefaultFastModel';
import { DEFAULT_SMART_MODEL } from '@/ai/constants/DefaultSmartModel';
import {
useAiModelLabel,
useAiModelOptions,
} from '@/ai/hooks/useAiModelOptions';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { aiModelsState } from '@/client-config/states/aiModelsState';
import {
StyledSettingsCardContent,
StyledSettingsCardDescription,
StyledSettingsCardIcon,
StyledSettingsCardTitle,
} from '@/settings/components/SettingsOptions/SettingsCardContentBase';
import { SettingsOptionIconCustomizer } from '@/settings/components/SettingsOptions/SettingsOptionIconCustomizer';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { Select } from '@/ui/input/components/Select';
import { t } from '@lingui/core/macro';
import { H2Title, IconBolt, IconBrain } from 'twenty-ui/display';
import { Card, Section } from 'twenty-ui/layout';
import { useUpdateWorkspaceMutation } from '~/generated-metadata/graphql';
import { useRecoilValueV2 } from '@/ui/utilities/state/jotai/hooks/useRecoilValueV2';
const StyledSelectContainer = styled.div`
justify-content: flex-end;
margin-left: auto;
max-width: 120px;
`;
const StyledErrorMessage = styled.div`
color: ${({ theme }) => theme.color.red};
font-size: ${({ theme }) => theme.font.size.sm};
margin-top: ${({ theme }) => theme.spacing(1)};
`;
export const SettingsAIRouterSettings = () => {
const { enqueueSuccessSnackBar, enqueueErrorSnackBar } = useSnackBar();
const [currentWorkspace, setCurrentWorkspace] = useRecoilState(
currentWorkspaceState,
);
const [updateWorkspace] = useUpdateWorkspaceMutation();
const aiModels = useRecoilValueV2(aiModelsState);
const activeModelOptions = useAiModelOptions();
const fastModelLabel = useAiModelLabel(currentWorkspace?.fastModel);
const smartModelLabel = useAiModelLabel(currentWorkspace?.smartModel);
const currentFastModel = aiModels.find(
(m) => m.modelId === currentWorkspace?.fastModel,
);
const currentSmartModel = aiModels.find(
(m) => m.modelId === currentWorkspace?.smartModel,
);
const fastModelOptions =
currentFastModel?.deprecated === true
? [
{
value: currentWorkspace?.fastModel ?? '',
label: `${fastModelLabel} (deprecated)`,
},
...activeModelOptions,
]
: activeModelOptions;
const smartModelOptions =
currentSmartModel?.deprecated === true
? [
{
value: currentWorkspace?.smartModel ?? '',
label: `${smartModelLabel} (deprecated)`,
},
...activeModelOptions,
]
: activeModelOptions;
const noModelsAvailable = activeModelOptions.length === 0;
const handleFastModelChange = async (value: string) => {
if (!currentWorkspace?.id) {
return;
}
const newValue = value;
const previousValue = currentWorkspace?.fastModel || DEFAULT_FAST_MODEL;
try {
setCurrentWorkspace({
...currentWorkspace,
fastModel: newValue,
});
await updateWorkspace({
variables: {
input: {
fastModel: newValue,
},
},
});
enqueueSuccessSnackBar({
message: t`Fast model updated successfully`,
});
} catch {
setCurrentWorkspace({
...currentWorkspace,
fastModel: previousValue,
});
enqueueErrorSnackBar({
message: t`Failed to update fast model`,
});
}
};
const handleSmartModelChange = async (value: string) => {
if (!currentWorkspace?.id) {
return;
}
const newValue = value;
const previousValue = currentWorkspace?.smartModel || DEFAULT_SMART_MODEL;
try {
setCurrentWorkspace({
...currentWorkspace,
smartModel: newValue,
});
await updateWorkspace({
variables: {
input: {
smartModel: newValue,
},
},
});
enqueueSuccessSnackBar({
message: t`Smart model updated successfully`,
});
} catch {
setCurrentWorkspace({
...currentWorkspace,
smartModel: previousValue,
});
enqueueErrorSnackBar({
message: t`Failed to update smart model`,
});
}
};
return (
<Section>
<H2Title
title={t`AI Models`}
description={t`Configure AI models for routing and planning`}
/>
{noModelsAvailable ? (
<Card rounded>
<StyledSettingsCardContent>
<StyledErrorMessage>
{t`No models available. Please configure AI models in your workspace settings.`}
</StyledErrorMessage>
</StyledSettingsCardContent>
</Card>
) : (
<Card rounded>
<StyledSettingsCardContent>
<StyledSettingsCardIcon>
<SettingsOptionIconCustomizer Icon={IconBolt} />
</StyledSettingsCardIcon>
<div>
<StyledSettingsCardTitle>{t`Fast Model`}</StyledSettingsCardTitle>
<StyledSettingsCardDescription>
{t`Quick model for routing decisions`}
</StyledSettingsCardDescription>
</div>
<StyledSelectContainer>
<Select
dropdownId="fast-model-select"
value={currentWorkspace?.fastModel || DEFAULT_FAST_MODEL}
onChange={handleFastModelChange}
options={fastModelOptions}
selectSizeVariant="small"
/>
</StyledSelectContainer>
</StyledSettingsCardContent>
<StyledSettingsCardContent>
<StyledSettingsCardIcon>
<SettingsOptionIconCustomizer Icon={IconBrain} />
</StyledSettingsCardIcon>
<div>
<StyledSettingsCardTitle>
{t`Smart Model`}
</StyledSettingsCardTitle>
<StyledSettingsCardDescription>
{t`Advanced model for complex planning`}
</StyledSettingsCardDescription>
</div>
<StyledSelectContainer>
<Select
dropdownId="smart-model-select"
value={currentWorkspace?.smartModel || DEFAULT_SMART_MODEL}
onChange={handleSmartModelChange}
options={smartModelOptions}
selectSizeVariant="small"
/>
</StyledSelectContainer>
</StyledSettingsCardContent>
</Card>
)}
</Section>
);
};
@@ -0,0 +1,23 @@
import {
IconBrandAnthropic,
IconBrandGoogle,
IconBrandGroq,
IconBrandMistral,
IconBrandOpenai,
IconBrandXai,
IconRobot,
type IconComponent,
} from 'twenty-ui/display';
export const PROVIDER_CONFIG: Record<
string,
{ label: string; Icon: IconComponent }
> = {
OPENAI: { label: 'OpenAI', Icon: IconBrandOpenai },
ANTHROPIC: { label: 'Anthropic', Icon: IconBrandAnthropic },
XAI: { label: 'xAI', Icon: IconBrandXai },
GOOGLE: { label: 'Google', Icon: IconBrandGoogle },
GROQ: { label: 'Groq', Icon: IconBrandGroq },
MISTRAL: { label: 'Mistral', Icon: IconBrandMistral },
NONE: { label: '', Icon: IconRobot },
};
@@ -1,8 +1,9 @@
export const SETTINGS_AI_TABS = {
COMPONENT_INSTANCE_ID: 'settings-ai-tab-list',
TABS_IDS: {
MODELS: 'models',
SKILLS: 'skills',
TOOLS: 'tools',
SETTINGS: 'settings',
MORE: 'more',
},
} as const;
@@ -0,0 +1,3 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="none" viewBox="0 0 1200 1200">
<path fill="currentColor" d="M233.96 800.21 468.64 668.54l3.95-11.44-3.95-6.36h-11.44l-39.22-2.42-134.09-3.62-116.3-4.83-112.67-6.04L26.58 627.79 0 592.75l2.74-17.48 23.84-16.03 34.15 2.98 75.46 5.15 113.24 7.81 82.15 4.83 121.69 12.65 19.33-.001 2.74-7.81-6.6-4.83-5.16-4.83L346.39 495.79 219.54 411.87l-66.44-48.32-35.92-24.48-18.12-22.96-7.81-50.09 32.62-35.92 43.81 2.98 11.2 2.98 44.37 34.15 94.79 73.37 123.79 91.17 18.12 15.06 7.25-5.15.89-3.63-8.14-13.61-67.46-121.69L320.78 181.93l-31.97-51.3-8.46-30.77c-2.98-12.64-5.15-23.27-5.15-36.24l37.13-50.42 20.54-6.6 49.53 6.6 20.86 18.12 30.77 70.39 49.85 110.82L561.18 363.22l22.63 44.7 12.08 41.4 4.51 12.64h7.81v-7.25l6.36-84.89 11.76-104.21 11.44-134.09 3.95-37.77 18.68-45.26 37.13-24.48 29 13.85 23.83 34.15-3.3 22.07-14.17 92.13-27.79 144.32-18.12 96.65 10.55-.001 12.08-12.08 48.89-64.91 82.15-102.68 36.24-40.75 42.28-45.02 27.14-21.42 51.3-.001 38.02 56.13-16.91 57.99-52.83 67.01-43.82 56.78-62.82 84.56-39.22 67.65 3.62 5.4 9.34-0.89 141.91-30.2 76.67-13.85 91.49-15.7 41.4 19.33 4.51 19.65-16.27 40.19-97.85 24.16-114.77 22.95-170.9 40.43-2.09 1.53 2.42 2.98 77 7.25 32.94 1.77 80.62-.001 150.12 11.2 39.22 25.93 23.52 31.73-3.95 24.16-60.4 30.77-81.5-19.33-190.23-45.26-65.46-16.27-9.02-.001v5.4l54.36 53.15 99.62 89.96 124.75 115.97 6.36 28.67-16.03 22.63-16.91-2.42-109.61-82.47-42.28-37.13-95.76-80.62-6.36-.001v8.46l22.07 32.29L919.09 1027.41l6.04 53.72-8.46 17.48-30.2 10.55-33.18-6.04-68.21-95.76-70.39-107.84-56.78-96.64-6.93 3.95-33.5 360.89-15.7 18.44-36.24 13.85-30.2-22.95-16.03-37.13 16.03-73.37 19.33-95.76 15.7-76.31 14.17-94.55 8.46-31.41-.56-2.09-6.93.89-71.28 97.85-108.68 146.5-85.77 91.81-20.54 8.14-35.6-18.44 3.3-32.94 19.89-29.32 118.71-150.9 71.6-93.58 46.23-54.04-.32-7.81-2.74-.001L205.29 929.4l-56.13 7.25-24.16-22.63 2.98-37.13 11.44-12.08 94.79-65.23-.32.32Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 32.25 142 55.5" fill="currentColor" preserveAspectRatio="xMidYMid meet">
<path d="M84.848 34.137c-9.798 0-17.769 7.971-17.769 17.77s7.971 17.769 17.769 17.769 17.77-7.971 17.77-17.769-7.972-17.77-17.77-17.77zm0 28.876c-6.124 0-11.106-4.983-11.106-11.106s4.982-11.106 11.106-11.106c6.124 0 11.106 4.982 11.106 11.106S90.973 63.013 84.848 63.013z" />
<path d="M60.315 34.206c-.607-.068-1.217-.104-1.827-.108-.304 0-.595.009-.893.014s-.594.033-.891.051c-1.197.094-2.382.299-3.541.611-2.329.629-4.574 1.723-6.515 3.277-1.97 1.57-3.548 3.575-4.611 5.859-.53 1.138-.921 2.336-1.165 3.567-.121.608-.21 1.222-.266 1.84-.02.307-.055.615-.059.921l-.011.459-.005.23v.19l.015 5.951.015 5.951.041 5.95h6.664l.042-5.95.015-5.952.015-5.951v-.182l.005-.142.008-.285c0-.191.028-.375.039-.564.036-.37.091-.738.165-1.102.146-.716.374-1.413.678-2.077.613-1.332 1.528-2.502 2.673-3.419 1.156-.932 2.541-1.628 4.038-2.042.757-.207 1.532-.344 2.314-.408.198-.011.395-.03.594-.037.199-.007.402-.013.595-.012.383 0 .76.025 1.142.06 1.518.153 2.989.619 4.318 1.368l3.326-5.776C65.108 35.263 62.753 34.484 60.315 34.206z" />
<path d="M17.77 34.048C7.971 34.048 0 42.019 0 51.817s7.971 17.77 17.77 17.77h5.844v-6.664H17.77c-6.124 0-11.106-4.982-11.106-11.106s4.982-11.106 11.106-11.106 11.132 4.982 11.132 11.106v16.365c0 6.084-4.954 11.039-11.023 11.103-2.904-.024-5.681-1.191-7.729-3.25l-4.712 4.712c3.266 3.283 7.691 5.151 12.321 5.201v.003c.04 0 .08 0 .119 0h.125v-.003c9.659-.131 17.48-8.005 17.525-17.686l.006-16.881C35.302 41.785 27.422 34.048 17.77 34.048z" />
<path d="M124.083 34.137c-9.798 0-17.769 7.971-17.769 17.77s7.971 17.769 17.769 17.769h6.08v-6.663h-6.08c-6.124 0-11.106-4.983-11.106-11.106s4.982-11.106 11.106-11.106c5.799 0 10.572 4.468 11.062 10.143h-.01v34.12h6.664V51.907C141.797 42.108 133.881 34.137 124.083 34.137z" />
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@@ -0,0 +1,14 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 129 91" fill="currentColor" preserveAspectRatio="xMidYMid meet">
<g>
<rect x="18.292" y="0" width="18.293" height="18.123" />
<rect x="91.473" y="0" width="18.293" height="18.123" />
<rect x="18.292" y="18.121" width="36.586" height="18.123" />
<rect x="73.181" y="18.121" width="36.586" height="18.123" />
<rect x="18.292" y="36.243" width="91.476" height="18.122" />
<rect x="18.292" y="54.37" width="18.293" height="18.123" />
<rect x="54.883" y="54.37" width="18.293" height="18.123" />
<rect x="91.473" y="54.37" width="18.293" height="18.123" />
<rect x="0" y="72.504" width="54.89" height="18.123" />
<rect x="73.181" y="72.504" width="54.89" height="18.123" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 778 B

@@ -0,0 +1,8 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.89 595.28" fill="currentColor" preserveAspectRatio="xMidYMid meet">
<g>
<polygon points="557.09,211.99 565.4,538.36 631.96,538.36 640.28,93.18" />
<polygon points="640.28,56.91 538.72,56.91 379.35,284.53 430.13,357.05" />
<polygon points="201.61,538.36 303.17,538.36 353.96,465.84 303.17,393.31" />
<polygon points="201.61,211.99 430.13,538.36 531.69,538.36 303.17,211.99" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 465 B

@@ -0,0 +1,19 @@
import { useTheme } from '@emotion/react';
import IconAnthropicRaw from '@assets/icons/anthropic.svg?react';
import { type IconComponentProps } from '@ui/display/icon/types/IconComponent';
type IconBrandAnthropicProps = Pick<IconComponentProps, 'size' | 'color'>;
export const IconBrandAnthropic = (props: IconBrandAnthropicProps) => {
const theme = useTheme();
const size = props.size ?? theme.icon.size.lg;
return (
<IconAnthropicRaw
height={size}
width={size}
color={props.color ?? 'currentColor'}
/>
);
};
@@ -0,0 +1,19 @@
import { useTheme } from '@emotion/react';
import IconBrandGroqRaw from '@assets/icons/groq.svg?react';
import { type IconComponentProps } from '@ui/display/icon/types/IconComponent';
type IconBrandGroqProps = Pick<IconComponentProps, 'size' | 'color'>;
export const IconBrandGroq = (props: IconBrandGroqProps) => {
const theme = useTheme();
const size = props.size ?? theme.icon.size.lg;
return (
<IconBrandGroqRaw
height={size}
width={size}
color={props.color ?? 'currentColor'}
/>
);
};
@@ -0,0 +1,19 @@
import { useTheme } from '@emotion/react';
import IconBrandMistralRaw from '@assets/icons/mistral.svg?react';
import { type IconComponentProps } from '@ui/display/icon/types/IconComponent';
type IconBrandMistralProps = Pick<IconComponentProps, 'size' | 'color'>;
export const IconBrandMistral = (props: IconBrandMistralProps) => {
const theme = useTheme();
const size = props.size ?? theme.icon.size.lg;
return (
<IconBrandMistralRaw
height={size}
width={size}
color={props.color ?? 'currentColor'}
/>
);
};
@@ -0,0 +1,19 @@
import { useTheme } from '@emotion/react';
import IconBrandXaiRaw from '@assets/icons/xai.svg?react';
import { type IconComponentProps } from '@ui/display/icon/types/IconComponent';
type IconBrandXaiProps = Pick<IconComponentProps, 'size' | 'color'>;
export const IconBrandXai = (props: IconBrandXaiProps) => {
const theme = useTheme();
const size = props.size ?? theme.icon.size.lg;
return (
<IconBrandXaiRaw
height={size}
width={size}
color={props.color ?? 'currentColor'}
/>
);
};
@@ -46,6 +46,7 @@ export {
IconBrandGoogle,
IconBrandGraphql,
IconBrandLinkedin,
IconBrandOpenai,
IconBrandX,
IconBriefcase,
IconBroadcast,
@@ -325,6 +326,7 @@ export {
IconSettings,
IconSettings2,
IconSettingsAutomation,
IconSettingsBolt,
IconShare,
IconShield,
IconSitemap,
+6
View File
@@ -34,6 +34,10 @@ export { CommandBlock } from './command-block/components/CommandBlock';
export type { IconProps } from './icon/components/Icon';
export { Icon } from './icon/components/Icon';
export { IconAddressBook } from './icon/components/IconAddressBook';
export { IconBrandAnthropic } from './icon/components/IconBrandAnthropic';
export { IconBrandGroq } from './icon/components/IconBrandGroq';
export { IconBrandMistral } from './icon/components/IconBrandMistral';
export { IconBrandXai } from './icon/components/IconBrandXai';
export { IconChartBarHorizontal } from './icon/components/IconChartBarHorizontal';
export { IconGmail } from './icon/components/IconGmail';
export { IconGoogle } from './icon/components/IconGoogle';
@@ -117,6 +121,7 @@ export {
IconBrandGoogle,
IconBrandGraphql,
IconBrandLinkedin,
IconBrandOpenai,
IconBrandX,
IconBriefcase,
IconBroadcast,
@@ -396,6 +401,7 @@ export {
IconSettings,
IconSettings2,
IconSettingsAutomation,
IconSettingsBolt,
IconShare,
IconShield,
IconSitemap,