1
0
mirror of https://github.com/Unleash/unleash.git synced 2025-02-14 00:19:16 +01:00

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.
This commit is contained in:
Thomas Heartman 2025-02-04 11:37:58 +01:00 committed by GitHub
parent 2980c0de4e
commit 96dac84880
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -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<Props> = ({ selectedPeriod, setPeriod }) => {
return (
<Box ref={ref}>
<Button
<SelectorDropdownButton
endIcon={open ? <ArrowDropUpIcon /> : <ArrowDropDownIcon />}
sx={(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',
})}
variant='outlined'
disableRipple
onClick={() => setOpen(true)}
>
{buttonText}
</Button>
</SelectorDropdownButton>
<StyledPopover
open={open}
anchorEl={ref.current}
@ -176,22 +179,19 @@ export const PeriodSelector: FC<Props> = ({ selectedPeriod, setPeriod }) => {
>
<Wrapper>
<MonthSelector>
<hgroup>
<MonthSelectorHeaderGroup>
<h3>Select month</h3>
<p>Last 12 months</p>
</hgroup>
</MonthSelectorHeaderGroup>
<MonthGrid>
{selectablePeriods.map((period, index) => (
<li key={period.label}>
<button
className={
<GridButton
selected={
selectedPeriod.grouping ===
'daily' &&
period.key === selectedPeriod.month
? 'selected'
: ''
}
type='button'
disabled={!period.selectable}
onClick={() => {
selectPeriod({
@ -201,25 +201,23 @@ export const PeriodSelector: FC<Props> = ({ selectedPeriod, setPeriod }) => {
}}
>
{period.shortLabel}
</button>
</GridButton>
</li>
))}
</MonthGrid>
</MonthSelector>
<RangeSelector>
<h4>Range</h4>
<RangeHeader>Range</RangeHeader>
<RangeList>
{rangeOptions.map((option) => (
<li key={option.label}>
<button
className={
<RangeButton
selected={
selectedPeriod.grouping ===
'monthly' &&
option.value ===
selectedPeriod.monthsBack
? 'selected'
: ''
}
type='button'
onClick={() => {
@ -230,7 +228,7 @@ export const PeriodSelector: FC<Props> = ({ selectedPeriod, setPeriod }) => {
}}
>
Last {option.value} months
</button>
</RangeButton>
</li>
))}
</RangeList>