mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-24 01:18:01 +02:00
refactor: styles batch 3 (#2821)
This commit is contained in:
parent
be1762d33f
commit
ddb9d11039
@ -137,7 +137,7 @@ const ProjectRoleForm: FC<IProjectRoleForm> = ({
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
<Button onClick={onCancel} sx={{ ml: 2 }}>
|
||||
<Button onClick={onCancel} sx={{ marginLeft: 2 }}>
|
||||
Cancel
|
||||
</Button>
|
||||
</Box>
|
||||
|
@ -264,7 +264,10 @@ export const ChangeRequestOverview: FC = () => {
|
||||
}
|
||||
show={
|
||||
<Button
|
||||
sx={{ ml: 2 }}
|
||||
sx={{
|
||||
marginLeft: theme =>
|
||||
theme.spacing(2),
|
||||
}}
|
||||
variant="outlined"
|
||||
onClick={onCancel}
|
||||
>
|
||||
|
@ -1,13 +1,11 @@
|
||||
import React, { useEffect, useState, useRef, FC } from 'react';
|
||||
import React, { CSSProperties, useEffect, useState, useRef, FC } from 'react';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
|
||||
interface IAnimateOnMountProps {
|
||||
mounted: boolean;
|
||||
enter: string;
|
||||
start: string;
|
||||
leave?: string;
|
||||
container?: string;
|
||||
style?: React.CSSProperties;
|
||||
enter: CSSProperties;
|
||||
start: CSSProperties;
|
||||
leave?: CSSProperties;
|
||||
onStart?: () => void;
|
||||
onEnd?: () => void;
|
||||
}
|
||||
@ -17,14 +15,12 @@ const AnimateOnMount: FC<IAnimateOnMountProps> = ({
|
||||
enter,
|
||||
start,
|
||||
leave,
|
||||
container,
|
||||
children,
|
||||
style,
|
||||
onStart,
|
||||
onEnd,
|
||||
}) => {
|
||||
const [show, setShow] = useState(mounted);
|
||||
const [styles, setStyles] = useState('');
|
||||
const [styles, setStyles] = useState<CSSProperties>({});
|
||||
const mountedRef = useRef<null | boolean>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@ -39,7 +35,7 @@ const AnimateOnMount: FC<IAnimateOnMountProps> = ({
|
||||
if (!leave) {
|
||||
setShow(false);
|
||||
}
|
||||
setStyles(leave || '');
|
||||
setStyles(leave || {});
|
||||
}
|
||||
}
|
||||
}, [mounted, enter, onStart, leave]);
|
||||
@ -56,11 +52,8 @@ const AnimateOnMount: FC<IAnimateOnMountProps> = ({
|
||||
condition={show}
|
||||
show={
|
||||
<div
|
||||
className={`${start} ${styles} ${
|
||||
container ? container : ''
|
||||
}`}
|
||||
onTransitionEnd={onTransitionEnd}
|
||||
style={{ ...style }}
|
||||
style={{ ...start, ...styles }}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
|
@ -1,47 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
alignItems: 'center',
|
||||
position: 'relative',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
maxWidth: '400px',
|
||||
[theme.breakpoints.down('md')]: {
|
||||
marginTop: theme.spacing(1),
|
||||
maxWidth: '100%',
|
||||
},
|
||||
},
|
||||
search: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
border: `1px solid ${theme.palette.grey[500]}`,
|
||||
borderRadius: theme.shape.borderRadiusExtraLarge,
|
||||
padding: '3px 5px 3px 12px',
|
||||
width: '100%',
|
||||
zIndex: 3,
|
||||
'&.search-container:focus-within': {
|
||||
borderColor: theme.palette.primary.light,
|
||||
boxShadow: theme.boxShadows.main,
|
||||
},
|
||||
},
|
||||
searchIcon: {
|
||||
marginRight: 8,
|
||||
color: theme.palette.inactiveIcon,
|
||||
},
|
||||
clearContainer: {
|
||||
width: '30px',
|
||||
'& > button': {
|
||||
padding: '7px',
|
||||
},
|
||||
},
|
||||
clearIcon: {
|
||||
color: theme.palette.grey[700],
|
||||
fontSize: '18px',
|
||||
},
|
||||
inputRoot: {
|
||||
width: '100%',
|
||||
},
|
||||
}));
|
@ -1,13 +1,11 @@
|
||||
import React, { useRef, useState } from 'react';
|
||||
import { IconButton, InputBase, Tooltip } from '@mui/material';
|
||||
import { useAsyncDebounce } from 'react-table';
|
||||
import { Box, IconButton, InputBase, styled, Tooltip } from '@mui/material';
|
||||
import { Search as SearchIcon, Close } from '@mui/icons-material';
|
||||
import classnames from 'classnames';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useStyles } from './Search.styles';
|
||||
import { SearchSuggestions } from './SearchSuggestions/SearchSuggestions';
|
||||
import { IGetSearchContextOutput } from 'hooks/useSearch';
|
||||
import { useKeyboardShortcut } from 'hooks/useKeyboardShortcut';
|
||||
import { useAsyncDebounce } from 'react-table';
|
||||
|
||||
interface ISearchProps {
|
||||
initialValue?: string;
|
||||
@ -21,6 +19,43 @@ interface ISearchProps {
|
||||
debounceTime?: number;
|
||||
}
|
||||
|
||||
const StyledContainer = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexGrow: 1,
|
||||
alignItems: 'center',
|
||||
position: 'relative',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
maxWidth: '400px',
|
||||
[theme.breakpoints.down('md')]: {
|
||||
marginTop: theme.spacing(1),
|
||||
maxWidth: '100%',
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledSearch = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
border: `1px solid ${theme.palette.neutral.border}`,
|
||||
borderRadius: theme.shape.borderRadiusExtraLarge,
|
||||
padding: '3px 5px 3px 12px',
|
||||
width: '100%',
|
||||
zIndex: 3,
|
||||
'&:focus-within': {
|
||||
borderColor: theme.palette.primary.light,
|
||||
boxShadow: theme.boxShadows.main,
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledInputBase = styled(InputBase)(({ theme }) => ({
|
||||
width: '100%',
|
||||
}));
|
||||
|
||||
const StyledClose = styled(Close)(({ theme }) => ({
|
||||
color: theme.palette.neutral.main,
|
||||
fontSize: theme.typography.body1.fontSize,
|
||||
}));
|
||||
|
||||
export const Search = ({
|
||||
initialValue = '',
|
||||
onChange,
|
||||
@ -33,7 +68,6 @@ export const Search = ({
|
||||
debounceTime = 200,
|
||||
}: ISearchProps) => {
|
||||
const ref = useRef<HTMLInputElement>();
|
||||
const { classes: styles } = useStyles();
|
||||
const [showSuggestions, setShowSuggestions] = useState(false);
|
||||
|
||||
const [value, setValue] = useState(initialValue);
|
||||
@ -62,23 +96,17 @@ export const Search = ({
|
||||
const placeholder = `${customPlaceholder ?? 'Search'} (${hotkey})`;
|
||||
|
||||
return (
|
||||
<div className={styles.container} style={containerStyles}>
|
||||
<div
|
||||
className={classnames(
|
||||
styles.search,
|
||||
className,
|
||||
'search-container'
|
||||
)}
|
||||
>
|
||||
<StyledContainer style={containerStyles}>
|
||||
<StyledSearch className={className}>
|
||||
<SearchIcon
|
||||
className={classnames(styles.searchIcon, 'search-icon')}
|
||||
sx={{
|
||||
mr: 1,
|
||||
color: theme => theme.palette.inactiveIcon,
|
||||
}}
|
||||
/>
|
||||
<InputBase
|
||||
<StyledInputBase
|
||||
inputRef={ref}
|
||||
placeholder={placeholder}
|
||||
classes={{
|
||||
root: classnames(styles.inputRoot, 'input-container'),
|
||||
}}
|
||||
inputProps={{ 'aria-label': placeholder }}
|
||||
value={value}
|
||||
onChange={e => onSearchChange(e.target.value)}
|
||||
@ -86,12 +114,7 @@ export const Search = ({
|
||||
onBlur={() => setShowSuggestions(false)}
|
||||
disabled={disabled}
|
||||
/>
|
||||
<div
|
||||
className={classnames(
|
||||
styles.clearContainer,
|
||||
'clear-container'
|
||||
)}
|
||||
>
|
||||
<Box sx={{ width: theme => theme.spacing(4) }}>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(value)}
|
||||
show={
|
||||
@ -102,20 +125,21 @@ export const Search = ({
|
||||
onSearchChange('');
|
||||
ref.current?.focus();
|
||||
}}
|
||||
sx={{ padding: theme => theme.spacing(1) }}
|
||||
>
|
||||
<Close className={styles.clearIcon} />
|
||||
<StyledClose />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Box>
|
||||
</StyledSearch>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(hasFilters) && showSuggestions}
|
||||
show={
|
||||
<SearchSuggestions getSearchContext={getSearchContext!} />
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
@ -1,78 +0,0 @@
|
||||
import React, { useState, VFC } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { debounce } from 'debounce';
|
||||
import { InputBase, Chip } from '@mui/material';
|
||||
import SearchIcon from '@mui/icons-material/Search';
|
||||
import { useStyles } from 'component/common/SearchField/styles';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
|
||||
interface ISearchFieldProps {
|
||||
updateValue: (value: string) => void;
|
||||
initialValue?: string;
|
||||
className?: string;
|
||||
showValueChip?: boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use `Search` instead.
|
||||
*/
|
||||
export const SearchField: VFC<ISearchFieldProps> = ({
|
||||
updateValue,
|
||||
initialValue = '',
|
||||
className = '',
|
||||
showValueChip,
|
||||
}) => {
|
||||
const { classes: styles } = useStyles();
|
||||
const [localValue, setLocalValue] = useState(initialValue);
|
||||
const debounceUpdateValue = debounce(updateValue, 500);
|
||||
|
||||
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
event.preventDefault();
|
||||
const value = event.target.value || '';
|
||||
setLocalValue(value);
|
||||
debounceUpdateValue(value);
|
||||
};
|
||||
|
||||
const handleKeyPress = (event: React.KeyboardEvent) => {
|
||||
if (event.key === 'Enter') {
|
||||
updateValue(localValue);
|
||||
}
|
||||
};
|
||||
|
||||
const updateNow = () => {
|
||||
updateValue(localValue);
|
||||
};
|
||||
|
||||
const onDelete = () => {
|
||||
setLocalValue('');
|
||||
updateValue('');
|
||||
};
|
||||
|
||||
return (
|
||||
<form className={styles.container} role="search">
|
||||
<div className={classnames(styles.search, className)}>
|
||||
<SearchIcon className={styles.searchIcon} />
|
||||
<InputBase
|
||||
placeholder="Search..."
|
||||
classes={{ root: styles.inputRoot }}
|
||||
inputProps={{ 'aria-label': 'search' }}
|
||||
value={localValue}
|
||||
onChange={handleChange}
|
||||
onBlur={updateNow}
|
||||
onKeyPress={handleKeyPress}
|
||||
type="search"
|
||||
/>
|
||||
</div>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(showValueChip && localValue)}
|
||||
show={
|
||||
<Chip
|
||||
label={localValue}
|
||||
onDelete={onDelete}
|
||||
title="Clear search query"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
};
|
@ -1,28 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
flexWrap: 'wrap',
|
||||
gap: '1rem',
|
||||
},
|
||||
search: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
backgroundColor: theme.palette.background.default,
|
||||
borderRadius: theme.shape.borderRadiusExtraLarge,
|
||||
padding: '0.25rem 0.5rem',
|
||||
maxWidth: '450px',
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
width: '100%',
|
||||
},
|
||||
},
|
||||
searchIcon: {
|
||||
marginRight: 8,
|
||||
color: theme.palette.inactiveIcon,
|
||||
},
|
||||
inputRoot: {
|
||||
width: '100%',
|
||||
},
|
||||
}));
|
@ -1,48 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
container: {
|
||||
width: '100%',
|
||||
padding: theme.spacing(2, 3),
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'flex-start',
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
border: `1px solid ${theme.palette.dividerAlternative}`,
|
||||
position: 'relative',
|
||||
borderRadius: '5px',
|
||||
},
|
||||
link: {
|
||||
textDecoration: 'none',
|
||||
marginLeft: theme.spacing(1),
|
||||
'&:hover': {
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
},
|
||||
accordion: {
|
||||
border: `1px solid ${theme.palette.dividerAlternative}`,
|
||||
borderRadius: theme.shape.borderRadiusMedium,
|
||||
backgroundColor: '#fff',
|
||||
boxShadow: 'none',
|
||||
margin: 0,
|
||||
},
|
||||
accordionRoot: {
|
||||
transition: 'all 0.1s ease',
|
||||
'&:before': {
|
||||
opacity: '0 !important',
|
||||
},
|
||||
},
|
||||
accordionExpanded: {
|
||||
backgroundColor: theme.palette.neutral.light,
|
||||
},
|
||||
previewButton: {
|
||||
paddingTop: 0,
|
||||
paddingBottom: 0,
|
||||
marginLeft: 'auto',
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
},
|
||||
summary: {
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
margin: theme.spacing(0.5, 0),
|
||||
},
|
||||
}));
|
@ -7,11 +7,11 @@ import {
|
||||
AccordionDetails,
|
||||
AccordionSummary,
|
||||
Button,
|
||||
styled,
|
||||
Typography,
|
||||
} from '@mui/material';
|
||||
import { ConstraintAccordionList } from '../ConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
|
||||
import { ConditionallyRender } from '../ConditionallyRender/ConditionallyRender';
|
||||
import { useStyles } from './SegmentItem.styles';
|
||||
import { ConstraintAccordionList } from 'component/common/ConstraintAccordion/ConstraintAccordionList/ConstraintAccordionList';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
|
||||
interface ISegmentItemProps {
|
||||
segment: Partial<ISegment>;
|
||||
@ -20,36 +20,52 @@ interface ISegmentItemProps {
|
||||
headerContent?: JSX.Element;
|
||||
}
|
||||
|
||||
const StyledAccordion = styled(Accordion)(({ theme }) => ({
|
||||
border: `1px solid ${theme.palette.dividerAlternative}`,
|
||||
borderRadius: theme.shape.borderRadiusMedium,
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
boxShadow: 'none',
|
||||
margin: 0,
|
||||
transition: 'all 0.1s ease',
|
||||
'&:before': {
|
||||
opacity: '0 !important',
|
||||
},
|
||||
'&.Mui-expanded': { backgroundColor: theme.palette.neutral.light },
|
||||
}));
|
||||
|
||||
const StyledAccordionSummary = styled(AccordionSummary)(({ theme }) => ({
|
||||
margin: theme.spacing(0, 0.5),
|
||||
fontSize: theme.typography.body2.fontSize,
|
||||
'.MuiAccordionSummary-content': {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledLink = styled(Link)(({ theme }) => ({
|
||||
textDecoration: 'none',
|
||||
marginLeft: theme.spacing(1),
|
||||
'&:hover': {
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
}));
|
||||
|
||||
export const SegmentItem: VFC<ISegmentItemProps> = ({
|
||||
segment,
|
||||
isExpanded,
|
||||
headerContent,
|
||||
constraintList,
|
||||
}) => {
|
||||
const { classes } = useStyles();
|
||||
const [isOpen, setIsOpen] = useState(isExpanded || false);
|
||||
|
||||
return (
|
||||
<Accordion
|
||||
expanded={isOpen}
|
||||
className={classes.accordion}
|
||||
classes={{
|
||||
root: classes.accordionRoot,
|
||||
expanded: classes.accordionExpanded,
|
||||
}}
|
||||
>
|
||||
<AccordionSummary
|
||||
id={`segment-accordion-${segment.id}`}
|
||||
className={classes.summary}
|
||||
>
|
||||
<StyledAccordion expanded={isOpen}>
|
||||
<StyledAccordionSummary id={`segment-accordion-${segment.id}`}>
|
||||
<DonutLarge color="secondary" sx={{ mr: 1 }} />
|
||||
Segment:
|
||||
<Link
|
||||
to={`/segments/edit/${segment.id}`}
|
||||
className={classes.link}
|
||||
>
|
||||
<span>Segment:</span>
|
||||
<StyledLink to={`/segments/edit/${segment.id}`}>
|
||||
{segment.name}
|
||||
</Link>
|
||||
</StyledLink>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(headerContent)}
|
||||
show={headerContent}
|
||||
@ -61,13 +77,18 @@ export const SegmentItem: VFC<ISegmentItemProps> = ({
|
||||
size="small"
|
||||
variant="outlined"
|
||||
onClick={() => setIsOpen(value => !value)}
|
||||
className={classes.previewButton}
|
||||
sx={{
|
||||
my: 0,
|
||||
ml: 'auto',
|
||||
fontSize: theme =>
|
||||
theme.typography.body2.fontSize,
|
||||
}}
|
||||
>
|
||||
{isOpen ? 'Close preview' : 'Preview'}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</AccordionSummary>
|
||||
</StyledAccordionSummary>
|
||||
<AccordionDetails sx={{ pt: 0 }}>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(constraintList)}
|
||||
@ -90,6 +111,6 @@ export const SegmentItem: VFC<ISegmentItemProps> = ({
|
||||
}
|
||||
/>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</StyledAccordion>
|
||||
);
|
||||
};
|
||||
|
@ -1,33 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
link: {
|
||||
position: 'fixed',
|
||||
overflow: 'hidden',
|
||||
zIndex: 1000,
|
||||
top: '1.125rem',
|
||||
left: '1.125rem',
|
||||
padding: '0.5rem 1rem',
|
||||
whiteSpace: 'nowrap',
|
||||
textDecoration: 'none',
|
||||
background: theme.palette.primary.dark,
|
||||
color: theme.palette.primary.contrastText,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
|
||||
[theme.breakpoints.down(960)]: {
|
||||
top: '0.8rem',
|
||||
left: '0.8rem',
|
||||
},
|
||||
|
||||
'&:not(:focus):not(:active)': {
|
||||
clip: 'rect(0 0 0 0)',
|
||||
clipPath: 'inset(50%)',
|
||||
zIndex: -1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
margin: -1,
|
||||
padding: 0,
|
||||
},
|
||||
},
|
||||
}));
|
@ -1,12 +0,0 @@
|
||||
import { SKIP_NAV_TARGET_ID } from 'component/common/SkipNav/SkipNavTarget';
|
||||
import { useStyles } from 'component/common/SkipNav/SkipNavLink.styles';
|
||||
|
||||
export const SkipNavLink = () => {
|
||||
const { classes: styles } = useStyles();
|
||||
|
||||
return (
|
||||
<a href={`#${SKIP_NAV_TARGET_ID}`} className={styles.link}>
|
||||
Skip to content <span aria-hidden>↓</span>
|
||||
</a>
|
||||
);
|
||||
};
|
38
frontend/src/component/common/SkipNavLink/SkipNavLink.tsx
Normal file
38
frontend/src/component/common/SkipNavLink/SkipNavLink.tsx
Normal file
@ -0,0 +1,38 @@
|
||||
import { SKIP_NAV_TARGET_ID } from 'component/common/SkipNavLink/SkipNavTarget';
|
||||
import { styled } from '@mui/material';
|
||||
|
||||
const StyledLink = styled('a')(({ theme }) => ({
|
||||
position: 'fixed',
|
||||
overflow: 'hidden',
|
||||
zIndex: 1000,
|
||||
top: theme.spacing(2.25),
|
||||
left: theme.spacing(2.25),
|
||||
padding: theme.spacing(1, 2),
|
||||
whiteSpace: 'nowrap',
|
||||
textDecoration: 'none',
|
||||
background: theme.palette.primary.dark,
|
||||
color: theme.palette.primary.contrastText,
|
||||
borderRadius: theme.shape.borderRadius,
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
|
||||
[theme.breakpoints.down(960)]: {
|
||||
top: '0.8rem',
|
||||
left: '0.8rem',
|
||||
},
|
||||
|
||||
'&:not(:focus):not(:active)': {
|
||||
clip: 'rect(0 0 0 0)',
|
||||
clipPath: 'inset(50%)',
|
||||
zIndex: -1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
margin: -1,
|
||||
padding: 0,
|
||||
},
|
||||
}));
|
||||
|
||||
export const SkipNavLink = () => (
|
||||
<StyledLink href={`#${SKIP_NAV_TARGET_ID}`}>
|
||||
Skip to content <span aria-hidden>↓</span>
|
||||
</StyledLink>
|
||||
);
|
@ -1,7 +1,11 @@
|
||||
import { Typography, Button, useTheme, useMediaQuery } from '@mui/material';
|
||||
import EventDiff from 'component/events/EventDiff/EventDiff';
|
||||
import { useThemeStyles } from 'themes/themeStyles';
|
||||
import {
|
||||
fadeInBottomEnter,
|
||||
fadeInBottomStartWithoutFixed,
|
||||
} from 'themes/themeStyles';
|
||||
import AnimateOnMount from 'component/common/AnimateOnMount/AnimateOnMount';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
interface IStaleDataNotification {
|
||||
refresh: () => void;
|
||||
@ -18,12 +22,12 @@ export const StaleDataNotification = ({
|
||||
data,
|
||||
cache,
|
||||
}: IStaleDataNotification) => {
|
||||
const { classes: themeStyles } = useThemeStyles();
|
||||
const theme = useTheme();
|
||||
const isExtraSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));
|
||||
|
||||
const getStyles = () => {
|
||||
const style = useMemo(() => {
|
||||
const base = {
|
||||
...fadeInBottomStartWithoutFixed,
|
||||
padding: `${theme.spacing(3)} ${theme.spacing(4)}`,
|
||||
boxShadow: theme.boxShadows.elevated,
|
||||
borderRadius: theme.shape.borderRadiusLarge,
|
||||
@ -41,15 +45,10 @@ export const StaleDataNotification = ({
|
||||
};
|
||||
}
|
||||
return base;
|
||||
};
|
||||
}, [theme, isExtraSmallScreen]);
|
||||
|
||||
return (
|
||||
<AnimateOnMount
|
||||
mounted={show}
|
||||
start={themeStyles.fadeInBottomStartWithoutFixed}
|
||||
enter={themeStyles.fadeInBottomEnter}
|
||||
style={getStyles()}
|
||||
>
|
||||
<AnimateOnMount mounted={show} start={style} enter={fadeInBottomEnter}>
|
||||
<Typography variant="h5" sx={{ my: 2, mb: 2 }}>
|
||||
Your data is stale
|
||||
</Typography>
|
||||
|
@ -1,39 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
container: {
|
||||
borderRadius: theme.shape.borderRadiusMedium,
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
'& + &': {
|
||||
marginTop: theme.spacing(2),
|
||||
},
|
||||
background: theme.palette.background.paper,
|
||||
},
|
||||
header: {
|
||||
padding: theme.spacing(0.5, 2),
|
||||
display: 'flex',
|
||||
gap: theme.spacing(1),
|
||||
alignItems: 'center',
|
||||
borderBottom: `1px solid ${theme.palette.divider}`,
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
},
|
||||
headerDraggable: {
|
||||
paddingLeft: theme.spacing(1),
|
||||
},
|
||||
icon: {
|
||||
fill: theme.palette.inactiveIcon,
|
||||
},
|
||||
actions: {
|
||||
marginLeft: 'auto',
|
||||
display: 'flex',
|
||||
minHeight: theme.spacing(6),
|
||||
alignItems: 'center',
|
||||
},
|
||||
resultChip: {
|
||||
marginLeft: 'auto',
|
||||
},
|
||||
body: {
|
||||
padding: theme.spacing(2),
|
||||
justifyItems: 'center',
|
||||
},
|
||||
}));
|
@ -1,7 +1,6 @@
|
||||
import { DragEventHandler, FC, ReactNode } from 'react';
|
||||
import { DragIndicator } from '@mui/icons-material';
|
||||
import { styled, IconButton, Box } from '@mui/material';
|
||||
import classNames from 'classnames';
|
||||
import { IFeatureStrategy } from 'interfaces/strategy';
|
||||
import {
|
||||
getFeatureStrategyIcon,
|
||||
@ -9,7 +8,6 @@ import {
|
||||
} from 'utils/strategyNames';
|
||||
import StringTruncator from 'component/common/StringTruncator/StringTruncator';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useStyles } from './StrategyItemContainer.styles';
|
||||
import { PlaygroundStrategySchema } from 'openapi';
|
||||
|
||||
interface IStrategyItemContainerProps {
|
||||
@ -40,6 +38,27 @@ const StyledIndexLabel = styled('div')(({ theme }) => ({
|
||||
},
|
||||
}));
|
||||
|
||||
const StyledContainer = styled(Box)(({ theme }) => ({
|
||||
borderRadius: theme.shape.borderRadiusMedium,
|
||||
border: `1px solid ${theme.palette.divider}`,
|
||||
'& + &': {
|
||||
marginTop: theme.spacing(2),
|
||||
},
|
||||
background: theme.palette.background.paper,
|
||||
}));
|
||||
|
||||
const StyledHeader = styled('div', {
|
||||
shouldForwardProp: prop => prop !== 'draggable',
|
||||
})(({ theme, draggable }) => ({
|
||||
padding: theme.spacing(0.5, 2),
|
||||
display: 'flex',
|
||||
gap: theme.spacing(1),
|
||||
alignItems: 'center',
|
||||
borderBottom: `1px solid ${theme.palette.divider}`,
|
||||
fontWeight: theme.typography.fontWeightMedium,
|
||||
paddingLeft: draggable ? theme.spacing(1) : theme.spacing(2),
|
||||
}));
|
||||
|
||||
export const StrategyItemContainer: FC<IStrategyItemContainerProps> = ({
|
||||
strategy,
|
||||
onDragStart,
|
||||
@ -49,7 +68,6 @@ export const StrategyItemContainer: FC<IStrategyItemContainerProps> = ({
|
||||
orderNumber,
|
||||
style = {},
|
||||
}) => {
|
||||
const { classes: styles } = useStyles();
|
||||
const Icon = getFeatureStrategyIcon(strategy.name);
|
||||
|
||||
return (
|
||||
@ -58,12 +76,8 @@ export const StrategyItemContainer: FC<IStrategyItemContainerProps> = ({
|
||||
condition={orderNumber !== undefined}
|
||||
show={<StyledIndexLabel>{orderNumber}</StyledIndexLabel>}
|
||||
/>
|
||||
<Box className={styles.container} style={{ ...style }}>
|
||||
<div
|
||||
className={classNames(styles.header, {
|
||||
[styles.headerDraggable]: Boolean(onDragStart),
|
||||
})}
|
||||
>
|
||||
<StyledContainer style={style}>
|
||||
<StyledHeader draggable={Boolean(onDragStart)}>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(onDragStart)}
|
||||
show={() => (
|
||||
@ -83,16 +97,36 @@ export const StrategyItemContainer: FC<IStrategyItemContainerProps> = ({
|
||||
</DragIcon>
|
||||
)}
|
||||
/>
|
||||
<Icon className={styles.icon} />
|
||||
<Icon
|
||||
sx={{
|
||||
fill: theme => theme.palette.inactiveIcon,
|
||||
}}
|
||||
/>
|
||||
<StringTruncator
|
||||
maxWidth="150"
|
||||
maxLength={15}
|
||||
text={formatStrategyName(strategy.name)}
|
||||
/>
|
||||
<div className={styles.actions}>{actions}</div>
|
||||
</div>
|
||||
<div className={styles.body}>{children}</div>
|
||||
<Box
|
||||
sx={{
|
||||
marginLeft: 'auto',
|
||||
display: 'flex',
|
||||
minHeight: theme => theme.spacing(6),
|
||||
alignItems: 'center',
|
||||
}}
|
||||
>
|
||||
{actions}
|
||||
</Box>
|
||||
</StyledHeader>
|
||||
<Box
|
||||
sx={{
|
||||
p: 2,
|
||||
justifyItems: 'center',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
</StyledContainer>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@ -1,15 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
tabNav: {
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
borderBottom: '1px solid',
|
||||
borderBottomColor: theme.palette.grey[300],
|
||||
borderRadius: 0,
|
||||
},
|
||||
tab: {
|
||||
[theme.breakpoints.up('lg')]: {
|
||||
minWidth: 160,
|
||||
},
|
||||
},
|
||||
}));
|
@ -1,7 +1,5 @@
|
||||
import React, { useState, ReactNode } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { Tabs, Tab, Paper } from '@mui/material';
|
||||
import { useStyles } from 'component/common/TabNav/TabNav/TabNav.styles';
|
||||
import { TabPanel } from 'component/common/TabNav/TabPanel/TabPanel';
|
||||
|
||||
interface ITabNavProps {
|
||||
@ -15,13 +13,13 @@ interface ITabData {
|
||||
label: string;
|
||||
component: ReactNode;
|
||||
}
|
||||
|
||||
export const TabNav = ({
|
||||
tabData,
|
||||
className = '',
|
||||
navClass = '',
|
||||
startingTab = 0,
|
||||
}: ITabNavProps) => {
|
||||
const { classes: styles } = useStyles();
|
||||
const [activeTab, setActiveTab] = useState(startingTab);
|
||||
const renderTabs = () =>
|
||||
tabData.map((tab, index) => (
|
||||
@ -30,7 +28,11 @@ export const TabNav = ({
|
||||
label={tab.label}
|
||||
id={`tab-${index}`}
|
||||
aria-controls={`tabpanel-${index}`}
|
||||
className={styles.tab}
|
||||
sx={{
|
||||
minWidth: {
|
||||
lg: 160,
|
||||
},
|
||||
}}
|
||||
/>
|
||||
));
|
||||
|
||||
@ -44,8 +46,14 @@ export const TabNav = ({
|
||||
return (
|
||||
<>
|
||||
<Paper
|
||||
className={classnames(styles.tabNav, navClass)}
|
||||
className={navClass}
|
||||
elevation={0}
|
||||
sx={{
|
||||
backgroundColor: theme => theme.palette.background.paper,
|
||||
borderBottom: '1px solid',
|
||||
borderBottomColor: theme => theme.palette.grey[300],
|
||||
borderRadius: 0,
|
||||
}}
|
||||
>
|
||||
<Tabs
|
||||
value={activeTab}
|
||||
|
@ -1,11 +1,16 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import { styled, TableCell } from '@mui/material';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
header: {
|
||||
export const StyledTableCell = styled(TableCell, {
|
||||
shouldForwardProp: prop =>
|
||||
prop !== 'isFlex' && prop !== 'isSortable' && prop !== 'isFlexGrow',
|
||||
})<{
|
||||
isFlex?: boolean;
|
||||
isSortable?: boolean;
|
||||
isFlexGrow?: boolean;
|
||||
}>(({ theme, isFlex, isSortable, isFlexGrow }) => ({
|
||||
position: 'relative',
|
||||
fontWeight: theme.fontWeight.medium,
|
||||
},
|
||||
flex: {
|
||||
fontWeight: theme.typography.fontWeightRegular,
|
||||
...(isFlex && {
|
||||
justifyContent: 'stretch',
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
@ -13,11 +18,8 @@ export const useStyles = makeStyles()(theme => ({
|
||||
'& > *': {
|
||||
flexGrow: 1,
|
||||
},
|
||||
},
|
||||
flexGrow: {
|
||||
flexGrow: 1,
|
||||
},
|
||||
sortable: {
|
||||
}),
|
||||
...(isSortable && {
|
||||
padding: 0,
|
||||
'&:hover, &:focus': {
|
||||
backgroundColor: theme.palette.tableHeaderHover,
|
||||
@ -25,8 +27,15 @@ export const useStyles = makeStyles()(theme => ({
|
||||
color: 'inherit',
|
||||
},
|
||||
},
|
||||
},
|
||||
sortButton: {
|
||||
}),
|
||||
...(isFlexGrow && {
|
||||
flexGrow: 1,
|
||||
}),
|
||||
}));
|
||||
|
||||
export const StyledButton = styled('button', {
|
||||
shouldForwardProp: prop => prop !== 'isSorted',
|
||||
})<{ isSorted?: boolean }>(({ theme, isSorted }) => ({
|
||||
all: 'unset',
|
||||
whiteSpace: 'nowrap',
|
||||
width: '100%',
|
||||
@ -41,11 +50,12 @@ export const useStyles = makeStyles()(theme => ({
|
||||
display: 'flex',
|
||||
boxSizing: 'inherit',
|
||||
cursor: 'pointer',
|
||||
},
|
||||
sortedButton: {
|
||||
fontWeight: theme.fontWeight.bold,
|
||||
},
|
||||
label: {
|
||||
...(isSorted && {
|
||||
fontWeight: theme.typography.fontWeightBold,
|
||||
}),
|
||||
}));
|
||||
|
||||
export const StyledLabel = styled('span')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
flexShrink: 1,
|
||||
@ -58,27 +68,17 @@ export const useStyles = makeStyles()(theme => ({
|
||||
visibility: 'hidden',
|
||||
overflow: 'hidden',
|
||||
},
|
||||
},
|
||||
alignLeft: {
|
||||
justifyContent: 'flex-start',
|
||||
textAlign: 'left',
|
||||
},
|
||||
alignRight: {
|
||||
justifyContent: 'flex-end',
|
||||
textAlign: 'right',
|
||||
},
|
||||
alignCenter: {
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center',
|
||||
},
|
||||
hiddenMeasurementLayer: {
|
||||
}));
|
||||
|
||||
export const StyledHiddenMeasurementLayer = styled('span')(({ theme }) => ({
|
||||
padding: theme.spacing(2),
|
||||
visibility: 'hidden',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
width: '100%',
|
||||
},
|
||||
visibleAbsoluteLayer: {
|
||||
}));
|
||||
|
||||
export const StyledVisibleAbsoluteLayer = styled('span')(({ theme }) => ({
|
||||
padding: theme.spacing(2),
|
||||
position: 'absolute',
|
||||
display: 'flex',
|
||||
@ -95,5 +95,4 @@ export const useStyles = makeStyles()(theme => ({
|
||||
overflowX: 'hidden',
|
||||
overflowY: 'visible',
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
@ -7,11 +7,16 @@ import {
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { TableCell, Tooltip } from '@mui/material';
|
||||
import classnames from 'classnames';
|
||||
import { Tooltip } from '@mui/material';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useStyles } from './CellSortable.styles';
|
||||
import { AnnouncerContext } from 'component/common/Announcer/AnnouncerContext/AnnouncerContext';
|
||||
import {
|
||||
StyledButton,
|
||||
StyledHiddenMeasurementLayer,
|
||||
StyledLabel,
|
||||
StyledTableCell,
|
||||
StyledVisibleAbsoluteLayer,
|
||||
} from './CellSortable.styles';
|
||||
import { SortArrow } from './SortArrow/SortArrow';
|
||||
|
||||
interface ICellSortableProps {
|
||||
@ -45,7 +50,6 @@ export const CellSortable: FC<ICellSortableProps> = ({
|
||||
const { setAnnouncement } = useContext(AnnouncerContext);
|
||||
const [title, setTitle] = useState('');
|
||||
const ref = useRef<HTMLSpanElement>(null);
|
||||
const { classes: styles } = useStyles();
|
||||
|
||||
const ariaSort = isSorted
|
||||
? isDescending
|
||||
@ -62,18 +66,27 @@ export const CellSortable: FC<ICellSortableProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
const alignClass = useMemo(() => {
|
||||
const alignStyle = useMemo(() => {
|
||||
switch (align) {
|
||||
case 'left':
|
||||
return styles.alignLeft;
|
||||
return {
|
||||
justifyContent: 'flex-start',
|
||||
textAlign: 'left',
|
||||
} as const;
|
||||
case 'center':
|
||||
return styles.alignCenter;
|
||||
return {
|
||||
justifyContent: 'center',
|
||||
textAlign: 'center',
|
||||
} as const;
|
||||
case 'right':
|
||||
return styles.alignRight;
|
||||
return {
|
||||
justifyContent: 'flex-end',
|
||||
textAlign: 'right',
|
||||
} as const;
|
||||
default:
|
||||
return undefined;
|
||||
}
|
||||
}, [align, styles]);
|
||||
}, [align]);
|
||||
|
||||
useEffect(() => {
|
||||
const updateTitle = () => {
|
||||
@ -93,55 +106,36 @@ export const CellSortable: FC<ICellSortableProps> = ({
|
||||
}, [setTitle, ariaTitle]); // eslint-disable-line react-hooks/exhaustive-deps
|
||||
|
||||
return (
|
||||
<TableCell
|
||||
<StyledTableCell
|
||||
component="th"
|
||||
aria-sort={ariaSort}
|
||||
className={classnames(
|
||||
styles.header,
|
||||
isSortable && styles.sortable,
|
||||
isFlex && styles.flex,
|
||||
isFlexGrow && styles.flexGrow
|
||||
)}
|
||||
style={{ width, minWidth, maxWidth }}
|
||||
isFlex={isFlex}
|
||||
isFlexGrow={isFlexGrow}
|
||||
isSortable={isSortable}
|
||||
>
|
||||
<ConditionallyRender
|
||||
condition={isSortable}
|
||||
show={
|
||||
<Tooltip title={title} arrow>
|
||||
<button
|
||||
<StyledButton
|
||||
isSorted={isSorted}
|
||||
type="button"
|
||||
className={classnames(
|
||||
isSorted && styles.sortedButton,
|
||||
styles.sortButton,
|
||||
alignClass
|
||||
)}
|
||||
onClick={onSortClick}
|
||||
>
|
||||
<span
|
||||
className={classnames(
|
||||
styles.hiddenMeasurementLayer,
|
||||
alignClass
|
||||
)}
|
||||
<StyledHiddenMeasurementLayer
|
||||
style={alignStyle}
|
||||
aria-hidden
|
||||
>
|
||||
<span
|
||||
className={styles.label}
|
||||
tabIndex={-1}
|
||||
data-text={children}
|
||||
>
|
||||
<StyledLabel tabIndex={-1} data-text={children}>
|
||||
{children}
|
||||
</span>
|
||||
</StyledLabel>
|
||||
<SortArrow
|
||||
isSorted={isSorted}
|
||||
isDesc={isDescending}
|
||||
/>
|
||||
</span>
|
||||
<span
|
||||
className={classnames(
|
||||
styles.visibleAbsoluteLayer,
|
||||
alignClass
|
||||
)}
|
||||
>
|
||||
</StyledHiddenMeasurementLayer>
|
||||
<StyledVisibleAbsoluteLayer style={alignStyle}>
|
||||
<span ref={ref} tabIndex={-1}>
|
||||
<span>{children}</span>
|
||||
</span>
|
||||
@ -150,12 +144,12 @@ export const CellSortable: FC<ICellSortableProps> = ({
|
||||
isDesc={isDescending}
|
||||
className="sort-arrow"
|
||||
/>
|
||||
</span>
|
||||
</button>
|
||||
</StyledVisibleAbsoluteLayer>
|
||||
</StyledButton>
|
||||
</Tooltip>
|
||||
}
|
||||
elseShow={<div className={alignClass}>{children}</div>}
|
||||
elseShow={<div style={alignStyle}>{children}</div>}
|
||||
/>
|
||||
</TableCell>
|
||||
</StyledTableCell>
|
||||
);
|
||||
};
|
||||
|
@ -1,14 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
icon: {
|
||||
marginLeft: theme.spacing(0.25),
|
||||
marginRight: theme.spacing(-0.5),
|
||||
color: theme.palette.grey[700],
|
||||
fontSize: theme.fontSizes.mainHeader,
|
||||
verticalAlign: 'middle',
|
||||
},
|
||||
sorted: {
|
||||
color: theme.palette.grey[900],
|
||||
},
|
||||
}));
|
@ -5,8 +5,8 @@ import {
|
||||
UnfoldMoreOutlined,
|
||||
} from '@mui/icons-material';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useStyles } from './SortArrow.styles';
|
||||
import classnames from 'classnames';
|
||||
import { Theme } from '@mui/material';
|
||||
|
||||
interface ISortArrowProps {
|
||||
isSorted?: boolean;
|
||||
@ -14,14 +14,19 @@ interface ISortArrowProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
const iconStyle = (theme: Theme) => ({
|
||||
marginLeft: theme.spacing(0.25),
|
||||
marginRight: theme.spacing(-0.5),
|
||||
color: theme.palette.neutral.main,
|
||||
fontSize: theme.fontSizes.mainHeader,
|
||||
verticalAlign: 'middle',
|
||||
});
|
||||
|
||||
export const SortArrow: VFC<ISortArrowProps> = ({
|
||||
isSorted: sorted,
|
||||
isDesc: desc = false,
|
||||
className,
|
||||
}) => {
|
||||
const { classes: styles } = useStyles();
|
||||
|
||||
return (
|
||||
}) => (
|
||||
<ConditionallyRender
|
||||
condition={Boolean(sorted)}
|
||||
show={
|
||||
@ -29,21 +34,21 @@ export const SortArrow: VFC<ISortArrowProps> = ({
|
||||
condition={Boolean(desc)}
|
||||
show={
|
||||
<KeyboardArrowDown
|
||||
className={classnames(
|
||||
styles.icon,
|
||||
styles.sorted,
|
||||
className
|
||||
)}
|
||||
sx={theme => ({
|
||||
...iconStyle(theme),
|
||||
color: theme.palette.tableHeaderColor,
|
||||
})}
|
||||
className={className}
|
||||
fontSize="inherit"
|
||||
/>
|
||||
}
|
||||
elseShow={
|
||||
<KeyboardArrowUp
|
||||
className={classnames(
|
||||
styles.icon,
|
||||
styles.sorted,
|
||||
className
|
||||
)}
|
||||
sx={theme => ({
|
||||
...iconStyle(theme),
|
||||
color: theme.palette.tableHeaderColor,
|
||||
})}
|
||||
className={className}
|
||||
fontSize="inherit"
|
||||
/>
|
||||
}
|
||||
@ -51,10 +56,12 @@ export const SortArrow: VFC<ISortArrowProps> = ({
|
||||
}
|
||||
elseShow={
|
||||
<UnfoldMoreOutlined
|
||||
className={classnames(styles.icon, className, 'hover-only')}
|
||||
sx={theme => ({
|
||||
...iconStyle(theme),
|
||||
})}
|
||||
className={classnames(className, 'hover-only')}
|
||||
fontSize="inherit"
|
||||
/>
|
||||
}
|
||||
/>
|
||||
);
|
||||
};
|
||||
);
|
||||
|
@ -1,20 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
tableHeader: {
|
||||
'& > 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,
|
||||
},
|
||||
'&:last-of-type': {
|
||||
borderTopRightRadius: theme.shape.borderRadiusMedium,
|
||||
borderBottomRightRadius: theme.shape.borderRadiusMedium,
|
||||
},
|
||||
},
|
||||
},
|
||||
}));
|
@ -1,7 +1,6 @@
|
||||
import { VFC } from 'react';
|
||||
import { TableHead, TableRow } from '@mui/material';
|
||||
import { styled, TableHead, TableRow } from '@mui/material';
|
||||
import { HeaderGroup } from 'react-table';
|
||||
import { useStyles } from './SortableTableHeader.styles';
|
||||
import { CellSortable } from './CellSortable/CellSortable';
|
||||
|
||||
interface ISortableTableHeaderProps {
|
||||
@ -10,20 +9,31 @@ interface ISortableTableHeaderProps {
|
||||
flex?: boolean;
|
||||
}
|
||||
|
||||
const StyledTableRow = styled(TableRow)(({ 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,
|
||||
},
|
||||
'&:last-of-type': {
|
||||
borderTopRightRadius: theme.shape.borderRadiusMedium,
|
||||
borderBottomRightRadius: theme.shape.borderRadiusMedium,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
export const SortableTableHeader: VFC<ISortableTableHeaderProps> = ({
|
||||
headerGroups,
|
||||
className,
|
||||
flex,
|
||||
}) => {
|
||||
const { classes: styles } = useStyles();
|
||||
|
||||
return (
|
||||
}) => (
|
||||
<TableHead className={className}>
|
||||
{headerGroups.map(headerGroup => (
|
||||
<TableRow
|
||||
{...headerGroup.getHeaderGroupProps()}
|
||||
className={styles.tableHeader}
|
||||
>
|
||||
<StyledTableRow {...headerGroup.getHeaderGroupProps()}>
|
||||
{headerGroup.headers.map((column: HeaderGroup) => {
|
||||
const content = column.render('Header');
|
||||
|
||||
@ -54,8 +64,7 @@ export const SortableTableHeader: VFC<ISortableTableHeaderProps> = ({
|
||||
</CellSortable>
|
||||
);
|
||||
})}
|
||||
</TableRow>
|
||||
</StyledTableRow>
|
||||
))}
|
||||
</TableHead>
|
||||
);
|
||||
};
|
||||
);
|
||||
|
@ -1,19 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles<{
|
||||
rowHeight: 'auto' | 'standard' | 'dense' | 'compact' | number;
|
||||
}>()((theme, { rowHeight }) => ({
|
||||
table: {
|
||||
position: 'relative',
|
||||
|
||||
'& tbody tr': {
|
||||
height:
|
||||
{
|
||||
auto: 'auto',
|
||||
standard: theme.shape.tableRowHeight,
|
||||
compact: theme.shape.tableRowHeightCompact,
|
||||
dense: theme.shape.tableRowHeightDense,
|
||||
}[rowHeight] ?? rowHeight,
|
||||
},
|
||||
},
|
||||
}));
|
@ -1,16 +1,24 @@
|
||||
import { FC } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { Table as MUITable, TableProps } from '@mui/material';
|
||||
import { useStyles } from './Table.styles';
|
||||
|
||||
export const Table: FC<
|
||||
TableProps & {
|
||||
rowHeight?: 'auto' | 'dense' | 'standard' | 'compact' | number;
|
||||
}
|
||||
> = ({ rowHeight = 'auto', className, ...props }) => {
|
||||
const { classes } = useStyles({ rowHeight });
|
||||
|
||||
return (
|
||||
<MUITable className={classnames(classes.table, className)} {...props} />
|
||||
);
|
||||
};
|
||||
> = ({ rowHeight = 'auto', ...props }) => (
|
||||
<MUITable
|
||||
sx={{
|
||||
position: 'relative',
|
||||
'& tbody tr': {
|
||||
height: theme =>
|
||||
({
|
||||
auto: 'auto',
|
||||
standard: theme.shape.tableRowHeight,
|
||||
compact: theme.shape.tableRowHeightCompact,
|
||||
dense: theme.shape.tableRowHeightDense,
|
||||
}[rowHeight] ?? rowHeight),
|
||||
},
|
||||
}}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
@ -1,7 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
tableCell: {
|
||||
padding: 0,
|
||||
},
|
||||
}));
|
@ -1,18 +1,16 @@
|
||||
import { FC, ForwardedRef, forwardRef } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { TableCell as MUITableCell, TableCellProps } from '@mui/material';
|
||||
import { useStyles } from './TableCell.styles';
|
||||
import {
|
||||
styled,
|
||||
TableCell as MUITableCell,
|
||||
TableCellProps,
|
||||
} from '@mui/material';
|
||||
|
||||
const StyledTableCell = styled(MUITableCell)(({ theme }) => ({
|
||||
padding: 0,
|
||||
}));
|
||||
|
||||
export const TableCell: FC<TableCellProps> = forwardRef(
|
||||
({ className, ...props }, ref: ForwardedRef<unknown>) => {
|
||||
const { classes: styles } = useStyles();
|
||||
|
||||
return (
|
||||
<MUITableCell
|
||||
className={classnames(styles.tableCell, className)}
|
||||
{...props}
|
||||
ref={ref}
|
||||
/>
|
||||
);
|
||||
}
|
||||
({ className, ...props }, ref: ForwardedRef<unknown>) => (
|
||||
<StyledTableCell {...props} ref={ref} />
|
||||
)
|
||||
);
|
||||
|
@ -1,14 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
emptyStateListItem: {
|
||||
border: `2px dashed ${theme.palette.neutral.light}`,
|
||||
padding: '0.8rem',
|
||||
textAlign: 'center',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
marginTop: theme.spacing(2),
|
||||
width: '100%',
|
||||
},
|
||||
}));
|
@ -1,9 +1,19 @@
|
||||
import { FC } from 'react';
|
||||
import { Box } from '@mui/material';
|
||||
import { useStyles } from 'component/common/Table/TablePlaceholder/TablePlaceholder.styles';
|
||||
|
||||
export const TablePlaceholder: FC = ({ children }) => {
|
||||
const { classes: styles } = useStyles();
|
||||
|
||||
return <Box className={styles.emptyStateListItem}>{children}</Box>;
|
||||
};
|
||||
export const TablePlaceholder: FC = ({ children }) => (
|
||||
<Box
|
||||
sx={{
|
||||
border: theme => `2px dashed ${theme.palette.neutral.light}`,
|
||||
p: 1.6,
|
||||
textAlign: 'center',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
mt: 2,
|
||||
width: '100%',
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
|
@ -1,21 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(() => ({
|
||||
row: {
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
'&:hover': {
|
||||
'.show-row-hover': {
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
cell: {
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
flexShrink: 0,
|
||||
'& > *': {
|
||||
flexGrow: 1,
|
||||
},
|
||||
},
|
||||
}));
|
@ -3,12 +3,11 @@ import { useTheme } from '@mui/material';
|
||||
import {
|
||||
SortableTableHeader,
|
||||
Table,
|
||||
TableCell,
|
||||
TableBody,
|
||||
TableRow,
|
||||
TableCell,
|
||||
} from 'component/common/Table';
|
||||
import { useVirtualizedRange } from 'hooks/useVirtualizedRange';
|
||||
import { useStyles } from './VirtualizedTable.styles';
|
||||
import { HeaderGroup, Row } from 'react-table';
|
||||
|
||||
interface IVirtualizedTableProps {
|
||||
@ -34,7 +33,6 @@ export const VirtualizedTable: VFC<IVirtualizedTableProps> = ({
|
||||
rows,
|
||||
prepareRow,
|
||||
}) => {
|
||||
const { classes } = useStyles();
|
||||
const theme = useTheme();
|
||||
const rowHeight = useMemo(
|
||||
() => rowHeightOverride || theme.shape.tableRowHeight,
|
||||
@ -56,7 +54,28 @@ export const VirtualizedTable: VFC<IVirtualizedTableProps> = ({
|
||||
style={{ height: tableHeight }}
|
||||
>
|
||||
<SortableTableHeader headerGroups={headerGroups} flex />
|
||||
<TableBody role="rowgroup">
|
||||
<TableBody
|
||||
role="rowgroup"
|
||||
sx={{
|
||||
'& tr': {
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
'&:hover': {
|
||||
'.show-row-hover': {
|
||||
opacity: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
'& tr td': {
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
flexShrink: 0,
|
||||
'& > *': {
|
||||
flexGrow: 1,
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
{rows.map((row, index) => {
|
||||
const top =
|
||||
index * rowHeight + theme.shape.tableRowHeightCompact;
|
||||
@ -73,10 +92,10 @@ export const VirtualizedTable: VFC<IVirtualizedTableProps> = ({
|
||||
return (
|
||||
<TableRow
|
||||
hover
|
||||
{...row.getRowProps()}
|
||||
{...row.getRowProps({
|
||||
style: { display: 'flex', top },
|
||||
})}
|
||||
key={row.id}
|
||||
className={classes.row}
|
||||
style={{ display: 'flex', top }}
|
||||
>
|
||||
{row.cells.map(cell => (
|
||||
<TableCell
|
||||
@ -87,7 +106,6 @@ export const VirtualizedTable: VFC<IVirtualizedTableProps> = ({
|
||||
: undefined,
|
||||
},
|
||||
})}
|
||||
className={classes.cell}
|
||||
>
|
||||
{cell.render('Cell')}
|
||||
</TableCell>
|
||||
|
@ -1,15 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: theme.spacing(0, 1.5),
|
||||
},
|
||||
divider: {
|
||||
borderColor: theme.palette.dividerAlternative,
|
||||
height: theme.spacing(3),
|
||||
margin: theme.spacing(0, 2),
|
||||
},
|
||||
}));
|
@ -1,24 +1,27 @@
|
||||
import { Box, Divider } from '@mui/material';
|
||||
import { Box, Divider, styled } from '@mui/material';
|
||||
import { FC, VFC } from 'react';
|
||||
import { useStyles } from './ActionCell.styles';
|
||||
|
||||
const ActionCellDivider: VFC = () => {
|
||||
const { classes } = useStyles();
|
||||
return (
|
||||
<Divider
|
||||
className={classes.divider}
|
||||
orientation="vertical"
|
||||
variant="middle"
|
||||
/>
|
||||
);
|
||||
};
|
||||
const StyledContainer = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
padding: theme.spacing(0, 1.5),
|
||||
}));
|
||||
|
||||
const StyledDivider = styled(Divider)(({ theme }) => ({
|
||||
borderColor: theme.palette.dividerAlternative,
|
||||
height: theme.spacing(3),
|
||||
margin: theme.spacing(0, 2),
|
||||
}));
|
||||
|
||||
const ActionCellDivider: VFC = () => (
|
||||
<StyledDivider orientation="vertical" variant="middle" />
|
||||
);
|
||||
|
||||
const ActionCellComponent: FC & {
|
||||
Divider: typeof ActionCellDivider;
|
||||
} = ({ children }) => {
|
||||
const { classes } = useStyles();
|
||||
|
||||
return <Box className={classes.container}>{children}</Box>;
|
||||
return <StyledContainer>{children}</StyledContainer>;
|
||||
};
|
||||
|
||||
ActionCellComponent.Divider = ActionCellDivider;
|
||||
|
@ -1,20 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
padding: theme.spacing(1.5),
|
||||
},
|
||||
box: {
|
||||
width: '38px',
|
||||
height: '38px',
|
||||
background: 'gray',
|
||||
borderRadius: '4px',
|
||||
textAlign: 'center',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontSize: theme.fontSizes.smallerBody,
|
||||
margin: '0 auto',
|
||||
},
|
||||
}));
|
@ -1,8 +1,7 @@
|
||||
import React, { FC, VFC } from 'react';
|
||||
import TimeAgo from 'react-timeago';
|
||||
import { Tooltip, useTheme } from '@mui/material';
|
||||
import { styled, Tooltip, useTheme } from '@mui/material';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useStyles } from './FeatureSeenCell.styles';
|
||||
|
||||
function shortenUnitName(unit?: string): string {
|
||||
switch (unit) {
|
||||
@ -50,6 +49,24 @@ const useFeatureColor = () => {
|
||||
};
|
||||
};
|
||||
|
||||
const StyledContainer = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
padding: theme.spacing(1.5),
|
||||
}));
|
||||
|
||||
const StyledBox = styled('div')(({ theme }) => ({
|
||||
width: '38px',
|
||||
height: '38px',
|
||||
background: theme.palette.background.paper,
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
textAlign: 'center',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontSize: theme.typography.body2.fontSize,
|
||||
margin: '0 auto',
|
||||
}));
|
||||
|
||||
interface IFeatureSeenCellProps {
|
||||
value?: string | Date | null;
|
||||
}
|
||||
@ -59,21 +76,16 @@ const Wrapper: FC<{ unit?: string; tooltip: string }> = ({
|
||||
tooltip,
|
||||
children,
|
||||
}) => {
|
||||
const { classes: styles } = useStyles();
|
||||
const getColor = useFeatureColor();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<StyledContainer>
|
||||
<Tooltip title={tooltip} arrow describeChild>
|
||||
<div
|
||||
className={styles.box}
|
||||
style={{ background: getColor(unit) }}
|
||||
data-loading
|
||||
>
|
||||
<StyledBox style={{ background: getColor(unit) }} data-loading>
|
||||
{children}
|
||||
</div>
|
||||
</StyledBox>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,15 +1,21 @@
|
||||
import { VFC } from 'react';
|
||||
import { Tooltip } from '@mui/material';
|
||||
import { styled, Tooltip } from '@mui/material';
|
||||
import { getFeatureTypeIcons } from 'utils/getFeatureTypeIcons';
|
||||
import useFeatureTypes from 'hooks/api/getters/useFeatureTypes/useFeatureTypes';
|
||||
import { useStyles } from './FeatureTypeCell.styles';
|
||||
|
||||
interface IFeatureTypeProps {
|
||||
value?: string;
|
||||
}
|
||||
|
||||
const StyledContainer = styled('div')(({ theme }) => ({
|
||||
padding: theme.spacing(1.5),
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
color: theme.palette.text.disabled,
|
||||
}));
|
||||
|
||||
export const FeatureTypeCell: VFC<IFeatureTypeProps> = ({ value }) => {
|
||||
const { classes: styles } = useStyles();
|
||||
const { featureTypes } = useFeatureTypes();
|
||||
const IconComponent = getFeatureTypeIcons(value);
|
||||
|
||||
@ -20,10 +26,10 @@ export const FeatureTypeCell: VFC<IFeatureTypeProps> = ({ value }) => {
|
||||
const title = `This is a "${typeName || value}" toggle`;
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<StyledContainer>
|
||||
<Tooltip arrow title={title} describeChild>
|
||||
<IconComponent data-loading className={styles.icon} />
|
||||
<IconComponent data-loading />
|
||||
</Tooltip>
|
||||
</div>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
@ -1,29 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
container: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
wordBreak: 'break-word',
|
||||
padding: theme.spacing(1, 2),
|
||||
},
|
||||
title: {
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
display: '-webkit-box',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
WebkitLineClamp: '1',
|
||||
lineClamp: '1',
|
||||
},
|
||||
subtitle: {
|
||||
color: theme.palette.text.secondary,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
fontSize: 'inherit',
|
||||
WebkitLineClamp: '1',
|
||||
lineClamp: '1',
|
||||
display: '-webkit-box',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
},
|
||||
}));
|
@ -1,8 +1,7 @@
|
||||
import { VFC } from 'react';
|
||||
import { Highlighter } from 'component/common/Highlighter/Highlighter';
|
||||
import { useSearchHighlightContext } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||
import { Box, Typography } from '@mui/material';
|
||||
import { useStyles } from './HighlightCell.styles';
|
||||
import { Box, styled } from '@mui/material';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
|
||||
interface IHighlightCellProps {
|
||||
@ -10,17 +9,43 @@ interface IHighlightCellProps {
|
||||
subtitle?: string;
|
||||
}
|
||||
|
||||
const StyledContainer = styled(Box)(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
wordBreak: 'break-word',
|
||||
padding: theme.spacing(1, 2),
|
||||
}));
|
||||
|
||||
const StyledTitle = styled('span')(({ theme }) => ({
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
display: '-webkit-box',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
WebkitLineClamp: '1',
|
||||
lineClamp: '1',
|
||||
}));
|
||||
|
||||
const StyledSubtitle = styled('span')(({ theme }) => ({
|
||||
color: theme.palette.text.secondary,
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
fontSize: 'inherit',
|
||||
WebkitLineClamp: '1',
|
||||
lineClamp: '1',
|
||||
display: '-webkit-box',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
}));
|
||||
|
||||
export const HighlightCell: VFC<IHighlightCellProps> = ({
|
||||
value,
|
||||
subtitle,
|
||||
}) => {
|
||||
const { searchQuery } = useSearchHighlightContext();
|
||||
const { classes } = useStyles();
|
||||
|
||||
return (
|
||||
<Box className={classes.container}>
|
||||
<span
|
||||
className={classes.title}
|
||||
<StyledContainer>
|
||||
<StyledTitle
|
||||
style={{
|
||||
WebkitLineClamp: Boolean(subtitle) ? 1 : 2,
|
||||
lineClamp: Boolean(subtitle) ? 1 : 2,
|
||||
@ -28,21 +53,17 @@ export const HighlightCell: VFC<IHighlightCellProps> = ({
|
||||
data-loading
|
||||
>
|
||||
<Highlighter search={searchQuery}>{value}</Highlighter>
|
||||
</span>
|
||||
</StyledTitle>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(subtitle)}
|
||||
show={() => (
|
||||
<Typography
|
||||
component="span"
|
||||
className={classes.subtitle}
|
||||
data-loading
|
||||
>
|
||||
<StyledSubtitle data-loading>
|
||||
<Highlighter search={searchQuery}>
|
||||
{subtitle}
|
||||
</Highlighter>
|
||||
</Typography>
|
||||
</StyledSubtitle>
|
||||
)}
|
||||
/>
|
||||
</Box>
|
||||
</StyledContainer>
|
||||
);
|
||||
};
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import { Link, styled, Theme } from '@mui/material';
|
||||
import { ComponentType } from 'react';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
wrapper: {
|
||||
export const wrapperStyles = (theme: Theme) => ({
|
||||
paddingTop: theme.spacing(1.5),
|
||||
paddingBottom: theme.spacing(1.5),
|
||||
paddingLeft: theme.spacing(2),
|
||||
@ -9,28 +9,38 @@ export const useStyles = makeStyles()(theme => ({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
minHeight: '62px',
|
||||
},
|
||||
link: {
|
||||
});
|
||||
|
||||
export const StyledWrapper = styled('div')(({ theme }) => wrapperStyles(theme));
|
||||
|
||||
export const StyledLink = styled(Link)<{
|
||||
component?: ComponentType<any>;
|
||||
to?: string;
|
||||
}>(({ theme }) => ({
|
||||
...wrapperStyles(theme),
|
||||
'&:hover, &:focus': {
|
||||
textDecoration: 'none',
|
||||
'& > div > span:first-of-type': {
|
||||
textDecoration: 'underline',
|
||||
},
|
||||
},
|
||||
},
|
||||
container: {
|
||||
}));
|
||||
|
||||
export const StyledContainer = styled('div')(({ theme }) => ({
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
justifyContent: 'center',
|
||||
wordBreak: 'break-all',
|
||||
},
|
||||
title: {
|
||||
}));
|
||||
|
||||
export const StyledTitle = styled('span')(({ theme }) => ({
|
||||
overflow: 'hidden',
|
||||
textOverflow: 'ellipsis',
|
||||
display: '-webkit-box',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
},
|
||||
description: {
|
||||
}));
|
||||
|
||||
export const StyledDescription = styled('span')(({ theme }) => ({
|
||||
color: theme.palette.text.secondary,
|
||||
textDecoration: 'none',
|
||||
fontSize: 'inherit',
|
||||
@ -40,5 +50,4 @@ export const useStyles = makeStyles()(theme => ({
|
||||
textOverflow: 'ellipsis',
|
||||
display: '-webkit-box',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
},
|
||||
}));
|
||||
|
@ -1,11 +1,16 @@
|
||||
import { FC } from 'react';
|
||||
import { Link, Typography } from '@mui/material';
|
||||
import { ComponentType, FC } from 'react';
|
||||
import { Link, styled, Typography } from '@mui/material';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useStyles } from './LinkCell.styles';
|
||||
import { Highlighter } from 'component/common/Highlighter/Highlighter';
|
||||
import { useSearchHighlightContext } from 'component/common/Table/SearchHighlightContext/SearchHighlightContext';
|
||||
import classnames from 'classnames';
|
||||
import {
|
||||
StyledWrapper,
|
||||
StyledLink,
|
||||
StyledContainer,
|
||||
StyledTitle,
|
||||
StyledDescription,
|
||||
} from './LinkCell.styles';
|
||||
|
||||
interface ILinkCellProps {
|
||||
title?: string;
|
||||
@ -21,14 +26,12 @@ export const LinkCell: FC<ILinkCellProps> = ({
|
||||
subtitle,
|
||||
children,
|
||||
}) => {
|
||||
const { classes: styles } = useStyles();
|
||||
const { searchQuery } = useSearchHighlightContext();
|
||||
|
||||
const content = (
|
||||
<div className={styles.container}>
|
||||
<span
|
||||
<StyledContainer>
|
||||
<StyledTitle
|
||||
data-loading
|
||||
className={styles.title}
|
||||
style={{
|
||||
WebkitLineClamp: Boolean(subtitle) ? 1 : 2,
|
||||
lineClamp: Boolean(subtitle) ? 1 : 2,
|
||||
@ -36,44 +39,31 @@ export const LinkCell: FC<ILinkCellProps> = ({
|
||||
>
|
||||
<Highlighter search={searchQuery}>{title}</Highlighter>
|
||||
{children}
|
||||
</span>
|
||||
</StyledTitle>
|
||||
<ConditionallyRender
|
||||
condition={Boolean(subtitle)}
|
||||
show={
|
||||
<>
|
||||
<Typography
|
||||
className={styles.description}
|
||||
component="span"
|
||||
data-loading
|
||||
>
|
||||
<StyledDescription data-loading>
|
||||
<Highlighter search={searchQuery}>
|
||||
{subtitle}
|
||||
</Highlighter>
|
||||
</Typography>
|
||||
</StyledDescription>
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</StyledContainer>
|
||||
);
|
||||
|
||||
return to ? (
|
||||
<Link
|
||||
component={RouterLink}
|
||||
to={to}
|
||||
underline="hover"
|
||||
className={classnames(styles.wrapper, styles.link)}
|
||||
>
|
||||
<StyledLink component={RouterLink} to={to} underline="hover">
|
||||
{content}
|
||||
</Link>
|
||||
</StyledLink>
|
||||
) : onClick ? (
|
||||
<Link
|
||||
onClick={onClick}
|
||||
underline="hover"
|
||||
className={classnames(styles.wrapper, styles.link)}
|
||||
>
|
||||
<StyledLink onClick={onClick} underline="hover">
|
||||
{content}
|
||||
</Link>
|
||||
</StyledLink>
|
||||
) : (
|
||||
<span className={styles.wrapper}>{content}</span>
|
||||
<StyledWrapper>{content}</StyledWrapper>
|
||||
);
|
||||
};
|
||||
|
@ -1,17 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles<{ lineClamp?: number }>()(
|
||||
(theme, { lineClamp }) => ({
|
||||
wrapper: {
|
||||
padding: theme.spacing(1, 2),
|
||||
display: '-webkit-box',
|
||||
overflow: lineClamp ? 'hidden' : 'auto',
|
||||
WebkitLineClamp: lineClamp ? lineClamp : 'none',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
wordBreak: 'break-all',
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
wordBreak: 'normal',
|
||||
},
|
||||
},
|
||||
})
|
||||
);
|
@ -1,6 +1,5 @@
|
||||
import { FC } from 'react';
|
||||
import { Box, SxProps, Theme } from '@mui/material';
|
||||
import { useStyles } from './TextCell.styles';
|
||||
import { Box, styled, SxProps, Theme } from '@mui/material';
|
||||
|
||||
interface ITextCellProps {
|
||||
value?: string | null;
|
||||
@ -9,20 +8,30 @@ interface ITextCellProps {
|
||||
sx?: SxProps<Theme>;
|
||||
}
|
||||
|
||||
const StyledWrapper = styled(Box, {
|
||||
shouldForwardProp: prop => prop !== 'lineClamp',
|
||||
})<{ lineClamp?: number }>(({ theme, lineClamp }) => ({
|
||||
padding: theme.spacing(1, 2),
|
||||
display: '-webkit-box',
|
||||
overflow: lineClamp ? 'hidden' : 'auto',
|
||||
WebkitLineClamp: lineClamp ? lineClamp : 'none',
|
||||
WebkitBoxOrient: 'vertical',
|
||||
wordBreak: 'break-all',
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
wordBreak: 'normal',
|
||||
},
|
||||
}));
|
||||
|
||||
export const TextCell: FC<ITextCellProps> = ({
|
||||
value,
|
||||
children,
|
||||
lineClamp,
|
||||
sx,
|
||||
'data-testid': testid,
|
||||
}) => {
|
||||
const { classes } = useStyles({ lineClamp });
|
||||
|
||||
return (
|
||||
<Box className={classes.wrapper} sx={sx}>
|
||||
}) => (
|
||||
<StyledWrapper lineClamp={lineClamp} sx={sx}>
|
||||
<span data-loading="true" data-testid={testid}>
|
||||
{children ?? value}
|
||||
</span>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
</StyledWrapper>
|
||||
);
|
||||
|
@ -1,10 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
toastWrapper: {
|
||||
right: 0,
|
||||
left: 0,
|
||||
margin: '0 auto',
|
||||
maxWidth: '450px',
|
||||
},
|
||||
}));
|
@ -1,16 +1,17 @@
|
||||
import { Portal } from '@mui/material';
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { useThemeStyles } from 'themes/themeStyles';
|
||||
import { useContext, useEffect, useMemo } from 'react';
|
||||
import {
|
||||
fadeInBottomEnter,
|
||||
fadeInBottomLeave,
|
||||
fadeInBottomStartWithoutFixed,
|
||||
} from 'themes/themeStyles';
|
||||
import UIContext from 'contexts/UIContext';
|
||||
import { useStyles } from './ToastRenderer.styles';
|
||||
import AnimateOnMount from '../AnimateOnMount/AnimateOnMount';
|
||||
import Toast from './Toast/Toast';
|
||||
import { IToast } from 'interfaces/toast';
|
||||
|
||||
const ToastRenderer = () => {
|
||||
const { toastData, setToast } = useContext(UIContext);
|
||||
const { classes: themeStyles } = useThemeStyles();
|
||||
const { classes: styles } = useStyles();
|
||||
|
||||
const hide = () => {
|
||||
setToast((prev: IToast) => ({ ...prev, show: false }));
|
||||
@ -28,14 +29,28 @@ const ToastRenderer = () => {
|
||||
/* eslint-disable-next-line */
|
||||
}, [toastData?.show]);
|
||||
|
||||
const animations = useMemo(
|
||||
() => ({
|
||||
start: {
|
||||
...fadeInBottomStartWithoutFixed,
|
||||
right: 0,
|
||||
left: 0,
|
||||
margin: '0 auto',
|
||||
maxWidth: '450px',
|
||||
},
|
||||
enter: fadeInBottomEnter,
|
||||
leave: fadeInBottomLeave,
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
return (
|
||||
<Portal>
|
||||
<AnimateOnMount
|
||||
mounted={Boolean(toastData?.show)}
|
||||
start={themeStyles.fadeInBottomStartWithoutFixed}
|
||||
enter={themeStyles.fadeInBottomEnter}
|
||||
leave={themeStyles.fadeInBottomLeave}
|
||||
container={styles.toastWrapper}
|
||||
start={animations.start}
|
||||
enter={animations.enter}
|
||||
leave={animations.leave}
|
||||
>
|
||||
<Toast {...toastData} />
|
||||
</AnimateOnMount>
|
||||
|
@ -1,37 +0,0 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
|
||||
export const useStyles = makeStyles()(theme => ({
|
||||
feedback: {
|
||||
borderRadius: '12.5px',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
zIndex: 9999,
|
||||
boxShadow: '2px 2px 4px 4px rgba(143,143,143, 0.25)',
|
||||
padding: '1.5rem',
|
||||
maxWidth: '400px',
|
||||
},
|
||||
animateContainer: {
|
||||
zIndex: 9999,
|
||||
},
|
||||
container: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
position: 'relative',
|
||||
},
|
||||
close: {
|
||||
position: 'absolute',
|
||||
right: '-38px',
|
||||
top: '-47px',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
boxShadow: '2px 2px 4px 4px rgba(143,143,143, 0.25)',
|
||||
['&:hover']: {
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
},
|
||||
logo: {
|
||||
width: '25px',
|
||||
height: '25px',
|
||||
},
|
||||
cancel: {
|
||||
marginLeft: '1rem',
|
||||
},
|
||||
}));
|
@ -1,12 +1,15 @@
|
||||
import { useContext, useState } from 'react';
|
||||
import { Button, IconButton, Tooltip } from '@mui/material';
|
||||
import classnames from 'classnames';
|
||||
import { useContext, useMemo, useState } from 'react';
|
||||
import { Box, Button, IconButton, Tooltip, useTheme } from '@mui/material';
|
||||
import CloseIcon from '@mui/icons-material/Close';
|
||||
import { ReactComponent as Logo } from 'assets/icons/logoPlain.svg';
|
||||
import { useStyles } from 'component/feedback/FeedbackNPS/FeedbackNPS.styles';
|
||||
import AnimateOnMount from 'component/common/AnimateOnMount/AnimateOnMount';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
import { useThemeStyles } from 'themes/themeStyles';
|
||||
import {
|
||||
contentSpacingY,
|
||||
fadeInTopEnter,
|
||||
fadeInTopLeave,
|
||||
fadeInTopStart,
|
||||
} from 'themes/themeStyles';
|
||||
import UIContext from 'contexts/UIContext';
|
||||
import {
|
||||
PNPS_FEEDBACK_ID,
|
||||
@ -24,10 +27,18 @@ export const FeedbackNPS = ({ openUrl }: IFeedbackNPSProps) => {
|
||||
const { createFeedback, updateFeedback } = useAuthFeedbackApi();
|
||||
const { feedback } = useAuthFeedback();
|
||||
const [answeredNotNow, setAnsweredNotNow] = useState(false);
|
||||
const { classes: styles } = useStyles();
|
||||
const { classes: themeStyles } = useThemeStyles();
|
||||
const theme = useTheme();
|
||||
const feedbackId = PNPS_FEEDBACK_ID;
|
||||
|
||||
const animations = useMemo(
|
||||
() => ({
|
||||
start: { ...fadeInTopStart(theme), zIndex: theme.zIndex.tooltip },
|
||||
enter: fadeInTopEnter,
|
||||
leave: fadeInTopLeave,
|
||||
}),
|
||||
[theme]
|
||||
);
|
||||
|
||||
const onConfirm = async () => {
|
||||
try {
|
||||
await createFeedback({ feedbackId });
|
||||
@ -61,28 +72,53 @@ export const FeedbackNPS = ({ openUrl }: IFeedbackNPSProps) => {
|
||||
return (
|
||||
<AnimateOnMount
|
||||
mounted={showFeedback}
|
||||
start={themeStyles.fadeInTopStart}
|
||||
enter={themeStyles.fadeInTopEnter}
|
||||
leave={themeStyles.fadeInTopLeave}
|
||||
container={styles.animateContainer}
|
||||
start={animations.start}
|
||||
enter={animations.enter}
|
||||
leave={animations.leave}
|
||||
>
|
||||
<div className={styles.feedback}>
|
||||
<div
|
||||
className={classnames(
|
||||
styles.container,
|
||||
themeStyles.contentSpacingY
|
||||
)}
|
||||
<Box
|
||||
sx={{
|
||||
borderRadius: '12.5px',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
zIndex: 9999,
|
||||
boxShadow: '2px 2px 4px 4px rgba(143,143,143, 0.25)',
|
||||
padding: theme.spacing(3),
|
||||
maxWidth: '400px',
|
||||
}}
|
||||
>
|
||||
<Box
|
||||
sx={{
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
position: 'relative',
|
||||
...contentSpacingY(theme),
|
||||
}}
|
||||
>
|
||||
<Tooltip title="Close" arrow>
|
||||
<IconButton
|
||||
className={styles.close}
|
||||
sx={{
|
||||
position: 'absolute',
|
||||
right: '-38px',
|
||||
top: '-47px',
|
||||
backgroundColor: theme.palette.background.paper,
|
||||
boxShadow:
|
||||
'2px 2px 4px 4px rgba(143,143,143, 0.25)',
|
||||
'&:hover': {
|
||||
backgroundColor: '#fff',
|
||||
},
|
||||
}}
|
||||
onClick={() => setShowFeedback(false)}
|
||||
size="large"
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Logo className={styles.logo} />
|
||||
<Logo
|
||||
style={{
|
||||
width: '25px',
|
||||
height: '25px',
|
||||
}}
|
||||
/>
|
||||
<ConditionallyRender
|
||||
condition={answeredNotNow}
|
||||
show={
|
||||
@ -99,7 +135,7 @@ export const FeedbackNPS = ({ openUrl }: IFeedbackNPSProps) => {
|
||||
}
|
||||
/>
|
||||
|
||||
<div>
|
||||
<Box>
|
||||
<ConditionallyRender
|
||||
condition={answeredNotNow}
|
||||
show={
|
||||
@ -120,7 +156,10 @@ export const FeedbackNPS = ({ openUrl }: IFeedbackNPSProps) => {
|
||||
Yes, no problem
|
||||
</Button>
|
||||
<Button
|
||||
className={styles.cancel}
|
||||
sx={{
|
||||
marginLeft: theme =>
|
||||
theme.spacing(2),
|
||||
}}
|
||||
onClick={() => setAnsweredNotNow(true)}
|
||||
>
|
||||
Not now
|
||||
@ -128,9 +167,9 @@ export const FeedbackNPS = ({ openUrl }: IFeedbackNPSProps) => {
|
||||
</>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
</AnimateOnMount>
|
||||
);
|
||||
};
|
||||
|
@ -6,8 +6,8 @@ import Proclamation from 'component/common/Proclamation/Proclamation';
|
||||
import BreadcrumbNav from 'component/common/BreadcrumbNav/BreadcrumbNav';
|
||||
import textureImage from 'assets/img/texture.png';
|
||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||
import { SkipNavLink } from 'component/common/SkipNav/SkipNavLink';
|
||||
import { SkipNavTarget } from 'component/common/SkipNav/SkipNavTarget';
|
||||
import { SkipNavLink } from 'component/common/SkipNavLink/SkipNavLink';
|
||||
import { SkipNavTarget } from 'component/common/SkipNavLink/SkipNavTarget';
|
||||
import { formatAssetPath } from 'utils/formatPath';
|
||||
import { useOptionalPathParam } from 'hooks/useOptionalPathParam';
|
||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||
|
@ -32,14 +32,14 @@ exports[`renders an empty list correctly 1`] = `
|
||||
className="css-j2179i"
|
||||
>
|
||||
<div
|
||||
className="css-1oozr04-container"
|
||||
className="css-uds21r"
|
||||
>
|
||||
<div
|
||||
className="css-1xjrf9m-search search-container"
|
||||
className="css-19ebc6o"
|
||||
>
|
||||
<svg
|
||||
aria-hidden={true}
|
||||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium search-icon css-1kyy7n4-MuiSvgIcon-root-searchIcon"
|
||||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeMedium css-1dfm5ba-MuiSvgIcon-root"
|
||||
data-testid="SearchIcon"
|
||||
focusable="false"
|
||||
viewBox="0 0 24 24"
|
||||
@ -49,7 +49,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
/>
|
||||
</svg>
|
||||
<div
|
||||
className="MuiInputBase-root input-container MuiInputBase-colorPrimary css-tubodl-MuiInputBase-root-inputRoot"
|
||||
className="MuiInputBase-root MuiInputBase-colorPrimary css-1vp7ju7-MuiInputBase-root"
|
||||
onClick={[Function]}
|
||||
>
|
||||
<input
|
||||
@ -65,7 +65,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
className="css-llttyo-clearContainer clear-container"
|
||||
className="MuiBox-root css-1ty7gog"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -112,7 +112,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
className="body css-ccg7sp-bodyContainer"
|
||||
>
|
||||
<table
|
||||
className="MuiTable-root css-1h6dscb-MuiTable-root-table"
|
||||
className="MuiTable-root css-1repbac-MuiTable-root"
|
||||
role="table"
|
||||
>
|
||||
<thead
|
||||
@ -120,11 +120,11 @@ exports[`renders an empty list correctly 1`] = `
|
||||
role={null}
|
||||
>
|
||||
<tr
|
||||
className="MuiTableRow-root MuiTableRow-head css-1gnoged-MuiTableRow-root-tableHeader"
|
||||
className="MuiTableRow-root MuiTableRow-head css-1b9hsk7-MuiTableRow-root"
|
||||
role="row"
|
||||
>
|
||||
<th
|
||||
className="MuiTableCell-root MuiTableCell-head MuiTableCell-sizeMedium css-b9leyc-MuiTableCell-root-header"
|
||||
className="MuiTableCell-root MuiTableCell-head MuiTableCell-sizeMedium css-uzyimr-MuiTableCell-root"
|
||||
scope="col"
|
||||
style={
|
||||
{
|
||||
@ -140,7 +140,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
</th>
|
||||
<th
|
||||
aria-sort="ascending"
|
||||
className="MuiTableCell-root MuiTableCell-head MuiTableCell-sizeMedium css-masipn-MuiTableCell-root-header-sortable"
|
||||
className="MuiTableCell-root MuiTableCell-head MuiTableCell-sizeMedium css-1ts7or6-MuiTableCell-root"
|
||||
scope="col"
|
||||
style={
|
||||
{
|
||||
@ -153,7 +153,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
<button
|
||||
aria-label=""
|
||||
aria-labelledby={null}
|
||||
className="css-14l86a5-sortedButton css-1inbba3-sortButton"
|
||||
className=" css-1xwc11x"
|
||||
data-mui-internal-clone-element={true}
|
||||
onBlur={[Function]}
|
||||
onClick={[Function]}
|
||||
@ -166,10 +166,10 @@ exports[`renders an empty list correctly 1`] = `
|
||||
>
|
||||
<span
|
||||
aria-hidden={true}
|
||||
className="css-r8z9jm-hiddenMeasurementLayer"
|
||||
className="css-15yxmxx"
|
||||
>
|
||||
<span
|
||||
className="css-1j5tskk-label"
|
||||
className="css-1w3kvnb"
|
||||
data-text="Name"
|
||||
tabIndex={-1}
|
||||
>
|
||||
@ -177,7 +177,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
</span>
|
||||
<svg
|
||||
aria-hidden={true}
|
||||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-1ekkz6x-MuiSvgIcon-root-icon-sorted"
|
||||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit css-57xzpo-MuiSvgIcon-root"
|
||||
data-testid="KeyboardArrowUpIcon"
|
||||
focusable="false"
|
||||
viewBox="0 0 24 24"
|
||||
@ -188,7 +188,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
</svg>
|
||||
</span>
|
||||
<span
|
||||
className="css-bqel7i-visibleAbsoluteLayer"
|
||||
className="css-y8b3t8"
|
||||
>
|
||||
<span
|
||||
tabIndex={-1}
|
||||
@ -199,7 +199,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
</span>
|
||||
<svg
|
||||
aria-hidden={true}
|
||||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit sort-arrow css-1ekkz6x-MuiSvgIcon-root-icon-sorted"
|
||||
className="MuiSvgIcon-root MuiSvgIcon-fontSizeInherit sort-arrow css-57xzpo-MuiSvgIcon-root"
|
||||
data-testid="KeyboardArrowUpIcon"
|
||||
focusable="false"
|
||||
viewBox="0 0 24 24"
|
||||
@ -212,7 +212,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
</button>
|
||||
</th>
|
||||
<th
|
||||
className="MuiTableCell-root MuiTableCell-head MuiTableCell-sizeMedium css-b9leyc-MuiTableCell-root-header"
|
||||
className="MuiTableCell-root MuiTableCell-head MuiTableCell-sizeMedium css-uzyimr-MuiTableCell-root"
|
||||
scope="col"
|
||||
style={
|
||||
{
|
||||
@ -223,7 +223,12 @@ exports[`renders an empty list correctly 1`] = `
|
||||
}
|
||||
>
|
||||
<div
|
||||
className="css-1x6va6g-alignCenter"
|
||||
style={
|
||||
{
|
||||
"justifyContent": "center",
|
||||
"textAlign": "center",
|
||||
}
|
||||
}
|
||||
>
|
||||
Actions
|
||||
</div>
|
||||
@ -240,7 +245,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<div
|
||||
@ -262,17 +267,17 @@ exports[`renders an empty list correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<span
|
||||
className="css-g3rrgy-wrapper"
|
||||
<div
|
||||
className="css-1prhjm6"
|
||||
>
|
||||
<div
|
||||
className="css-1sfnvgj-container"
|
||||
className="css-u8cmsa"
|
||||
>
|
||||
<span
|
||||
className="css-lcjmxf-title"
|
||||
className="css-697v50"
|
||||
data-loading={true}
|
||||
style={
|
||||
{
|
||||
@ -284,17 +289,17 @@ exports[`renders an empty list correctly 1`] = `
|
||||
Tag type name
|
||||
</span>
|
||||
<span
|
||||
className="MuiTypography-root MuiTypography-body1 css-kyf98y-MuiTypography-root-description"
|
||||
className="css-1121jr7"
|
||||
data-loading={true}
|
||||
>
|
||||
Tag type description when loading
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<div
|
||||
@ -410,7 +415,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<div
|
||||
@ -432,17 +437,17 @@ exports[`renders an empty list correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<span
|
||||
className="css-g3rrgy-wrapper"
|
||||
<div
|
||||
className="css-1prhjm6"
|
||||
>
|
||||
<div
|
||||
className="css-1sfnvgj-container"
|
||||
className="css-u8cmsa"
|
||||
>
|
||||
<span
|
||||
className="css-lcjmxf-title"
|
||||
className="css-697v50"
|
||||
data-loading={true}
|
||||
style={
|
||||
{
|
||||
@ -454,17 +459,17 @@ exports[`renders an empty list correctly 1`] = `
|
||||
Tag type name
|
||||
</span>
|
||||
<span
|
||||
className="MuiTypography-root MuiTypography-body1 css-kyf98y-MuiTypography-root-description"
|
||||
className="css-1121jr7"
|
||||
data-loading={true}
|
||||
>
|
||||
Tag type description when loading
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<div
|
||||
@ -580,7 +585,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<div
|
||||
@ -602,17 +607,17 @@ exports[`renders an empty list correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<span
|
||||
className="css-g3rrgy-wrapper"
|
||||
<div
|
||||
className="css-1prhjm6"
|
||||
>
|
||||
<div
|
||||
className="css-1sfnvgj-container"
|
||||
className="css-u8cmsa"
|
||||
>
|
||||
<span
|
||||
className="css-lcjmxf-title"
|
||||
className="css-697v50"
|
||||
data-loading={true}
|
||||
style={
|
||||
{
|
||||
@ -624,17 +629,17 @@ exports[`renders an empty list correctly 1`] = `
|
||||
Tag type name
|
||||
</span>
|
||||
<span
|
||||
className="MuiTypography-root MuiTypography-body1 css-kyf98y-MuiTypography-root-description"
|
||||
className="css-1121jr7"
|
||||
data-loading={true}
|
||||
>
|
||||
Tag type description when loading
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<div
|
||||
@ -750,7 +755,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<div
|
||||
@ -772,17 +777,17 @@ exports[`renders an empty list correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<span
|
||||
className="css-g3rrgy-wrapper"
|
||||
<div
|
||||
className="css-1prhjm6"
|
||||
>
|
||||
<div
|
||||
className="css-1sfnvgj-container"
|
||||
className="css-u8cmsa"
|
||||
>
|
||||
<span
|
||||
className="css-lcjmxf-title"
|
||||
className="css-697v50"
|
||||
data-loading={true}
|
||||
style={
|
||||
{
|
||||
@ -794,17 +799,17 @@ exports[`renders an empty list correctly 1`] = `
|
||||
Tag type name
|
||||
</span>
|
||||
<span
|
||||
className="MuiTypography-root MuiTypography-body1 css-kyf98y-MuiTypography-root-description"
|
||||
className="css-1121jr7"
|
||||
data-loading={true}
|
||||
>
|
||||
Tag type description when loading
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<div
|
||||
@ -920,7 +925,7 @@ exports[`renders an empty list correctly 1`] = `
|
||||
>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<div
|
||||
@ -942,17 +947,17 @@ exports[`renders an empty list correctly 1`] = `
|
||||
</td>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<span
|
||||
className="css-g3rrgy-wrapper"
|
||||
<div
|
||||
className="css-1prhjm6"
|
||||
>
|
||||
<div
|
||||
className="css-1sfnvgj-container"
|
||||
className="css-u8cmsa"
|
||||
>
|
||||
<span
|
||||
className="css-lcjmxf-title"
|
||||
className="css-697v50"
|
||||
data-loading={true}
|
||||
style={
|
||||
{
|
||||
@ -964,17 +969,17 @@ exports[`renders an empty list correctly 1`] = `
|
||||
Tag type name
|
||||
</span>
|
||||
<span
|
||||
className="MuiTypography-root MuiTypography-body1 css-kyf98y-MuiTypography-root-description"
|
||||
className="css-1121jr7"
|
||||
data-loading={true}
|
||||
>
|
||||
Tag type description when loading
|
||||
</span>
|
||||
</div>
|
||||
</span>
|
||||
</div>
|
||||
</td>
|
||||
<td
|
||||
aria-sort={null}
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-fv4mw1-MuiTableCell-root-tableCell"
|
||||
className="MuiTableCell-root MuiTableCell-body MuiTableCell-sizeMedium css-iiibbc-MuiTableCell-root"
|
||||
role="cell"
|
||||
>
|
||||
<div
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { makeStyles } from 'tss-react/mui';
|
||||
import { Theme } from '@mui/material';
|
||||
import { CSSProperties } from 'react';
|
||||
|
||||
export const focusable = (theme: Theme) => ({
|
||||
'&:focus-visible': {
|
||||
@ -51,6 +52,54 @@ export const defaultBorderRadius = (theme: Theme) => ({
|
||||
borderRadius: `${theme.shape.borderRadius}px`,
|
||||
});
|
||||
|
||||
export const fadeInBottomStart = () => ({
|
||||
opacity: '0',
|
||||
position: 'fixed',
|
||||
right: '40px',
|
||||
bottom: '40px',
|
||||
transform: 'translateY(400px)',
|
||||
});
|
||||
export const fadeInBottomStartWithoutFixed: CSSProperties = {
|
||||
opacity: '0',
|
||||
right: '40px',
|
||||
bottom: '40px',
|
||||
transform: 'translateY(400px)',
|
||||
zIndex: 1400,
|
||||
position: 'fixed',
|
||||
};
|
||||
export const fadeInBottomEnter: CSSProperties = {
|
||||
transform: 'translateY(0)',
|
||||
opacity: '1',
|
||||
transition: 'transform 0.6s ease, opacity 1s ease',
|
||||
};
|
||||
export const fadeInBottomLeave: CSSProperties = {
|
||||
transform: 'translateY(400px)',
|
||||
opacity: '0',
|
||||
transition: 'transform 1.25s ease, opacity 1s ease',
|
||||
};
|
||||
export const fadeInTopStart = (theme: Theme): CSSProperties => ({
|
||||
opacity: '0',
|
||||
position: 'fixed',
|
||||
right: '40px',
|
||||
top: '40px',
|
||||
transform: 'translateY(-400px)',
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
right: 20,
|
||||
left: 10,
|
||||
top: 40,
|
||||
},
|
||||
});
|
||||
export const fadeInTopEnter: CSSProperties = {
|
||||
transform: 'translateY(100px)',
|
||||
opacity: '1',
|
||||
transition: 'transform 0.6s ease, opacity 1s ease',
|
||||
};
|
||||
export const fadeInTopLeave: CSSProperties = {
|
||||
transform: 'translateY(-400px)',
|
||||
opacity: '0',
|
||||
transition: 'transform 1.25s ease, opacity 1s ease',
|
||||
};
|
||||
|
||||
/**
|
||||
* Please extract styles below into MUI fragments as shown above
|
||||
* @deprecated
|
||||
@ -117,53 +166,6 @@ export const useThemeStyles = makeStyles()(theme => ({
|
||||
fontWeight: 'bold',
|
||||
marginBottom: '0.5rem',
|
||||
},
|
||||
fadeInBottomStart: {
|
||||
opacity: '0',
|
||||
position: 'fixed',
|
||||
right: '40px',
|
||||
bottom: '40px',
|
||||
transform: 'translateY(400px)',
|
||||
},
|
||||
fadeInBottomStartWithoutFixed: {
|
||||
opacity: '0',
|
||||
right: '40px',
|
||||
bottom: '40px',
|
||||
transform: 'translateY(400px)',
|
||||
zIndex: 1400,
|
||||
position: 'fixed',
|
||||
},
|
||||
fadeInBottomEnter: {
|
||||
transform: 'translateY(0)',
|
||||
opacity: '1',
|
||||
transition: 'transform 0.6s ease, opacity 1s ease',
|
||||
},
|
||||
fadeInBottomLeave: {
|
||||
transform: 'translateY(400px)',
|
||||
opacity: '0',
|
||||
transition: 'transform 1.25s ease, opacity 1s ease',
|
||||
},
|
||||
fadeInTopStart: {
|
||||
opacity: '0',
|
||||
position: 'fixed',
|
||||
right: '40px',
|
||||
top: '40px',
|
||||
transform: 'translateY(-400px)',
|
||||
[theme.breakpoints.down('sm')]: {
|
||||
right: 20,
|
||||
left: 10,
|
||||
top: 40,
|
||||
},
|
||||
},
|
||||
fadeInTopEnter: {
|
||||
transform: 'translateY(100px)',
|
||||
opacity: '1',
|
||||
transition: 'transform 0.6s ease, opacity 1s ease',
|
||||
},
|
||||
fadeInTopLeave: {
|
||||
transform: 'translateY(-400px)',
|
||||
opacity: '0',
|
||||
transition: 'transform 1.25s ease, opacity 1s ease',
|
||||
},
|
||||
error: {
|
||||
fontSize: theme.fontSizes.smallBody,
|
||||
color: theme.palette.error.main,
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { FC, ElementType } from 'react';
|
||||
import { FC } from 'react';
|
||||
import { SvgIcon, useTheme } from '@mui/material';
|
||||
import LocationOnIcon from '@mui/icons-material/LocationOn';
|
||||
import PeopleIcon from '@mui/icons-material/People';
|
||||
@ -19,7 +19,7 @@ const RolloutSvgIcon: FC = props => (
|
||||
/>
|
||||
);
|
||||
|
||||
export const getFeatureStrategyIcon = (strategyName: string): ElementType => {
|
||||
export const getFeatureStrategyIcon = (strategyName: string) => {
|
||||
switch (strategyName) {
|
||||
case 'default':
|
||||
return PowerSettingsNewIcon;
|
||||
|
Loading…
Reference in New Issue
Block a user