pgadmin4/web/pgadmin/static/js/Theme/index.jsx

601 lines
14 KiB
JavaScript

/////////////////////////////////////////////////////////////
//
// pgAdmin 4 - PostgreSQL Tools
//
// Copyright (C) 2013 - 2022, The pgAdmin Development Team
// This software is released under the PostgreSQL Licence
//
//////////////////////////////////////////////////////////////
/* The complete styling file for Material-UI components used
* This will become the main theme file for pgAdmin. All the
* custom themes info will come here.
*/
import React, { useMemo } from 'react';
import { createMuiTheme, ThemeProvider, makeStyles } from '@material-ui/core/styles';
import CustomPropTypes from '../custom_prop_types';
import getStandardTheme from './standard';
import getDarkTheme from './dark';
import getHightContrastTheme from './high_contrast';
/* Common settings across all themes */
let basicSettings = createMuiTheme();
basicSettings = createMuiTheme(basicSettings, {
typography: {
fontSize: 14,
htmlFontSize: 14,
},
shape: {
borderRadius: 4,
},
palette: {
action: {
disabledOpacity: 0.32,
}
},
overrides: {
MuiTabs: {
root: {
minHeight: 0,
}
},
PrivateTabIndicator: {
root: {
height: '3px',
transition: basicSettings.transitions.create(['all'], {duration: '150ms'}),
}
},
MuiTab: {
root: {
textTransform: 'none',
minHeight: 0,
padding: '3px 10px',
[basicSettings.breakpoints.up('xs')]: {
minWidth: 0,
},
[basicSettings.breakpoints.up('sm')]: {
minWidth: 0,
},
[basicSettings.breakpoints.up('md')]: {
minWidth: 0,
},
[basicSettings.breakpoints.up('lg')]: {
minWidth: 0,
},
},
textColorInherit: {
textTransform: 'none',
opacity: 1,
}
},
MuiButton: {
root: {
textTransform: 'none',
padding: basicSettings.spacing(0.5, 1.5),
'&.Mui-disabled': {
opacity: 0.60,
},
'&.MuiButton-sizeSmall, &.MuiButton-outlinedSizeSmall, &.MuiButton-containedSizeSmall': {
height: '28px',
fontSize: '0.875rem',
'& .MuiSvgIcon-root': {
height: '0.8em',
}
},
},
contained: {
boxShadow: 'none',
'&:hover': {
boxShadow: 'none',
}
},
outlined: {
padding: basicSettings.spacing(0.375, 1),
},
startIcon: {
marginRight: basicSettings.spacing(0.5),
},
},
MuiOutlinedInput: {
multiline: {
padding: '0px',
},
input: {
padding: basicSettings.spacing(0.75, 1.5),
borderRadius: 'inherit',
},
inputMultiline: {
padding: basicSettings.spacing(0.75, 1.5),
resize: 'vertical',
},
adornedEnd: {
paddingRight: basicSettings.spacing(0.75),
}
},
MuiAccordion: {
root: {
boxShadow: 'none',
}
},
MuiAccordionSummary: {
root: {
minHeight: 0,
'&.Mui-expanded': {
minHeight: 0,
},
padding: basicSettings.spacing(0, 1),
fontWeight: basicSettings.typography.fontWeightBold,
},
content: {
margin: basicSettings.spacing(1),
'&.Mui-expanded': {
margin: basicSettings.spacing(1),
}
},
expandIcon: {
order: -1,
}
},
MuiAccordionDetails: {
root: {
padding: basicSettings.spacing(1),
}
},
MuiFormControlLabel: {
root: {
marginBottom: 0,
marginLeft: 0,
marginRight: 0,
}
},
MuiFormHelperText: {
root: {
fontSize: '1em',
},
contained: {
marginLeft: 0,
marginRight: 0,
}
},
MuiTypography: {
body1: {
fontSize: '1em',
}
},
MuiDialog: {
paper: {
margin: 0,
}
},
MuiTooltip: {
popper: {
top: 0,
zIndex: 9999,
}
},
MuiMenu: {
list: {
padding: '0',
}
},
MuiMenuItem: {
root: {
fontSize: 14,
}
},
MuiSelect: {
selectMenu: {
minHeight: 'unset',
},
select:{
'&:focus':{
backgroundColor: 'unset',
}
}
}
},
transitions: {
create: () => 'none',
},
zIndex: {
modal: 2000,
},
props: {
MuiTextField: {
variant: 'outlined',
},
MuiButton: {
disableTouchRipple: true,
},
MuiIconButton: {
size: 'small',
disableTouchRipple: true,
},
MuiAccordion: {
defaultExpanded: true,
},
MuiTab: {
textColor: 'inherit',
},
MuiCheckbox: {
disableTouchRipple: true,
},
MuiDialogTitle: {
disableTypography: true,
},
MuiCardHeader: {
disableTypography: true,
},
MuiListItem: {
disableGutters: true,
},
},
});
/* Get the final theme after merging base theme with selected theme */
function getFinalTheme(baseTheme) {
let mixins = {
panelBorder: {
border: '1px solid '+baseTheme.otherVars.borderColor,
all: {
border: '1px solid '+baseTheme.otherVars.borderColor,
},
top: {
borderTop: '1px solid '+baseTheme.otherVars.borderColor,
},
bottom: {
borderBottom: '1px solid '+baseTheme.otherVars.borderColor,
},
right: {
borderRight: '1px solid '+baseTheme.otherVars.borderColor,
}
},
nodeIcon: {
backgroundPosition: 'center',
padding: baseTheme.spacing(0, 1.5),
},
tabPanel: {
height: '100%',
padding: baseTheme.spacing(1),
overflow: 'auto',
backgroundColor: baseTheme.palette.grey[400],
position: 'relative',
},
fontSourceCode: {
fontFamily: '"Source Code Pro", SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
}
};
return createMuiTheme({
mixins: mixins,
overrides: {
MuiOutlinedInput: {
root: {
'&.Mui-disabled .MuiOutlinedInput-notchedOutline': {
borderColor: baseTheme.otherVars.inputBorderColor,
},
},
notchedOutline: {
borderColor: baseTheme.otherVars.inputBorderColor,
}
},
MuiFormControlLabel: {
label: {
'&.Mui-disabled': {
color: baseTheme.palette.text.muted
}
}
},
MuiTabs: {
root: {
backgroundColor: baseTheme.otherVars.headerBg,
...mixins.panelBorder.bottom
},
indicator: {
backgroundColor: baseTheme.otherVars.activeColor,
}
},
MuiFormLabel: {
root: {
color: baseTheme.palette.text.primary,
fontSize: baseTheme.typography.fontSize,
},
asterisk: {
color: baseTheme.palette.error.main,
}
},
MuiInputBase: {
root: {
backgroundColor: baseTheme.palette.background.default,
textOverflow: 'ellipsis',
'&.Mui-disabled': {
backgroundColor: baseTheme.otherVars.inputDisabledBg,
},
},
inputMultiline: {
fontSize: baseTheme.typography.fontSize,
height: 'unset',
backgroundColor: baseTheme.palette.background.default,
'&[readonly], &.Mui-disabled': {
color: baseTheme.palette.text.muted,
backgroundColor: baseTheme.otherVars.inputDisabledBg,
},
},
input: {
fontSize: baseTheme.typography.fontSize,
height: 'unset',
backgroundColor: baseTheme.palette.background.default,
'&[readonly], &.Mui-disabled': {
color: baseTheme.palette.text.muted,
backgroundColor: baseTheme.otherVars.inputDisabledBg,
},
'&:focus': {
outline: '0 !important',
}
},
},
MuiIconButton: {
root: {
color: baseTheme.palette.text.primary,
'&$disabled': {
color: 'abc',
}
}
},
MuiAccordion: {
root: {
...mixins.panelBorder,
}
},
MuiAccordionSummary: {
root: {
...mixins.panelBorder.bottom,
backgroundColor: baseTheme.otherVars.headerBg,
}
},
MuiToggleButtonGroup: {
groupedHorizontal : {
'&:not(:first-child)': {
borderLeft: 'abc'
}
}
},
MuiSwitch: {
root: {
width: 54,
height: 28,
padding: '7px 12px',
},
colorPrimary: {
'&$disabled': {
color: 'abc',
'& + .MuiSwitch-track': {
backgroundColor: 'abc',
}
}
},
switchBase: {
padding: baseTheme.spacing(0.5),
'&$disabled': {
color: 'abc',
'& + .MuiSwitch-track': {
opacity: baseTheme.palette.action.disabledOpacity,
}
},
'&.Mui-checked': {
color: baseTheme.palette.success.main,
transform: 'translateX(24px)',
'& .MuiSwitch-thumb': {
border: 0
}
},
'&.Mui-checked + .MuiSwitch-track': {
backgroundColor: baseTheme.palette.success.light,
},
},
thumb: {
border: '1px solid ' + baseTheme.otherVars.inputBorderColor
},
track: {
backgroundColor: baseTheme.otherVars.toggleBtnBg
}
},
MuiCheckbox: {
root: {
padding: '0px',
color: baseTheme.otherVars.inputBorderColor,
},
colorPrimary: {
'&.Mui-disabled': {
color: baseTheme.palette.checkbox.disabled
}
}
},
MuiToggleButton: {
root: {
padding: 'abc',
paddingRight: baseTheme.spacing(2.5),
paddingLeft: baseTheme.spacing(0.5),
color: 'abc',
'&:hover':{
backgroundColor: 'abc',
},
'&$selected': {
color: 'abc',
backgroundColor: 'abc',
'&:hover':{
backgroundColor: 'abc',
}
}
},
label: {
textTransform: 'initial',
}
},
MuiFormHelperText: {
root: {
color: baseTheme.palette.text.muted,
},
},
MuiDialogContent: {
root: {
padding: 0,
userSelect: 'text',
}
},
MuiDialogTitle: {
root: {
fontWeight: 'bold',
padding: '5px 10px',
cursor: 'move',
display: 'flex',
alignItems: 'center',
...mixins.panelBorder.bottom,
}
},
MuiCardHeader: {
root: {
padding: '4px 8px',
...mixins.panelBorder.bottom,
}
},
MuiCardContent: {
root: {
padding: 0,
'&:last-child': {
paddingBottom: 0,
}
}
},
MuiListItem: {
root: {
color: baseTheme.palette.text.primary,
backgroundColor: baseTheme.palette.background.default,
flexDirection: 'column',
alignItems: 'initial',
padding: '0px 4px',
paddingTop: '0px',
paddingBottom: '0px',
...mixins.panelBorder.top,
...mixins.panelBorder.bottom,
borderTopColor: 'transparent',
cursor: 'pointer',
'&$selected': {
backgroundColor: baseTheme.palette.primary.light,
borderColor: baseTheme.palette.primary.main,
'&:hover': {
backgroundColor: baseTheme.palette.primary.light,
}
},
}
}
}
}, baseTheme);
}
/* Theme wrapper used by DOM containers to apply theme */
/* In future, this will be moved to App container */
export default function Theme(props) {
const theme = useMemo(()=>{
/* We'll remove this in future, we can get the value from preferences directly */
let themeName = document.querySelector('link[data-theme]')?.getAttribute('data-theme');
let baseTheme = getStandardTheme(basicSettings);
switch(themeName) {
case 'dark':
baseTheme = getDarkTheme(baseTheme);
break;
case 'high_contrast':
baseTheme = getHightContrastTheme(baseTheme);
break;
}
return getFinalTheme(baseTheme);
}, []);
return (
<ThemeProvider theme={theme}>
{props.children}
</ThemeProvider>
);
}
Theme.propTypes = {
children: CustomPropTypes.children,
};
export const commonTableStyles = makeStyles((theme)=>({
table: {
borderSpacing: 0,
width: '100%',
overflow: 'auto',
backgroundColor: theme.otherVars.tableBg,
border: '1px solid '+theme.otherVars.borderColor,
'& tbody td, & thead th': {
margin: 0,
padding: theme.spacing(0.5),
border: '1px solid '+theme.otherVars.borderColor,
borderBottom: 'none',
position: 'relative',
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
userSelect: 'text',
'&:first-of-type':{
borderLeft: 'none',
},
},
'& thead tr:first-of-type th': {
borderTop: 'none',
},
'& tbody tr:last-of-type': {
'&:hover td': {
borderBottomColor: theme.palette.primary.main,
},
'& td': {
borderBottomColor: theme.otherVars.borderColor,
}
},
'& th': {
fontWeight: theme.typography.fontWeightBold,
padding: theme.spacing(1, 0.5),
textAlign: 'left',
},
'& tbody > tr': {
'&:hover': {
backgroundColor: theme.palette.primary.light,
'& td': {
borderBottom: '1px solid '+theme.palette.primary.main,
borderTop: '1px solid '+theme.palette.primary.main,
},
'&:last-of-type td': {
borderBottomColor: theme.palette.primary.main,
},
},
},
},
noBorder: {
border: 0,
},
borderBottom: {
'& tbody tr:last-of-type td': {
borderBottom: '1px solid '+theme.otherVars.borderColor,
},
},
noHover: {
'& tbody > tr': {
'&:hover': {
backgroundColor: theme.otherVars.tableBg,
'& td': {
borderBottomColor: theme.otherVars.borderColor,
borderTopColor: theme.otherVars.borderColor,
},
'&:last-of-type td': {
borderBottomColor: theme.otherVars.borderColor,
},
},
},
}
}));