mirror of
https://github.com/Unleash/unleash.git
synced 2025-05-22 01:16:07 +02:00
Feat: sticky insights header and widget tooltip icon (#6537)
What it says on the tin Closes # [1-2182](https://linear.app/unleash/issue/1-2182/sticky-header-on-scroll) <img width="1442" alt="Screenshot 2024-03-14 at 10 47 32" src="https://github.com/Unleash/unleash/assets/104830839/5b57cd95-3c40-48e7-b25b-823df025e68c"> https://github.com/Unleash/unleash/assets/104830839/f5249fd6-a4cc-4e52-9b01-89ef3cbeb47c --------- Signed-off-by: andreas-unleash <andreas@getunleash.ai>
This commit is contained in:
parent
d6482ab07d
commit
513d60c14d
@ -1,4 +1,4 @@
|
|||||||
import { VFC } from 'react';
|
import { useState, VFC } from 'react';
|
||||||
import { Box, styled } from '@mui/material';
|
import { Box, styled } from '@mui/material';
|
||||||
import { ArrayParam, withDefault } from 'use-query-params';
|
import { ArrayParam, withDefault } from 'use-query-params';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
@ -45,7 +45,19 @@ const ChartWidget = styled(Widget)(({ theme }) => ({
|
|||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const StickyWrapper = styled(Box)<{ scrolled?: boolean }>(
|
||||||
|
({ theme, scrolled }) => ({
|
||||||
|
position: 'sticky',
|
||||||
|
top: 0,
|
||||||
|
zIndex: 1000,
|
||||||
|
padding: scrolled ? theme.spacing(2, 0) : theme.spacing(0, 0, 2),
|
||||||
|
background: theme.palette.background.application,
|
||||||
|
transition: 'padding 0.3s ease',
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
export const ExecutiveDashboard: VFC = () => {
|
export const ExecutiveDashboard: VFC = () => {
|
||||||
|
const [scrolled, setScrolled] = useState(false);
|
||||||
const { executiveDashboardData, loading, error } = useExecutiveDashboard();
|
const { executiveDashboardData, loading, error } = useExecutiveDashboard();
|
||||||
const stateConfig = {
|
const stateConfig = {
|
||||||
projects: withDefault(ArrayParam, [allOption.id]),
|
projects: withDefault(ArrayParam, [allOption.id]),
|
||||||
@ -72,9 +84,21 @@ export const ExecutiveDashboard: VFC = () => {
|
|||||||
const summary = useFilteredFlagsSummary(projectsData);
|
const summary = useFilteredFlagsSummary(projectsData);
|
||||||
const isOneProjectSelected = projects.length === 1;
|
const isOneProjectSelected = projects.length === 1;
|
||||||
|
|
||||||
|
const handleScroll = () => {
|
||||||
|
if (!scrolled && window.scrollY > 0) {
|
||||||
|
setScrolled(true);
|
||||||
|
} else if (scrolled && window.scrollY === 0) {
|
||||||
|
setScrolled(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.addEventListener('scroll', handleScroll);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box sx={(theme) => ({ paddingBottom: theme.spacing(4) })}>
|
<StickyWrapper scrolled={scrolled}>
|
||||||
<DashboardHeader
|
<DashboardHeader
|
||||||
actions={
|
actions={
|
||||||
<ProjectSelect
|
<ProjectSelect
|
||||||
@ -85,7 +109,7 @@ export const ExecutiveDashboard: VFC = () => {
|
|||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</StickyWrapper>
|
||||||
<StyledGrid>
|
<StyledGrid>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={showAllProjects}
|
condition={showAllProjects}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ReactNode, VFC } from 'react';
|
import { ReactNode, VFC, useState } from 'react';
|
||||||
import { useUiFlag } from 'hooks/useUiFlag';
|
import { useUiFlag } from 'hooks/useUiFlag';
|
||||||
import { useFeedback } from 'component/feedbackNew/useFeedback';
|
import { useFeedback } from 'component/feedbackNew/useFeedback';
|
||||||
import ReviewsOutlined from '@mui/icons-material/ReviewsOutlined';
|
import ReviewsOutlined from '@mui/icons-material/ReviewsOutlined';
|
||||||
@ -8,6 +8,7 @@ import {
|
|||||||
styled,
|
styled,
|
||||||
useMediaQuery,
|
useMediaQuery,
|
||||||
useTheme,
|
useTheme,
|
||||||
|
Box,
|
||||||
} from '@mui/material';
|
} from '@mui/material';
|
||||||
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
import { PageHeader } from 'component/common/PageHeader/PageHeader';
|
||||||
import { Badge } from 'component/common/Badge/Badge';
|
import { Badge } from 'component/common/Badge/Badge';
|
||||||
|
@ -27,13 +27,15 @@ export const createOptions = (
|
|||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
position: 'nearest',
|
||||||
external: createTooltip(setTooltip),
|
external: createTooltip(setTooltip),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
locale: locationSettings.locale,
|
locale: locationSettings.locale,
|
||||||
interaction: {
|
interaction: {
|
||||||
intersect: localTooltip || false,
|
intersect: false,
|
||||||
axis: 'x',
|
axis: 'x',
|
||||||
|
mode: 'index',
|
||||||
},
|
},
|
||||||
elements: {
|
elements: {
|
||||||
point: {
|
point: {
|
||||||
|
@ -3,6 +3,7 @@ import { Paper, Typography, styled, SxProps } from '@mui/material';
|
|||||||
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
import { HelpIcon } from 'component/common/HelpIcon/HelpIcon';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { Theme } from '@mui/material/styles/createTheme';
|
import { Theme } from '@mui/material/styles/createTheme';
|
||||||
|
import InfoOutlined from '@mui/icons-material/InfoOutlined';
|
||||||
|
|
||||||
const StyledPaper = styled(Paper)(({ theme }) => ({
|
const StyledPaper = styled(Paper)(({ theme }) => ({
|
||||||
padding: theme.spacing(3),
|
padding: theme.spacing(3),
|
||||||
@ -29,7 +30,11 @@ export const Widget: FC<{
|
|||||||
{title}
|
{title}
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={Boolean(tooltip)}
|
condition={Boolean(tooltip)}
|
||||||
show={<HelpIcon htmlTooltip tooltip={tooltip} />}
|
show={
|
||||||
|
<HelpIcon htmlTooltip tooltip={tooltip}>
|
||||||
|
<InfoOutlined />
|
||||||
|
</HelpIcon>
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</Typography>
|
</Typography>
|
||||||
{children}
|
{children}
|
||||||
|
@ -73,7 +73,7 @@ export const HealthStats: VFC<IHealthStatsProps> = ({
|
|||||||
x={206}
|
x={206}
|
||||||
y={72}
|
y={72}
|
||||||
fill={theme.palette.charts.health.text}
|
fill={theme.palette.charts.health.text}
|
||||||
fontSize={12}
|
fontSize={13}
|
||||||
textAnchor='middle'
|
textAnchor='middle'
|
||||||
>
|
>
|
||||||
Healthy
|
Healthy
|
||||||
@ -100,7 +100,7 @@ export const HealthStats: VFC<IHealthStatsProps> = ({
|
|||||||
x={53}
|
x={53}
|
||||||
y={81}
|
y={81}
|
||||||
fill={theme.palette.charts.health.text}
|
fill={theme.palette.charts.health.text}
|
||||||
fontSize={12}
|
fontSize={13}
|
||||||
textAnchor='middle'
|
textAnchor='middle'
|
||||||
>
|
>
|
||||||
Stale
|
Stale
|
||||||
@ -127,7 +127,7 @@ export const HealthStats: VFC<IHealthStatsProps> = ({
|
|||||||
x={144}
|
x={144}
|
||||||
y={232}
|
y={232}
|
||||||
fill={theme.palette.charts.health.text}
|
fill={theme.palette.charts.health.text}
|
||||||
fontSize={12}
|
fontSize={13}
|
||||||
textAnchor='middle'
|
textAnchor='middle'
|
||||||
>
|
>
|
||||||
<tspan x={144} dy='0'>
|
<tspan x={144} dy='0'>
|
||||||
|
@ -283,7 +283,7 @@ export const theme = {
|
|||||||
title: colors.grey[50],
|
title: colors.grey[50],
|
||||||
healthy: colors.purple[800],
|
healthy: colors.purple[800],
|
||||||
stale: colors.red[800],
|
stale: colors.red[800],
|
||||||
potentiallyStale: colors.orange[800],
|
potentiallyStale: colors.orange[900],
|
||||||
gradientStale: colors.red[300],
|
gradientStale: colors.red[300],
|
||||||
gradientPotentiallyStale: colors.orange[500],
|
gradientPotentiallyStale: colors.orange[500],
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user