New toasts (#1777)

This commit is contained in:
Matthew Diamant
2025-03-24 12:32:39 -07:00
committed by GitHub
parent 6f2842bfbf
commit 0cac3c148d
15 changed files with 242 additions and 136 deletions
+8
View File
@@ -398,6 +398,14 @@ export default function App() {
<>
<ToastContainer
aria-label="Toast notifications"
toastClassName={() =>
`relative min-h-16 mb-4 p-2 rounded-lg
flex justify-between overflow-hidden cursor-pointer
text-textProminentInverse bg-bgStandardInverse dark:bg-bgAppInverse
`
}
style={{ width: '380px' }}
className="mt-6"
position="top-right"
autoClose={3000}
closeOnClick
+39 -28
View File
@@ -4,6 +4,12 @@ import { ExtensionConfig } from '../api';
import { toast } from 'react-toastify';
import React, { useState } from 'react';
import { initializeAgent as startAgent, replaceWithShims } from './utils';
import {
ToastError,
ToastInfo,
ToastLoading,
ToastSuccess,
} from '../components/settings/models/toasts';
// extensionUpdate = an extension was newly added or updated so we should attempt to add it
@@ -25,9 +31,10 @@ export const useAgent = () => {
return true;
} catch (error) {
console.error('Failed to initialize agent:', error);
toast.error(
`Failed to initialize agent: ${error instanceof Error ? error.message : 'Unknown error'}`
);
ToastError({
title: 'Failed to initialize agent',
errorMessage: error instanceof Error ? error.message : 'Unknown error',
});
return false;
}
};
@@ -84,10 +91,14 @@ export const useAgent = () => {
try {
let toastId;
if (!silent) {
toastId = toast.loading(`Adding ${extension.name} extension...`, {
position: 'top-center',
toastId = ToastLoading({
title: extension.name,
msg: 'Adding extension...',
toastOptions: { position: 'top-center' },
});
ToastInfo({
msg: 'Press the escape key to continue using goose while extension loads',
});
toast.info('Press the escape key to continue using goose while extension loads');
}
const response = await fetch(getApiUrl('/extensions/add'), {
@@ -108,14 +119,20 @@ export const useAgent = () => {
if (response.status === 428) {
if (!silent) {
if (toastId) toast.dismiss(toastId);
toast.error('Agent is not initialized. Please initialize the agent first.');
ToastError({
msg: 'Agent is not initialized. Please initialize the agent first.',
});
}
return response;
}
if (!silent) {
if (toastId) toast.dismiss(toastId);
toast.error(`Failed to add ${extension.name} extension: ${errorMsg}`);
ToastError({
title: extension.name,
msg: 'Failed to add extension',
errorMessage: errorMsg,
});
}
return response;
}
@@ -135,40 +152,34 @@ export const useAgent = () => {
if (!data.error) {
if (!silent) {
if (toastId) toast.dismiss(toastId);
toast.success(`Successfully enabled ${extension.name} extension`);
ToastSuccess({
title: extension.name,
msg: 'Successfully added extension',
});
}
return response;
}
console.log('Error trying to send a request to the extensions endpoint');
const errorMessage = `Error adding ${extension.name} extension${data.message ? `. ${data.message}` : ''}`;
const ErrorMsg = ({ closeToast }: { closeToast?: () => void }) => (
<div className="flex flex-col gap-1">
<div>Error adding {extension.name} extension</div>
<div>
<button
className="text-sm rounded px-2 py-1 bg-gray-400 hover:bg-gray-300 text-white cursor-pointer"
onClick={() => {
navigator.clipboard.writeText(data.message || 'Unknown error');
closeToast?.();
}}
>
Copy error message
</button>
</div>
</div>
);
console.error(errorMessage);
if (toastId) toast.dismiss(toastId);
toast(ErrorMsg, { type: 'error', autoClose: false });
ToastError({
title: extension.name,
msg: 'Failed to add extension',
errorMessage: data.message,
});
return response;
} catch (error) {
console.log('Got some other error');
const errorMessage = `Failed to add ${extension.name} extension: ${error instanceof Error ? error.message : 'Unknown error'}`;
console.error(errorMessage);
toast.error(errorMessage, { autoClose: false });
ToastError({
title: extension.name,
msg: 'Failed to add extension',
errorMessage: error.message,
});
throw error;
}
};
+1
View File
@@ -27,6 +27,7 @@ import {
getTextContent,
createAssistantMessage,
} from '../types/message';
import { ToastSuccess } from './settings/models/toasts';
export interface ChatType {
id: string;
+14 -12
View File
@@ -12,9 +12,9 @@ import { createSelectedModel } from './settings/models/utils';
import { getDefaultModel } from './settings/models/hardcoded_stuff';
import { initializeSystem } from '../utils/providerUtils';
import { getApiUrl, getSecretKey } from '../config';
import { toast } from 'react-toastify';
import { getActiveProviders, isSecretKey } from './settings/api_keys/utils';
import { BaseProviderGrid, getProviderDescription } from './settings/providers/BaseProviderGrid';
import { ToastError, ToastSuccess } from './settings/models/toasts';
interface ProviderGridProps {
onSubmit?: () => void;
@@ -55,9 +55,10 @@ export function ProviderGrid({ onSubmit }: ProviderGridProps) {
addRecentModel(model);
localStorage.setItem('GOOSE_PROVIDER', providerId);
toast.success(
`Selected ${provider.name} provider. Starting Goose with default model: ${getDefaultModel(provider.name.toLowerCase().replace(/ /g, '_'))}.`
);
ToastSuccess({
title: provider.name,
msg: `Starting Goose with default model: ${getDefaultModel(provider.name.toLowerCase().replace(/ /g, '_'))}.`,
});
onSubmit?.();
};
@@ -134,11 +135,10 @@ export function ProviderGrid({ onSubmit }: ProviderGridProps) {
}
}
toast.success(
isUpdate
? `Successfully updated configuration for ${provider}`
: `Successfully added configuration for ${provider}`
);
ToastSuccess({
title: provider,
msg: isUpdate ? `Successfully updated configuration` : `Successfully added configuration`,
});
const updatedKeys = await getActiveProviders();
setActiveKeys(updatedKeys);
@@ -147,9 +147,11 @@ export function ProviderGrid({ onSubmit }: ProviderGridProps) {
setSelectedId(null);
} catch (error) {
console.error('Error handling modal submit:', error);
toast.error(
`Failed to ${providers.find((p) => p.id === selectedId)?.isConfigured ? 'update' : 'add'} configuration for ${provider}`
);
ToastError({
title: provider,
msg: `Failed to ${providers.find((p) => p.id === selectedId)?.isConfigured ? 'update' : 'add'} configuration`,
errorMessage: error.message,
});
}
};
@@ -1,6 +1,5 @@
import React, { useState, useEffect } from 'react';
import { ScrollArea } from '../ui/scroll-area';
import { toast } from 'react-toastify';
import { Settings as SettingsType } from './types';
import {
FullExtensionConfig,
@@ -16,6 +15,7 @@ import { RecentModelsRadio } from './models/RecentModels';
import { ExtensionItem } from './extensions/ExtensionItem';
import type { View } from '../../App';
import { ModeSelection } from './basic/ModeSelection';
import { ToastSuccess } from './models/toasts';
const EXTENSIONS_DESCRIPTION =
'The Model Context Protocol (MCP) is a system that allows AI models to securely connect with local or remote resources using standard server setups. It works like a client-server setup and expands AI capabilities using three main components: Prompts, Resources, and Tools.';
@@ -164,7 +164,10 @@ export default function SettingsView({
const response = await removeExtension(extensionBeingConfigured.name, true);
if (response.ok) {
toast.success(`Successfully removed ${extensionBeingConfigured.name} extension`);
ToastSuccess({
title: extensionBeingConfigured.name,
msg: `Successfully removed extension`,
});
// Remove from localstorage
setSettings((prev) => ({
@@ -6,6 +6,7 @@ import { FullExtensionConfig } from '../../../extensions';
import { getApiUrl, getSecretKey } from '../../../config';
import { addExtension } from '../../../extensions';
import { toast } from 'react-toastify';
import { ToastError, ToastSuccess } from '../models/toasts';
interface ConfigureExtensionModalProps {
isOpen: boolean;
@@ -68,12 +69,19 @@ export function ConfigureBuiltInExtensionModal({
throw new Error('Failed to add system configuration');
}
toast.success(`Successfully configured the ${extension.name} extension`);
ToastSuccess({
title: extension.name,
msg: `Successfully configured extension`,
});
onSubmit();
onClose();
} catch (error) {
console.error('Error configuring extension:', error);
toast.error('Failed to configure extension');
ToastError({
title: extension.name,
msg: `Failed to configure the extension`,
errorMessage: error.message,
});
} finally {
setIsSubmitting(false);
}
@@ -6,6 +6,7 @@ import { FullExtensionConfig } from '../../../extensions';
import { getApiUrl, getSecretKey } from '../../../config';
import { addExtension } from '../../../extensions';
import { toast } from 'react-toastify';
import { ToastError, ToastSuccess } from '../models/toasts';
interface ConfigureExtensionModalProps {
isOpen: boolean;
@@ -70,12 +71,19 @@ export function ConfigureExtensionModal({
throw new Error('Failed to add system configuration');
}
toast.success(`Successfully configured the ${extension.name} extension`);
ToastSuccess({
title: extension.name,
msg: `Successfully configured extension`,
});
onSubmit();
onClose();
} catch (error) {
console.error('Error configuring extension:', error);
toast.error('Failed to configure extension');
ToastError({
title: extension.name,
msg: `Failed to configure extension`,
errorMessage: error.message,
});
} finally {
setIsSubmitting(false);
}
@@ -7,6 +7,7 @@ import { toast } from 'react-toastify';
import Select from 'react-select';
import { createDarkSelectStyles, darkSelectTheme } from '../../ui/select-styles';
import { getApiUrl, getSecretKey } from '../../../config';
import { ToastError } from '../models/toasts';
interface ManualExtensionModalProps {
isOpen: boolean;
@@ -38,22 +39,22 @@ export function ManualExtensionModal({ isOpen, onClose, onSubmit }: ManualExtens
e.preventDefault();
if (!formData.id || !formData.name || !formData.description) {
toast.error('Please fill in all required fields');
ToastError({ title: 'Please fill in all required fields' });
return;
}
if (formData.type === 'stdio' && !formData.commandInput) {
toast.error('Command is required for stdio type');
ToastError({ title: 'Command is required for stdio type' });
return;
}
if (formData.type === 'sse' && !formData.uri) {
toast.error('URI is required for SSE type');
ToastError({ title: 'URI is required for SSE type' });
return;
}
if (formData.type === 'builtin' && !formData.name) {
toast.error('Name is required for builtin type');
ToastError({ title: 'Name is required for builtin type' });
return;
}
@@ -98,7 +99,7 @@ export function ManualExtensionModal({ isOpen, onClose, onSubmit }: ManualExtens
resetForm();
} catch (error) {
console.error('Error configuring extension:', error);
toast.error('Failed to configure extension');
ToastError({ title: 'Failed to configure extension', errorMessage: error.message });
}
};
@@ -1,37 +1,72 @@
import { toast } from 'react-toastify';
import { toast, ToastOptions } from 'react-toastify';
import React from 'react';
import { Model } from './ModelContext';
export function ToastSuccessModelSwitch(model: Model) {
const commonToastOptions: ToastOptions = {
position: 'top-right',
closeButton: false,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
};
type ToastSuccessProps = { title?: string; msg?: string; toastOptions?: ToastOptions };
export function ToastSuccess({ title, msg, toastOptions = {} }: ToastSuccessProps) {
return toast.success(
<div>
<strong>Model Changed</strong>
<div>Switched to {model.alias ?? model.name}</div>
{title ? <strong className="font-medium">{title}</strong> : null}
{title ? <div>{msg}</div> : null}
</div>,
{
position: 'top-right',
autoClose: 5000,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
}
{ ...commonToastOptions, autoClose: 3000, ...toastOptions }
);
}
export function ToastFailureGeneral(msg?: string) {
type ToastErrorProps = {
title?: string;
msg?: string;
errorMessage?: string;
toastOptions?: ToastOptions;
};
export function ToastError({ title, msg, errorMessage, toastOptions }: ToastErrorProps) {
return toast.error(
<div>
<strong>Error</strong>
<div>{msg}</div>
<div className="flex gap-4">
<div className="flex-grow">
{title ? <strong className="font-medium">{title}</strong> : null}
{msg ? <div>{msg}</div> : null}
</div>
<div className="flex-none flex items-center">
{errorMessage ? (
<button
className="text-textProminentInverse font-medium"
onClick={() => navigator.clipboard.writeText(errorMessage)}
>
Copy error
</button>
) : null}
</div>
</div>,
{
position: 'top-right',
autoClose: 3000,
hideProgressBar: true,
closeOnClick: true,
pauseOnHover: true,
draggable: true,
}
{ ...commonToastOptions, autoClose: errorMessage ? false : 5000, ...toastOptions }
);
}
type ToastLoadingProps = { title?: string; msg?: string; toastOptions?: ToastOptions };
export function ToastLoading({ title, msg, toastOptions }: ToastLoadingProps) {
return toast.loading(
<div>
{title ? <strong className="font-medium">{title}</strong> : null}
{title ? <div>{msg}</div> : null}
</div>,
{ ...commonToastOptions, autoClose: false, ...toastOptions }
);
}
type ToastInfoProps = { title?: string; msg?: string; toastOptions?: ToastOptions };
export function ToastInfo({ title, msg, toastOptions }: ToastInfoProps) {
return toast.info(
<div>
{title ? <strong className="font-medium">{title}</strong> : null}
{msg ? <div>{msg}</div> : null}
</div>,
{ ...commonToastOptions, ...toastOptions }
);
}
@@ -2,7 +2,7 @@ import { useModel } from './ModelContext'; // Import the useModel hook
import { Model } from './ModelContext';
import { useMemo } from 'react';
import { gooseModels } from './GooseModels';
import { ToastFailureGeneral, ToastSuccessModelSwitch } from './toasts';
import { ToastError, ToastSuccess } from './toasts';
import { initializeSystem } from '../../../utils/providerUtils';
import { useRecentModels } from './RecentModels';
@@ -32,12 +32,19 @@ export function useHandleModelSelection() {
console.log(`[${componentName}] Switched to model: ${model.name} (${model.provider})`);
// Display a success toast notification
ToastSuccessModelSwitch(model);
ToastSuccess({
title: 'Model changed',
msg: `Switched to ${model.alias ?? model.name}`,
});
} catch (error) {
// Handle errors gracefully
console.error(`[${componentName}] Failed to switch model:`, error);
// Display an error toast notification
ToastFailureGeneral(`Failed to switch to model: ${model.name}`);
ToastError({
title: model.name,
msg: `Failed to switch to model`,
errorMessage: error.message,
});
}
};
}
@@ -8,6 +8,7 @@ import { toast } from 'react-toastify';
import { getActiveProviders, isSecretKey } from '../api_keys/utils';
import { useModel } from '../models/ModelContext';
import { Button } from '../../ui/button';
import { ToastError, ToastSuccess } from '../models/toasts';
function ConfirmationModal({ message, onConfirm, onCancel }) {
return (
@@ -141,11 +142,10 @@ export function ConfigureProvidersGrid() {
}
}
toast.success(
isUpdate
? `Successfully updated configuration for ${provider}`
: `Successfully added configuration for ${provider}`
);
ToastSuccess({
title: provider,
msg: isUpdate ? `Successfully updated configuration` : `Successfully added configuration`,
});
const updatedKeys = await getActiveProviders();
setActiveKeys(updatedKeys);
@@ -155,9 +155,11 @@ export function ConfigureProvidersGrid() {
setModalMode('setup');
} catch (error) {
console.error('Error handling modal submit:', error);
toast.error(
`Failed to ${providers.find((p) => p.id === selectedForSetup)?.isConfigured ? 'update' : 'add'} configuration for ${provider}`
);
ToastError({
title: provider,
msg: `Failed to ${providers.find((p) => p.id === selectedForSetup)?.isConfigured ? 'update' : 'add'} configuration`,
errorMessage: error.message,
});
}
};
@@ -178,9 +180,8 @@ export function ConfigureProvidersGrid() {
try {
// Check if the selected provider is currently active
if (currentModel?.provider === providerToDelete.name) {
toast.error(
`Cannot delete the configuration for ${providerToDelete.name} because it's the provider of the current model (${currentModel.name}). Please switch to a different model first.`
);
const msg = `Cannot delete the configuration because it's the provider of the current model (${currentModel.name}). Please switch to a different model first.`;
ToastError({ title: providerToDelete.name, msg, errorMessage: msg });
setIsConfirmationOpen(false);
return;
}
@@ -208,13 +209,20 @@ export function ConfigureProvidersGrid() {
}
console.log('Configuration deleted successfully.');
toast.success(`Successfully deleted configuration for ${providerToDelete.name}`);
ToastSuccess({
title: providerToDelete.name,
msg: 'Successfully deleted configuration',
});
const updatedKeys = await getActiveProviders();
setActiveKeys(updatedKeys);
} catch (error) {
console.error('Error deleting configuration:', error);
toast.error(`Unable to delete configuration for ${providerToDelete.name}`);
ToastError({
title: providerToDelete.name,
msg: 'Failed to delete configuration',
errorMessage: error.message,
});
}
setIsConfirmationOpen(false);
};
@@ -7,7 +7,7 @@ import { QUICKSTART_GUIDE_URL } from '../providers/modal/constants';
import { Input } from '../../ui/input';
import { Select } from '../../ui/Select';
import { useConfig } from '../../ConfigContext';
import { ToastFailureGeneral, ToastSuccessModelSwitch } from '../../settings/models/toasts';
import { ToastError, ToastSuccess } from '../../settings/models/toasts';
import { initializeSystem } from '../../../../src/utils/providerUtils';
const ModalButtons = ({ onSubmit, onCancel }) => (
@@ -43,10 +43,16 @@ export const AddModelModal = ({ onClose }: AddModelModalProps) => {
await upsert('GOOSE_PROVIDER', provider, false);
await upsert('GOOSE_MODEL', modelName, false);
await initializeSystem(provider, modelName);
ToastSuccessModelSwitch({ provider, name: modelName });
ToastSuccess({
title: 'Model changed',
msg: `Switched to ${modelName}.`,
});
onClose();
} catch (e) {
ToastFailureGeneral(e.message);
ToastError({
title: 'Failed to add model',
errorMessage: e.message,
});
}
};
+40 -41
View File
@@ -5,6 +5,8 @@ import { type SettingsViewOptions } from './components/settings/SettingsView';
import { toast } from 'react-toastify';
import builtInExtensionsData from './built-in-extensions.json';
import { ToastError, ToastLoading, ToastSuccess } from './components/settings/models/toasts';
import { Toast } from 'react-toastify/dist/components';
// Hardcoded default extension timeout in seconds
export const DEFAULT_EXTENSION_TIMEOUT = 300;
@@ -82,7 +84,7 @@ export async function addExtension(
};
let toastId;
if (!silent) toastId = toast.loading(`Adding ${extension.name} extension...`);
if (!silent) toastId = ToastLoading({ title: extension.name, msg: 'Adding extension...' });
const response = await fetch(getApiUrl('/extensions/add'), {
method: 'POST',
@@ -98,38 +100,31 @@ export async function addExtension(
if (!data.error) {
if (!silent) {
if (toastId) toast.dismiss(toastId);
toast.success(`Successfully enabled ${extension.name} extension`);
ToastSuccess({ title: extension.name, msg: `Successfully enabled extension` });
}
return response;
}
const errorMessage = `Error adding ${extension.name} extension ${data.message ? `. ${data.message}` : ''}`;
const ErrorMsg = ({ closeToast }: { closeToast?: () => void }) => (
<div className="flex flex-col gap-1">
<div>Error adding {extension.name} extension</div>
<div>
<button
className="text-sm rounded px-2 py-1 bg-gray-400 hover:bg-gray-300 text-white cursor-pointer"
onClick={() => {
navigator.clipboard.writeText(data.message);
closeToast();
}}
>
Copy error message
</button>
</div>
</div>
);
const errorMessage = `Error adding extension`;
console.error(errorMessage);
if (toastId) toast.dismiss(toastId);
toast(ErrorMsg, { type: 'error', autoClose: false });
ToastError({
title: extension.name,
msg: errorMessage,
errorMessage: data.message,
toastOptions: { autoClose: false },
});
return response;
} catch (error) {
const errorMessage = `Failed to add ${extension.name} extension: ${error instanceof Error ? error.message : 'Unknown error'}`;
console.error(errorMessage);
toast.error(errorMessage, { autoClose: false });
ToastError({
title: extension.name,
msg: 'Failed to add extension',
errorMessage: error.message,
toastOptions: { autoClose: false },
});
throw error;
}
}
@@ -149,19 +144,29 @@ export async function removeExtension(name: string, silent: boolean = false): Pr
if (!data.error) {
if (!silent) {
toast.success(`Successfully disabled ${name} extension`);
ToastSuccess({ title: name, msg: 'Successfully disabled extension' });
}
return response;
}
const errorMessage = `Error removing ${name} extension${data.message ? `. ${data.message}` : ''}`;
console.error(errorMessage);
toast.error(errorMessage, { autoClose: false });
ToastError({
title: name,
msg: 'Error removing extension',
errorMessage: data.message,
toastOptions: { autoClose: false },
});
return response;
} catch (error) {
const errorMessage = `Failed to remove ${name} extension: ${error instanceof Error ? error.message : 'Unknown error'}`;
console.error(errorMessage);
toast.error(errorMessage, { autoClose: false });
ToastError({
title: name,
msg: 'Error removing extension',
errorMessage: error.message,
toastOptions: { autoClose: false },
});
throw error;
}
}
@@ -241,7 +246,12 @@ function envVarsRequired(config: ExtensionConfig) {
}
function handleError(message: string, shouldThrow = false): void {
toast.error(message, { autoClose: false });
ToastError({
title: 'Failed to install extension',
msg: message,
errorMessage: message,
toastOptions: { autoClose: false },
});
console.error(message);
if (shouldThrow) {
throw new Error(message);
@@ -253,19 +263,14 @@ export async function addExtensionFromDeepLink(
setView: (view: View, options: SettingsViewOptions) => void
) {
if (!url.startsWith('goose://extension')) {
handleError(
'Failed to install extension: Invalid URL: URL must use the goose://extension scheme'
);
handleError('Invalid URL: URL must use the goose://extension scheme');
return;
}
const parsedUrl = new URL(url);
if (parsedUrl.protocol !== 'goose:') {
handleError(
'Failed to install extension: Invalid protocol: URL must use the goose:// scheme',
true
);
handleError('Invalid protocol: URL must use the goose:// scheme', true);
}
// Check that all required fields are present and not empty
@@ -274,10 +279,7 @@ export async function addExtensionFromDeepLink(
for (const field of requiredFields) {
const value = parsedUrl.searchParams.get(field);
if (!value || value.trim() === '') {
handleError(
`Failed to install extension: The link is missing required field '${field}'`,
true
);
handleError(`The link is missing required field '${field}'`, true);
}
}
@@ -298,10 +300,7 @@ export async function addExtensionFromDeepLink(
// Check for security risk with npx -c command
const args = parsedUrl.searchParams.getAll('arg');
if (cmd === 'npx' && args.includes('-c')) {
handleError(
'Failed to install extension: npx with -c argument can lead to code injection',
true
);
handleError('npx with -c argument can lead to code injection', true);
}
const envList = parsedUrl.searchParams.getAll('env');
+6
View File
@@ -98,6 +98,8 @@
--background-prominent: var(--grey-80);
--background-standard: var(--grey-90);
--background-subtle: var(--grey-95);
--background-app-inverse: var(--constant-black);
--background-standard-inverse: var(--dark-grey-25);
--border-divider: var(--grey-90);
--border-inverse: var(--constant-white);
@@ -116,12 +118,15 @@
--text-prominent: var(--grey-10);
--text-standard: var(--grey-20);
--text-subtle: var(--grey-50);
--text-prominent-inverse: var(--constant-white);
&.dark {
--background-app: var(--constant-black);
--background-prominent: var(--dark-grey-40);
--background-standard: var(--dark-grey-25);
--background-subtle: var(--dark-grey-15);
--background-app-inverse: var(--constant-white);
--background-prominent-inverse: var(--grey-80);
--border-divider: var(--dark-grey-25);
--border-inverse: var(--constant-black);
@@ -140,6 +145,7 @@
--text-prominent: var(--constant-white);
--text-standard: var(--dark-grey-90);
--text-subtle: var(--dark-grey-60);
--text-prominent-inverse: var(--grey-20);
}
/* end arcade colors */
}
+3
View File
@@ -53,6 +53,8 @@ export default {
bgSubtle: 'var(--background-subtle)',
bgStandard: 'var(--background-standard)',
bgProminent: 'var(--background-prominent)',
bgAppInverse: 'var(--background-app-inverse)',
bgStandardInverse: 'var(--background-standard-inverse)',
borderSubtle: 'var(--border-subtle)',
borderStandard: 'var(--border-standard)',
@@ -61,6 +63,7 @@ export default {
textStandard: 'var(--text-standard)',
textSubtle: 'var(--text-subtle)',
textPlaceholder: 'var(--text-placeholder)',
textProminentInverse: 'var(--text-prominent-inverse)',
iconProminent: 'var(--icon-prominent)',
iconStandard: 'var(--icon-standard)',