diff --git a/public/locales/en/translation.json b/public/locales/en/translation.json index 5acb57b3e..14c2dd2c0 100644 --- a/public/locales/en/translation.json +++ b/public/locales/en/translation.json @@ -95,6 +95,14 @@ } } }, + "tabLayout": { + "statusBar": { + "prerun": { + "message": "This scenario has not been run yet.", + "tooltip": "This scenario has not been run yet." + } + } + }, "cytoviz": { "elementDetails": "Details", "loading": "Loading...", diff --git a/src/components/AppBar/AppBar.js b/src/components/AppBar/AppBar.js index b6f5ce463..9ced7e930 100644 --- a/src/components/AppBar/AppBar.js +++ b/src/components/AppBar/AppBar.js @@ -1,33 +1,47 @@ // Copyright (c) Cosmo Tech. // Licensed under the MIT license. +import { Bot, Languages } from 'lucide-react'; import React from 'react'; import PropTypes from 'prop-types'; -import { AppBar as MuiAppBar, Toolbar } from '@mui/material'; -import { HelpMenuWrapper, Logo, ThemeSwitch, UserInfoWrapper, WorkspaceInfo } from './components'; +import { Button, AppBar as MuiAppBar, Toolbar } from '@mui/material'; +import { StatusBar } from '../'; +import { useCurrentSimulationRunner } from '../../state/runner/hooks'; +import { ThemeSwitch } from './components'; export const AppBar = ({ children }) => { + const currentScenario = useCurrentSimulationRunner(); + return ( theme.palette.appbar.main, - color: (theme) => theme.palette.appbar.contrastText, + backgroundColor: (theme) => theme.palette.background.background01.main, + color: (theme) => theme.palette.neutral.neutral02.main, + boxShadow: 'none', + borderBottom: (theme) => `1px solid ${theme.palette.background.background02.main}`, }} > - - - {children} + + {children} + {currentScenario?.data?.name && ( + + )} + }> + CoPilot + - - - + theme.palette.neutral.neutral04.main }} + variant="default" + state="enabled" + startIcon={} + > + English + ); }; AppBar.propTypes = { - /** - * React component to be implemented in dynamic part of the app bar - */ children: PropTypes.node, }; diff --git a/src/components/AppBar/components/ThemeSwitch.js b/src/components/AppBar/components/ThemeSwitch.js index 6034d799a..d6f4607f3 100644 --- a/src/components/AppBar/components/ThemeSwitch.js +++ b/src/components/AppBar/components/ThemeSwitch.js @@ -1,30 +1,33 @@ // Copyright (c) Cosmo Tech. // Licensed under the MIT license. +import { Moon, Sun } from 'lucide-react'; import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; -import { Brightness2 as Brightness2Icon, WbSunny as WbSunnyIcon } from '@mui/icons-material'; -import { Fade, IconButton, Tooltip } from '@mui/material'; +import { Button, Fade, Tooltip } from '@mui/material'; import { useApplicationTheme } from '../../../state/app/hooks'; export const ThemeSwitch = () => { const { t } = useTranslation(); const { isDarkTheme, toggleTheme } = useApplicationTheme(); - const { tooltipText, icon } = useMemo( + const { tooltipText } = useMemo( () => ({ tooltipText: isDarkTheme ? t('genericcomponent.switchtheme.light', 'Switch to light') : t('genericcomponent.switchtheme.dark', 'Switch to dark'), - icon: isDarkTheme ? : , }), [t, isDarkTheme] ); return ( - theme.palette.appbar.contrastText }} onClick={toggleTheme} size="large"> - {icon} - + : } + onClick={toggleTheme} + /> ); }; diff --git a/src/components/CreateScenarioButton/CreateScenarioButtonHook.js b/src/components/CreateScenarioButton/CreateScenarioButtonHook.js index 3e6a69623..a22ef986f 100644 --- a/src/components/CreateScenarioButton/CreateScenarioButtonHook.js +++ b/src/components/CreateScenarioButton/CreateScenarioButtonHook.js @@ -26,7 +26,7 @@ export const useCreateScenarioButton = ({ disabled, onScenarioCreated }) => { const solution = useSolution(); const workspaceData = useWorkspaceData(); - const workspaceId = workspaceData.id; + const workspaceId = workspaceData?.id; const workspaceDatasets = useWorkspaceDatasets(); const usableDatasets = workspaceDatasets.filter( (dataset) => diff --git a/src/components/MainNavigation/MainNavigation.js b/src/components/MainNavigation/MainNavigation.js index 45df96de6..21341b668 100644 --- a/src/components/MainNavigation/MainNavigation.js +++ b/src/components/MainNavigation/MainNavigation.js @@ -44,19 +44,19 @@ export const MainNavigation = ({ activeSection, onSectionChange, onDrawerWidthCh const isUserMenuOpen = Boolean(userMenuAnchor); const [activeUserMenuItem, setActiveUserMenuItem] = useState('profile'); - const navigationPalette = theme.palette?.navigation; + const navigationPalette = theme.palette; const navColors = { - background: navigationPalette?.background, - border: navigationPalette?.border, - text: navigationPalette?.text, - hoverBg: navigationPalette?.hoverBg, - mutedBg: navigationPalette?.mutedBg, - activeBg: navigationPalette?.activeBg, - activeText: navigationPalette?.activeText, - icon: navigationPalette?.icon, - menuBackground: navigationPalette?.menuBackground, - scrollbarThumb: navigationPalette?.scrollbarThumb, - scrollbarThumbHover: navigationPalette?.scrollbarThumbHover, + background: navigationPalette?.background.background01.main, + border: navigationPalette?.background.background02.main, + text: navigationPalette?.secondary.main, + hoverBg: navigationPalette?.background.background02.main, + mutedBg: navigationPalette?.neutral.neutral05.main, + activeBg: navigationPalette?.neutral.neutral04.main, + activeText: navigationPalette?.neutral.neutral04.main, + icon: navigationPalette?.secondary.main, + menuBackground: navigationPalette?.neutral.neutral04.main, + scrollbarThumb: navigationPalette?.neutral.neutral06.main, + scrollbarThumbHover: navigationPalette?.neutral.neutral07.main, }; const publicUrl = ConfigService.getParameterValue('PUBLIC_URL') ?? ''; diff --git a/src/components/MainNavigation/components/ScenarioList.js b/src/components/MainNavigation/components/ScenarioList.js index 6fcfbf083..9ad51a392 100644 --- a/src/components/MainNavigation/components/ScenarioList.js +++ b/src/components/MainNavigation/components/ScenarioList.js @@ -39,7 +39,7 @@ const buildScenarioTree = (scenarios) => { export const ScenarioList = ({ disabled, scenarios, activeScenarioId, onScenarioChange, isCollapsed }) => { const theme = useTheme(); - const navColors = theme.palette?.navigation ?? {}; + const navColors = theme.palette ?? {}; const scenarioTree = useMemo(() => buildScenarioTree(scenarios), [scenarios]); const handleScenarioClick = (scenarioId) => { @@ -67,16 +67,16 @@ export const ScenarioList = ({ disabled, scenarios, activeScenarioId, onScenario mb: 0.5, '&::-webkit-scrollbar': { width: 8, - border: `1px solid ${navColors.border}`, + border: `1px solid ${navColors.background.background02.main}`, }, '&::-webkit-scrollbar-track': { background: 'transparent', }, '&::-webkit-scrollbar-thumb': { - background: navColors.scrollbarThumb, + background: navColors.neutral.neutral06.main, borderRadius: '4px', '&:hover': { - background: navColors.scrollbarThumbHover, + background: navColors.neutral.neutral07.main, }, }, }} diff --git a/src/components/MainNavigation/components/UserMenu.js b/src/components/MainNavigation/components/UserMenu.js index a0d86f036..c72403646 100644 --- a/src/components/MainNavigation/components/UserMenu.js +++ b/src/components/MainNavigation/components/UserMenu.js @@ -8,7 +8,7 @@ import { useTheme } from '@mui/material/styles'; export const UserMenu = ({ anchorEl, open, onClose, userName, userEmail, activeUserMenuItem, onMenuAction }) => { const theme = useTheme(); - const navColors = theme.palette?.navigation ?? {}; + const navColors = theme.palette ?? {}; const menuItems = [ { id: 'settings', label: 'Settings', icon: Settings }, { id: 'profile', label: 'Profile', icon: User }, @@ -39,8 +39,8 @@ export const UserMenu = ({ anchorEl, open, onClose, userName, userEmail, activeU paper: { sx: { borderRadius: '4px', - border: `1px solid ${navColors.border}`, - backgroundColor: navColors.menuBackground, + border: `1px solid ${navColors.background.background02.main}`, + backgroundColor: navColors.neutral.neutral04.main, minWidth: 200, mt: 1, p: 0, @@ -54,13 +54,13 @@ export const UserMenu = ({ anchorEl, open, onClose, userName, userEmail, activeU px: 2, pt: 2, pb: 1, - borderBottom: `1px solid ${navColors.border}`, + borderBottom: `1px solid ${navColors.background.background02.main}`, }} > @@ -69,7 +69,7 @@ export const UserMenu = ({ anchorEl, open, onClose, userName, userEmail, activeU {userEmail || 'Anonymous'} @@ -90,18 +90,18 @@ export const UserMenu = ({ anchorEl, open, onClose, userName, userEmail, activeU py: 1.25, minHeight: 48, gap: 1.5, - color: navColors.text, + color: navColors.secondary.main, borderRadius: 0, - backgroundColor: isActive ? navColors.mutedBg : navColors.menuBackground, + backgroundColor: isActive ? navColors.neutral.neutral05.main : navColors.neutral.neutral04.main, '&:hover': { - backgroundColor: navColors.mutedBg, + backgroundColor: navColors.neutral.neutral05.main, }, }} > @@ -120,7 +120,7 @@ export const UserMenu = ({ anchorEl, open, onClose, userName, userEmail, activeU })} - + diff --git a/src/components/MainNavigation/components/UserProfile.js b/src/components/MainNavigation/components/UserProfile.js index 0fab5005f..050154ec4 100644 --- a/src/components/MainNavigation/components/UserProfile.js +++ b/src/components/MainNavigation/components/UserProfile.js @@ -10,7 +10,7 @@ import { getNavigationItemStyles, getListItemIconStyles, getListItemTextStyles } export const UserProfile = ({ userName, userEmail, userProfilePic, isCollapsed, onUserMenuClick, isUserMenuOpen }) => { const theme = useTheme(); - const navColors = theme.palette?.navigation ?? {}; + const navColors = theme.palette ?? {}; const truncatedEmail = React.useMemo(() => { if (!userEmail) return 'Anonymous'; if (userEmail.length > 25) { @@ -55,7 +55,7 @@ export const UserProfile = ({ userName, userEmail, userProfilePic, isCollapsed, diff --git a/src/components/ShareCurrentScenarioButton/ShareCurrentScenarioButtonHook.js b/src/components/ShareCurrentScenarioButton/ShareCurrentScenarioButtonHook.js index adaefef6e..fb6e713f1 100644 --- a/src/components/ShareCurrentScenarioButton/ShareCurrentScenarioButtonHook.js +++ b/src/components/ShareCurrentScenarioButton/ShareCurrentScenarioButtonHook.js @@ -40,7 +40,7 @@ export const useShareCurrentScenarioButton = () => { return SecurityUtils.getScenarioPermissionsLabels(t, permissionsNames); }, [permissions.runner, t]); - const workspaceUsers = useMemo(() => workspaceData.users.map((user) => ({ id: user })), [workspaceData.users]); + const workspaceUsers = useMemo(() => workspaceData?.users?.map((user) => ({ id: user })), [workspaceData?.users]); const accessListSpecific = useMemo( () => currentScenarioData?.security?.accessControlList ?? [], diff --git a/src/components/StatusBar/StatusBar.js b/src/components/StatusBar/StatusBar.js new file mode 100644 index 000000000..648e6d763 --- /dev/null +++ b/src/components/StatusBar/StatusBar.js @@ -0,0 +1,142 @@ +// Copyright (c) Cosmo Tech. +// Licensed under the MIT license. +import { TriangleAlert, Lock, CircleHelp, CircleCheck } from 'lucide-react'; +import React, { Fragment } from 'react'; +import PropTypes from 'prop-types'; +import { Box, Tooltip, Typography, useTheme } from '@mui/material'; + +const STATUS_CONFIG = (theme) => ({ + valid: { + label: 'Valid', + bg: theme.palette.neutral.neutral08.main, + text: theme.palette.status.success.main, + icon: , + }, + invalid: { + label: 'Invalid', + bg: theme.palette.status.error.background, + text: theme.palette.status.error.main, + icon: , + }, + edited: { + label: 'Edited', + bg: theme.palette.status.warning.background, + text: theme.palette.status.warning.main, + icon: , + }, + prerun: { + label: 'Pre-run', + bg: theme.palette.status.information.background, + text: theme.palette.status.information.main, + icon: , + }, + locked: { + label: 'Locked', + bg: theme.palette.neutral.neutral03.main, + text: theme.palette.neutral.neutral02.main, + icon: , + }, +}); + +const SIZE_CONFIG = { + small: { height: 36, padding: '0 8px', fontSize: '14px' }, + medium: { height: 36, padding: '0 8px', fontSize: '14px' }, + full: { height: 44, padding: '0 16px', fontSize: '14px' }, +}; + +export const StatusBar = ({ status, size, message, tooltip }) => { + const sizeConfig = SIZE_CONFIG[size]; + const theme = useTheme(); + const statusConfig = STATUS_CONFIG(theme)[status]; + + if (!statusConfig) return null; + + return ( + + {statusConfig.icon} + + {size !== 'small' && ( + + + Status: + + + theme.palette.secondary.main, + }} + > + {statusConfig.label} + {size === 'full' ? ':' : ''} + + + )} + + {size === 'full' && message && ( + theme.palette.secondary.main, + }} + > + {message} + + )} + theme.palette.neutral.neutral04.main, + color: (theme) => theme.palette.secondary.main, + }, + }, + }} + > + + + + + + ); +}; + +StatusBar.propTypes = { + status: PropTypes.oneOf(['valid', 'invalid', 'edited', 'prerun', 'locked']).isRequired, + size: PropTypes.oneOf(['small', 'medium', 'full']), + message: PropTypes.string, + tooltip: PropTypes.string, +}; + +StatusBar.defaultProps = { + size: 'medium', + message: '', +}; diff --git a/src/components/StatusBar/index.js b/src/components/StatusBar/index.js new file mode 100644 index 000000000..f3ca8d09e --- /dev/null +++ b/src/components/StatusBar/index.js @@ -0,0 +1,4 @@ +// Copyright (c) Cosmo Tech. +// Licensed under the MIT license. + +export { StatusBar } from './StatusBar'; diff --git a/src/components/StyledErrorContainer/StyledErrorContainer.js b/src/components/StyledErrorContainer/StyledErrorContainer.js index c813878f9..1f0551fc3 100644 --- a/src/components/StyledErrorContainer/StyledErrorContainer.js +++ b/src/components/StyledErrorContainer/StyledErrorContainer.js @@ -11,7 +11,7 @@ const Container = styled('div')(({ theme }) => ({ position: 'absolute', textAlign: 'center', padding: '5px 0', - backgroundColor: theme.palette.error.main, + backgroundColor: theme.palette.error, color: theme.palette.error.contrastText, display: 'flex', flexDirection: 'column', diff --git a/src/components/index.js b/src/components/index.js index f08fbfd7e..44034e5e3 100644 --- a/src/components/index.js +++ b/src/components/index.js @@ -27,3 +27,4 @@ export { ScenarioSelect, } from './ScenarioParameters'; export { default as LoadingBackdrop } from './LoadingBackdrop'; +export { StatusBar } from './StatusBar'; diff --git a/src/hooks/DynamicValuesHooks.js b/src/hooks/DynamicValuesHooks.js index efda49fab..d3de9badb 100644 --- a/src/hooks/DynamicValuesHooks.js +++ b/src/hooks/DynamicValuesHooks.js @@ -98,7 +98,7 @@ export const useDynamicValues = (parameter, targetDatasetId) => { const dynamicValuesError = useMemo( () => typeof dynamicValues === 'string' ? ( - theme.palette.error.main }}>{dynamicValues} + theme.palette.error }}>{dynamicValues} ) : null, [dynamicValues] ); diff --git a/src/layouts/TabLayout/TabLayout.js b/src/layouts/TabLayout/TabLayout.js index 0f4fcc846..a6efa9550 100644 --- a/src/layouts/TabLayout/TabLayout.js +++ b/src/layouts/TabLayout/TabLayout.js @@ -1,17 +1,20 @@ // Copyright (c) Cosmo Tech. // Licensed under the MIT license. -import React, { useEffect } from 'react'; +import { CircleArrowRight } from 'lucide-react'; +import React, { Fragment, useEffect } from 'react'; +import { useTranslation } from 'react-i18next'; import { useLocation, Outlet, useParams, useNavigate } from 'react-router-dom'; -import { Box, Breadcrumbs, Link as MuiLink, Stack } from '@mui/material'; -import { ApplicationErrorBanner } from '../../components'; +import { Link as MuiLink, Box, Stack, Typography } from '@mui/material'; +import { ApplicationErrorBanner, StatusBar } from '../../components'; import { AppBar } from '../../components/AppBar'; import { MainNavigation } from '../../components/MainNavigation'; -import { useGetRunner } from '../../state/runner/hooks'; +import { useCurrentSimulationRunner, useGetRunner } from '../../state/runner/hooks'; import { useSelectWorkspace, useWorkspace } from '../../state/workspaces/hooks'; export const TabLayout = () => { const location = useLocation(); const currentTabPathname = location?.pathname; + const { t } = useTranslation(); const routerParameters = useParams(); sessionStorage.removeItem('providedUrlBeforeSignIn'); @@ -19,6 +22,7 @@ export const TabLayout = () => { const navigate = useNavigate(); const selectWorkspace = useSelectWorkspace(); const getScenario = useGetRunner(); + const currentScenario = useCurrentSimulationRunner(); useEffect(() => { if (currentWorkspace?.status === 'ERROR') { @@ -48,31 +52,45 @@ export const TabLayout = () => { ); const BreadcrumbBar = () => ( - - - Workspaces - - - Overall - - - Main - - - ); - const StatusBar = () => ( - - StatusBar + + {currentWorkspace.data ? ( + + + {currentWorkspace?.data?.name} + + + + Scenarios + + + + {currentScenario?.data?.name} + + + ) : ( + {t('genericcomponent.workspaceselector.homebutton')} + )} ); return ( - + - + {currentScenario?.data && ( + + )} diff --git a/src/stories/atoms/StatusBar/StatusBar.stories.js b/src/stories/atoms/StatusBar/StatusBar.stories.js new file mode 100644 index 000000000..a6a955352 --- /dev/null +++ b/src/stories/atoms/StatusBar/StatusBar.stories.js @@ -0,0 +1,93 @@ +import React from 'react'; +import { StatusBar } from '../../../components'; + +export default { + title: 'Atoms/StatusBar', + component: StatusBar, + tags: ['autodocs'], + parameters: { + layout: 'centered', + }, + argTypes: { + status: { + control: 'select', + options: ['valid', 'invalid', 'edited', 'prerun', 'locked'], + }, + size: { + control: 'select', + options: ['small', 'medium', 'full'], + }, + message: { control: 'text' }, + tooltip: { control: 'text' }, + }, +}; + +const Template = (args) => ; + +export const Default = Template.bind({}); +Default.args = { + status: 'prerun', + size: 'medium', + message: '', + tooltip: 'Additional information', +}; + +export const StatusVariants = () => ( + + + + + + + +); + +export const SizeVariants = () => ( + + + + + +); + +export const FullWidthVariants = () => ( + + + + + + + +); + +export const StatusSizeMatrix = () => ( + + Status + Small + Medium + Full + + {['valid', 'invalid', 'edited', 'prerun', 'locked'].map((status) => ( + + {status} + + + + + + + + ))} + +); + +export const TooltipDemo = () => ( + +); diff --git a/src/theme/custom/cosmoDark/palette.js b/src/theme/custom/cosmoDark/palette.js index 7d7355362..ff6fa5d07 100644 --- a/src/theme/custom/cosmoDark/palette.js +++ b/src/theme/custom/cosmoDark/palette.js @@ -4,64 +4,68 @@ export default { type: 'dark', primary: { - main: '#a4bfe4', - light: '#d6f2ff', - dark: '#748fb2', - contrastText: '#000000', + main: '#FFB039', }, secondary: { - main: '#ffe26b', - dark: '#c9b03a', - light: '#ffff9c', - contrastText: '#000000', + main: '#292F33', }, - error: { - main: '#e57373', - dark: '#A05050', - light: '#EA8F8F', - contrastText: '#000000', + tertiary: { + main: '#F36121', }, - warning: { - main: '#ffa726', - dark: '#f57c00', - light: '#ffb74d', - contrastText: '#000000', + neutral: { + neutral01: { + main: '#47525F', + }, + neutral02: { + main: '#68788A', + }, + neutral03: { + main: '#919EAF', + }, + neutral04: { + main: '#FFFFFF', + }, + neutral05: { + main: '#E9EEF5', + }, + neutral06: { + main: 'rgba(204, 204, 204, 0.72)', + }, + neutral07: { + main: 'rgba(170, 170, 170, 0.72)', + }, + neutral08: { + main: '#DEECD0', + }, }, - info: { - main: '#67B8E3', - dark: '#48809E', - light: '#85C6E8', - contrastText: '#000000', + background: { + background01: { + main: '#F1F5F9', + }, + background02: { + main: '#D9DDE2', + }, }, - success: { - main: '#66bb6a', - dark: '#388e3c', - light: '#81c784', - contrastText: '#000000', + status: { + error: { + main: '#D32F2F', + background: '#ECD0D0', + }, + warning: { + main: '#8A8768', + background: '#ECDEC7', + }, + success: { + main: '#738A68', + background: '#DDECD0', + }, + information: { + main: '#516388', + background: '#D0D9EC', + }, }, microsoft: { - main: '#2F2F2F', - contrastText: '#FFFFFF', - }, - appbar: { - main: '#121212', - contrastText: '#FFFFFF', - contrastTextSoft: 'rgba(255, 255, 255, 0.7)', - }, - login: { - main: '#2F363B', - }, - navigation: { - background: '#1F252A', - border: '#2F363B', - text: '#FFFFFF', - hoverBg: '#2A3139', - mutedBg: '#252C34', - activeBg: '#FFFFFF', - activeText: '#1F252A', - icon: '#FFFFFF', - menuBackground: '#2A3139', - scrollbarThumb: 'rgba(255, 255, 255, 0.35)', - scrollbarThumbHover: 'rgba(255, 255, 255, 0.5)', + main: '#FFFFFF', + contrastText: '#5E5E5E', }, }; diff --git a/src/theme/custom/cosmoLight/palette.js b/src/theme/custom/cosmoLight/palette.js index 03fcf49fc..ac1b7e8f0 100644 --- a/src/theme/custom/cosmoLight/palette.js +++ b/src/theme/custom/cosmoLight/palette.js @@ -4,68 +4,68 @@ export default { type: 'light', primary: { - main: '#466282', - contrastText: '#FFFFFF', + main: '#FFB039', }, secondary: { - main: '#ffb039', - contrastText: '#000000', + main: '#292F33', }, - text: { - secondary: 'rgba(0,0,0,0.6)', + tertiary: { + main: '#F36121', }, - error: { - main: '#d32f2f', - light: '#ef5350', - dark: '#c62828', - contrastText: '#FFFFFF', - }, - warning: { - main: '#ed6c02', - dark: '#e65100', - light: '#ff9800', - contrastText: '#000000', - }, - info: { - main: '#0288d1', - dark: '#01579b', - light: '#03a9f4', - contrastText: '#000000', - }, - success: { - main: '#2e7d32', - dark: '#1b5e20', - light: '#4caf50', - contrastText: '#FFFFFF', + neutral: { + neutral01: { + main: '#47525F', + }, + neutral02: { + main: '#68788A', + }, + neutral03: { + main: '#919EAF', + }, + neutral04: { + main: '#FFFFFF', + }, + neutral05: { + main: '#E9EEF5', + }, + neutral06: { + main: 'rgba(204, 204, 204, 0.72)', + }, + neutral07: { + main: 'rgba(170, 170, 170, 0.72)', + }, + neutral08: { + main: '#DEECD0', + }, }, background: { - default: '#FAFAFA', + background01: { + main: '#F1F5F9', + }, + background02: { + main: '#D9DDE2', + }, + }, + status: { + error: { + main: '#D32F2F', + background: '#ECD0D0', + }, + warning: { + main: '#8A8768', + background: '#ECDEC7', + }, + success: { + main: '#738A68', + background: '#DDECD0', + }, + information: { + main: '#516388', + background: '#D0D9EC', + }, }, microsoft: { main: '#FFFFFF', contrastText: '#5E5E5E', }, - appbar: { - main: '#FFFFFF', - contrastText: '#000000', - }, - login: { - main: '#EBE7E2', - }, - navigation: { - background: '#F1F5F9', - border: '#D9DDE2', - text: '#292F33', - hoverBg: '#D9DDE2', - mutedBg: '#E9EEF5', - activeBg: '#292F33', - activeText: '#FFFFFF', - icon: '#292F33', - menuBackground: '#FFFFFF', - scrollbarThumb: 'rgba(204, 204, 204, 0.72)', - scrollbarThumbHover: 'rgba(170, 170, 170, 0.72)', - white: '#FFFFFF', - grey03: '#68788A', - grey04: '#919EAF', - }, }; diff --git a/src/theme/index.js b/src/theme/index.js index d8761104e..77f869f15 100644 --- a/src/theme/index.js +++ b/src/theme/index.js @@ -5,7 +5,7 @@ import createComponents from './overrides'; import typography from './typography'; export const getTheme = (isDarkTheme) => { - let theme = createTheme({ + const theme = createTheme({ colorSchemes: { light: { palette: paletteLight, picture: pictureLight, grid: gridLight }, dark: { palette: paletteDark, picture: pictureDark, grid: gridDark }, @@ -14,9 +14,7 @@ export const getTheme = (isDarkTheme) => { }); const components = createComponents(theme); - theme = createTheme(theme, { components }); - - return theme; + return createTheme(theme, { components }); }; export { paletteLight, paletteDark, pictureLight, pictureDark, gridLight, gridDark }; diff --git a/src/theme/overrides/MuiButton.js b/src/theme/overrides/MuiButton.js index aa8baecdf..2ff09c156 100644 --- a/src/theme/overrides/MuiButton.js +++ b/src/theme/overrides/MuiButton.js @@ -6,57 +6,56 @@ export default function MuiButton(theme) { const variants = getCosmoButtonVariants(theme.palette); return { - MuiButton: { - styleOverrides: { - root: ({ ownerState }) => { - const variant = ownerState.variant; - const state = ownerState.state ?? 'enabled'; - const iconOnly = ownerState.iconOnly; - - if (!variants[variant]) return {}; - - const cfg = variants[variant][state]; - if (!cfg) return {}; - - return { - textTransform: 'none', - fontFamily: "'Open Sans', sans-serif", - fontSize: '14px', - fontWeight: 600, - - padding: iconOnly ? '9.5px' : '8px 8px', - minWidth: iconOnly ? 'fit-content' : 'unset', - width: iconOnly ? 'fit-content' : 'auto', - - borderRadius: '6px', + styleOverrides: { + root: ({ ownerState }) => { + const variant = ownerState.variant; + const state = ownerState.state ?? 'enabled'; + const iconOnly = !ownerState?.children && !ownerState?.label; + + if (!variants[variant]) return {}; + + const cfg = variants[variant][state]; + if (!cfg) return {}; + + return { + textTransform: 'none', + fontFamily: "'Open Sans', sans-serif", + fontSize: '14px', + fontWeight: 600, + + padding: iconOnly ? '9.5px' : '8px 8px', + minWidth: iconOnly ? 'fit-content' : 'unset', + width: iconOnly ? 'fit-content' : 'auto', + + borderRadius: '6px', + background: cfg.bg, + color: cfg.text, + border: `1px solid ${cfg.border}`, + + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: 36, + gap: iconOnly ? 0 : '8px', + + '& svg': { + width: 16, + height: 16, + color: cfg.icon, + strokeWidth: 1.5, + margin: iconOnly ? 0 : undefined, + }, + + '& .MuiButton-startIcon': { + marginRight: '0 !important', + marginLeft: '0 !important', + }, + + '&:hover': { background: cfg.bg, - color: cfg.text, - border: `1px solid ${cfg.border}`, - - display: 'inline-flex', - alignItems: 'center', - justifyContent: 'center', - gap: iconOnly ? 0 : '8px', - - '& svg': { - width: 16, - height: 16, - color: cfg.icon, - strokeWidth: 1.5, - margin: iconOnly ? 0 : undefined, - }, - - '& .MuiButton-startIcon': { - marginRight: '0 !important', - marginLeft: '0 !important', - }, - - '&:hover': { - background: cfg.bg, - opacity: 0.9, - }, - }; - }, + opacity: 0.9, + }, + }; }, }, }; diff --git a/src/theme/overrides/MuiListItemButton.js b/src/theme/overrides/MuiListItemButton.js index 8577e5ca7..c85915198 100644 --- a/src/theme/overrides/MuiListItemButton.js +++ b/src/theme/overrides/MuiListItemButton.js @@ -5,14 +5,14 @@ const MuiListItemButton = (theme) => ({ { props: { variant: 'navigation' }, style: () => { - const navColors = theme.palette.navigation; + const navColors = theme.palette; return { borderRadius: 18, padding: theme.spacing(1, 1.5), minHeight: 40, fontFamily: theme.typography.fontFamily, fontWeight: theme.typography.fontWeightMedium, - color: navColors.text, + color: navColors.secondary.main, transition: theme.transitions.create(['background-color', 'color', 'width'], { duration: theme.transitions.duration.short, }), @@ -20,18 +20,18 @@ const MuiListItemButton = (theme) => ({ color: 'inherit', }, '&.Mui-selected': { - backgroundColor: navColors.activeBg, - color: navColors.activeText, + backgroundColor: navColors.secondary.main, + color: navColors.neutral.neutral04.main, '& .MuiListItemIcon-root': { - color: navColors.activeText, + color: navColors.neutral.neutral04.main, }, }, '&:hover': { - backgroundColor: navColors.hoverBg, - color: navColors.text, + backgroundColor: navColors.background.background02.main, + color: navColors.secondary.main, '&.Mui-selected': { - backgroundColor: navColors.activeBg, - color: navColors.activeText, + backgroundColor: navColors.secondary.main, + color: navColors.neutral.neutral04.main, }, }, }; diff --git a/src/theme/overrides/MuiListItemIcon.js b/src/theme/overrides/MuiListItemIcon.js index eab5fbcba..06066004b 100644 --- a/src/theme/overrides/MuiListItemIcon.js +++ b/src/theme/overrides/MuiListItemIcon.js @@ -5,13 +5,13 @@ const MuiListItemIcon = (theme) => ({ { props: { variant: 'navigation' }, style: () => { - const navColors = theme.palette.navigation; + const navColors = theme.palette; return { minWidth: 20, display: 'flex', justifyContent: 'flex-start', marginRight: theme.spacing(1.5), - color: navColors.text, + color: navColors.secondary.main, }; }, }, diff --git a/src/theme/overrides/MuiMenuItem.js b/src/theme/overrides/MuiMenuItem.js index 9cb7ab917..2bfc1fd8d 100644 --- a/src/theme/overrides/MuiMenuItem.js +++ b/src/theme/overrides/MuiMenuItem.js @@ -6,15 +6,15 @@ const MuiMenuItem = (theme) => ({ { props: { variant: 'navigation' }, style: () => { - const navColors = theme.palette.navigation; + const navColors = theme.palette; return { fontFamily: theme.typography.fontFamily, fontWeight: theme.typography.fontWeightMedium, fontSize: 14, - color: navColors.text, + color: navColors.secondary.main, borderRadius: 0, '&:hover': { - backgroundColor: navColors.mutedBg, + backgroundColor: navColors.neutral.neutral05.main, }, }; }, diff --git a/src/theme/overrides/index.js b/src/theme/overrides/index.js index 668629d26..84a1eb3f0 100644 --- a/src/theme/overrides/index.js +++ b/src/theme/overrides/index.js @@ -7,9 +7,9 @@ import MuiMenuItem from './MuiMenuItem'; export default function createComponents(theme) { return { - ...MuiButton(theme), - ...MuiListItemButton(theme), - ...MuiListItemIcon(theme), - ...MuiMenuItem(theme), + MuiButton: MuiButton(theme), + MuiListItemButton: MuiListItemButton(theme), + MuiListItemIcon: MuiListItemIcon(theme), + MuiMenuItem: MuiMenuItem(theme), }; } diff --git a/src/theme/overrides/utils/cosmoButton.variants.js b/src/theme/overrides/utils/cosmoButton.variants.js index ab1d2fb18..d316db96e 100644 --- a/src/theme/overrides/utils/cosmoButton.variants.js +++ b/src/theme/overrides/utils/cosmoButton.variants.js @@ -3,14 +3,14 @@ export const getCosmoButtonVariants = (palette) => { const COLOR = { - white: palette.navigation.background, - yellow: palette.secondary.main, - grey01: palette.navigation.text, - grey02: palette.primary.main, - grey03: palette.navigation.grey03, - grey04: palette.navigation.grey04, - grey05: palette.navigation.border, - grey06: palette.navigation.background, + white: palette.background.background01.main, + yellow: palette.primary.main, + grey01: palette.secondary.main, + grey02: palette.neutral.neutral01.main, + grey03: palette.neutral.neutral02.main, + grey04: palette.neutral.neutral03.main, + grey05: palette.background.background02.main, + grey06: palette.background.background01.main, }; const BASE_STATES = { diff --git a/src/views/AccessDenied/AccessDenied.js b/src/views/AccessDenied/AccessDenied.js index 3e85ef35c..ac227ba27 100644 --- a/src/views/AccessDenied/AccessDenied.js +++ b/src/views/AccessDenied/AccessDenied.js @@ -18,12 +18,12 @@ const buildErrorMessage = (error) => { }; const Root = styled('div')(({ theme }) => ({ - backgroundColor: theme.palette.login.main, + backgroundColor: theme.palette?.login?.main, height: '100%', })); const TitleDiv = styled('div')(({ theme }) => ({ - backgroundColor: theme.palette.login.main, + backgroundColor: theme.palette?.login.main, height: '100%', display: 'flex', justifyContent: 'center', @@ -104,7 +104,7 @@ const AccessDenied = ({ application }) => { theme.palette.error.main, + background: (theme) => theme.palette?.error?.main, paddingBottom: 8, paddingTop: 8, paddingLeft: 6, diff --git a/src/views/Dashboards/Dashboards.js b/src/views/Dashboards/Dashboards.js index 25fad68fe..7bc301980 100644 --- a/src/views/Dashboards/Dashboards.js +++ b/src/views/Dashboards/Dashboards.js @@ -43,7 +43,7 @@ const Dashboards = () => { width: '100%', maxWidth: '900px', '& .MuiTabs-indicator': { - backgroundColor: (theme) => theme.palette.primary.main, + backgroundColor: (theme) => theme.palette?.primary?.main, }, '& .MuiButtonBase-root': { maxWidth: '900px', diff --git a/src/views/SignIn/SignIn.js b/src/views/SignIn/SignIn.js index 2e732cf38..ab4e2f567 100644 --- a/src/views/SignIn/SignIn.js +++ b/src/views/SignIn/SignIn.js @@ -33,7 +33,7 @@ const classes = { }; const Root = styled('div')(({ theme }) => ({ - backgroundColor: theme.palette.login.main, + backgroundColor: theme.palette?.login?.main, height: '100%', [`&.${classes.errorPaper}`]: {