From 96dac848804b9580373d5376c0648b4df3d253d0 Mon Sep 17 00:00:00 2001 From: Thomas Heartman Date: Tue, 4 Feb 2025 11:37:58 +0100 Subject: [PATCH] refactor: period selector component (#9202) Refactors the period selector component now that the design / system is pretty much finished. Main points are: change from using CSS selectors to using styled components; use props instead of classes. This is in keeping with the general Unleash approach. There's two very slight visual changes here: 1. There is 4px of added space below the "range" "header" text. 2. The months in the grid are a little closer together and not as wide. This is because we remove the explicit column gap due to the grid having a set width. Previously the width was automatic, but because we want this to line up with the button, we need to set the width explicitly on both items. As such, with the padding, the grid was a little too wide, so there was too little padding on the right. This rectifies that. --- .../NetworkTrafficUsage/PeriodSelector.tsx | 166 +++++++++--------- 1 file changed, 82 insertions(+), 84 deletions(-) diff --git a/frontend/src/component/admin/network/NetworkTrafficUsage/PeriodSelector.tsx b/frontend/src/component/admin/network/NetworkTrafficUsage/PeriodSelector.tsx index caf2391fb8..764a20a5e8 100644 --- a/frontend/src/component/admin/network/NetworkTrafficUsage/PeriodSelector.tsx +++ b/frontend/src/component/admin/network/NetworkTrafficUsage/PeriodSelector.tsx @@ -9,52 +9,79 @@ import { selectablePeriods } from './selectable-periods'; const dropdownWidth = '15rem'; const dropdownInlinePadding = (theme: Theme) => theme.spacing(3); +const BaseButton = styled('button', { + shouldForwardProp: (prop) => prop !== 'selected', +})<{ selected?: boolean }>(({ theme, selected }) => ({ + cursor: 'pointer', + border: 'none', + backgroundColor: selected ? theme.palette.secondary.light : 'inherit', + fontSize: theme.typography.body1.fontSize, + padding: theme.spacing(0.5), + borderRadius: theme.shape.borderRadius, + color: theme.palette.text.primary, + transition: 'background-color 0.2s ease', + + ':focus-visible': { + outline: `2px solid ${theme.palette.primary.main}`, + }, + ':hover:not(:disabled)': { + backgroundColor: theme.palette.action.hover, + }, +})); + +const GridButton = styled(BaseButton)(({ theme }) => ({ + ':disabled': { + cursor: 'default', + color: theme.palette.text.disabled, + }, +})); + +const RangeButton = styled(BaseButton)(({ theme }) => ({ + width: '100%', + paddingBlock: theme.spacing(1), + textAlign: 'left', + borderRadius: 0, + paddingInline: dropdownInlinePadding(theme), +})); + +const SelectorDropdownButton = styled(Button)(({ theme }) => ({ + whiteSpace: 'nowrap', + width: dropdownWidth, + justifyContent: 'space-between', + fontWeight: 'normal', + color: theme.palette.text.primary, + borderColor: theme.palette.divider, + ':focus-within': { + borderColor: theme.palette.primary.main, + }, + ':hover': { + borderColor: theme.palette.text.disabled, + backgroundColor: 'inherit', + }, + + transition: 'border-color 0.1s ease', +})); + const Wrapper = styled('article')(({ theme }) => ({ width: dropdownWidth, paddingBlock: theme.spacing(2), display: 'flex', flexFlow: 'column', gap: theme.spacing(2), - button: { - cursor: 'pointer', - border: 'none', - background: 'none', - fontSize: theme.typography.body1.fontSize, - padding: theme.spacing(0.5), - borderRadius: theme.shape.borderRadius, - color: theme.palette.text.primary, - transition: 'background-color 0.2s ease', - - '&.selected': { - backgroundColor: theme.palette.secondary.light, - }, - }, - 'button:disabled': { - cursor: 'default', - color: theme.palette.text.disabled, - }, - 'button:hover:not(:disabled)': { - backgroundColor: theme.palette.action.hover, - }, - 'button:focus': { - outline: `2px solid ${theme.palette.primary.main}`, - }, })); const MonthSelector = styled('article')(({ theme }) => ({ - border: 'none', paddingInline: dropdownInlinePadding(theme), - hgroup: { - h3: { - margin: 0, - fontSize: theme.typography.h3.fontSize, - }, - p: { - color: theme.palette.text.secondary, - fontSize: theme.typography.body2.fontSize, - }, +})); - marginBottom: theme.spacing(1), +const MonthSelectorHeaderGroup = styled('hgroup')(({ theme }) => ({ + h3: { + margin: 0, + fontSize: theme.typography.h3.fontSize, + }, + p: { + color: theme.palette.text.secondary, + fontSize: theme.typography.body2.fontSize, }, })); @@ -64,20 +91,21 @@ const MonthGrid = styled('ul')(({ theme }) => ({ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', rowGap: theme.spacing(1), - columnGap: theme.spacing(2), })); const RangeSelector = styled('article')(({ theme }) => ({ display: 'flex', width: '100%', flexFlow: 'column', - gap: theme.spacing(0), - h4: { - paddingInline: dropdownInlinePadding(theme), - fontSize: theme.typography.body2.fontSize, - margin: 0, - color: theme.palette.text.secondary, - }, + gap: theme.spacing(0.5), +})); + +const RangeHeader = styled('p')(({ theme }) => ({ + paddingInline: dropdownInlinePadding(theme), + fontSize: theme.typography.body2.fontSize, + margin: 0, + color: theme.palette.text.secondary, + fontWeight: 'bold', })); const RangeList = styled('ul')(({ theme }) => ({ @@ -88,14 +116,6 @@ const RangeList = styled('ul')(({ theme }) => ({ li: { width: '100%', }, - - button: { - width: '100%', - paddingBlock: theme.spacing(1), - textAlign: 'left', - borderRadius: 0, - paddingInline: dropdownInlinePadding(theme), - }, })); type Props = { @@ -136,31 +156,14 @@ export const PeriodSelector: FC = ({ selectedPeriod, setPeriod }) => { return ( - + = ({ selectedPeriod, setPeriod }) => { > -
+

Select month

Last 12 months

-
+ {selectablePeriods.map((period, index) => (
  • - +
  • ))}
    -

    Range

    + Range {rangeOptions.map((option) => (
  • - +
  • ))}