diff --git a/striker-ui/components/Bars/AllocationBar.tsx b/striker-ui/components/Bars/AllocationBar.tsx index 90b3df0f..ebbe6292 100644 --- a/striker-ui/components/Bars/AllocationBar.tsx +++ b/striker-ui/components/Bars/AllocationBar.tsx @@ -1,13 +1,9 @@ -import { LinearProgress } from '@mui/material'; -import { styled } from '@mui/material/styles'; +import { styled } from '@mui/material'; + +import { PURPLE, RED, BLUE } from '../../lib/consts/DEFAULT_THEME'; -import { - PURPLE, - RED, - BLUE, - BORDER_RADIUS, -} from '../../lib/consts/DEFAULT_THEME'; import BorderLinearProgress from './BorderLinearProgress'; +import Underline from './Underline'; const PREFIX = 'AllocationBar'; @@ -15,7 +11,6 @@ const classes = { barOk: `${PREFIX}-barOk`, barWarning: `${PREFIX}-barWarning`, barAlert: `${PREFIX}-barAlert`, - underline: `${PREFIX}-underline`, }; const StyledDiv = styled('div')(() => ({ @@ -30,10 +25,6 @@ const StyledDiv = styled('div')(() => ({ [`& .${classes.barAlert}`]: { backgroundColor: RED, }, - - [`& .${classes.underline}`]: { - borderRadius: BORDER_RADIUS, - }, })); const breakpointWarning = 70; @@ -54,11 +45,7 @@ const AllocationBar = ({ allocated }: { allocated: number }): JSX.Element => ( variant="determinate" value={allocated} /> - + ); diff --git a/striker-ui/components/Bars/BorderLinearProgress.tsx b/striker-ui/components/Bars/BorderLinearProgress.tsx index 50c1de44..57509a31 100644 --- a/striker-ui/components/Bars/BorderLinearProgress.tsx +++ b/striker-ui/components/Bars/BorderLinearProgress.tsx @@ -1,14 +1,15 @@ -import { LinearProgress } from '@mui/material'; -import { styled } from '@mui/material/styles'; -import { - PANEL_BACKGROUND, - BORDER_RADIUS, -} from '../../lib/consts/DEFAULT_THEME'; +import { LinearProgress, linearProgressClasses, styled } from '@mui/material'; + +import { BORDER_RADIUS } from '../../lib/consts/DEFAULT_THEME'; const BorderLinearProgress = styled(LinearProgress)({ - height: '1em', + backgroundColor: 'transparent', borderRadius: BORDER_RADIUS, - backgroundColor: PANEL_BACKGROUND, + height: '1em', + + [`& .${linearProgressClasses.bar}`]: { + borderRadius: BORDER_RADIUS, + }, }); export default BorderLinearProgress; diff --git a/striker-ui/components/Bars/ProgressBar.tsx b/striker-ui/components/Bars/ProgressBar.tsx index 9f0280ad..d122acf2 100644 --- a/striker-ui/components/Bars/ProgressBar.tsx +++ b/striker-ui/components/Bars/ProgressBar.tsx @@ -1,15 +1,15 @@ -import { LinearProgress } from '@mui/material'; -import { styled } from '@mui/material/styles'; +import { styled } from '@mui/material'; + +import { PURPLE, BLUE } from '../../lib/consts/DEFAULT_THEME'; -import { PURPLE, BLUE, BORDER_RADIUS } from '../../lib/consts/DEFAULT_THEME'; import BorderLinearProgress from './BorderLinearProgress'; +import Underline from './Underline'; const PREFIX = 'ProgressBar'; const classes = { barOk: `${PREFIX}-barOk`, barInProgress: `${PREFIX}-barInProgress`, - underline: `${PREFIX}-underline`, }; const StyledDiv = styled('div')(() => ({ @@ -20,10 +20,6 @@ const StyledDiv = styled('div')(() => ({ [`& .${classes.barInProgress}`]: { backgroundColor: PURPLE, }, - - [`& .${classes.underline}`]: { - borderRadius: BORDER_RADIUS, - }, })); const completed = 100; @@ -44,11 +40,7 @@ const ProgressBar = ({ variant="determinate" value={progressPercentage} /> - + ); diff --git a/striker-ui/components/Bars/StackBar.tsx b/striker-ui/components/Bars/StackBar.tsx new file mode 100644 index 00000000..d0676490 --- /dev/null +++ b/striker-ui/components/Bars/StackBar.tsx @@ -0,0 +1,72 @@ +import { Box, linearProgressClasses } from '@mui/material'; +import { FC, ReactElement, useMemo } from 'react'; + +import { GREY } from '../../lib/consts/DEFAULT_THEME'; + +import BorderLinearProgress from './BorderLinearProgress'; +import Underline from './Underline'; + +const StackBar: FC = (props) => { + const { value } = props; + + const values = useMemo>( + () => ('value' in value ? { default: value as StackBarValue } : value), + [value], + ); + + const entries = useMemo<[string, StackBarValue][]>( + () => Object.entries(values).reverse(), + [values], + ); + + const bars = useMemo( + () => + entries.map( + ([id, { colour = GREY, value: val }], index) => { + const backgroundColor = + typeof colour === 'string' + ? colour + : Object.entries(colour).findLast( + ([mark]) => val >= Number(mark), + )?.[1] ?? GREY; + + let position: 'absolute' | 'relative' = 'relative'; + let top: 0 | undefined; + let width: string | undefined; + + if (index) { + position = 'absolute'; + top = 0; + width = '100%'; + } + + return ( + + ); + }, + ), + [entries], + ); + + return ( + + {bars} + + + ); +}; + +export default StackBar; diff --git a/striker-ui/components/Bars/Underline.tsx b/striker-ui/components/Bars/Underline.tsx new file mode 100644 index 00000000..b2553a2a --- /dev/null +++ b/striker-ui/components/Bars/Underline.tsx @@ -0,0 +1,13 @@ +import { Box, styled } from '@mui/material'; + +import { BORDER_RADIUS, DISABLED } from '../../lib/consts/DEFAULT_THEME'; + +const Underline = styled(Box)({ + backgroundColor: DISABLED, + borderRadius: BORDER_RADIUS, + display: 'block', + height: '4px', + position: 'relative', +}); + +export default Underline; diff --git a/striker-ui/components/Bars/index.tsx b/striker-ui/components/Bars/index.tsx index 0863c898..d321b41e 100644 --- a/striker-ui/components/Bars/index.tsx +++ b/striker-ui/components/Bars/index.tsx @@ -1,4 +1,5 @@ import AllocationBar from './AllocationBar'; import ProgressBar from './ProgressBar'; +import StackBar from './StackBar'; -export { AllocationBar, ProgressBar }; +export { AllocationBar, ProgressBar, StackBar }; diff --git a/striker-ui/types/StackBar.d.ts b/striker-ui/types/StackBar.d.ts new file mode 100644 index 00000000..b0af9b11 --- /dev/null +++ b/striker-ui/types/StackBar.d.ts @@ -0,0 +1,8 @@ +type StackBarValue = { + colour?: string | Record; + value: number; +}; + +type StackBarProps = { + value: StackBarValue | Record; +};