Skip to content

Commit b45af28

Browse files
committed
Add Vote Proposal card layout
1 parent 7937cac commit b45af28

File tree

9 files changed

+318
-2
lines changed

9 files changed

+318
-2
lines changed

src/components/v2/Icon/icons/check.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@ import * as React from 'react';
22
import { SVGProps } from 'react';
33

44
const SvgCheck = (props: SVGProps<SVGSVGElement>) => (
5-
<svg viewBox="0 0 65 64" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
5+
<svg
6+
viewBox="0 0 65 64"
7+
fill="none"
8+
xmlns="http://www.w3.org/2000/svg"
9+
strokeWidth={4}
10+
{...props}
11+
>
612
<circle cx={32.5} cy={32} r={24} fill="currentColor" />
713
<path
814
d="m41.5 26-12 12-6-6"
915
stroke="#fff"
10-
strokeWidth={4}
16+
strokeWidth="inherit"
1117
strokeLinecap="round"
1218
strokeLinejoin="round"
1319
/>

src/components/v2/Icon/icons/dots.tsx

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import * as React from 'react';
2+
import { SVGProps } from 'react';
3+
4+
const SvgDots = (props: SVGProps<SVGSVGElement>) => (
5+
<svg
6+
width="21"
7+
height="4"
8+
viewBox="0 0 21 4"
9+
fill="none"
10+
xmlns="http://www.w3.org/2000/svg"
11+
{...props}
12+
>
13+
<circle cx="10.5" cy="2" r="2" fill="currentColor" />
14+
<circle cx="18.5" cy="2" r="2" fill="currentColor" />
15+
<circle cx="2.5" cy="2" r="2" fill="currentColor" />
16+
</svg>
17+
);
18+
19+
export default SvgDots;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import * as React from 'react';
2+
import { SVGProps } from 'react';
3+
4+
const SvgExclamation = (props: SVGProps<SVGSVGElement>) => (
5+
<svg viewBox="0 0 3 18" fill="none" xmlns="http://www.w3.org/2000/svg" {...props}>
6+
<circle cx="1.5" cy="16.5" r="1.5" fill="currentColor" />
7+
<rect x="0.5" width="2" height="12" rx="1" fill="currentColor" />
8+
</svg>
9+
);
10+
11+
export default SvgExclamation;

src/components/v2/Icon/icons/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ export { default as checkInline } from './checkInline';
3535
export { default as mark } from './mark';
3636
export { default as arrowShaft } from './arrowShaft';
3737
export { default as notice } from './notice';
38+
export { default as dots } from './dots';
39+
export { default as exclamation } from './exclamation';
3840

3941
// Coin icons
4042
export { default as aave } from './coins/aave';
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react';
2+
import { withThemeProvider, withCenterStory } from 'stories/decorators';
3+
import { VoteProposalUi } from '.';
4+
5+
export default {
6+
title: 'Components/VoteProposalUi',
7+
decorators: [withThemeProvider, withCenterStory({ width: 600 })],
8+
parameters: {
9+
backgrounds: {
10+
default: 'Default',
11+
},
12+
},
13+
};
14+
15+
export const Active = () => <VoteProposalUi status="active" />;
16+
export const Queued = () => <VoteProposalUi status="queued" />;
17+
export const ReadyToExecute = () => <VoteProposalUi status="readyToExecute" />;
18+
export const Executed = () => <VoteProposalUi status="executed" />;
19+
export const Cancelled = () => <VoteProposalUi status="cancelled" />;
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/** @jsxImportSource @emotion/react */
2+
import React from 'react';
3+
import Paper from '@mui/material/Paper';
4+
import Grid from '@mui/material/Grid';
5+
import Typography from '@mui/material/Typography';
6+
7+
import { Icon } from '../Icon';
8+
import { useStyles } from './styles';
9+
10+
type Status = 'active' | 'queued' | 'readyToExecute' | 'executed' | 'cancelled';
11+
12+
interface IStatusCard {
13+
status: Status;
14+
}
15+
16+
const StatusCard: React.FC<IStatusCard> = ({ status }) => {
17+
const styles = useStyles();
18+
19+
switch (status) {
20+
case 'active':
21+
return (
22+
<>
23+
<Typography css={styles.statusText} variant="body2">
24+
stats
25+
</Typography>
26+
</>
27+
);
28+
case 'queued':
29+
return (
30+
<>
31+
<div css={[styles.iconWrapper, styles.iconDotsWrapper]}>
32+
<Icon css={styles.icon} name="dots" />
33+
</div>
34+
<Typography css={styles.statusText} variant="body2">
35+
Queue
36+
</Typography>
37+
</>
38+
);
39+
case 'readyToExecute':
40+
return (
41+
<>
42+
<div css={[styles.iconWrapper, styles.iconInfoWrapper]}>
43+
<Icon css={styles.icon} name="exclamation" />
44+
</div>
45+
<Typography css={styles.statusText} variant="body2">
46+
Ready to execute
47+
</Typography>
48+
</>
49+
);
50+
case 'executed':
51+
return (
52+
<>
53+
<div css={[styles.iconWrapper, styles.iconMarkWrapper]}>
54+
<Icon css={[styles.icon, styles.iconCheck]} name="mark" />
55+
</div>
56+
<Typography css={styles.statusText} variant="body2">
57+
Executed
58+
</Typography>
59+
</>
60+
);
61+
default:
62+
case 'cancelled':
63+
return (
64+
<>
65+
<div css={[styles.iconWrapper, styles.iconCloseWrapper]}>
66+
<Icon css={styles.icon} name="close" />
67+
</div>
68+
<Typography css={styles.statusText} variant="body2">
69+
Cancelled
70+
</Typography>
71+
</>
72+
);
73+
}
74+
};
75+
76+
interface IVoteProposalUiProps {
77+
className?: string;
78+
status: Status;
79+
}
80+
81+
export const VoteProposalUi: React.FC<IVoteProposalUiProps> = ({ className, status }) => {
82+
const styles = useStyles();
83+
return (
84+
<Paper className={className} css={styles.root}>
85+
<Grid container>
86+
<Grid css={[styles.gridItem, styles.gridItemLeft]} item xs={12} sm={8}>
87+
<div css={styles.cardHeader}>
88+
<div css={styles.cardBadges}>
89+
<Typography
90+
variant="small2"
91+
color="textPrimary"
92+
css={[styles.cardBadgeItem, styles.cardBadgeNumber]}
93+
>
94+
#57
95+
</Typography>
96+
<Typography
97+
variant="small2"
98+
color="textPrimary"
99+
css={[styles.cardBadgeItem, styles.cardBadgeActive]}
100+
>
101+
Active
102+
</Typography>
103+
</div>
104+
105+
<Typography variant="small2">Not voted</Typography>
106+
</div>
107+
108+
<Typography variant="h4" css={styles.cardTitle}>
109+
Buy back and burn and Tokenomic contribution finised soon
110+
</Typography>
111+
112+
<div css={styles.cardFooter}>
113+
<Typography variant="small2">
114+
Active until:
115+
<Typography variant="small2" color="textPrimary">
116+
27 Jun 13:54
117+
</Typography>
118+
</Typography>
119+
120+
<Typography color="textPrimary" variant="small2">
121+
27h : 13m : 54s
122+
</Typography>
123+
</div>
124+
</Grid>
125+
<Grid css={[styles.gridItem, styles.gridItemRight]} item xs={12} sm={4}>
126+
<StatusCard status={status} />
127+
</Grid>
128+
</Grid>
129+
</Paper>
130+
);
131+
};
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
import { css } from '@emotion/react';
2+
import { alpha, useTheme } from '@mui/material';
3+
4+
export const useStyles = () => {
5+
const theme = useTheme();
6+
7+
return {
8+
root: css`
9+
padding-top: 0;
10+
padding-bottom: 0;
11+
${theme.breakpoints.down('sm')} {
12+
padding-left: 0;
13+
padding-right: 0;
14+
}
15+
`,
16+
gridItem: css`
17+
padding: ${theme.spacing(6, 0)};
18+
${theme.breakpoints.down('sm')} {
19+
padding-left: ${theme.spacing(6)};
20+
padding-right: ${theme.spacing(6)};
21+
}
22+
`,
23+
gridItemLeft: css`
24+
padding-right: ${theme.spacing(6)};
25+
display: flex;
26+
flex-direction: column;
27+
justify-content: space-between;
28+
`,
29+
cardHeader: css`
30+
display: flex;
31+
justify-content: space-between;
32+
`,
33+
cardBadges: css`
34+
/* TODO */
35+
`,
36+
cardBadgeItem: css`
37+
padding: ${theme.spacing(1, 3)};
38+
background-color: ${theme.palette.secondary.light};
39+
border-radius: ${theme.shape.borderRadius.small}px;
40+
margin-right: ${theme.spacing(2)};
41+
`,
42+
cardBadgeNumber: css`
43+
/* TODO */
44+
`,
45+
cardBadgeActive: css`
46+
background-color: ${alpha(theme.palette.interactive.success as string, 0.1)};
47+
color: ${theme.palette.interactive.success};
48+
`,
49+
cardTitle: css`
50+
padding-top: ${theme.spacing(5)};
51+
padding-bottom: ${theme.spacing(6)};
52+
`,
53+
cardFooter: css`
54+
display: flex;
55+
justify-content: space-between;
56+
`,
57+
gridItemRight: css`
58+
padding-left: ${theme.spacing(6)};
59+
border-left: 1px solid ${theme.palette.secondary.light};
60+
display: flex;
61+
flex-direction: column;
62+
align-items: center;
63+
justify-content: center;
64+
${theme.breakpoints.down('sm')} {
65+
flex-direction: row;
66+
border-left: none;
67+
border-top: 1px solid ${theme.palette.secondary.light};
68+
padding-top: ${theme.spacing(10)};
69+
padding-bottom: ${theme.spacing(10)};
70+
}
71+
`,
72+
73+
/* StatusCard styles */
74+
statusText: css`
75+
color: ${theme.palette.text.primary};
76+
text-transform: none;
77+
margin-top: ${theme.spacing(2)};
78+
text-align: center;
79+
${theme.breakpoints.down('sm')} {
80+
margin-top: 0;
81+
margin-left: ${theme.spacing(3)};
82+
}
83+
`,
84+
85+
iconWrapper: css`
86+
border-radius: 50%;
87+
width: ${theme.shape.iconSize.xxLarge}px;
88+
height: ${theme.shape.iconSize.xxLarge}px;
89+
display: flex;
90+
align-items: center;
91+
justify-content: center;
92+
${theme.breakpoints.down('sm')} {
93+
width: ${theme.shape.iconSize.xLarge}px;
94+
height: ${theme.shape.iconSize.xLarge}px;
95+
}
96+
`,
97+
iconDotsWrapper: css`
98+
background-color: ${theme.palette.text.secondary};
99+
`,
100+
iconInfoWrapper: css`
101+
background-color: ${theme.palette.interactive.primary};
102+
`,
103+
iconMarkWrapper: css`
104+
background-color: ${theme.palette.interactive.success};
105+
`,
106+
iconCloseWrapper: css`
107+
background-color: ${theme.palette.interactive.error};
108+
`,
109+
icon: css`
110+
width: ${theme.shape.iconSize.medium}px;
111+
height: ${theme.shape.iconSize.medium}px;
112+
color: white;
113+
${theme.breakpoints.down('sm')} {
114+
width: ${theme.shape.iconSize.small}px;
115+
height: ${theme.shape.iconSize.small}px;
116+
}
117+
`,
118+
iconCheck: css`
119+
background-color: ${theme.palette.interactive.success};
120+
border-radius: 50%;
121+
stroke-width: ${theme.spacing(0.5)};
122+
`,
123+
};
124+
};

src/theme/MuiThemeProvider/muiTheme.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,11 @@ export const SHAPE = {
8888
large: SPACING * 6,
8989
} as any, // our custom types seem to clash with the default MUI types
9090
iconSize: {
91+
small: SPACING * 3,
9192
medium: SPACING * 4,
9293
large: SPACING * 5,
9394
xLarge: SPACING * 6,
95+
xxLarge: SPACING * 10,
9496
},
9597
footerHeight: '56px',
9698
bannerHeight: '56px',

src/types/mui.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@ declare module '@mui/material/styles' {
4545
large: number;
4646
};
4747
iconSize: {
48+
small: number;
4849
medium: number;
4950
large: number;
5051
xLarge: number;
52+
xxLarge: number;
5153
};
5254
footerHeight: string;
5355
bannerHeight: string;

0 commit comments

Comments
 (0)