mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	Feat/dark mode exp (#1137)
* feat: add dark mode theme * fix: feature metrics * fix: add color * styling * fix: add switch * fix: form sidebar * fix: remove console log * fix: add properties * fix: strategy container * feat: feature flag * fix: tests * fix: build * fix: logo * fix: icon * fix: update snapshots * fix: CES operator * fix: typography * fix: input styling * fix: remove initial load * fix: change flag name * fix: refactor to custom hook * fix: remove unused import * fix: dialog headers * fix: use uiConfig flags instead of flags
This commit is contained in:
		
							parent
							
								
									e6b72ff4a0
								
							
						
					
					
						commit
						6818a82cd1
					
				| @ -39,6 +39,7 @@ | ||||
|     "isready": "yarn lint && yarn fmt && yarn prepare" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@codemirror/lang-json": "6.0.0", | ||||
|     "@emotion/react": "11.9.3", | ||||
|     "@emotion/styled": "11.9.3", | ||||
|     "@mui/icons-material": "5.8.4", | ||||
| @ -62,6 +63,7 @@ | ||||
|     "@types/react-test-renderer": "17.0.2", | ||||
|     "@types/react-timeago": "4.1.3", | ||||
|     "@types/semver": "7.3.12", | ||||
|     "@uiw/react-codemirror": "4.11.4", | ||||
|     "@vitejs/plugin-react": "1.3.2", | ||||
|     "chart.js": "3.9.1", | ||||
|     "chartjs-adapter-date-fns": "2.0.0", | ||||
| @ -102,8 +104,7 @@ | ||||
|     "vite-tsconfig-paths": "3.5.0", | ||||
|     "vitest": "0.22.1", | ||||
|     "whatwg-fetch": "3.6.2", | ||||
|     "@codemirror/lang-json": "6.0.0", | ||||
|     "@uiw/react-codemirror": "4.11.4" | ||||
|     "@uiw/codemirror-theme-duotone": "^4.11.5" | ||||
|   }, | ||||
|   "jest": { | ||||
|     "moduleNameMapper": { | ||||
|  | ||||
							
								
								
									
										1
									
								
								frontend/src/assets/img/logoWithWhiteText.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								frontend/src/assets/img/logoWithWhiteText.svg
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1 @@ | ||||
| <svg id="bg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 653.4 251.24"><defs><style>.cls-1{fill:#fff;}.cls-2{fill:#1a4049;}.cls-3{fill:#817afe;}</style></defs><circle class="cls-1" cx="125.62" cy="125.62" r="80"/><polygon class="cls-1" points="137.05 91.33 137.05 114.19 137.05 137.05 159.9 137.05 159.9 114.19 159.9 91.33 137.05 91.33"/><polygon class="cls-1" points="114.19 114.19 114.19 91.33 91.33 91.33 91.33 114.19 91.33 137.05 91.33 159.9 114.19 159.9 137.05 159.9 137.05 137.05 114.19 137.05 114.19 114.19"/><polygon class="cls-2" points="137.05 91.33 137.05 114.19 137.05 137.05 159.9 137.05 159.9 114.19 159.9 91.33 137.05 91.33"/><polygon class="cls-2" points="114.19 114.19 114.19 91.33 91.33 91.33 91.33 114.19 91.33 137.05 91.33 159.9 114.19 159.9 137.05 159.9 137.05 137.05 114.19 137.05 114.19 114.19"/><rect class="cls-3" x="137.05" y="137.05" width="22.86" height="22.86"/><path class="cls-1" d="M251.58,139.13V112.77h11.93v25.06c0,7.36,3.91,12.2,11.27,12.2s11.27-4.84,11.27-12.2V112.77h12v26.36c0,12.67-8.48,21.8-23.1,21.8C260.06,160.93,251.58,151.8,251.58,139.13Z"/><path class="cls-1" d="M321.91,159.9H310.08V112.77h11.83v7.92a17.93,17.93,0,0,1,15.65-9c11.83,0,19.66,8.67,19.66,20.68V159.9h-12V134.75c0-7.45-4.38-12.39-11.46-12.39s-11.83,5-11.83,12.39Z"/><path class="cls-1" d="M369.42,91.34h11.92V159.9H369.42Z"/><path class="cls-1" d="M441.24,137v1.3H403.79c.47,7.36,5.87,13,13.69,13,7.55,0,10.62-3.82,11.46-5.12h11.74c-.75,4.84-7.17,15-23.2,15-15.27,0-25.61-10.61-25.61-24.77,0-14.63,10.24-24.78,24.68-24.78S441.24,121.62,441.24,137Zm-37.08-6.9h24.6c-1.77-6-6.15-9.31-12.21-9.31C410.12,120.78,405.65,124.23,404.16,130.09Z"/><path class="cls-1" d="M467.78,130.37h15.47c0-5.68-4.29-9.31-11.27-9.31-6.62,0-9,3.54-9.78,4.75h-12c1-4.94,6.89-14.25,21.8-14.25,14.62,0,22.73,7.64,22.73,18.81V146.3c0,2.89,1,4,3.72,4.29v9.59h-3.72c-6.06-.09-9.69-2.33-11-6.52-2.23,3.45-7.26,7.27-15.27,7.27-11.09,0-19.47-6.24-19.47-15.93S456.14,130.37,467.78,130.37Zm15.47,12.11v-4H469.74c-5.59,0-9,2-9,6.33,0,4.57,4.29,7.27,10.25,7.27C477.66,152.08,483.25,148.82,483.25,142.48Z"/><path class="cls-1" d="M523.12,140.62c-10.34-.74-17.33-5.59-17.33-14.72,0-8.85,8.1-14.44,20.77-14.44,17,0,21.8,8.76,23.1,13.32H537.09c-.84-1-3.54-4.28-10.62-4.28-5.68,0-8.66,1.86-8.66,4.75,0,2.61,2,4.29,6.7,4.94l8,.84c12.77,1.11,18,6,18,15.27,0,8.85-7.36,14.91-21.8,14.91-17.51,0-23.19-10.16-24.12-14.53h12.76c.47,1.11,3.35,5.31,11.36,5.31,6.62,0,9.69-2.24,9.69-5.22s-1.67-4.66-7-5.31C528.05,141.18,526.38,141,523.12,140.62Z"/><path class="cls-1" d="M571.55,159.9H559.72V91.34h11.83v29.35a17.93,17.93,0,0,1,15.65-9c11.83,0,19.66,8.67,19.66,20.68V159.9h-12V134.75c0-7.45-4.38-12.39-11.46-12.39s-11.83,5-11.83,12.39Z"/></svg> | ||||
| After Width: | Height: | Size: 2.6 KiB | 
| @ -17,7 +17,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         margin: '0 auto', | ||||
|         flex: 1, | ||||
|         width: '100%', | ||||
|         backgroundColor: theme.palette.grey[300], | ||||
|         backgroundColor: theme.palette.contentWrapper, | ||||
|     }, | ||||
|     content: { | ||||
|         width: '1250px', | ||||
|  | ||||
| @ -10,7 +10,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         }, | ||||
|     }, | ||||
|     icon: { | ||||
|         background: theme.palette.primary.main, | ||||
|         background: theme.palette.featureSegmentSearchBackground, | ||||
|         height: 48, | ||||
|         width: 48, | ||||
|         display: 'flex', | ||||
|  | ||||
| @ -2,7 +2,7 @@ import { makeStyles } from 'tss-react/mui'; | ||||
| 
 | ||||
| export const useStyles = makeStyles()(theme => ({ | ||||
|     badge: { | ||||
|         backgroundColor: theme.palette.primary.main, | ||||
|         backgroundColor: theme.palette.checkmarkBadge, | ||||
|         width: '75px', | ||||
|         height: '75px', | ||||
|         borderRadius: '50px', | ||||
|  | ||||
| @ -2,7 +2,7 @@ import { makeStyles } from 'tss-react/mui'; | ||||
| 
 | ||||
| export const useStyles = makeStyles()(theme => ({ | ||||
|     container: { | ||||
|         backgroundColor: theme.palette.sidebarContainer, | ||||
|         backgroundColor: theme.palette.codebox, | ||||
|         padding: '1rem', | ||||
|         borderRadius: theme.shape.borderRadiusMedium, | ||||
|         position: 'relative', | ||||
| @ -13,7 +13,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         margin: 0, | ||||
|         wordBreak: 'break-all', | ||||
|         whiteSpace: 'pre-wrap', | ||||
|         color: '#fff', | ||||
|         color: theme.palette.formSidebarTextColor, | ||||
|         fontSize: 14, | ||||
|     }, | ||||
|     icon: { | ||||
|  | ||||
| @ -1,10 +1,25 @@ | ||||
| import { makeStyles } from 'tss-react/mui'; | ||||
| 
 | ||||
| export const useStyles = makeStyles()(theme => ({ | ||||
|     constraintIconContainer: { | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|         borderRadius: '50%', | ||||
|         display: 'flex', | ||||
|         alignItems: 'center', | ||||
|         justifyContent: 'center', | ||||
|         marginRight: theme.spacing(1), | ||||
|         [theme.breakpoints.down(650)]: { | ||||
|             marginBottom: '1rem', | ||||
|             marginRight: 0, | ||||
|         }, | ||||
|     }, | ||||
|     constraintIcon: { | ||||
|         fill: '#fff', | ||||
|     }, | ||||
|     accordion: { | ||||
|         border: `1px solid ${theme.palette.dividerAlternative}`, | ||||
|         borderRadius: theme.shape.borderRadiusMedium, | ||||
|         backgroundColor: '#fff', | ||||
|         backgroundColor: theme.palette.constraintAccordion.background, | ||||
|         boxShadow: 'none', | ||||
|         margin: 0, | ||||
|     }, | ||||
| @ -14,7 +29,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         }, | ||||
|     }, | ||||
|     accordionEdit: { | ||||
|         backgroundColor: '#F6F6FA', | ||||
|         backgroundColor: theme.palette.constraintAccordion.editBackground, | ||||
|     }, | ||||
|     headerMetaInfo: { | ||||
|         display: 'flex', | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| import { Box, Tooltip } from '@mui/material'; | ||||
| import { Box, Tooltip, useTheme } from '@mui/material'; | ||||
| import { ReactComponent as NegatedIcon } from 'assets/icons/24_Negator.svg'; | ||||
| import { ReactComponent as NegatedIconOff } from 'assets/icons/24_Negator off.svg'; | ||||
| import { IConstraint } from 'interfaces/strategy'; | ||||
| @ -7,6 +7,7 @@ import { | ||||
|     StyledToggleButtonOn, | ||||
| } from '../StyledToggleButton'; | ||||
| import { ConditionallyRender } from '../../../../ConditionallyRender/ConditionallyRender'; | ||||
| import { ThemeMode } from 'component/common/ThemeMode/ThemeMode'; | ||||
| 
 | ||||
| interface InvertedOperatorButtonProps { | ||||
|     localConstraint: IConstraint; | ||||
| @ -16,35 +17,59 @@ interface InvertedOperatorButtonProps { | ||||
| export const InvertedOperatorButton = ({ | ||||
|     localConstraint, | ||||
|     setInvertedOperator, | ||||
| }: InvertedOperatorButtonProps) => ( | ||||
|     <Tooltip | ||||
|         title={ | ||||
|             Boolean(localConstraint.inverted) | ||||
|                 ? 'Remove negation' | ||||
|                 : 'Negate operator' | ||||
|         } | ||||
|         arrow | ||||
|     > | ||||
|         <Box sx={{ display: 'flex', alignItems: 'stretch' }}> | ||||
|             <ConditionallyRender | ||||
|                 condition={Boolean(localConstraint.inverted)} | ||||
|                 show={ | ||||
|                     <StyledToggleButtonOn | ||||
|                         onClick={setInvertedOperator} | ||||
|                         disableRipple | ||||
|                     > | ||||
|                         <NegatedIcon /> | ||||
|                     </StyledToggleButtonOn> | ||||
|                 } | ||||
|                 elseShow={ | ||||
|                     <StyledToggleButtonOff | ||||
|                         onClick={setInvertedOperator} | ||||
|                         disableRipple | ||||
|                     > | ||||
|                         <NegatedIconOff /> | ||||
|                     </StyledToggleButtonOff> | ||||
|                 } | ||||
|             /> | ||||
|         </Box> | ||||
|     </Tooltip> | ||||
| ); | ||||
| }: InvertedOperatorButtonProps) => { | ||||
|     const theme = useTheme(); | ||||
| 
 | ||||
|     return ( | ||||
|         <Tooltip | ||||
|             title={ | ||||
|                 Boolean(localConstraint.inverted) | ||||
|                     ? 'Remove negation' | ||||
|                     : 'Negate operator' | ||||
|             } | ||||
|             arrow | ||||
|         > | ||||
|             <Box sx={{ display: 'flex', alignItems: 'stretch' }}> | ||||
|                 <ConditionallyRender | ||||
|                     condition={Boolean(localConstraint.inverted)} | ||||
|                     show={ | ||||
|                         <StyledToggleButtonOn | ||||
|                             onClick={setInvertedOperator} | ||||
|                             disableRipple | ||||
|                         > | ||||
|                             <ThemeMode | ||||
|                                 darkmode={ | ||||
|                                     <NegatedIcon | ||||
|                                         style={{ | ||||
|                                             fill: theme.palette.background | ||||
|                                                 .paper, | ||||
|                                         }} | ||||
|                                     /> | ||||
|                                 } | ||||
|                                 lightmode={<NegatedIcon />} | ||||
|                             /> | ||||
|                         </StyledToggleButtonOn> | ||||
|                     } | ||||
|                     elseShow={ | ||||
|                         <StyledToggleButtonOff | ||||
|                             onClick={setInvertedOperator} | ||||
|                             disableRipple | ||||
|                         > | ||||
|                             <ThemeMode | ||||
|                                 darkmode={ | ||||
|                                     <NegatedIconOff | ||||
|                                         style={{ | ||||
|                                             fill: theme.palette.background | ||||
|                                                 .paper, | ||||
|                                         }} | ||||
|                                     /> | ||||
|                                 } | ||||
|                                 lightmode={<NegatedIconOff />} | ||||
|                             /> | ||||
|                         </StyledToggleButtonOff> | ||||
|                     } | ||||
|                 /> | ||||
|             </Box> | ||||
|         </Tooltip> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| @ -14,6 +14,7 @@ export const ConstraintIcon: VFC<IConstraintIconProps> = ({ compact }) => ( | ||||
|             borderRadius: '50%', | ||||
|             width: compact ? '18px' : '24px', | ||||
|             height: compact ? '18px' : '24px', | ||||
|             marginRight: '13px', | ||||
|         }} | ||||
|     > | ||||
|         <TrackChanges | ||||
|  | ||||
| @ -4,7 +4,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|     container: { | ||||
|         padding: theme.spacing(0.5, 1.5), | ||||
|         borderRadius: theme.shape.borderRadius, | ||||
|         backgroundColor: theme.palette.grey[200], | ||||
|         backgroundColor: theme.palette.constraintAccordion.operatorBackground, | ||||
|         lineHeight: 1.25, | ||||
|     }, | ||||
|     name: { | ||||
|  | ||||
| @ -2,8 +2,8 @@ import { makeStyles } from 'tss-react/mui'; | ||||
| 
 | ||||
| export const useStyles = makeStyles()(theme => ({ | ||||
|     dialogTitle: { | ||||
|         backgroundColor: theme.palette.primary.main, | ||||
|         color: '#fff', | ||||
|         backgroundColor: theme.palette.dialogHeaderBackground, | ||||
|         color: theme.palette.dialogHeaderText, | ||||
|         height: '150px', | ||||
|         padding: '2rem 3rem', | ||||
|         clipPath: ' ellipse(130% 115px at 120% 20%)', | ||||
|  | ||||
| @ -20,7 +20,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         borderRadius: 0, | ||||
|     }, | ||||
|     sidebar: { | ||||
|         backgroundColor: theme.palette.primary.main, | ||||
|         backgroundColor: theme.palette.formSidebar, | ||||
|         padding: '2rem', | ||||
|         flexGrow: 0, | ||||
|         flexShrink: 0, | ||||
| @ -42,7 +42,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         fontWeight: 'normal', | ||||
|     }, | ||||
|     subtitle: { | ||||
|         color: '#fff', | ||||
|         color: theme.palette.formSidebarTextColor, | ||||
|         marginBottom: '1rem', | ||||
|         display: 'flex', | ||||
|         justifyContent: 'space-between', | ||||
| @ -51,7 +51,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         fontSize: theme.fontSizes.bodySize, | ||||
|     }, | ||||
|     description: { | ||||
|         color: '#fff', | ||||
|         color: theme.palette.formSidebarTextColor, | ||||
|         zIndex: 1, | ||||
|         position: 'relative', | ||||
|     }, | ||||
| @ -72,7 +72,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         }, | ||||
|     }, | ||||
|     formContent: { | ||||
|         backgroundColor: '#fff', | ||||
|         backgroundColor: theme.palette.formBackground, | ||||
|         display: 'flex', | ||||
|         flexDirection: 'column', | ||||
|         padding: '3rem', | ||||
|  | ||||
| @ -3,7 +3,7 @@ import React, { FC, VFC, useEffect, useState, useContext } from 'react'; | ||||
| import { InstanceStatusBar } from 'component/common/InstanceStatus/InstanceStatusBar'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| import { Dialogue } from 'component/common/Dialogue/Dialogue'; | ||||
| import { Typography } from '@mui/material'; | ||||
| import { Typography, useTheme } from '@mui/material'; | ||||
| import { useNavigate } from 'react-router-dom'; | ||||
| import { IInstanceStatus } from 'interfaces/instance'; | ||||
| import { ADMIN } from 'component/providers/AccessProvider/permissions'; | ||||
| @ -91,6 +91,7 @@ export const InstanceStatus: FC = ({ children }) => { | ||||
|         useInstanceStatus(); | ||||
|     const { extendTrial } = useInstanceStatusApi(); | ||||
|     const { setToastApiError } = useToast(); | ||||
|     const theme = useTheme(); | ||||
| 
 | ||||
|     const onExtendTrial = async () => { | ||||
|         try { | ||||
| @ -102,7 +103,12 @@ export const InstanceStatus: FC = ({ children }) => { | ||||
|     }; | ||||
| 
 | ||||
|     return ( | ||||
|         <div style={{ height: '100%' }}> | ||||
|         <div | ||||
|             style={{ | ||||
|                 height: '100%', | ||||
|                 backgroundColor: theme.palette.background.paper, | ||||
|             }} | ||||
|         > | ||||
|             <ConditionallyRender | ||||
|                 condition={isBilling && Boolean(instanceStatus)} | ||||
|                 show={() => ( | ||||
|  | ||||
| @ -6,6 +6,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         justifyContent: 'center', | ||||
|         alignItems: 'center', | ||||
|         height: '100%', | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|     }, | ||||
|     img: { | ||||
|         width: '100px', | ||||
|  | ||||
| @ -6,6 +6,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         flexGrow: 1, | ||||
|         alignItems: 'center', | ||||
|         position: 'relative', | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|         maxWidth: '400px', | ||||
|         [theme.breakpoints.down('md')]: { | ||||
|             marginTop: theme.spacing(1), | ||||
|  | ||||
| @ -7,7 +7,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         '& + &': { | ||||
|             marginTop: theme.spacing(2), | ||||
|         }, | ||||
|         background: theme.palette.background.default, | ||||
|         background: theme.palette.background.paper, | ||||
|     }, | ||||
|     header: { | ||||
|         padding: theme.spacing(0.5, 2), | ||||
|  | ||||
| @ -5,7 +5,8 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         '& > th': { | ||||
|             height: theme.shape.tableRowHeightCompact, | ||||
|             border: 0, | ||||
| 
 | ||||
|             backgroundColor: theme.palette.tableHeaderBackground, | ||||
|             color: theme.palette.tableHeaderColor, | ||||
|             '&:first-of-type': { | ||||
|                 borderTopLeftRadius: theme.shape.borderRadiusMedium, | ||||
|                 borderBottomLeftRadius: theme.shape.borderRadiusMedium, | ||||
|  | ||||
							
								
								
									
										20
									
								
								frontend/src/component/common/ThemeMode/ThemeMode.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								frontend/src/component/common/ThemeMode/ThemeMode.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | ||||
| import UIContext from 'contexts/UIContext'; | ||||
| import { useContext } from 'react'; | ||||
| import { ConditionallyRender } from '../ConditionallyRender/ConditionallyRender'; | ||||
| 
 | ||||
| interface IThemeModeProps { | ||||
|     darkmode: JSX.Element; | ||||
|     lightmode: JSX.Element; | ||||
| } | ||||
| 
 | ||||
| export const ThemeMode = ({ darkmode, lightmode }: IThemeModeProps) => { | ||||
|     const { themeMode } = useContext(UIContext); | ||||
| 
 | ||||
|     return ( | ||||
|         <ConditionallyRender | ||||
|             condition={themeMode === 'dark'} | ||||
|             show={darkmode} | ||||
|             elseShow={lightmode} | ||||
|         /> | ||||
|     ); | ||||
| }; | ||||
| @ -3,7 +3,7 @@ import { makeStyles } from 'tss-react/mui'; | ||||
| export const useStyles = makeStyles()(theme => ({ | ||||
|     container: { | ||||
|         maxWidth: '450px', | ||||
|         background: '#fff', | ||||
|         background: theme.palette.background.paper, | ||||
|         boxShadow: '2px 2px 4px rgba(0,0,0,0.4)', | ||||
|         zIndex: 500, | ||||
|         margin: '0 0.8rem', | ||||
|  | ||||
| @ -10,7 +10,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         paddingBlockStart: 4, | ||||
|         paddingBlockEnd: 4, | ||||
|         borderRadius: '100rem', | ||||
|         background: theme.palette.primary.main, | ||||
|         background: theme.palette.featureStrategySegmentChipBackground, | ||||
|         color: 'white', | ||||
|     }, | ||||
|     link: { | ||||
|  | ||||
| @ -3,7 +3,7 @@ import { makeStyles } from 'tss-react/mui'; | ||||
| export const useStyles = makeStyles()(theme => ({ | ||||
|     container: { | ||||
|         borderRadius: '12.5px', | ||||
|         backgroundColor: '#fff', | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|         padding: '2rem', | ||||
|     }, | ||||
| })); | ||||
|  | ||||
| @ -3,7 +3,7 @@ import { makeStyles } from 'tss-react/mui'; | ||||
| export const useStyles = makeStyles()(theme => ({ | ||||
|     item: { | ||||
|         padding: theme.spacing(2), | ||||
|         background: theme.palette.secondaryContainer, | ||||
|         background: theme.palette.featureMetricsBackground, | ||||
|         borderRadius: theme.spacing(2), | ||||
|         textAlign: 'center', | ||||
|         [theme.breakpoints.up('md')]: { | ||||
|  | ||||
| @ -9,7 +9,7 @@ import { styled } from '@mui/material'; | ||||
| 
 | ||||
| const StyledContainer = styled('div')(({ theme }) => ({ | ||||
|     borderRadius: theme.shape.borderRadiusLarge, | ||||
|     backgroundColor: '#fff', | ||||
|     backgroundColor: theme.palette.background.paper, | ||||
|     display: 'flex', | ||||
|     flexDirection: 'column', | ||||
|     padding: '1.5rem', | ||||
|  | ||||
| @ -4,7 +4,8 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|     featureOverviewEnvironment: { | ||||
|         borderRadius: theme.shape.borderRadiusLarge, | ||||
|         marginBottom: theme.spacing(2), | ||||
|         background: theme.palette.background.default, | ||||
|         padding: '0.2rem', | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|     }, | ||||
|     accordion: { | ||||
|         boxShadow: 'none', | ||||
|  | ||||
| @ -53,7 +53,7 @@ const FeatureOverviewEnvironment = ({ | ||||
|             style={{ | ||||
|                 background: !env.enabled | ||||
|                     ? theme.palette.neutral.light | ||||
|                     : theme.palette.background.default, | ||||
|                     : theme.palette.background.paper, | ||||
|             }} | ||||
|         > | ||||
|             <Accordion | ||||
|  | ||||
| @ -4,7 +4,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|     container: { | ||||
|         borderRadius: theme.shape.borderRadiusLarge, | ||||
|         color: '#fff', | ||||
|         backgroundColor: theme.palette.primary.main, | ||||
|         backgroundColor: theme.palette.featureMetaData, | ||||
|         display: 'flex', | ||||
|         flexDirection: 'column', | ||||
|         maxWidth: '350px', | ||||
|  | ||||
| @ -7,7 +7,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         display: 'flex', | ||||
|     }, | ||||
|     header: { | ||||
|         backgroundColor: '#fff', | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|         borderRadius: theme.shape.borderRadiusLarge, | ||||
|         marginBottom: '1rem', | ||||
|     }, | ||||
|  | ||||
| @ -15,7 +15,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         pointerEvents: 'auto', | ||||
|         position: 'relative', | ||||
|         padding: '4rem', | ||||
|         background: 'white', | ||||
|         background: theme.palette.background.paper, | ||||
|         boxShadow: '0 0 1rem rgba(0, 0, 0, 0.25)', | ||||
|         borderRadius: '1rem', | ||||
|         [theme.breakpoints.down('md')]: { | ||||
|  | ||||
| @ -131,18 +131,18 @@ exports[`FeedbackCESForm 1`] = ` | ||||
|             class="MuiFormControl-root MuiFormControl-fullWidth MuiTextField-root mui-wb57ya-MuiFormControl-root-MuiTextField-root" | ||||
|           > | ||||
|             <div | ||||
|               class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-multiline mui-181wpo2-MuiInputBase-root-MuiOutlinedInput-root" | ||||
|               class="MuiInputBase-root MuiOutlinedInput-root MuiInputBase-colorPrimary MuiInputBase-fullWidth MuiInputBase-formControl MuiInputBase-multiline mui-1qvtpcv-MuiInputBase-root-MuiOutlinedInput-root" | ||||
|             > | ||||
|               <textarea | ||||
|                 aria-invalid="false" | ||||
|                 class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputMultiline mui-1632cvv-MuiInputBase-input-MuiOutlinedInput-input" | ||||
|                 class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputMultiline mui-1wvz5kg-MuiInputBase-input-MuiOutlinedInput-input" | ||||
|                 id="mui-1" | ||||
|                 rows="3" | ||||
|                 style="height: 0px; overflow: hidden;" | ||||
|               /> | ||||
|               <textarea | ||||
|                 aria-hidden="true" | ||||
|                 class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputMultiline mui-1632cvv-MuiInputBase-input-MuiOutlinedInput-input" | ||||
|                 class="MuiInputBase-input MuiOutlinedInput-input MuiInputBase-inputMultiline mui-1wvz5kg-MuiInputBase-input-MuiOutlinedInput-input" | ||||
|                 readonly="" | ||||
|                 style="visibility: hidden; position: absolute; overflow: hidden; height: 0px; top: 0px; left: 0px; transform: translateZ(0); padding: 0px; width: 100%;" | ||||
|                 tabindex="-1" | ||||
|  | ||||
| @ -3,7 +3,7 @@ import { makeStyles } from 'tss-react/mui'; | ||||
| export const useStyles = makeStyles()(theme => ({ | ||||
|     feedback: { | ||||
|         borderRadius: '12.5px', | ||||
|         backgroundColor: '#fff', | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|         zIndex: 9999, | ||||
|         boxShadow: '2px 2px 4px 4px rgba(143,143,143, 0.25)', | ||||
|         padding: '1.5rem', | ||||
| @ -21,7 +21,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         position: 'absolute', | ||||
|         right: '-38px', | ||||
|         top: '-47px', | ||||
|         backgroundColor: '#fff', | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|         boxShadow: '2px 2px 4px 4px rgba(143,143,143, 0.25)', | ||||
|         ['&:hover']: { | ||||
|             backgroundColor: '#fff', | ||||
|  | ||||
| @ -6,6 +6,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         width: '100%', | ||||
|         flexGrow: 1, | ||||
|         zIndex: 100, | ||||
|         backgroundColor: theme.palette.footerBackground, | ||||
|     }, | ||||
|     list: { | ||||
|         padding: 0, | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| exports[`should render DrawerMenu 1`] = ` | ||||
| [ | ||||
|   <footer | ||||
|     className="tss-wd65c0-footer" | ||||
|     className="tss-16d7ppb-footer" | ||||
|   > | ||||
|     <div | ||||
|       className="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-10 mui-16chest-MuiGrid-root" | ||||
| @ -448,7 +448,7 @@ exports[`should render DrawerMenu 1`] = ` | ||||
| exports[`should render DrawerMenu with "features" selected 1`] = ` | ||||
| [ | ||||
|   <footer | ||||
|     className="tss-wd65c0-footer" | ||||
|     className="tss-16d7ppb-footer" | ||||
|   > | ||||
|     <div | ||||
|       className="MuiGrid-root MuiGrid-container MuiGrid-spacing-xs-10 mui-16chest-MuiGrid-root" | ||||
|  | ||||
| @ -2,8 +2,7 @@ import { makeStyles } from 'tss-react/mui'; | ||||
| 
 | ||||
| export const useStyles = makeStyles()(theme => ({ | ||||
|     header: { | ||||
|         backgroundColor: '#fff', | ||||
|         color: '#000', | ||||
|         backgroundColor: theme.palette.headerBackground, | ||||
|         padding: '0.5rem', | ||||
|         boxShadow: 'none', | ||||
|         position: 'relative', | ||||
| @ -80,7 +79,6 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         textDecoration: 'none', | ||||
|         alignItems: 'center', | ||||
|         display: 'flex', | ||||
|         color: '#000', | ||||
|     }, | ||||
|     icon: { | ||||
|         color: theme.palette.grey[700], | ||||
|  | ||||
| @ -2,13 +2,21 @@ import { useEffect, useState, VFC } from 'react'; | ||||
| import useMediaQuery from '@mui/material/useMediaQuery'; | ||||
| import { useTheme } from '@mui/material/styles'; | ||||
| import { Link } from 'react-router-dom'; | ||||
| import { AppBar, Container, IconButton, Tooltip } from '@mui/material'; | ||||
| import { | ||||
|     AppBar, | ||||
|     Container, | ||||
|     FormControlLabel, | ||||
|     IconButton, | ||||
|     Tooltip, | ||||
|     Switch, | ||||
| } from '@mui/material'; | ||||
| import MenuIcon from '@mui/icons-material/Menu'; | ||||
| import SettingsIcon from '@mui/icons-material/Settings'; | ||||
| import UserProfile from 'component/user/UserProfile'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| import MenuBookIcon from '@mui/icons-material/MenuBook'; | ||||
| import { ReactComponent as UnleashLogo } from 'assets/img/logoDarkWithText.svg'; | ||||
| import { ReactComponent as UnleashLogoWhite } from 'assets/img/logoWithWhiteText.svg'; | ||||
| 
 | ||||
| import { DrawerMenu } from './DrawerMenu/DrawerMenu'; | ||||
| import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; | ||||
| @ -24,8 +32,11 @@ import { useStyles } from './Header.styles'; | ||||
| import classNames from 'classnames'; | ||||
| import { useId } from 'hooks/useId'; | ||||
| import { IRoute } from 'interfaces/route'; | ||||
| import { ThemeMode } from 'component/common/ThemeMode/ThemeMode'; | ||||
| import { useThemeMode } from 'hooks/useThemeMode'; | ||||
| 
 | ||||
| const Header: VFC = () => { | ||||
|     const { onSetThemeMode, themeMode } = useThemeMode(); | ||||
|     const theme = useTheme(); | ||||
|     const adminId = useId(); | ||||
|     const configId = useId(); | ||||
| @ -111,9 +122,19 @@ const Header: VFC = () => { | ||||
|                     )} | ||||
|                     aria-label="Home" | ||||
|                 > | ||||
|                     <UnleashLogo | ||||
|                         className={styles.logo} | ||||
|                         aria-label="Unleash logo" | ||||
|                     <ThemeMode | ||||
|                         darkmode={ | ||||
|                             <UnleashLogoWhite | ||||
|                                 className={styles.logo} | ||||
|                                 aria-label="Unleash logo" | ||||
|                             /> | ||||
|                         } | ||||
|                         lightmode={ | ||||
|                             <UnleashLogo | ||||
|                                 className={styles.logo} | ||||
|                                 aria-label="Unleash logo" | ||||
|                             /> | ||||
|                         } | ||||
|                     /> | ||||
|                 </Link> | ||||
|                 <nav className={styles.nav}> | ||||
| @ -148,6 +169,22 @@ const Header: VFC = () => { | ||||
|                         /> | ||||
|                     </div> | ||||
|                     <div className={styles.userContainer}> | ||||
|                         <ConditionallyRender | ||||
|                             condition={Boolean( | ||||
|                                 uiConfig.flags.ENABLE_DARK_MODE_SUPPORT | ||||
|                             )} | ||||
|                             show={ | ||||
|                                 <FormControlLabel | ||||
|                                     control={ | ||||
|                                         <Switch | ||||
|                                             onChange={onSetThemeMode} | ||||
|                                             checked={themeMode === 'dark'} | ||||
|                                         /> | ||||
|                                     } | ||||
|                                     label="darkmode" | ||||
|                                 /> | ||||
|                             } | ||||
|                         /> | ||||
|                         <Tooltip title="Documentation" arrow> | ||||
|                             <IconButton | ||||
|                                 href="https://docs.getunleash.io/" | ||||
|  | ||||
| @ -20,7 +20,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         textDecoration: 'none', | ||||
|         alignItems: 'center', | ||||
|         display: 'flex', | ||||
|         color: '#000', | ||||
|         color: 'inherit', | ||||
|         height: '100%', | ||||
|         width: '100%', | ||||
|         '&&': { | ||||
|  | ||||
| @ -159,7 +159,7 @@ export const Playground: VFC<{}> = () => { | ||||
|             > | ||||
|                 <Box | ||||
|                     sx={{ | ||||
|                         background: theme.palette.grey[200], | ||||
|                         background: theme.palette.playgroundBackground, | ||||
|                         borderBottomLeftRadius: theme.shape.borderRadiusMedium, | ||||
|                     }} | ||||
|                 > | ||||
| @ -170,7 +170,7 @@ export const Playground: VFC<{}> = () => { | ||||
|                             py: 3, | ||||
|                             mb: 4, | ||||
|                             mt: 2, | ||||
|                             background: theme.palette.grey[200], | ||||
|                             background: theme.palette.playgroundBackground, | ||||
|                             transition: 'width 0.4s ease', | ||||
|                             minWidth: matches ? 'auto' : '500px', | ||||
|                             width: formWidth, | ||||
|  | ||||
| @ -1,10 +1,13 @@ | ||||
| import CodeMirror from '@uiw/react-codemirror'; | ||||
| import { useContext } from 'react'; | ||||
| import { json } from '@codemirror/lang-json'; | ||||
| import { Dispatch, SetStateAction, VFC, useCallback } from 'react'; | ||||
| import { styled, useTheme, Box } from '@mui/material'; | ||||
| import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; | ||||
| import { duotoneDark, duotoneLight } from '@uiw/codemirror-theme-duotone'; | ||||
| import Check from '@mui/icons-material/Check'; | ||||
| import { Error } from '@mui/icons-material'; | ||||
| import UIContext from 'contexts/UIContext'; | ||||
| 
 | ||||
| interface IPlaygroundEditorProps { | ||||
|     context: string | undefined; | ||||
| @ -78,6 +81,7 @@ export const PlaygroundEditor: VFC<IPlaygroundEditorProps> = ({ | ||||
|     setContext, | ||||
|     error, | ||||
| }) => { | ||||
|     const { themeMode } = useContext(UIContext); | ||||
|     const theme = useTheme(); | ||||
|     const onCodeFieldChange = useCallback( | ||||
|         context => { | ||||
| @ -109,6 +113,7 @@ export const PlaygroundEditor: VFC<IPlaygroundEditorProps> = ({ | ||||
|             <CodeMirror | ||||
|                 value={context} | ||||
|                 height="200px" | ||||
|                 theme={themeMode === 'dark' ? duotoneDark : duotoneLight} | ||||
|                 extensions={[json()]} | ||||
|                 onChange={onCodeFieldChange} | ||||
|                 style={{ | ||||
|  | ||||
| @ -13,7 +13,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         minWidth: 0, | ||||
|     }, | ||||
|     header: { | ||||
|         backgroundColor: '#fff', | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|         borderRadius: theme.shape.borderRadiusLarge, | ||||
|         marginBottom: '1rem', | ||||
|     }, | ||||
|  | ||||
| @ -55,7 +55,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         margin: '0', | ||||
|         textAlign: 'center', | ||||
|         marginBottom: '1rem', | ||||
|         backgroundColor: '#fff', | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|         borderRadius: theme.shape.borderRadiusLarge, | ||||
|         width: '100%', | ||||
|         padding: '1.5rem 1rem 1.5rem 1rem', | ||||
|  | ||||
| @ -16,7 +16,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         }, | ||||
|         '&:hover': { | ||||
|             transition: 'background-color 0.2s ease-in-out', | ||||
|             backgroundColor: theme.palette.neutral.light, | ||||
|             backgroundColor: theme.palette.projectCard.hover, | ||||
|         }, | ||||
|     }, | ||||
|     header: { | ||||
| @ -49,7 +49,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         textAlign: 'center', | ||||
|     }, | ||||
|     infoStats: { | ||||
|         color: '#4A4599', | ||||
|         color: theme.palette.projectCard.textColor, | ||||
|         fontWeight: 'bold', | ||||
|     }, | ||||
|     actionsBtn: { | ||||
|  | ||||
| @ -1,10 +1,36 @@ | ||||
| import React, { useState } from 'react'; | ||||
| import UIContext, { createEmptyToast } from 'contexts/UIContext'; | ||||
| import UIContext, { createEmptyToast, themeMode } from 'contexts/UIContext'; | ||||
| import { IToast } from 'interfaces/toast'; | ||||
| import { getLocalStorageItem } from 'utils/storage'; | ||||
| 
 | ||||
| const UIProvider: React.FC = ({ children }) => { | ||||
| const resolveMode = (darkmode: boolean): themeMode => { | ||||
|     const value = getLocalStorageItem('unleash-theme'); | ||||
|     if (value) { | ||||
|         return value as themeMode; | ||||
|     } | ||||
| 
 | ||||
|     let osDark; | ||||
|     if (darkmode) { | ||||
|         osDark = window.matchMedia('(prefers-color-scheme: dark)').matches; | ||||
|     } | ||||
| 
 | ||||
|     if (osDark) { | ||||
|         return 'dark'; | ||||
|     } | ||||
|     return 'light'; | ||||
| }; | ||||
| 
 | ||||
| interface IUiProviderProps { | ||||
|     darkmode: boolean; | ||||
| } | ||||
| 
 | ||||
| const UIProvider: React.FC<IUiProviderProps> = ({ | ||||
|     children, | ||||
|     darkmode = false, | ||||
| }) => { | ||||
|     const [toastData, setToast] = useState<IToast>(createEmptyToast()); | ||||
|     const [showFeedback, setShowFeedback] = useState(false); | ||||
|     const [themeMode, setThemeMode] = useState(resolveMode(darkmode)); | ||||
| 
 | ||||
|     const context = React.useMemo( | ||||
|         () => ({ | ||||
| @ -12,8 +38,10 @@ const UIProvider: React.FC = ({ children }) => { | ||||
|             toastData, | ||||
|             showFeedback, | ||||
|             setShowFeedback, | ||||
|             themeMode, | ||||
|             setThemeMode, | ||||
|         }), | ||||
|         [toastData, showFeedback] | ||||
|         [toastData, showFeedback, themeMode] | ||||
|     ); | ||||
| 
 | ||||
|     return <UIContext.Provider value={context}>{children}</UIContext.Provider>; | ||||
|  | ||||
| @ -0,0 +1,16 @@ | ||||
| import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; | ||||
| import UIProvider from './UIProvider'; | ||||
| 
 | ||||
| export const UIProviderContainer: React.FC = ({ children }) => { | ||||
|     const { uiConfig } = useUiConfig(); | ||||
| 
 | ||||
|     if (!uiConfig.flags) { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     return ( | ||||
|         <UIProvider darkmode={uiConfig.flags.ENABLE_DARK_MODE_SUPPORT || false}> | ||||
|             {children} | ||||
|         </UIProvider> | ||||
|     ); | ||||
| }; | ||||
| @ -17,7 +17,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|     steps: { | ||||
|         position: 'relative', | ||||
|         borderRadius: 10, | ||||
|         background: '#fff', | ||||
|         background: theme.palette.background.paper, | ||||
|         padding: '0.6rem 1.5rem', | ||||
|         margin: 'auto', | ||||
|         display: 'flex', | ||||
|  | ||||
| @ -13,7 +13,7 @@ test('renders an empty list correctly', () => { | ||||
|         <MemoryRouter> | ||||
|             <ThemeProvider> | ||||
|                 <AnnouncerProvider> | ||||
|                     <UIProvider> | ||||
|                     <UIProvider darkmode={false}> | ||||
|                         <AccessProviderMock | ||||
|                             permissions={[{ permission: ADMIN }]} | ||||
|                         > | ||||
|  | ||||
| @ -7,7 +7,7 @@ exports[`renders an empty list correctly 1`] = ` | ||||
|     aria-live="polite" | ||||
|   > | ||||
|     <div | ||||
|       className="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 tss-15wj2kz-container mui-177gdp-MuiPaper-root" | ||||
|       className="MuiPaper-root MuiPaper-elevation MuiPaper-rounded MuiPaper-elevation1 tss-15wj2kz-container mui-lorrhs-MuiPaper-root" | ||||
|     > | ||||
|       <div | ||||
|         className="header tss-1ywhhai-headerContainer" | ||||
| @ -32,7 +32,7 @@ exports[`renders an empty list correctly 1`] = ` | ||||
|               className="tss-u5t8ea-headerActions" | ||||
|             > | ||||
|               <div | ||||
|                 className="tss-119iiqp-container" | ||||
|                 className="tss-1oozr04-container" | ||||
|               > | ||||
|                 <div | ||||
|                   className="tss-1xjrf9m-search search-container" | ||||
| @ -49,12 +49,12 @@ exports[`renders an empty list correctly 1`] = ` | ||||
|                     /> | ||||
|                   </svg> | ||||
|                   <div | ||||
|                     className="MuiInputBase-root tss-11gf6cf-inputRoot input-container MuiInputBase-colorPrimary mui-1v3pvzz-MuiInputBase-root" | ||||
|                     className="MuiInputBase-root tss-11gf6cf-inputRoot input-container MuiInputBase-colorPrimary mui-qtv7d9-MuiInputBase-root" | ||||
|                     onClick={[Function]} | ||||
|                   > | ||||
|                     <input | ||||
|                       aria-label="Search (Ctrl+K)" | ||||
|                       className="MuiInputBase-input mui-j79lc6-MuiInputBase-input" | ||||
|                       className="MuiInputBase-input mui-mfsqjb-MuiInputBase-input" | ||||
|                       onAnimationStart={[Function]} | ||||
|                       onBlur={[Function]} | ||||
|                       onChange={[Function]} | ||||
| @ -120,7 +120,7 @@ exports[`renders an empty list correctly 1`] = ` | ||||
|             role={null} | ||||
|           > | ||||
|             <tr | ||||
|               className="MuiTableRow-root MuiTableRow-head tss-1sk7xq7-tableHeader mui-cn4v9y-MuiTableRow-root" | ||||
|               className="MuiTableRow-root MuiTableRow-head tss-1u2w2tj-tableHeader mui-cn4v9y-MuiTableRow-root" | ||||
|               role="row" | ||||
|             > | ||||
|               <th | ||||
|  | ||||
| @ -17,8 +17,8 @@ const StandaloneBanner: FC<IStandaloneBannerProps> = ({ title, children }) => { | ||||
| 
 | ||||
|     return ( | ||||
|         <Gradient | ||||
|             from={theme.palette.primary.main} | ||||
|             to="#173341" | ||||
|             from={theme.palette.standaloneBannerGradient.from} | ||||
|             to={theme.palette.standaloneBannerGradient.to} | ||||
|             className={styles.gradient} | ||||
|         > | ||||
|             <div className={styles.container}> | ||||
|  | ||||
| @ -75,6 +75,7 @@ const UserProfile = ({ | ||||
|                     disableRipple | ||||
|                 > | ||||
|                     <Avatar | ||||
|                         style={{ backgroundColor: '#fff', padding: '0.15rem' }} | ||||
|                         alt="Your Gravatar" | ||||
|                         src={imageUrl} | ||||
|                         data-testid={HEADER_USER_AVATAR} | ||||
|  | ||||
| @ -20,6 +20,7 @@ import { basePath } from 'utils/formatPath'; | ||||
| import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig'; | ||||
| import { IUser } from 'interfaces/user'; | ||||
| import { ILocationSettings } from 'hooks/useLocationSettings'; | ||||
| import { useTheme } from '@mui/material/styles'; | ||||
| 
 | ||||
| interface IUserProfileContentProps { | ||||
|     id: string; | ||||
| @ -45,6 +46,8 @@ const UserProfileContent = ({ | ||||
|     setLocationSettings, | ||||
| }: IUserProfileContentProps) => { | ||||
|     const { classes: themeStyles } = useThemeStyles(); | ||||
|     const theme = useTheme(); | ||||
| 
 | ||||
|     const { uiConfig } = useUiConfig(); | ||||
|     const [updatedPassword, setUpdatedPassword] = useState(false); | ||||
|     const [editingProfile, setEditingProfile] = useState(false); | ||||
| @ -121,7 +124,11 @@ const UserProfileContent = ({ | ||||
|                                     > | ||||
|                                         <InputLabel | ||||
|                                             htmlFor="locale-select" | ||||
|                                             style={{ backgroundColor: '#fff' }} | ||||
|                                             style={{ | ||||
|                                                 backgroundColor: | ||||
|                                                     theme.palette | ||||
|                                                         .inputLabelBackground, | ||||
|                                             }} | ||||
|                                         > | ||||
|                                             Date/Time formatting | ||||
|                                         </InputLabel> | ||||
|  | ||||
| @ -3,7 +3,7 @@ import { makeStyles } from 'tss-react/mui'; | ||||
| export const useStyles = makeStyles()(theme => ({ | ||||
|     container: { | ||||
|         padding: '5.5rem', | ||||
|         background: '#EFF2F2', | ||||
|         background: theme.palette.standaloneBackground, | ||||
|         display: 'flex', | ||||
|         [theme.breakpoints.down('md')]: { | ||||
|             flexDirection: 'column', | ||||
| @ -27,7 +27,7 @@ export const useStyles = makeStyles()(theme => ({ | ||||
|         flex: '1', | ||||
|         borderTopRightRadius: '3px', | ||||
|         borderBottomRightRadius: '3px', | ||||
|         backgroundColor: '#fff', | ||||
|         backgroundColor: theme.palette.background.paper, | ||||
|         position: 'relative', | ||||
|         [theme.breakpoints.down('md')]: { | ||||
|             borderRadius: '0', | ||||
|  | ||||
| @ -6,8 +6,12 @@ interface IUIContext { | ||||
|     setToast: React.Dispatch<React.SetStateAction<IToast>>; | ||||
|     showFeedback: boolean; | ||||
|     setShowFeedback: React.Dispatch<React.SetStateAction<boolean>>; | ||||
|     setThemeMode: React.Dispatch<React.SetStateAction<themeMode>>; | ||||
|     themeMode: themeMode; | ||||
| } | ||||
| 
 | ||||
| export type themeMode = 'light' | 'dark'; | ||||
| 
 | ||||
| export const createEmptyToast = (): IToast => { | ||||
|     return { | ||||
|         type: 'success', | ||||
| @ -27,11 +31,17 @@ const setShowFeedbackPlaceholder = () => { | ||||
|     throw new Error('setShowFeedback called outside UIContext'); | ||||
| }; | ||||
| 
 | ||||
| const setThemeModePlaceholder = () => { | ||||
|     throw new Error('setMode called outside UIContext'); | ||||
| }; | ||||
| 
 | ||||
| const UIContext = React.createContext<IUIContext>({ | ||||
|     toastData: createEmptyToast(), | ||||
|     setToast: setToastPlaceholder, | ||||
|     showFeedback: false, | ||||
|     setShowFeedback: setShowFeedbackPlaceholder, | ||||
|     themeMode: 'light', | ||||
|     setThemeMode: setThemeModePlaceholder, | ||||
| }); | ||||
| 
 | ||||
| export default UIContext; | ||||
|  | ||||
							
								
								
									
										37
									
								
								frontend/src/hooks/useThemeMode.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								frontend/src/hooks/useThemeMode.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| import UIContext, { themeMode } from 'contexts/UIContext'; | ||||
| import { useContext } from 'react'; | ||||
| import { setLocalStorageItem } from 'utils/storage'; | ||||
| import mainTheme from 'themes/theme'; | ||||
| import darkTheme from 'themes/dark-theme'; | ||||
| import { Theme } from '@emotion/react'; | ||||
| 
 | ||||
| interface IUseThemeModeOutput { | ||||
|     resolveTheme: () => Theme; | ||||
|     onSetThemeMode: () => void; | ||||
|     themeMode: themeMode; | ||||
| } | ||||
| 
 | ||||
| export const useThemeMode = (): IUseThemeModeOutput => { | ||||
|     const { themeMode, setThemeMode } = useContext(UIContext); | ||||
| 
 | ||||
|     const resolveTheme = () => { | ||||
|         if (themeMode === 'light') { | ||||
|             return mainTheme; | ||||
|         } | ||||
| 
 | ||||
|         return darkTheme; | ||||
|     }; | ||||
| 
 | ||||
|     const onSetThemeMode = () => { | ||||
|         setThemeMode((prev: themeMode) => { | ||||
|             if (prev === 'light') { | ||||
|                 setLocalStorageItem('unleash-theme', 'dark'); | ||||
|                 return 'dark'; | ||||
|             } | ||||
|             setLocalStorageItem('unleash-theme', 'light'); | ||||
|             return 'light'; | ||||
|         }); | ||||
|     }; | ||||
| 
 | ||||
|     return { resolveTheme, onSetThemeMode, themeMode }; | ||||
| }; | ||||
| @ -10,12 +10,12 @@ import { ScrollTop } from 'component/common/ScrollTop/ScrollTop'; | ||||
| import { AccessProvider } from 'component/providers/AccessProvider/AccessProvider'; | ||||
| import { basePath } from 'utils/formatPath'; | ||||
| import { FeedbackCESProvider } from 'component/feedback/FeedbackCESContext/FeedbackCESProvider'; | ||||
| import UIProvider from 'component/providers/UIProvider/UIProvider'; | ||||
| import { AnnouncerProvider } from 'component/common/Announcer/AnnouncerProvider/AnnouncerProvider'; | ||||
| import { InstanceStatus } from 'component/common/InstanceStatus/InstanceStatus'; | ||||
| import { UIProviderContainer } from 'component/providers/UIProvider/UIProviderContainer'; | ||||
| 
 | ||||
| ReactDOM.render( | ||||
|     <UIProvider> | ||||
|     <UIProviderContainer> | ||||
|         <AccessProvider> | ||||
|             <BrowserRouter basename={basePath}> | ||||
|                 <ThemeProvider> | ||||
| @ -30,6 +30,6 @@ ReactDOM.render( | ||||
|                 </ThemeProvider> | ||||
|             </BrowserRouter> | ||||
|         </AccessProvider> | ||||
|     </UIProvider>, | ||||
|     </UIProviderContainer>, | ||||
|     document.getElementById('app') | ||||
| ); | ||||
|  | ||||
| @ -39,6 +39,7 @@ export interface IFlags { | ||||
|     T?: boolean; | ||||
|     UNLEASH_CLOUD?: boolean; | ||||
|     UG?: boolean; | ||||
|     ENABLE_DARK_MODE_SUPPORT?: boolean; | ||||
| } | ||||
| 
 | ||||
| export interface IVersionInfo { | ||||
|  | ||||
| @ -1,19 +1,24 @@ | ||||
| import React, { FC } from 'react'; | ||||
| import { CssBaseline, ThemeProvider as MuiThemeProvider } from '@mui/material'; | ||||
| import mainTheme from 'themes/theme'; | ||||
| 
 | ||||
| import createCache from '@emotion/cache'; | ||||
| import { CacheProvider } from '@emotion/react'; | ||||
| import { useThemeMode } from 'hooks/useThemeMode'; | ||||
| 
 | ||||
| export const muiCache = createCache({ | ||||
|     key: 'mui', | ||||
|     prepend: true, | ||||
| }); | ||||
| 
 | ||||
| export const ThemeProvider: FC = ({ children }) => ( | ||||
|     <CacheProvider value={muiCache}> | ||||
|         <MuiThemeProvider theme={mainTheme}> | ||||
|             <CssBaseline /> | ||||
|             {children} | ||||
|         </MuiThemeProvider> | ||||
|     </CacheProvider> | ||||
| ); | ||||
| export const ThemeProvider: FC = ({ children }) => { | ||||
|     const { resolveTheme } = useThemeMode(); | ||||
| 
 | ||||
|     return ( | ||||
|         <CacheProvider value={muiCache}> | ||||
|             <MuiThemeProvider theme={resolveTheme()}> | ||||
|                 <CssBaseline /> | ||||
|                 {children} | ||||
|             </MuiThemeProvider> | ||||
|         </CacheProvider> | ||||
|     ); | ||||
| }; | ||||
|  | ||||
| @ -17,10 +17,6 @@ button { | ||||
|     font-family: 'Sen', sans-serif; | ||||
| } | ||||
| 
 | ||||
| .MuiInputBase-root { | ||||
|     background-color: #fff; | ||||
| } | ||||
| 
 | ||||
| .MuiAccordion-root.Mui-expanded { | ||||
|     margin: 0; | ||||
| } | ||||
|  | ||||
| @ -78,4 +78,12 @@ export const colors = { | ||||
|         100: '#DCEEFA', | ||||
|         50: '#EBF7FF', | ||||
|     }, | ||||
|     darkblue: { | ||||
|         1000: '#091826', | ||||
|         900: '#041c32', | ||||
|         800: '#1d3247', | ||||
|         700: '#28415c', | ||||
|         600: '#1f3751', | ||||
|         500: '#0e2840', | ||||
|     }, | ||||
| } as const; | ||||
|  | ||||
							
								
								
									
										418
									
								
								frontend/src/themes/dark-theme.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										418
									
								
								frontend/src/themes/dark-theme.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,418 @@ | ||||
| import { createTheme } from '@mui/material/styles'; | ||||
| import { colors } from './colors'; | ||||
| 
 | ||||
| const themeColors = { | ||||
|     main: colors.darkblue[900], | ||||
|     secondary: colors.darkblue[800], | ||||
|     textColor: '#ffffffe6', | ||||
|     hover: 'rgb(255, 255, 255, 0.7)', | ||||
| }; | ||||
| 
 | ||||
| export default createTheme({ | ||||
|     breakpoints: { | ||||
|         values: { | ||||
|             xs: 0, | ||||
|             sm: 600, | ||||
|             md: 960, | ||||
|             lg: 1260, | ||||
|             xl: 1536, | ||||
|         }, | ||||
|     }, | ||||
|     boxShadows: { | ||||
|         main: '0px 2px 4px rgba(129, 122, 254, 0.2)', | ||||
|         card: '0px 2px 10px rgba(28, 25, 78, 0.12)', | ||||
|         elevated: '0px 1px 20px rgba(45, 42, 89, 0.1)', | ||||
|     }, | ||||
|     typography: { | ||||
|         fontFamily: 'Sen, Roboto, sans-serif', | ||||
|         fontWeightBold: '700', | ||||
|         fontWeightMedium: '700', | ||||
|         allVariants: { lineHeight: 1.4 }, | ||||
|         button: { lineHeight: 1.75 }, | ||||
|         h1: { | ||||
|             fontSize: '1.5rem', | ||||
|             lineHeight: 1.875, | ||||
|         }, | ||||
|         h3: { | ||||
|             fontSize: '1rem', | ||||
|             fontWeight: '700', | ||||
|         }, | ||||
|         caption: { | ||||
|             fontSize: `${12 / 16}rem`, | ||||
|         }, | ||||
|     }, | ||||
|     fontSizes: { | ||||
|         mainHeader: '1.25rem', | ||||
|         bodySize: '1rem', | ||||
|         smallBody: `${14 / 16}rem`, | ||||
|         smallerBody: `${12 / 16}rem`, | ||||
|     }, | ||||
|     fontWeight: { | ||||
|         thin: 300, | ||||
|         medium: 400, | ||||
|         semi: 700, | ||||
|         bold: 700, | ||||
|     }, | ||||
|     shape: { | ||||
|         borderRadius: 4, | ||||
|         borderRadiusMedium: 8, | ||||
|         borderRadiusLarge: 12, | ||||
|         borderRadiusExtraLarge: 20, | ||||
|         tableRowHeight: 64, | ||||
|         tableRowHeightCompact: 56, | ||||
|         tableRowHeightDense: 48, | ||||
|     }, | ||||
|     palette: { | ||||
|         primary: { | ||||
|             main: themeColors.textColor, | ||||
|             light: colors.purple[700], | ||||
|             dark: colors.purple[900], | ||||
|         }, | ||||
|         secondary: { | ||||
|             main: colors.purple[800], | ||||
|             light: colors.purple[700], | ||||
|             dark: colors.purple[900], | ||||
|         }, | ||||
|         info: { | ||||
|             light: colors.blue[50], | ||||
|             main: colors.blue[500], | ||||
|             dark: colors.blue[700], | ||||
|             border: colors.blue[200], | ||||
|         }, | ||||
|         success: { | ||||
|             light: colors.green[50], | ||||
|             main: colors.green[600], | ||||
|             dark: themeColors.main, | ||||
|             border: colors.green[300], | ||||
|         }, | ||||
|         warning: { | ||||
|             light: colors.orange[100], | ||||
|             main: colors.orange[800], | ||||
|             dark: colors.orange[900], | ||||
|             border: colors.orange[500], | ||||
|         }, | ||||
|         error: { | ||||
|             light: colors.red[50], | ||||
|             main: colors.red[700], | ||||
|             dark: colors.red[800], | ||||
|             border: colors.red[300], | ||||
|         }, | ||||
|         background: { | ||||
|             paper: themeColors.main, | ||||
|         }, | ||||
|         divider: themeColors.secondary, | ||||
|         dividerAlternative: colors.grey[400], | ||||
|         tableHeaderHover: colors.darkblue[700], | ||||
|         tableHeaderBackground: themeColors.secondary, | ||||
|         tableHeaderColor: themeColors.textColor, | ||||
|         highlight: '#FFEACC', | ||||
|         secondaryContainer: themeColors.secondary, | ||||
|         contentWrapper: colors.darkblue[800], | ||||
|         formBackground: themeColors.main, | ||||
|         formSidebar: colors.darkblue[1000], | ||||
|         headerBackground: themeColors.main, | ||||
|         footerBackground: themeColors.main, | ||||
|         sidebarContainer: 'rgba(32,32,33, 0.2)', | ||||
|         codebox: colors.darkblue[600], | ||||
|         featureMetaData: colors.darkblue[1000], | ||||
|         playgroundBackground: colors.darkblue[600], | ||||
|         playgroundFormBackground: themeColors.secondary, | ||||
|         standaloneBackground: colors.black, | ||||
|         featureStrategySegmentChipBackground: themeColors.secondary, | ||||
|         featureSegmentSearchBackground: themeColors.secondary, | ||||
|         dialogHeaderBackground: themeColors.secondary, | ||||
|         dialogHeaderText: themeColors.textColor, | ||||
|         lightBorder: colors.darkblue[500], | ||||
|         constraintAccordion: { | ||||
|             editBackground: colors.darkblue[600], | ||||
|             background: themeColors.secondary, | ||||
|             operatorBackground: themeColors.main, | ||||
|         }, | ||||
|         standaloneBannerGradient: { | ||||
|             from: colors.darkblue[1000], | ||||
|             to: colors.black, | ||||
|         }, | ||||
|         projectCard: { | ||||
|             hover: themeColors.secondary, | ||||
|             textColor: themeColors.textColor, | ||||
|         }, | ||||
|         formSidebarTextColor: themeColors.textColor, | ||||
|         checkmarkBadge: themeColors.secondary, | ||||
|         inputLabelBackground: 'transparent', | ||||
|         featureMetricsBackground: themeColors.secondary, | ||||
|         grey: colors.grey, | ||||
|         text: { | ||||
|             primary: themeColors.textColor, | ||||
|             secondary: colors.grey[800], | ||||
|             disabled: colors.grey[600], | ||||
|         }, | ||||
|         code: { | ||||
|             main: '#0b8c8f', | ||||
|             diffAdd: 'green', | ||||
|             diffSub: 'red', | ||||
|             diffNeutral: 'black', | ||||
|             edited: 'blue', | ||||
|         }, | ||||
|         neutral: { | ||||
|             light: colors.darkblue[500], | ||||
|             main: colors.grey[700], | ||||
|             dark: colors.grey[800], | ||||
|             border: colors.grey[500], | ||||
|         }, | ||||
|         activityIndicators: { | ||||
|             primary: themeColors.secondary, | ||||
|             unknown: themeColors.secondary, | ||||
|             recent: themeColors.secondary, | ||||
|             inactive: themeColors.secondary, | ||||
|             abandoned: themeColors.secondary, | ||||
|         }, | ||||
|         tertiary: { | ||||
|             light: themeColors.secondary, | ||||
|             main: colors.grey[400], | ||||
|             dark: colors.grey[600], | ||||
|             background: 'white', | ||||
|             contrast: colors.grey[300], | ||||
|         }, | ||||
|         inactiveIcon: colors.grey[600], | ||||
|     }, | ||||
|     components: { | ||||
|         MuiAppBar: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     color: themeColors.textColor, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiInputLabel: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     color: themeColors.textColor, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiIconButton: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     color: colors.white, | ||||
|                     '&:hover': { | ||||
|                         backgroundColor: themeColors.hover, | ||||
|                     }, | ||||
|                     '&.Mui-disabled': { | ||||
|                         '& .MuiSvgIcon-root': { | ||||
|                             color: colors.grey[700], | ||||
|                         }, | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiLink: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     color: colors.white, | ||||
|                     '&:hover': { | ||||
|                         textDecoration: 'none', | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiBreadcrumbs: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     color: themeColors.textColor, | ||||
|                     fontSize: '0.875rem', | ||||
|                     '& a': { | ||||
|                         color: themeColors.textColor, | ||||
|                         textDecoration: 'underline', | ||||
|                         '&:hover': { | ||||
|                             textDecoration: 'none', | ||||
|                         }, | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiTableHead: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     background: 'transparent', | ||||
|                     '& th': { | ||||
|                         background: colors.grey[200], | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiTableRow: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     '&.MuiTableRow-hover:hover': { | ||||
|                         background: themeColors.secondary, | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiTableCell: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     borderBottomColor: themeColors.main, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiAlert: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     borderRadius: '8px', | ||||
|                     a: { | ||||
|                         color: 'inherit', | ||||
|                     }, | ||||
|                     '&.MuiAlert-standardInfo': { | ||||
|                         backgroundColor: colors.blue[50], | ||||
|                         color: colors.blue[700], | ||||
|                         border: `1px solid ${colors.blue[200]}`, | ||||
|                         '& .MuiAlert-icon .MuiSvgIcon-root': { | ||||
|                             color: colors.blue[500], | ||||
|                         }, | ||||
|                     }, | ||||
|                     '&.MuiAlert-standardSuccess': { | ||||
|                         backgroundColor: colors.green[50], | ||||
|                         color: colors.green[800], | ||||
|                         border: `1px solid ${colors.green[300]}`, | ||||
|                         '& .MuiAlert-icon .MuiSvgIcon-root': { | ||||
|                             color: colors.green[500], | ||||
|                         }, | ||||
|                     }, | ||||
|                     '&.MuiAlert-standardWarning': { | ||||
|                         backgroundColor: colors.orange[100], | ||||
|                         color: colors.orange[900], | ||||
|                         border: `1px solid ${colors.orange[500]}`, | ||||
|                         '& .MuiAlert-icon .MuiSvgIcon-root': { | ||||
|                             color: colors.orange[800], | ||||
|                         }, | ||||
|                     }, | ||||
|                     '&.MuiAlert-standardError': { | ||||
|                         backgroundColor: colors.red[50], | ||||
|                         color: colors.red[800], | ||||
|                         border: `1px solid ${colors.red[300]}`, | ||||
|                         '& .MuiAlert-icon .MuiSvgIcon-root': { | ||||
|                             color: colors.red[700], | ||||
|                         }, | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiButton: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     '&.Mui-disabled': { | ||||
|                         backgroundColor: colors.grey[400], | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiSvgIcon: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     color: themeColors.textColor, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiTabs: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     backgroundColor: themeColors.main, | ||||
|                     color: themeColors.textColor, | ||||
|                     '& .MuiTabs-indicator': { | ||||
|                         height: '4px', | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiTab: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     color: themeColors.textColor, | ||||
|                     fontSize: '1rem', | ||||
|                     textTransform: 'none', | ||||
|                     fontWeight: 400, | ||||
|                     minHeight: '62px', | ||||
|                     '&:hover': { | ||||
|                         backgroundColor: themeColors.secondary, | ||||
|                     }, | ||||
|                     '&.Mui-selected': { | ||||
|                         color: themeColors.textColor, | ||||
|                         fontWeight: 700, | ||||
|                     }, | ||||
|                     '& > span': { | ||||
|                         color: colors.purple[900], | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiAccordionSummary: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     '& > .MuiAccordionSummary-content.Mui-expanded': { | ||||
|                         margin: '12px 0', | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiSwitch: { | ||||
|             styleOverrides: { | ||||
|                 switchBase: { | ||||
|                     zIndex: 1, | ||||
|                     '&:not(.Mui-checked) .MuiTouchRipple-child': { | ||||
|                         color: colors.grey['500'], | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiIcon: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     color: colors.white, | ||||
|                 }, | ||||
|                 colorDisabled: { | ||||
|                     color: colors.white[600], | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiMenu: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     '.MuiMenu-list': { | ||||
|                         backgroundColor: colors.darkblue[600], | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiMenuItem: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     '&.Mui-disabled': { | ||||
|                         opacity: 0.66, | ||||
|                     }, | ||||
|                     '&:hover': { | ||||
|                         backgroundColor: themeColors.secondary, | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiInputBase: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     backgroundColor: colors.darkblue[1000], | ||||
|                     '.MuiSvgIcon-root': { | ||||
|                         color: '#fff', | ||||
|                     }, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiPaper: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     backgroundColor: themeColors.main, | ||||
|                     color: themeColors.textColor, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|     }, | ||||
| }); | ||||
| @ -107,9 +107,42 @@ export default createTheme({ | ||||
|         divider: colors.grey[300], | ||||
|         dividerAlternative: colors.grey[400], | ||||
|         tableHeaderHover: colors.grey[400], | ||||
|         tableHeaderBackground: colors.grey[200], | ||||
|         tableHeaderColor: colors.grey[900], | ||||
|         formSidebarTextColor: colors.white, | ||||
|         highlight: '#FFEACC', | ||||
|         secondaryContainer: colors.grey[200], | ||||
|         contentWrapper: colors.grey[300], | ||||
|         headerBackground: colors.white, | ||||
|         footerBackground: colors.white, | ||||
|         formBackground: colors.white, | ||||
|         formSidebar: colors.purple[800], | ||||
|         featureMetaData: colors.purple[800], | ||||
|         codebox: 'rgba(32,32,33, 0.2)', | ||||
|         sidebarContainer: 'rgba(32,32,33, 0.2)', | ||||
|         playgroundBackground: colors.grey[200], | ||||
|         playgroundFormBackground: colors.grey[200], | ||||
|         standaloneBackground: colors.grey[300], | ||||
|         constraintAccordion: { | ||||
|             editBackground: '#F6F6FA', | ||||
|             background: colors.white, | ||||
|             operatorBackground: colors.grey[200], | ||||
|         }, | ||||
|         projectCard: { | ||||
|             hover: colors.grey[100], | ||||
|             textColor: '#4A4599', | ||||
|         }, | ||||
|         standaloneBannerGradient: { | ||||
|             from: colors.purple[900], | ||||
|             to: '#173341', | ||||
|         }, | ||||
|         checkmarkBadge: colors.purple[800], | ||||
|         inputLabelBackground: colors.white, | ||||
|         featureMetricsBackground: colors.grey[100], | ||||
|         featureStrategySegmentChipBackground: colors.purple[800], | ||||
|         featureSegmentSearchBackground: colors.purple[800], | ||||
|         dialogHeaderBackground: colors.purple[800], | ||||
|         dialogHeaderText: '#ffffffe6', | ||||
|         grey: colors.grey, | ||||
|         lightBorder: colors.grey[400], | ||||
|         text: { | ||||
| @ -333,5 +366,26 @@ export default createTheme({ | ||||
|                 }), | ||||
|             }, | ||||
|         }, | ||||
|         MuiInputBase: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     backgroundColor: '#fff', | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiPaper: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     backgroundColor: '#fff', | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|         MuiAppBar: { | ||||
|             styleOverrides: { | ||||
|                 root: { | ||||
|                     color: colors.black, | ||||
|                 }, | ||||
|             }, | ||||
|         }, | ||||
|     }, | ||||
| }); | ||||
|  | ||||
| @ -54,10 +54,44 @@ declare module '@mui/material/styles' { | ||||
|             primary: string; | ||||
|         }; | ||||
|         dividerAlternative: string; | ||||
|         contentWrapper: string; | ||||
|         headerBackground: string; | ||||
|         footerBackground: string; | ||||
|         codebox: string; | ||||
|         featureMetaData: string; | ||||
|         playgroundBackground: string; | ||||
|         playgroundFormBackground: string; | ||||
|         standaloneBackground: string; | ||||
|         standaloneBannerGradient: { | ||||
|             from: string; | ||||
|             to: string; | ||||
|         }; | ||||
|         featureMetricsBackground: string; | ||||
|         constraintAccordion: { | ||||
|             editBackground: string; | ||||
|             background: string; | ||||
|             operatorBackground: string; | ||||
|         }; | ||||
|         projectCard: { | ||||
|             hover: string; | ||||
|             textColor: string; | ||||
|         }; | ||||
|         checkmarkBadge: string; | ||||
|         inputLabelBackground: string; | ||||
|         featureStrategySegmentChipBackground: string; | ||||
|         featureSegmentSearchBackground: string; | ||||
|         dialogHeaderBackground: string; | ||||
|         dialogHeaderText: string; | ||||
|         formSidebarTextColor: string; | ||||
|         /** | ||||
|          * For table header hover effect. | ||||
|          */ | ||||
|         tableHeaderBackground: string; | ||||
|         tableHeaderHover: string; | ||||
|         tableHeaderColor: string; | ||||
| 
 | ||||
|         formBackground: string; | ||||
|         formSidebar: string; | ||||
|         /** | ||||
|          * Text highlight effect color. Used when filtering/searching over content. | ||||
|          */ | ||||
|  | ||||
| @ -2447,6 +2447,22 @@ | ||||
|     "@codemirror/state" "^6.0.0" | ||||
|     "@codemirror/view" "^6.0.0" | ||||
| 
 | ||||
| "@uiw/codemirror-theme-duotone@^4.11.5": | ||||
|   version "4.11.5" | ||||
|   resolved "https://registry.yarnpkg.com/@uiw/codemirror-theme-duotone/-/codemirror-theme-duotone-4.11.5.tgz#12df3666337f757253f810fc4e61c8bc887e40c6" | ||||
|   integrity sha512-5Ea9naIp/KM6jZjog7tChdOjEPQgeKwSDuCh+TY1lQyt5YJS5P3eZSZq68KNZlwuBHj2c53h069brMnhguTFag== | ||||
|   dependencies: | ||||
|     "@uiw/codemirror-themes" "4.11.5" | ||||
| 
 | ||||
| "@uiw/codemirror-themes@4.11.5": | ||||
|   version "4.11.5" | ||||
|   resolved "https://registry.yarnpkg.com/@uiw/codemirror-themes/-/codemirror-themes-4.11.5.tgz#15926e65129b41c9ec607065416fc829970e122a" | ||||
|   integrity sha512-f2i3yGPzxmCsvx4t6HHykcEhAxbI4GDAMzdFtQfFYMuu1F5sQP43JQvBC8ESflYk05QmE9rCWWZZpvOathLzVw== | ||||
|   dependencies: | ||||
|     "@codemirror/language" "^6.0.0" | ||||
|     "@codemirror/state" "^6.0.0" | ||||
|     "@codemirror/view" "^6.0.0" | ||||
| 
 | ||||
| "@uiw/react-codemirror@4.11.4": | ||||
|   version "4.11.4" | ||||
|   resolved "https://registry.yarnpkg.com/@uiw/react-codemirror/-/react-codemirror-4.11.4.tgz#76adc757baa0b8b1a9bd30d7081f5622b896d607" | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user