1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-05-08 01:15:49 +02:00

fix: dark theme UI fixes (#3423)

https://linear.app/unleash/issue/2-849/dark-mode-ui-fixes


![image](https://user-images.githubusercontent.com/14320932/228607663-fd474e42-b23d-4fc2-a083-d42b87332399.png)


![image](https://user-images.githubusercontent.com/14320932/228607757-bf53d67b-8ef1-4aba-bcc1-f2c6b9cc56a2.png)


![image](https://user-images.githubusercontent.com/14320932/228607875-5bfaeb46-e37c-41d3-941f-bc89e10ad43f.png)

Also includes misc UI fixes and improvements we identified along the
way.

Co-authored by @NicolaeUnleash

---------

Co-authored-by: NicolaeUnleash <103567375+NicolaeUnleash@users.noreply.github.com>
This commit is contained in:
Nuno Góis 2023-03-30 16:57:35 +01:00 committed by GitHub
parent 9db40f50cf
commit 2e6b6cd354
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 201 additions and 116 deletions

View File

@ -1 +1 @@
<svg id="bg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 251.43 251.03"><defs><style>.cls-1{fill:#1a4049;}.cls-2{fill:#fff;}.cls-3{fill:#817afe;}</style></defs><circle class="cls-1" cx="125.71" cy="125.31" r="80"/><polygon class="cls-2" points="137.14 91.03 137.14 113.88 137.14 136.74 160 136.74 160 113.88 160 91.03 137.14 91.03"/><polygon class="cls-2" points="114.29 113.88 114.29 91.03 91.43 91.03 91.43 113.88 91.43 136.74 91.43 159.6 114.29 159.6 137.14 159.6 137.14 136.74 114.29 136.74 114.29 113.88"/><rect class="cls-3" x="137.14" y="136.74" width="22.86" height="22.86"/></svg> <svg width="35" height="35" viewBox="0 0 35 35" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M17.5 35C27.165 35 35 27.165 35 17.5S27.165 0 17.5 0 0 7.835 0 17.5 7.835 35 17.5 35Z" fill="#1A4049"/><path d="M15 10h-5v15h15V10h-5v10h-5V10Z" fill="#fff"/><path d="M20 20h5v5h-5v-5Z" fill="#817AFE"/></svg>

Before

Width:  |  Height:  |  Size: 593 B

After

Width:  |  Height:  |  Size: 312 B

View File

@ -1,7 +1 @@
<svg width="334" height="334" viewBox="0 0 334 334" fill="none" xmlns="http://www.w3.org/2000/svg"> <svg width="35" height="35" viewBox="0 0 35 35" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M17.5 35C27.165 35 35 27.165 35 17.5S27.165 0 17.5 0 0 7.835 0 17.5 7.835 35 17.5 35Z" fill="#fff"/><path d="M15 10h-5v15h15V10h-5v10h-5V10Z" fill="#1A4049"/><path d="M20 20h5v5h-5v-5Z" fill="#817AFE"/></svg>
<circle cx="167" cy="167" r="167" fill="white"/>
<rect x="96.3462" y="96.3457" width="44.9615" height="141.308" fill="#1A4049"/>
<rect x="192.692" y="96.3457" width="44.9615" height="141.308" fill="#1A4049"/>
<path d="M237.654 192.693L237.654 237.655L96.3461 237.655L96.3461 192.693L237.654 192.693Z" fill="#1A4049"/>
<rect x="192.692" y="192.693" width="44.9615" height="44.9615" fill="#817AFE"/>
</svg>

Before

Width:  |  Height:  |  Size: 505 B

After

Width:  |  Height:  |  Size: 312 B

View File

@ -10,13 +10,18 @@ import {
RequestsPerSecondSchemaDataResultItem, RequestsPerSecondSchemaDataResultItem,
} from 'openapi'; } from 'openapi';
import logoIcon from 'assets/icons/logoBg.svg'; import logoIcon from 'assets/icons/logoBg.svg';
import logoWhiteIcon from 'assets/icons/logoWhiteBg.svg';
import { formatAssetPath } from 'utils/formatPath'; import { formatAssetPath } from 'utils/formatPath';
import { useThemeMode } from 'hooks/useThemeMode';
const StyledMermaid = styled(Mermaid)(({ theme }) => ({ const StyledMermaid = styled(Mermaid)(({ theme }) => ({
'#mermaid .node rect': { '#mermaid .node rect': {
fill: theme.palette.secondary.light, fill: theme.palette.secondary.light,
stroke: theme.palette.secondary.border, stroke: theme.palette.secondary.border,
}, },
'#mermaid .unleash-logo': {
padding: theme.spacing(1),
},
})); }));
const isRecent = (value: ResultValue) => { const isRecent = (value: ResultValue) => {
@ -79,6 +84,7 @@ const toGraphData = (metrics?: RequestsPerSecondSchema) => {
export const NetworkOverview = () => { export const NetworkOverview = () => {
usePageTitle('Network - Overview'); usePageTitle('Network - Overview');
const { themeMode } = useThemeMode();
const { metrics } = useInstanceMetrics(); const { metrics } = useInstanceMetrics();
const apps = useMemo(() => { const apps = useMemo(() => {
return toGraphData(metrics); return toGraphData(metrics);
@ -89,8 +95,8 @@ export const NetworkOverview = () => {
subgraph _[ ] subgraph _[ ]
direction BT direction BT
Unleash(<img src='${formatAssetPath( Unleash(<img src='${formatAssetPath(
logoIcon themeMode === 'dark' ? logoWhiteIcon : logoIcon
)}' width='60' height='60' /><br/>Unleash) )}' width='72' height='72' class='unleash-logo'/><br/>Unleash)
${apps ${apps
.map( .map(
({ label, reqs, type }, i) => ({ label, reqs, type }, i) =>

View File

@ -18,16 +18,18 @@ import {
ILocationSettings, ILocationSettings,
useLocationSettings, useLocationSettings,
} from 'hooks/useLocationSettings'; } from 'hooks/useLocationSettings';
import theme from 'themes/theme';
import { formatDateHM } from 'utils/formatDate'; import { formatDateHM } from 'utils/formatDate';
import { RequestsPerSecondSchema } from 'openapi'; import { RequestsPerSecondSchema } from 'openapi';
import 'chartjs-adapter-date-fns'; import 'chartjs-adapter-date-fns';
import { Alert } from '@mui/material'; import { Alert, useTheme } from '@mui/material';
import { Box } from '@mui/system'; import { Box } from '@mui/system';
import { CyclicIterator } from 'utils/cyclicIterator'; import { CyclicIterator } from 'utils/cyclicIterator';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { usePageTitle } from 'hooks/usePageTitle'; import { usePageTitle } from 'hooks/usePageTitle';
import { unknownify } from 'utils/unknownify'; import { unknownify } from 'utils/unknownify';
import { Theme } from '@mui/material/styles/createTheme';
const pointStyles = ['circle', 'rect', 'rectRounded', 'rectRot', 'triangle'];
interface IPoint { interface IPoint {
x: number; x: number;
@ -49,6 +51,7 @@ const createChartPoints = (
}; };
const createInstanceChartOptions = ( const createInstanceChartOptions = (
theme: Theme,
locationSettings: ILocationSettings locationSettings: ILocationSettings
): ChartOptions<'line'> => ({ ): ChartOptions<'line'> => ({
locale: locationSettings.locale, locale: locationSettings.locale,
@ -58,6 +61,7 @@ const createInstanceChartOptions = (
mode: 'index', mode: 'index',
intersect: false, intersect: false,
}, },
color: theme.palette.text.secondary,
plugins: { plugins: {
tooltip: { tooltip: {
backgroundColor: theme.palette.background.paper, backgroundColor: theme.palette.background.paper,
@ -78,12 +82,13 @@ const createInstanceChartOptions = (
itemSort: (a, b) => b.parsed.y - a.parsed.y, itemSort: (a, b) => b.parsed.y - a.parsed.y,
}, },
legend: { legend: {
position: 'top', position: 'bottom',
align: 'end', align: 'start',
labels: { labels: {
boxWidth: 10, boxWidth: 10,
boxHeight: 10, boxHeight: 10,
usePointStyle: true, usePointStyle: true,
padding: 24,
}, },
}, },
title: { title: {
@ -95,6 +100,10 @@ const createInstanceChartOptions = (
size: 16, size: 16,
weight: '400', weight: '400',
}, },
color: theme.palette.text.primary,
padding: {
bottom: 32,
},
}, },
}, },
scales: { scales: {
@ -103,15 +112,24 @@ const createInstanceChartOptions = (
title: { title: {
display: true, display: true,
text: 'Requests per second', text: 'Requests per second',
color: theme.palette.text.secondary,
}, },
// min: 0, // min: 0,
suggestedMin: 0, suggestedMin: 0,
ticks: { precision: 0 }, ticks: { precision: 0, color: theme.palette.text.secondary },
grid: {
color: theme.palette.divider,
borderColor: theme.palette.divider,
},
}, },
x: { x: {
type: 'time', type: 'time',
time: { unit: 'minute' }, time: { unit: 'minute' },
grid: { display: true }, grid: {
display: true,
color: theme.palette.divider,
borderColor: theme.palette.divider,
},
ticks: { ticks: {
callback: (_, i, data) => callback: (_, i, data) =>
formatDateHM(data[i].value * 1000, locationSettings.locale), formatDateHM(data[i].value * 1000, locationSettings.locale),
@ -135,7 +153,10 @@ class ItemPicker<T> {
} }
} }
const toChartData = (rps?: RequestsPerSecondSchema): ChartDatasetType[] => { const toChartData = (
theme: Theme,
rps?: RequestsPerSecondSchema
): ChartDatasetType[] => {
if (rps?.data?.result) { if (rps?.data?.result) {
const colorPicker = new ItemPicker([ const colorPicker = new ItemPicker([
theme.palette.success, theme.palette.success,
@ -143,7 +164,7 @@ const toChartData = (rps?: RequestsPerSecondSchema): ChartDatasetType[] => {
theme.palette.primary, theme.palette.primary,
theme.palette.warning, theme.palette.warning,
]); ]);
return rps.data.result.map(dataset => { return rps.data.result.map((dataset, i) => {
const endpoint = unknownify(dataset.metric?.endpoint); const endpoint = unknownify(dataset.metric?.endpoint);
const appName = unknownify(dataset.metric?.appName); const appName = unknownify(dataset.metric?.appName);
const color = colorPicker.pick(endpoint); const color = colorPicker.pick(endpoint);
@ -156,7 +177,7 @@ const toChartData = (rps?: RequestsPerSecondSchema): ChartDatasetType[] => {
elements: { elements: {
point: { point: {
radius: 4, radius: 4,
pointStyle: 'circle', pointStyle: pointStyles[i % pointStyles.length],
}, },
line: { line: {
borderDash: [8, 4], borderDash: [8, 4],
@ -171,15 +192,16 @@ const toChartData = (rps?: RequestsPerSecondSchema): ChartDatasetType[] => {
export const NetworkTraffic: VFC = () => { export const NetworkTraffic: VFC = () => {
const { locationSettings } = useLocationSettings(); const { locationSettings } = useLocationSettings();
const { metrics } = useInstanceMetrics(); const { metrics } = useInstanceMetrics();
const theme = useTheme();
const options = useMemo(() => { const options = useMemo(() => {
return createInstanceChartOptions(locationSettings); return createInstanceChartOptions(theme, locationSettings);
}, [locationSettings]); }, [theme, locationSettings]);
usePageTitle('Network - Traffic'); usePageTitle('Network - Traffic');
const data = useMemo(() => { const data = useMemo(() => {
return { datasets: toChartData(metrics) }; return { datasets: toChartData(theme, metrics) };
}, [metrics, locationSettings]); }, [theme, metrics, locationSettings]);
return ( return (
<ConditionallyRender <ConditionallyRender

View File

@ -30,14 +30,14 @@ const StyledBar = styled(Paper)(({ theme }) => ({
marginRight: 'auto', marginRight: 'auto',
padding: theme.spacing(2, 3), padding: theme.spacing(2, 3),
backgroundColor: theme.palette.background.paper, backgroundColor: theme.palette.background.paper,
border: `1px solid ${theme.palette.secondary.main}`, border: `1px solid ${theme.palette.background.alternative}`,
borderRadius: theme.shape.borderRadiusLarge, borderRadius: theme.shape.borderRadiusLarge,
gap: theme.spacing(1), gap: theme.spacing(1),
flexWrap: 'wrap', flexWrap: 'wrap',
})); }));
const StyledCount = styled('span')(({ theme }) => ({ const StyledCount = styled('span')(({ theme }) => ({
background: theme.palette.secondary.main, background: theme.palette.background.alternative,
color: theme.palette.common.white, color: theme.palette.common.white,
padding: theme.spacing(0.5, 1), padding: theme.spacing(0.5, 1),
borderRadius: theme.shape.borderRadius, borderRadius: theme.shape.borderRadius,

View File

@ -1,4 +1,4 @@
import { Box, Tooltip, useTheme } from '@mui/material'; import { Box, Tooltip } from '@mui/material';
import { ReactComponent as NegatedIcon } from 'assets/icons/24_Negator.svg'; import { ReactComponent as NegatedIcon } from 'assets/icons/24_Negator.svg';
import { ReactComponent as NegatedIconOff } from 'assets/icons/24_Negator off.svg'; import { ReactComponent as NegatedIconOff } from 'assets/icons/24_Negator off.svg';
import { IConstraint } from 'interfaces/strategy'; import { IConstraint } from 'interfaces/strategy';

View File

@ -1,5 +1,6 @@
import { styled, Tooltip, TooltipProps } from '@mui/material'; import { styled, Tooltip, TooltipProps } from '@mui/material';
import { HelpOutline } from '@mui/icons-material'; import { HelpOutline } from '@mui/icons-material';
import { HtmlTooltip } from 'component/common/HtmlTooltip/HtmlTooltip';
const StyledContainer = styled('span')(({ theme }) => ({ const StyledContainer = styled('span')(({ theme }) => ({
display: 'inline-grid', display: 'inline-grid',
@ -22,12 +23,28 @@ const StyledContainer = styled('span')(({ theme }) => ({
})); }));
interface IHelpIconProps { interface IHelpIconProps {
tooltip: string; tooltip: React.ReactNode;
htmlTooltip?: boolean;
placement?: TooltipProps['placement']; placement?: TooltipProps['placement'];
children?: React.ReactNode; children?: React.ReactNode;
} }
export const HelpIcon = ({ tooltip, placement, children }: IHelpIconProps) => { export const HelpIcon = ({
tooltip,
htmlTooltip,
placement,
children,
}: IHelpIconProps) => {
if (htmlTooltip) {
return (
<HtmlTooltip title={tooltip} placement={placement} arrow>
<StyledContainer tabIndex={0} aria-label="Help">
{children ?? <HelpOutline />}
</StyledContainer>
</HtmlTooltip>
);
}
return ( return (
<Tooltip title={tooltip} placement={placement} arrow> <Tooltip title={tooltip} placement={placement} arrow>
<StyledContainer tabIndex={0} aria-label="Help"> <StyledContainer tabIndex={0} aria-label="Help">

View File

@ -5,8 +5,25 @@ import { useRef, useEffect } from 'react';
const StyledMermaid = styled('div')(({ theme }) => ({ const StyledMermaid = styled('div')(({ theme }) => ({
display: 'flex', display: 'flex',
justifyContent: 'center', justifyContent: 'center',
'#mermaid .edgeLabel': { '#mermaid': {
'.edgeLabel': {
backgroundColor: theme.palette.background.paper, backgroundColor: theme.palette.background.paper,
color: theme.palette.text.primary,
},
'.nodeLabel': {
color: theme.palette.secondary.dark,
},
'.edgePaths > path': {
stroke: theme.palette.secondary.dark,
},
'.arrowMarkerPath': {
fill: theme.palette.secondary.dark,
stroke: 'transparent',
},
},
'&&& #mermaid .node rect': {
stroke: theme.palette.secondary.border,
fill: theme.palette.secondary.light,
}, },
})); }));

View File

@ -56,7 +56,7 @@ const Toast = ({ title, text, type, confetti }: IToast) => {
}; };
return ( return (
<div className={styles.container}> <div className={classnames(styles.container, 'dropdown-outline')}>
<div className={styles.innerContainer}> <div className={styles.innerContainer}>
<div className={styles.confettiContainer}> <div className={styles.confettiContainer}>
{confetti && renderConfetti()} {confetti && renderConfetti()}

View File

@ -6,7 +6,7 @@ import {
FeatureMetricsHours, FeatureMetricsHours,
} from './FeatureMetricsHours/FeatureMetricsHours'; } from './FeatureMetricsHours/FeatureMetricsHours';
import { IFeatureMetricsRaw } from 'interfaces/featureToggle'; import { IFeatureMetricsRaw } from 'interfaces/featureToggle';
import { Grid, styled } from '@mui/material'; import { Grid } from '@mui/material';
import { FeatureMetricsContent } from './FeatureMetricsContent/FeatureMetricsContent'; import { FeatureMetricsContent } from './FeatureMetricsContent/FeatureMetricsContent';
import { useQueryStringNumberState } from 'hooks/useQueryStringNumberState'; import { useQueryStringNumberState } from 'hooks/useQueryStringNumberState';
import { useQueryStringState } from 'hooks/useQueryStringState'; import { useQueryStringState } from 'hooks/useQueryStringState';
@ -16,12 +16,6 @@ import { ConditionallyRender } from 'component/common/ConditionallyRender/Condit
import { usePageTitle } from 'hooks/usePageTitle'; import { usePageTitle } from 'hooks/usePageTitle';
import { useRequiredPathParam } from 'hooks/useRequiredPathParam'; import { useRequiredPathParam } from 'hooks/useRequiredPathParam';
const StyledContainer = styled('div')(({ theme }) => ({
[theme.breakpoints.down('md')]: {
marginTop: theme.spacing(2),
},
}));
export const FeatureMetrics = () => { export const FeatureMetrics = () => {
const projectId = useRequiredPathParam('projectId'); const projectId = useRequiredPathParam('projectId');
const featureId = useRequiredPathParam('featureId'); const featureId = useRequiredPathParam('featureId');
@ -62,12 +56,7 @@ export const FeatureMetrics = () => {
return ( return (
<PageContent> <PageContent>
<Grid <Grid container component="header" spacing={2}>
container
component="header"
spacing={2}
alignItems="flex-end"
>
<Grid item xs={12} md={5}> <Grid item xs={12} md={5}>
<ConditionallyRender <ConditionallyRender
condition={environments.size > 0} condition={environments.size > 0}
@ -95,12 +84,10 @@ export const FeatureMetrics = () => {
/> />
</Grid> </Grid>
<Grid item xs={12} md={2}> <Grid item xs={12} md={2}>
<StyledContainer>
<FeatureMetricsHours <FeatureMetricsHours
hoursBack={hoursBack} hoursBack={hoursBack}
setHoursBack={setHoursBack} setHoursBack={setHoursBack}
/> />
</StyledContainer>
</Grid> </Grid>
</Grid> </Grid>
<FeatureMetricsContent <FeatureMetricsContent

View File

@ -1,5 +1,5 @@
import { IFeatureMetricsRaw } from 'interfaces/featureToggle'; import { IFeatureMetricsRaw } from 'interfaces/featureToggle';
import React, { useMemo } from 'react'; import { useMemo } from 'react';
import { Line } from 'react-chartjs-2'; import { Line } from 'react-chartjs-2';
import { import {
CategoryScale, CategoryScale,
@ -16,6 +16,7 @@ import { useLocationSettings } from 'hooks/useLocationSettings';
import 'chartjs-adapter-date-fns'; import 'chartjs-adapter-date-fns';
import { createChartData } from './createChartData'; import { createChartData } from './createChartData';
import { createChartOptions } from './createChartOptions'; import { createChartOptions } from './createChartOptions';
import { useTheme } from '@mui/material';
interface IFeatureMetricsChartProps { interface IFeatureMetricsChartProps {
metrics: IFeatureMetricsRaw[]; metrics: IFeatureMetricsRaw[];
@ -28,6 +29,7 @@ export const FeatureMetricsChart = ({
hoursBack, hoursBack,
statsSectionId, statsSectionId,
}: IFeatureMetricsChartProps) => { }: IFeatureMetricsChartProps) => {
const theme = useTheme();
const { locationSettings } = useLocationSettings(); const { locationSettings } = useLocationSettings();
const sortedMetrics = useMemo(() => { const sortedMetrics = useMemo(() => {
@ -37,12 +39,17 @@ export const FeatureMetricsChart = ({
}, [metrics]); }, [metrics]);
const options = useMemo(() => { const options = useMemo(() => {
return createChartOptions(sortedMetrics, hoursBack, locationSettings); return createChartOptions(
}, [sortedMetrics, hoursBack, locationSettings]); theme,
sortedMetrics,
hoursBack,
locationSettings
);
}, [theme, sortedMetrics, hoursBack, locationSettings]);
const data = useMemo(() => { const data = useMemo(() => {
return createChartData(sortedMetrics, locationSettings); return createChartData(theme, sortedMetrics, locationSettings);
}, [sortedMetrics, locationSettings]); }, [theme, sortedMetrics, locationSettings]);
return ( return (
<div style={{ height: 400 }}> <div style={{ height: 400 }}>

View File

@ -1,8 +1,8 @@
import { IFeatureMetricsRaw } from 'interfaces/featureToggle'; import { IFeatureMetricsRaw } from 'interfaces/featureToggle';
import { ChartData } from 'chart.js'; import { ChartData } from 'chart.js';
import { ILocationSettings } from 'hooks/useLocationSettings'; import { ILocationSettings } from 'hooks/useLocationSettings';
import theme from 'themes/theme';
import 'chartjs-adapter-date-fns'; import 'chartjs-adapter-date-fns';
import { Theme } from '@mui/material/styles/createTheme';
interface IPoint { interface IPoint {
x: string; x: string;
@ -10,6 +10,7 @@ interface IPoint {
} }
export const createChartData = ( export const createChartData = (
theme: Theme,
metrics: IFeatureMetricsRaw[], metrics: IFeatureMetricsRaw[],
locationSettings: ILocationSettings locationSettings: ILocationSettings
): ChartData<'line', IPoint[], string> => { ): ChartData<'line', IPoint[], string> => {

View File

@ -2,10 +2,11 @@ import { ILocationSettings } from 'hooks/useLocationSettings';
import 'chartjs-adapter-date-fns'; import 'chartjs-adapter-date-fns';
import { ChartOptions, defaults } from 'chart.js'; import { ChartOptions, defaults } from 'chart.js';
import { IFeatureMetricsRaw } from 'interfaces/featureToggle'; import { IFeatureMetricsRaw } from 'interfaces/featureToggle';
import theme from 'themes/theme';
import { formatDateHM } from 'utils/formatDate'; import { formatDateHM } from 'utils/formatDate';
import { Theme } from '@mui/material/styles/createTheme';
export const createChartOptions = ( export const createChartOptions = (
theme: Theme,
metrics: IFeatureMetricsRaw[], metrics: IFeatureMetricsRaw[],
hoursBack: number, hoursBack: number,
locationSettings: ILocationSettings locationSettings: ILocationSettings
@ -18,6 +19,7 @@ export const createChartOptions = (
mode: 'index', mode: 'index',
intersect: false, intersect: false,
}, },
color: theme.palette.text.secondary,
plugins: { plugins: {
tooltip: { tooltip: {
backgroundColor: theme.palette.background.paper, backgroundColor: theme.palette.background.paper,
@ -56,6 +58,7 @@ export const createChartOptions = (
size: 16, size: 16,
weight: '400', weight: '400',
}, },
color: theme.palette.text.primary,
}, },
}, },
scales: { scales: {
@ -64,10 +67,15 @@ export const createChartOptions = (
title: { title: {
display: true, display: true,
text: 'Number of requests', text: 'Number of requests',
color: theme.palette.text.secondary,
}, },
// min: 0, // min: 0,
suggestedMin: 0, suggestedMin: 0,
ticks: { precision: 0 }, ticks: { precision: 0, color: theme.palette.text.secondary },
grid: {
color: theme.palette.divider,
borderColor: theme.palette.divider,
},
}, },
x: { x: {
type: 'time', type: 'time',
@ -76,6 +84,7 @@ export const createChartOptions = (
ticks: { ticks: {
callback: (_, i, data) => callback: (_, i, data) =>
formatDateHM(data[i].value, locationSettings.locale), formatDateHM(data[i].value, locationSettings.locale),
color: theme.palette.text.secondary,
}, },
}, },
}, },

View File

@ -11,7 +11,7 @@ interface IFeatureMetricsChipsProps {
const StyledTitle = styled('h2')(({ theme }) => ({ const StyledTitle = styled('h2')(({ theme }) => ({
margin: 0, margin: 0,
marginBottom: theme.spacing(1), marginBottom: theme.spacing(1.5),
fontSize: theme.fontSizes.smallBody, fontSize: theme.fontSizes.smallBody,
fontWeight: theme.fontWeight.thin, fontWeight: theme.fontWeight.thin,
color: theme.palette.text.secondary, color: theme.palette.text.secondary,

View File

@ -2,7 +2,6 @@ import { FeatureMetricsTable } from '../FeatureMetricsTable/FeatureMetricsTable'
import { IFeatureMetricsRaw } from 'interfaces/featureToggle'; import { IFeatureMetricsRaw } from 'interfaces/featureToggle';
import { FeatureMetricsStatsRaw } from '../FeatureMetricsStats/FeatureMetricsStatsRaw'; import { FeatureMetricsStatsRaw } from '../FeatureMetricsStats/FeatureMetricsStatsRaw';
import { Box, Typography } from '@mui/material'; import { Box, Typography } from '@mui/material';
import theme from 'themes/theme';
import { useId } from 'hooks/useId'; import { useId } from 'hooks/useId';
import React, { Suspense } from 'react'; import React, { Suspense } from 'react';
@ -35,12 +34,7 @@ export const FeatureMetricsContent = ({
return ( return (
<Suspense fallback={null}> <Suspense fallback={null}>
<Box <Box borderTop={1} pt={2} mt={3} borderColor="divider">
borderTop={1}
pt={2}
mt={3}
borderColor={theme.palette.divider}
>
<LazyFeatureMetricsChart <LazyFeatureMetricsChart
metrics={metrics} metrics={metrics}
hoursBack={hoursBack} hoursBack={hoursBack}

View File

@ -1,7 +1,16 @@
import { styled } from '@mui/material';
import GeneralSelect, { import GeneralSelect, {
IGeneralSelectProps, IGeneralSelectProps,
} from 'component/common/GeneralSelect/GeneralSelect'; } from 'component/common/GeneralSelect/GeneralSelect';
const StyledTitle = styled('h2')(({ theme }) => ({
margin: 0,
marginBottom: theme.spacing(1),
fontSize: theme.fontSizes.smallBody,
fontWeight: theme.fontWeight.thin,
color: theme.palette.text.secondary,
}));
interface IFeatureMetricsHoursProps { interface IFeatureMetricsHoursProps {
hoursBack: number; hoursBack: number;
setHoursBack: (value: number) => void; setHoursBack: (value: number) => void;
@ -18,8 +27,9 @@ export const FeatureMetricsHours = ({
}; };
return ( return (
<div>
<StyledTitle>Period</StyledTitle>
<GeneralSelect <GeneralSelect
label="Period"
name="feature-metrics-period" name="feature-metrics-period"
id="feature-metrics-period" id="feature-metrics-period"
options={hourOptions} options={hourOptions}
@ -27,6 +37,7 @@ export const FeatureMetricsHours = ({
onChange={onChange} onChange={onChange}
fullWidth fullWidth
/> />
</div>
); );
}; };

View File

@ -1,11 +1,18 @@
import { useContext, useMemo, useState } from 'react'; import { useContext, useMemo, useState } from 'react';
import { Box, Button, IconButton, Tooltip, useTheme } from '@mui/material'; import {
Box,
Button,
IconButton,
Tooltip,
useTheme,
styled,
} from '@mui/material';
import CloseIcon from '@mui/icons-material/Close'; import CloseIcon from '@mui/icons-material/Close';
import { ReactComponent as Logo } from 'assets/icons/logoPlain.svg'; import { ReactComponent as UnleashLogo } from 'assets/icons/logoBg.svg';
import { ReactComponent as UnleashLogoWhite } from 'assets/icons/logoWhiteBg.svg';
import AnimateOnMount from 'component/common/AnimateOnMount/AnimateOnMount'; import AnimateOnMount from 'component/common/AnimateOnMount/AnimateOnMount';
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender'; import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
import { import {
contentSpacingY,
fadeInTopEnter, fadeInTopEnter,
fadeInTopLeave, fadeInTopLeave,
fadeInTopStart, fadeInTopStart,
@ -17,6 +24,13 @@ import {
} from 'component/feedback/FeedbackNPS/showNPSFeedback'; } from 'component/feedback/FeedbackNPS/showNPSFeedback';
import { useAuthFeedback } from 'hooks/api/getters/useAuth/useAuthFeedback'; import { useAuthFeedback } from 'hooks/api/getters/useAuth/useAuthFeedback';
import { useAuthFeedbackApi } from 'hooks/api/actions/useAuthFeedbackApi/useAuthFeedbackApi'; import { useAuthFeedbackApi } from 'hooks/api/actions/useAuthFeedbackApi/useAuthFeedbackApi';
import { ThemeMode } from 'component/common/ThemeMode/ThemeMode';
const StyledHeader = styled('h3')(({ theme }) => ({
margin: 0,
color: theme.palette.text.primary,
marginLeft: theme.spacing(1),
}));
interface IFeedbackNPSProps { interface IFeedbackNPSProps {
openUrl: string; openUrl: string;
@ -77,12 +91,13 @@ export const FeedbackNPS = ({ openUrl }: IFeedbackNPSProps) => {
leave={animations.leave} leave={animations.leave}
> >
<Box <Box
className="dropdown-outline"
sx={{ sx={{
borderRadius: `${theme.shape.borderRadiusLarge}px`, borderRadius: `${theme.shape.borderRadiusLarge}px`,
backgroundColor: theme.palette.background.paper, backgroundColor: theme.palette.background.paper,
zIndex: 9999, zIndex: 9999,
boxShadow: theme.boxShadows.elevated, boxShadow: theme.boxShadows.elevated,
padding: theme.spacing(3), padding: theme.spacing(4),
maxWidth: '400px', maxWidth: '400px',
}} }}
> >
@ -90,35 +105,37 @@ export const FeedbackNPS = ({ openUrl }: IFeedbackNPSProps) => {
sx={{ sx={{
display: 'flex', display: 'flex',
flexDirection: 'column', flexDirection: 'column',
rowGap: theme.spacing(1.5),
position: 'relative', position: 'relative',
...contentSpacingY(theme),
}} }}
> >
<Tooltip title="Close" arrow> <Tooltip title="Close" arrow>
<IconButton <IconButton
sx={{ sx={theme => ({
position: 'absolute', position: 'absolute',
right: '-38px', right: theme.spacing(-4),
top: '-47px', top: theme.spacing(-4),
backgroundColor: theme.palette.background.paper, })}
boxShadow: theme.boxShadows.elevated,
'&:hover': {
backgroundColor:
theme.palette.background.paper,
},
}}
onClick={() => setShowFeedback(false)} onClick={() => setShowFeedback(false)}
size="large" size="large"
> >
<CloseIcon /> <CloseIcon />
</IconButton> </IconButton>
</Tooltip> </Tooltip>
<Logo <Box
style={{ sx={{
width: '25px', display: 'flex',
height: '25px', flexDirection: 'row',
alignItems: 'center',
}} }}
>
<ThemeMode
darkmode={<UnleashLogoWhite />}
lightmode={<UnleashLogo />}
/> />
<StyledHeader>Unleash feedback</StyledHeader>
</Box>
<ConditionallyRender <ConditionallyRender
condition={answeredNotNow} condition={answeredNotNow}
show={ show={
@ -135,7 +152,12 @@ export const FeedbackNPS = ({ openUrl }: IFeedbackNPSProps) => {
} }
/> />
<Box> <Box
sx={{
textAlign: 'right',
marginTop: theme.spacing(2.5),
}}
>
<ConditionallyRender <ConditionallyRender
condition={answeredNotNow} condition={answeredNotNow}
show={ show={

View File

@ -1,7 +1,6 @@
import { Box, styled, Typography } from '@mui/material'; import { Box, styled, Typography } from '@mui/material';
import { HelpOutline } from '@mui/icons-material'; import { FC } from 'react';
import { HtmlTooltip } from '../../../common/HtmlTooltip/HtmlTooltip'; import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
import React, { FC } from 'react';
const StyledTitle = styled(Typography)(({ theme }) => ({ const StyledTitle = styled(Typography)(({ theme }) => ({
fontWeight: theme.fontWeight.bold, fontWeight: theme.fontWeight.bold,
@ -13,8 +12,9 @@ const StyledDescription = styled(Typography)(({ theme }) => ({
})); }));
export const CollaborationModeTooltip: FC = () => ( export const CollaborationModeTooltip: FC = () => (
<HtmlTooltip <HelpIcon
title={ htmlTooltip
tooltip={
<> <>
<Box> <Box>
<StyledTitle>open: </StyledTitle> <StyledTitle>open: </StyledTitle>
@ -31,9 +31,5 @@ export const CollaborationModeTooltip: FC = () => (
</Box> </Box>
</> </>
} }
arrow />
describeChild
>
<HelpOutline />
</HtmlTooltip>
); );

View File

@ -140,10 +140,15 @@ const ProjectForm: React.FC<IProjectForm> = ({
condition={Boolean(projectModeFlag)} condition={Boolean(projectModeFlag)}
show={ show={
<> <>
<Box sx={{ display: 'flex' }}> <Box
<StyledDescription> sx={{
What is your project collaboration mode? display: 'flex',
</StyledDescription> alignItems: 'center',
marginBottom: 1,
gap: 1,
}}
>
<p>What is your project collaboration mode?</p>
<CollaborationModeTooltip /> <CollaborationModeTooltip />
</Box> </Box>
<Select <Select

View File

@ -3,7 +3,7 @@ import { useContext } from 'react';
import { setLocalStorageItem } from 'utils/storage'; import { setLocalStorageItem } from 'utils/storage';
import mainTheme from 'themes/theme'; import mainTheme from 'themes/theme';
import darkTheme from 'themes/dark-theme'; import darkTheme from 'themes/dark-theme';
import { Theme } from '@emotion/react'; import { Theme } from '@mui/material/styles/createTheme';
interface IUseThemeModeOutput { interface IUseThemeModeOutput {
resolveTheme: () => Theme; resolveTheme: () => Theme;

View File

@ -9,9 +9,6 @@ const actionColors = {
0.08: 'rgba(223, 222, 255, 0.08)', 0.08: 'rgba(223, 222, 255, 0.08)',
0.05: 'rgba(223, 222, 255, 0.05)', 0.05: 'rgba(223, 222, 255, 0.05)',
}; };
const purpleColor = {
0.5: 'rgba(151, 146, 237, 0.5))',
};
const theme = { const theme = {
breakpoints: { breakpoints: {
@ -95,7 +92,7 @@ const theme = {
}, },
secondary: { secondary: {
// Used for purple badges and puple light elements // Used for purple badges and puple light elements
main: '#57549C', // used on icons on these elements main: '#9792ED', // used on icons on these elements
light: '#34325E', // used as a bakground on these elements light: '#34325E', // used as a bakground on these elements
dark: '#EEEEFC', // used for text on these elements dark: '#EEEEFC', // used for text on these elements
border: '#4C4992', border: '#4C4992',
@ -543,7 +540,7 @@ export default createTheme({
'&:not(.Mui-disabled).MuiButton-containedPrimary': { '&:not(.Mui-disabled).MuiButton-containedPrimary': {
backgroundColor: theme.palette.background.alternative, backgroundColor: theme.palette.background.alternative,
'&:hover': { '&:hover': {
backgroundColor: theme.palette.secondary.main, backgroundColor: theme.palette.secondary.light,
}, },
}, },
}), }),