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:
parent
2980c0de4e
commit
96dac84880
@ -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>
|
||||
|
Loading…
Reference in New Issue
Block a user