From 8a668fec3b2b5d59a8722005cd2c3836daf13cba Mon Sep 17 00:00:00 2001 From: Gerard Date: Tue, 29 Oct 2024 10:50:43 +0100 Subject: [PATCH 01/11] saas voting view --- src/components/Process/Header.tsx | 24 ++-- src/components/Process/View.tsx | 17 ++- src/elements/Layout.tsx | 11 +- src/theme/colors.ts | 42 +++++++ src/theme/components/Questions.ts | 198 ++++++++++++++++++++++++++++++ src/theme/components/Tabs.ts | 33 +++++ src/theme/components/card.ts | 22 ++++ src/theme/index.ts | 2 + 8 files changed, 331 insertions(+), 18 deletions(-) create mode 100644 src/theme/components/Questions.ts diff --git a/src/components/Process/Header.tsx b/src/components/Process/Header.tsx index 5dfd05836..747843a3a 100644 --- a/src/components/Process/Header.tsx +++ b/src/components/Process/Header.tsx @@ -1,20 +1,14 @@ import { InfoIcon, WarningIcon } from '@chakra-ui/icons' -import { Box, Button, Flex, Icon, Image, Text, Tooltip } from '@chakra-ui/react' -import { - ElectionDescription, - ElectionSchedule, - ElectionStatusBadge, - ElectionTitle, - OrganizationName, -} from '@vocdoni/chakra-components' +import { Box, Flex, Icon, IconButton, Image, Text, Tooltip } from '@chakra-ui/react' +import { ElectionDescription, ElectionSchedule, ElectionStatusBadge, ElectionTitle } from '@vocdoni/chakra-components' import { useClient, useElection, useOrganization } from '@vocdoni/react-providers' import { CensusType, ElectionStatus, InvalidElection, PublishedElection, Strategy } from '@vocdoni/sdk' import { ReactNode, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' -import { Link } from 'react-router-dom' +import { MdKeyboardArrowLeft } from 'react-icons/md' +import { Link as ReactRouterLink } from 'react-router-dom' import { useReadMoreMarkdown } from '~components/Layout/use-read-more' import { ShareModalButton } from '~components/Share' -import { GoBack } from '~theme/icons' import { ActionsMenu } from './ActionsMenu' import { StampIcon } from './Census/StampIcon' import { CreatedBy } from './CreatedBy' @@ -58,10 +52,12 @@ const ProcessHeader = () => { return ( {showOrgInformation && ( - + } + /> )} {election?.header && ( diff --git a/src/components/Process/View.tsx b/src/components/Process/View.tsx index 9a8b426a9..e521aeb6e 100644 --- a/src/components/Process/View.tsx +++ b/src/components/Process/View.tsx @@ -106,8 +106,19 @@ export const ProcessView = () => { }, [formErrors]) return ( - - + +
{election instanceof PublishedElection && election?.streamUri && ( @@ -143,7 +154,7 @@ export const ProcessView = () => { - + { setFormErrors(args) diff --git a/src/elements/Layout.tsx b/src/elements/Layout.tsx index 939a12849..b0dcfa73a 100644 --- a/src/elements/Layout.tsx +++ b/src/elements/Layout.tsx @@ -7,7 +7,16 @@ const Layout = () => { const location = useLocation() return ( - + diff --git a/src/theme/colors.ts b/src/theme/colors.ts index f99d57e37..8bea07270 100644 --- a/src/theme/colors.ts +++ b/src/theme/colors.ts @@ -5,6 +5,7 @@ export const colorsBase = { grayish: '#2B2A33', dark: '#1A202C', }, + gradient: 'linear-gradient(to right, #546E39, #2E441A)', gray: { light: '#E2E8F0', normal: '#718096', @@ -153,6 +154,43 @@ export const colors = { }, }, org_text_secondary: colorsBase.gray.normal, + + process: { + aside: { + bg: colorsBase.gradient, + color: colorsBase.white.pure, + vote_btn_color: colorsBase.black, + vote_btn_bg: colorsBase.primary, + aside_footer_mbl_border: colorsBase.white.dark, + verify_link: colorsBase.white.pure, + }, + questions: { + alert: { + bg: colorsBase.primary, + color: colorsBase.white.pure, + link_color: colorsBase.black, + link_bg: colorsBase.white.pure, + }, + question_selected: { + bg: colorsBase.primary, + color: colorsBase.white.pure, + }, + hover: { + light: colorsBase.white.pure, + dark: colorsBase.blue.grayish, + }, + description: colorsBase.gray.normal, + title: { + ligth: colorsBase.primary, + dark: colorsBase.white.pure, + }, + }, + tabs: { + active_bg: colorsBase.gray.light, + hover_bg: colorsBase.gray.light, + border_bottom_list: colorsBase.gray.light, + }, + }, process_create: { bg: { dark: colorsBase.blue.dark, @@ -174,6 +212,10 @@ export const colors = { text_secondary: colorsBase.gray.normal, question_index: colorsBase.primary, }, + process_view: { + bg_light: colorsBase.white.dark, + bg_dark: colorsBase.blue.dark, + }, tab: { variant: { diff --git a/src/theme/components/Questions.ts b/src/theme/components/Questions.ts new file mode 100644 index 000000000..4879d9eb2 --- /dev/null +++ b/src/theme/components/Questions.ts @@ -0,0 +1,198 @@ +import { createMultiStyleConfigHelpers } from '@chakra-ui/react' +import { questionsAnatomy } from '@vocdoni/chakra-components' +import checkIcon from '/assets/check-icon.png' + +const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(questionsAnatomy) + +const baseStyle = definePartsStyle({ + alert: { + px: { base: 3, sm: 5 }, + py: 7, + mb: '30px', + borderRadius: '8px', + color: 'process.questions.alert.color', + bgColor: 'process.questions.alert.bg', + display: 'grid', + columnGap: 4, + justifyContent: 'center', + alignItems: 'center', + gridTemplateColumns: 'auto 1fr', + gridTemplateRows: 'auto auto', + boxShadow: 'var(--box-shadow-darker)', + border: 'none', + + '& span': { + color: 'white', + ml: { base: 2, lg: 10, xl: 2 }, + gridRow: '1/3', + gridColumn: '1/2', + }, + }, + + alertTitle: { + fontSize: 'lg', + mb: 3, + }, + + alertDescription: { + display: 'flex', + gap: 2, + flexDirection: { base: 'column', lg2: 'row' }, + justifyContent: 'center', + alignItems: { md: 'center' }, + whiteSpace: { base: 'pre-wrap', lg2: 'nowrap' }, + }, + + alertLink: { + display: 'block', + w: '100%', + px: 2, + py: 1, + textOverflow: 'ellipsis', + overflow: 'hidden', + whiteSpace: 'nowrap', + color: 'process.questions.alert.link_color', + backgroundColor: 'process.questions.alert.link_bg', + borderRadius: 'md', + fontSize: 'sm', + + _hover: { + textDecoration: 'none', + }, + }, + + wrapper: { + '& > form': { + display: 'flex', + flexDirection: 'column', + gap: 10, + }, + }, + + question: { + width: { base: 'full', xl: '80%' }, + m: 0, + mx: 'auto', + + '& > div': { + display: 'flex', + flexDirection: 'column', + overflow: 'hidden', + }, + }, + + title: { + display: 'block', + textAlign: 'start', + lineHeight: 1.3, + fontSize: 'xl !important', + color: 'process.questions.title.light', + + _dark: { + color: 'process.questions.title.dark', + }, + }, + + description: { + px: 1, + color: 'process.questions.description', + textAlign: 'start', + fontSize: 'md !important', + }, + + stack: { + '& label': { + borderRadius: 'lg', + overflow: 'hidden', + display: 'flex', + alignItems: 'center', + gap: 2, + w: { lg2: '99%' }, + _hover: { + bgColor: 'process.questions.hover.light', + + _dark: { + bgColor: 'process.questions.hover.dark', + }, + }, + + '& span:nth-of-type(1)': { + display: { base: 'none', md: 'block' }, + position: 'absolute', + width: '30px', + height: '30px', + background: 'transparent', + ml: '10px', + borderRadius: 'none', + + '&[data-checked=""]': { + '&:before': { + display: 'none', + bgColor: 'transparent', + }, + + background: 'process.questions.question_selected.bg', + borderColor: 'white', + borderWidth: '1px', + bgSize: '15px', + bgRepeat: 'no-repeat', + bgPosition: 'center', + bgImage: checkIcon, + + _hover: { + border: 'none', + background: 'process.questions.question_selected.bg', + borderColor: 'process.questions.question_selected.bg', + bgSize: '15px', + bgRepeat: 'no-repeat', + bgPosition: 'center', + bgImage: checkIcon, + }, + }, + + '&[data-disabled=""]': { + bgColor: 'white !important', + border: 'none !important', + }, + }, + '& span:nth-of-type(2)': { + p: 2, + pl: { md: 12 }, + m: 0, + border: '1px solid lightgray', + w: '100%', + borderRadius: 'lg', + }, + + '& input:checked ~ span:nth-of-type(2)': { + color: 'process.questions.question_selected.color', + bgColor: 'process.questions.question_selected.bg', + w: '100%', + }, + }, + }, + + radio: { + borderRadius: 'full !important', + }, + + checkbox: { + // Checkbox label style + '& span:nth-of-type(2)': { + display: 'flex', + flexDir: 'row', + justifyContent: 'space-between', + justifyItems: 'center', + alignItems: 'center', + }, + }, + + error: { + display: 'flex', + justifyContent: 'center', + }, +}) + +export const ElectionQuestions = defineMultiStyleConfig({ + baseStyle, +}) diff --git a/src/theme/components/Tabs.ts b/src/theme/components/Tabs.ts index 46114c17f..edc7b5a30 100644 --- a/src/theme/components/Tabs.ts +++ b/src/theme/components/Tabs.ts @@ -109,9 +109,42 @@ const card = definePartsStyle({ p: 0, }, }) +const process = definePartsStyle({ + root: {}, + tabpanel: { + px: { base: 0, sm: 4 }, + }, + tab: { + position: 'relative', + whiteSpace: 'nowrap', + color: 'process.tabs.color', + fontWeight: 'normal', + borderTopRadius: 'md', + fontSize: 'lg', + + _hover: { + bgColor: 'process.tabs.hover', + }, + _active: { + bgColor: 'process.tabs.active_bg', + }, + _selected: { + fontWeight: 'bold', + borderBottom: '1px solid', + }, + }, + tablist: { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + borderBottom: '1px solid', + borderColor: 'process.tabs.border_bottom_list', + }, +}) const variants = { card, + process, } export const Tabs = defineMultiStyleConfig({ variants }) diff --git a/src/theme/components/card.ts b/src/theme/components/card.ts index 771ed6cc7..b23279677 100644 --- a/src/theme/components/card.ts +++ b/src/theme/components/card.ts @@ -485,5 +485,27 @@ export const Card = defineMultiStyleConfig({ }, }, }, + aside: { + container: { + direction: 'column', + justifyContent: 'center', + alignItems: 'center', + px: { base: 6, lg2: 10 }, + py: { base: 6, lg2: 10 }, + w: 'full', + gap: 4, + mt: { md: 7 }, + mb: { base: 7, md: 0 }, + color: 'process.aside.color', + background: 'process.aside.bg', + boxShadow: 'var(--box-shadow-banner)', + borderRadius: 'lg', + fontSize: 'text', + + '& a': { + color: 'process.aside.color', + }, + }, + }, }, }) diff --git a/src/theme/index.ts b/src/theme/index.ts index c63666245..da9726a9c 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -21,6 +21,7 @@ import { Text } from './components/text' import { Textarea } from './components/textarea' import { editor } from './editor' import { spacing } from './space' +import { ElectionQuestions } from './components/Questions' export const theme = extendTheme(vtheme, { styles: { @@ -42,6 +43,7 @@ export const theme = extendTheme(vtheme, { Card, Checkbox, ElectionTitle, + ElectionQuestions, Form, Heading, Input, From 02854636d755b99d838d86bc21cfaed8c5211970 Mon Sep 17 00:00:00 2001 From: Gerard Date: Tue, 29 Oct 2024 11:21:52 +0100 Subject: [PATCH 02/11] dark disabled question radio bg and results --- src/theme/colors.ts | 12 ++++ src/theme/components/Questions.ts | 8 ++- src/theme/components/results.ts | 92 +++++++++++++++++++++++++++++++ src/theme/index.ts | 2 + 4 files changed, 112 insertions(+), 2 deletions(-) create mode 100644 src/theme/components/results.ts diff --git a/src/theme/colors.ts b/src/theme/colors.ts index 8bea07270..bf29c4df0 100644 --- a/src/theme/colors.ts +++ b/src/theme/colors.ts @@ -179,12 +179,24 @@ export const colors = { light: colorsBase.white.pure, dark: colorsBase.blue.grayish, }, + disabled: { + light: colorsBase.white.pure, + dark: colorsBase.blue.grayish, + }, description: colorsBase.gray.normal, title: { ligth: colorsBase.primary, dark: colorsBase.white.pure, }, }, + results: { + alert_bg: colorsBase.primary, + alert_color: colorsBase.white.pure, + bg: colorsBase.gray.light, + description: colorsBase.gray.normal, + progressbar_bg: colorsBase.gray.light, + title: colorsBase.primary, + }, tabs: { active_bg: colorsBase.gray.light, hover_bg: colorsBase.gray.light, diff --git a/src/theme/components/Questions.ts b/src/theme/components/Questions.ts index 4879d9eb2..5697c2a0c 100644 --- a/src/theme/components/Questions.ts +++ b/src/theme/components/Questions.ts @@ -151,8 +151,12 @@ const baseStyle = definePartsStyle({ }, '&[data-disabled=""]': { - bgColor: 'white !important', - border: 'none !important', + bgColor: 'process.questions.disabled.light', + border: 'none', + + _dark: { + bgColor: 'process.questions.disabled.dark', + }, }, }, '& span:nth-of-type(2)': { diff --git a/src/theme/components/results.ts b/src/theme/components/results.ts new file mode 100644 index 000000000..a5632b094 --- /dev/null +++ b/src/theme/components/results.ts @@ -0,0 +1,92 @@ +import { createMultiStyleConfigHelpers } from '@chakra-ui/react' +import { resultsAnatomy } from '@vocdoni/chakra-components' + +const { defineMultiStyleConfig, definePartsStyle } = createMultiStyleConfigHelpers(resultsAnatomy) + +const baseStyle = definePartsStyle({ + question: { + p: 4, + width: { base: 'full', xl: '80%' }, + m: 0, + mx: 'auto', + + '& > div:nth-of-type(1)': { + '& > p': { + fontSize: 'xl2', + mb: 5, + lineHeight: 1.3, + textAlign: 'start', + }, + }, + '& > div:nth-of-type(2) > div': { + display: 'flex', + flexDirection: { base: 'column', md: 'row' }, + alignItems: { base: 'center', md: 'start' }, + gap: 3, + mb: 5, + + '& p:nth-of-type(1)': { + maxW: '100%', + flexBasis: '33%', + flexGrow: 1, + color: 'process.results.description', + }, + '& p:nth-of-type(2)': { + mx: 4, + }, + '& div': { + w: 'full', + flexBasis: '33%', + flexGrow: 0, + flexShrink: 0, + h: 6, + borderRadius: 'md', + bgColor: 'results.progressbar_bg', + overflow: 'hidden', + position: 'relative', + + '& div': { + h: 6, + background: { + base: `linear-gradient(to right, #789D53 0%, #546E39 50%, #2E441A 100%) left/var(--p,100%) fixed;`, + md: `linear-gradient(to right, #789D53 65%, #546E39 79.5%, #2E441A 94%) left/var(--p,100%) fixed;`, + xl: `linear-gradient(to right, #789D53 46%, #546E39 56%, #2E441A 66%) left/var(--p,100%) fixed;`, + }, + }, + }, + + '& > div:nth-of-type(2) > div:last-of-type': { + mb: 0, + }, + }, + }, + + secret: { + px: 8, + py: 8, + my: 4, + color: 'process.results.alert_color', + bgColor: 'process.results.alert_bg', + borderRadius: 'lg', + whiteSpace: 'wrap', + }, + + title: { + fontWeight: 700, + fontSize: 'xl', + lineHeight: 7, + color: 'process.results.title', + textAlign: { base: 'center', md: 'start' }, + mb: 3, + }, + + wrapper: { + display: 'flex', + flexDirection: 'column', + gap: 10, + }, +}) + +export const ElectionResults = defineMultiStyleConfig({ + baseStyle, +}) diff --git a/src/theme/index.ts b/src/theme/index.ts index 723b5ab75..8a918803b 100644 --- a/src/theme/index.ts +++ b/src/theme/index.ts @@ -22,6 +22,7 @@ import { Textarea } from './components/textarea' import { editor } from './editor' import { spacing } from './space' import { ElectionQuestions } from './components/Questions' +import { ElectionResults } from './components/results' export const theme = extendTheme(vtheme, { config: { @@ -48,6 +49,7 @@ export const theme = extendTheme(vtheme, { Checkbox, ElectionTitle, ElectionQuestions, + ElectionResults, Form, Heading, Input, From e2131ca0caedc5a18a55c5cd0b004d6cce8a1661 Mon Sep 17 00:00:00 2001 From: Gerard Date: Tue, 29 Oct 2024 16:47:27 +0100 Subject: [PATCH 03/11] read more issue --- src/components/Dashboard/ProcessView.tsx | 9 +++- src/components/Layout/use-read-more.tsx | 62 ++++++++++++++---------- src/components/Organization/Header.tsx | 13 ++--- src/components/Process/CardDetailed.tsx | 2 +- src/components/Process/Header.tsx | 14 +++--- src/theme/colors.ts | 7 +++ src/theme/components/Questions.ts | 4 ++ 7 files changed, 69 insertions(+), 42 deletions(-) diff --git a/src/components/Dashboard/ProcessView.tsx b/src/components/Dashboard/ProcessView.tsx index 27cff0d09..5bc40ee67 100644 --- a/src/components/Dashboard/ProcessView.tsx +++ b/src/components/Dashboard/ProcessView.tsx @@ -47,7 +47,7 @@ import { Routes } from '~src/router/routes' export const ProcessView = () => { const { setTitle, setBack } = useOutletContext() const { id, election, participation, turnout } = useElection() - const { ReadMoreMarkdownWrapper } = useReadMoreMarkdown('rgba(242, 242, 242, 0)', 'rgba(242, 242, 242, 1)', 600, 20) + const { ReadMoreMarkdownWrapper } = useReadMoreMarkdown(600, 20) const votingLink = `${document.location.origin}${generatePath(Routes.processes.view, { id })}` const { hasCopied, onCopy } = useClipboard(votingLink) @@ -66,7 +66,12 @@ export const ProcessView = () => { {election instanceof PublishedElection && election.description && ( - + )} diff --git a/src/components/Layout/use-read-more.tsx b/src/components/Layout/use-read-more.tsx index 2934bb0b9..cd434dc53 100644 --- a/src/components/Layout/use-read-more.tsx +++ b/src/components/Layout/use-read-more.tsx @@ -2,17 +2,11 @@ import { Box, Button } from '@chakra-ui/react' import { useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -export const useReadMoreMarkdown = ( - colorFrom: string, - colorTo: string, - containerMaxHeightPx: number, - tantPerCentGradient?: number -) => { +export const useReadMoreMarkdown = (containerMaxHeightPx: number, tantPerCentGradient?: number) => { const { t } = useTranslation() const containerRef = useRef(null) const [isTruncated, setIsTruncated] = useState(false) const [readMore, setReadMore] = useState(false) - const handleReadMore = () => setReadMore((prev) => !prev) useEffect(() => { @@ -26,15 +20,22 @@ export const useReadMoreMarkdown = ( } }, []) - const ReadMoreMarkdownWrapper = ({ children, from, to, ...props }: any) => ( - { + return ( + - {children} - - ) + background: isTruncated && readMore ? `linear-gradient(to bottom, ${fromLight} 0%, ${toLight} 100%)` : '', + }} + _dark={{ + _before: { + content: '""', + position: 'absolute', + height: isTruncated + ? `${(containerMaxHeightPx * (tantPerCentGradient ? tantPerCentGradient : containerMaxHeightPx)) / 100}px` + : '0', + width: '100%', + bottom: 0, + background: isTruncated && readMore ? `linear-gradient(to bottom, ${fromDark} 0%, ${toDark} 100%)` : '', + }, + }} + > + {children} + + ) + } const ReadMoreMarkdownButton = ({ ...props }: any) => isTruncated ? (