Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LegendWidget #91

Merged
merged 37 commits into from
Jun 24, 2021
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
bbf2715
Added Layer, Multi Layer and Header
aaranadev Feb 8, 2021
3ff13e1
added hover and and tooltip
aaranadev Feb 8, 2021
544c2b4
added categories
aaranadev Feb 9, 2021
bb6e088
added icon
aaranadev Feb 9, 2021
61b0ce6
added note
aaranadev Feb 9, 2021
c6fab38
added changeVisibility event
aaranadev Feb 9, 2021
9f57eb5
added tooltip
aaranadev Feb 9, 2021
4230abc
added proportion
aaranadev Feb 9, 2021
9850c85
added custom
aaranadev Feb 9, 2021
352d14e
Merge branch 'master' of github.com:CartoDB/carto-react-lib into feat…
aaranadev Feb 24, 2021
13e56b5
Removed empty bodies and improve ternary operators readability.
Clebal Mar 1, 2021
c3ae6b4
Allow multiple colors gradient in StepsContinuous
Clebal Mar 1, 2021
2ed82ae
Changed point to line to show avg in Proportion legend
menusal Mar 3, 2021
7d5719d
wip
menusal Mar 5, 2021
6a2c8f0
wip
menusal Mar 5, 2021
ad0c30c
wip
menusal Mar 5, 2021
3cc3a27
wip
menusal Mar 5, 2021
bc70b66
Revert some changes
menusal Mar 8, 2021
1c2c184
Update with dev
Clebal Apr 28, 2021
df4051c
Update every legend interface. Add LegendWidget.
Clebal May 4, 2021
def4387
Comment unused code
Clebal May 4, 2021
53a2e7c
Merge branch 'master' of github.com:CartoDB/carto-react into feature/…
Jun 23, 2021
477ff7f
Added new legend system to storybook
Jun 23, 2021
1888b0f
added types
Jun 23, 2021
79f5955
removed custom classname
Jun 23, 2021
697e56d
added test (wip)
Jun 24, 2021
dabb6e5
added testing
Jun 24, 2021
265bfcd
fixed test
Jun 24, 2021
c57c65b
improve legend widget
Jun 24, 2021
562804a
added classname
Jun 24, 2021
67755c2
changed legend by layer
Jun 24, 2021
d215c4d
improve css
Jun 24, 2021
88ef69c
remove legend without layers
Jun 24, 2021
633ecde
Add note to changelog
VictorVelarde Jun 24, 2021
cb9eea5
Add relative units in LegendIcon
VictorVelarde Jun 24, 2021
fe6f2a5
Small refactor extracting 2 functions
VictorVelarde Jun 24, 2021
38e990a
Unify import
VictorVelarde Jun 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/ui/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import WrapperWidgetUI from './widgets/WrapperWidgetUI';
import CategoryWidgetUI from './widgets/CategoryWidgetUI';
import FormulaWidgetUI from './widgets/FormulaWidgetUI';
import HistogramWidgetUI from './widgets/HistogramWidgetUI';
import LegendUI from './legend/LegendUI';

export {
cartoThemeOptions,
WrapperWidgetUI,
CategoryWidgetUI,
FormulaWidgetUI,
HistogramWidgetUI
HistogramWidgetUI,
LegendUI
VictorVelarde marked this conversation as resolved.
Show resolved Hide resolved
};
64 changes: 64 additions & 0 deletions src/ui/legend/LegendCategories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Box, Grid, makeStyles, Tooltip, Typography } from '@material-ui/core';
import Note from './Note';

function LegendCategories({ data = [], info }) {
const max = 1;
return (
<Grid container direction='column' pb={16} spacing={1}>
{data.map((d, index) => {
const isMax = index === max;
return (
<Row key={d.label + index} isMax={isMax} label={d.label} color={d.color} />
);
})}
<Note>{info}</Note>
</Grid>
);
}

export default LegendCategories;

const useStyles = makeStyles((theme) => ({
root: {
alignItems: 'center',
'&:hover': {
'& $circle': {}
}
},
circle: {
display: 'block',
width: '8px',
height: '8px',
borderRadius: '50%',
position: 'relative',
'&::after': {
position: 'absolute',
display: ({ isMax }) => (isMax ? 'block' : 'none'),
content: '""',
width: '16px',
height: '16px',
border: `2px solid ${theme.palette.grey[900]}`,
transform: 'translate(-30%, -30%)',
borderRadius: '50%',
boxSizing: 'content-box'
}
}
}));

function Row({ label, isMax, color = '#000' }) {
const classes = useStyles({ isMax });

return (
<Grid container item className={classes.root}>
<Tooltip title={isMax ? 'Most representative' : ''} placement='right' arrow>
<Box
mr={1.5}
component='span'
className={classes.circle}
style={{ backgroundColor: color }}
/>
</Tooltip>
<Typography variant='overline'>{label}</Typography>
</Grid>
);
}
42 changes: 42 additions & 0 deletions src/ui/legend/LegendIcon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from 'react';
import { Box, Grid, makeStyles, Typography } from '@material-ui/core';
import Note from './Note';

function LegendIcon({ data = [], info }) {
return (
<Grid container direction='column' pb={16} spacing={1}>
{data.map((d, index) => (
<Row key={d.label + index} label={d.label} icon={d.icon} />
))}
<Note>{info}</Note>
</Grid>
);
}

export default LegendIcon;

const useStyles = makeStyles((theme) => ({
root: {
alignItems: 'center',
'&:hover': {
'& $circle': {}
}
},
icon: {
width: '16px',
height: '16px'
}
}));

function Row({ label, icon }) {
const classes = useStyles();

return (
<Grid container item className={classes.root}>
<Box mr={1.5}>
<img src={icon} className={classes.icon} alt={icon} />
</Box>
<Typography variant='overline'>{label}</Typography>
</Grid>
);
}
97 changes: 97 additions & 0 deletions src/ui/legend/LegendProportion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import React from 'react';
import { Box, Grid, makeStyles, Tooltip, Typography } from '@material-ui/core';
import Note from './Note';

function LegendProportion({ data = {}, info }) {
return (
<Grid container direction='column' pb={16} spacing={1}>
<Row data={data}></Row>
<Note>{info}</Note>
</Grid>
);
}

export default LegendProportion;

const useStyles = makeStyles((theme) => ({
circles: {
position: 'relative'
},
avg: {
width: 12,
height: 2,
position: 'absolute',
// TODO change color
border: `1px solid ${theme.palette.grey[900]}`,
borderRadius: 4,
backgroundColor: theme.palette.grey[900],
right: 0,
boxSizing: 'border-box'
}
}));

function Row({ data: { max, min, avg, values = [] } }) {
const classes = useStyles();

const gap = (max + min) / 4;

const avgPerc = (avg / (max + min)) * 100;

const step1 = min + gap;
const step2 = max - gap;

return (
<Grid container item direction='row' spacing={2}>
<Grid container item xs={6} justify='flex-end' className={classes.circles}>
<Circle index={0}></Circle>
<Circle index={1}></Circle>
<Circle index={2}></Circle>
<Circle index={3}></Circle>
<Tooltip title={'AVG: ' + avg} placement='top' arrow>
<Box className={classes.avg} style={{ bottom: `${avgPerc}%` }} />
</Tooltip>
</Grid>
<Grid container item direction='column' justify='space-between' xs={6} spacing={1}>
<Grid item>
<Typography variant='overline'>Max: {max}</Typography>
</Grid>
<Grid item>
<Typography variant='overline'>{step2}</Typography>
</Grid>
<Grid item>
<Typography variant='overline'>{step1}</Typography>
</Grid>
<Grid item>
<Typography variant='overline'>Min: {min}</Typography>
</Grid>
</Grid>
</Grid>
);
}

const useStylesCircle = makeStyles((theme) => ({
root: {
border: `solid 1px ${theme.palette.grey[100]}`,
backgroundColor: theme.palette.grey[50],
borderRadius: '50%',
position: 'absolute',
right: 0,
bottom: 0
}
}));

function Circle({ index = 0 }) {
const classes = useStylesCircle();

const sizes = {
0: 96,
1: 72,
2: 48,
3: 24
};

const width = sizes[index];
const height = sizes[index];

return <Box component='span' className={classes.root} style={{ width, height }}></Box>;
}
101 changes: 101 additions & 0 deletions src/ui/legend/LegendRamp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import React from 'react';
import { Box, Grid, makeStyles, Tooltip, Typography } from '@material-ui/core';
import Note from './Note';

function LegendRamp({ data = {}, info }) {
return (
<Grid container direction='column' pb={16} spacing={1}>
<Row data={data} />
<Note>{info}</Note>
</Grid>
);
}

export default LegendRamp;

const useStyles = makeStyles((theme) => ({
step: {
height: 8
},
avg: {
width: 2,
height: 12,
position: 'absolute',
// TODO change color
border: `1px solid ${theme.palette.common.white}`,
transform: 'translateY(1px)',
backgroundColor: theme.palette.grey[900]
}
}));

function Row({ data: { max, min, avg, values = [] } }) {
const classes = useStyles();

const avgPerc = (avg / (max + min)) * 100;

const hasStep = values.length > 2;

return (
<Grid container item direction='column' spacing={1}>
<Grid container item>
{!hasStep
? <StepsContinuous values={values} />
: <StepsDiscontinuous values={values} max={max} />}
</Grid>
<Tooltip title={'AVG: ' + avg} placement='top' arrow>
<Box className={classes.avg} style={{ left: `${avgPerc}%` }} />
</Tooltip>
<Grid container item justify='space-between'>
<Typography variant='overline'>{min}</Typography>
<Typography variant='overline'>{max}</Typography>
</Grid>
</Grid>
);
}

const useStylesStepsContinuous = makeStyles((theme) => ({
step: {
height: 8,
borderRadius: 4
}
}));

function StepsContinuous({ values = [] }) {
const classes = useStylesStepsContinuous();

const backgroundImage = `linear-gradient(to right, ${values.map(value => value.color).join(', ')})`;

return <Grid item xs className={classes.step} style={{ backgroundImage }} />;
}

const useStylesStepsDiscontinuous = makeStyles((theme) => ({
step: {
height: 8,
'&:first-child': {
borderRadius: '4px 0 0 4px'
},
'&:last-child': {
borderRadius: '0 4px 4px 0'
}
}
}));

function StepsDiscontinuous({ values = [], max }) {
const classes = useStylesStepsDiscontinuous();

return values.map((value, index) => (
<Tooltip
key={index}
title={value.value + ' - ' + (values[index + 1]?.value || max)}
placement='top'
arrow
>
<Grid
item
xs
className={classes.step}
style={{ backgroundColor: value.color }}
/>
</Tooltip>
));
}
Loading