diff --git a/frontend/src/components/DatePicker/Calendar/CalendarContext.tsx b/frontend/src/components/DatePicker/Calendar/CalendarContext.tsx index 0bbd892d66..77b950d5ff 100644 --- a/frontend/src/components/DatePicker/Calendar/CalendarContext.tsx +++ b/frontend/src/components/DatePicker/Calendar/CalendarContext.tsx @@ -17,6 +17,8 @@ import { import { Props as DayzedProps, RenderProps, useDayzed } from 'dayzed' import { inRange } from 'lodash' +import { ThemeColorScheme } from '~theme/foundations/colours' + import { DatePickerProps } from '../DatePicker' import { generateClassNameForDate, @@ -64,6 +66,10 @@ type PassthroughProps = { * Date currently being hovered, if any. */ hoveredDate?: Date + /** + * Color scheme of date input + */ + colorScheme?: ThemeColorScheme } export type UseProvideCalendarProps = Pick & PassthroughProps @@ -122,6 +128,7 @@ const useProvideCalendar = ({ onMouseLeaveCalendar, isDateInRange, hoveredDate, + colorScheme = 'primary', }: UseProvideCalendarProps) => { // Ensure that calculations are always made based on date of initial render, // so component state doesn't suddenly jump at midnight @@ -293,5 +300,6 @@ const useProvideCalendar = ({ onMouseLeaveCalendar, isDateInRange, hoveredDate, + colorScheme, } } diff --git a/frontend/src/components/DatePicker/Calendar/CalendarTodayButton.tsx b/frontend/src/components/DatePicker/Calendar/CalendarTodayButton.tsx index 431f080f75..d3c7d5b2ae 100644 --- a/frontend/src/components/DatePicker/Calendar/CalendarTodayButton.tsx +++ b/frontend/src/components/DatePicker/Calendar/CalendarTodayButton.tsx @@ -6,11 +6,12 @@ import { useCalendar } from './CalendarContext' export const CalendarTodayButton = (): JSX.Element => { const styles = useStyles() - const { handleTodayClick } = useCalendar() + const { handleTodayClick, colorScheme } = useCalendar() return ( - - {displayedInfo.helpText} - - + + + + + + {displayedInfo.helpText} + + + ) } diff --git a/frontend/src/features/public-form/components/FormEndPage/FormEndPage.stories.tsx b/frontend/src/features/public-form/components/FormEndPage/FormEndPage.stories.tsx index dc2297e344..5e57311ce4 100644 --- a/frontend/src/features/public-form/components/FormEndPage/FormEndPage.stories.tsx +++ b/frontend/src/features/public-form/components/FormEndPage/FormEndPage.stories.tsx @@ -1,5 +1,7 @@ import { Meta, Story } from '@storybook/react' +import { FormColorTheme } from '~shared/types' + import { getMobileViewParameters } from '~utils/storybook' import { FormEndPage, FormEndPageProps } from './FormEndPage' @@ -33,6 +35,36 @@ Default.args = { handleSubmitFeedback: (inputs) => console.log(inputs), } +export const ColorThemeGreen = Template.bind({}) +ColorThemeGreen.args = { + ...Default.args, + colorTheme: FormColorTheme.Green, +} + +export const ColorThemeGrey = Template.bind({}) +ColorThemeGrey.args = { + ...Default.args, + colorTheme: FormColorTheme.Grey, +} + +export const ColorThemeBrown = Template.bind({}) +ColorThemeBrown.args = { + ...Default.args, + colorTheme: FormColorTheme.Brown, +} + +export const ColorThemeRed = Template.bind({}) +ColorThemeRed.args = { + ...Default.args, + colorTheme: FormColorTheme.Red, +} + +export const ColorThemeOrange = Template.bind({}) +ColorThemeOrange.args = { + ...Default.args, + colorTheme: FormColorTheme.Orange, +} + export const FeedbackSubmitted = Template.bind({}) FeedbackSubmitted.args = { ...Default.args, diff --git a/frontend/src/features/public-form/components/FormEndPage/FormEndPage.tsx b/frontend/src/features/public-form/components/FormEndPage/FormEndPage.tsx index 150291e578..a11ebfe971 100644 --- a/frontend/src/features/public-form/components/FormEndPage/FormEndPage.tsx +++ b/frontend/src/features/public-form/components/FormEndPage/FormEndPage.tsx @@ -1,6 +1,6 @@ import { Container, Flex, Stack, StackDivider } from '@chakra-ui/react' -import { FormDto } from '~shared/types/form' +import { FormColorTheme, FormDto } from '~shared/types/form' import { SubmissionData } from '~features/public-form/PublicFormContext' @@ -15,11 +15,13 @@ export interface FormEndPageProps { submissionData: SubmissionData handleSubmitFeedback: (inputs: FeedbackFormInput) => void isFeedbackSubmitted: boolean + colorTheme: FormColorTheme } export const FormEndPage = ({ handleSubmitFeedback, isFeedbackSubmitted, + colorTheme, ...endPageProps }: FormEndPageProps): JSX.Element => { return ( @@ -34,9 +36,12 @@ export const FormEndPage = ({ w="100%" divider={} > - + {isFeedbackSubmitted ? null : ( - + )} diff --git a/frontend/src/features/public-form/components/FormEndPage/FormEndPageContainer.tsx b/frontend/src/features/public-form/components/FormEndPage/FormEndPageContainer.tsx index 046306cb85..f150d6c55a 100644 --- a/frontend/src/features/public-form/components/FormEndPage/FormEndPageContainer.tsx +++ b/frontend/src/features/public-form/components/FormEndPage/FormEndPageContainer.tsx @@ -31,6 +31,7 @@ export const FormEndPageContainer = (): JSX.Element | null => { return ( { const prettifiedDateString = useMemo(() => { return format(new Date(submissionData.timeInEpochMs), 'dd MMM yyyy, h:mm a') @@ -74,7 +76,7 @@ export const EndPageBlock = ({ as="a" href={endPage.buttonLink ?? ''} variant="solid" - colorScheme="primary" + colorScheme={`theme-${colorTheme}`} > {endPage.buttonText} diff --git a/frontend/src/features/public-form/components/FormEndPage/components/FeedbackBlock.tsx b/frontend/src/features/public-form/components/FormEndPage/components/FeedbackBlock.tsx index 285bc337b5..b83acccaab 100644 --- a/frontend/src/features/public-form/components/FormEndPage/components/FeedbackBlock.tsx +++ b/frontend/src/features/public-form/components/FormEndPage/components/FeedbackBlock.tsx @@ -1,6 +1,9 @@ +import { useMemo } from 'react' import { Controller, useForm } from 'react-hook-form' import { chakra, Flex, FormControl } from '@chakra-ui/react' +import { FormColorTheme } from '~shared/types/form' + import Button from '~components/Button' import Rating from '~components/Field/Rating' import FormErrorMessage from '~components/FormControl/FormErrorMessage' @@ -14,10 +17,12 @@ export type FeedbackFormInput = { export interface FeedbackBlockProps { onSubmit: (input: FeedbackFormInput) => void + colorTheme?: FormColorTheme } export const FeedbackBlock = ({ onSubmit, + colorTheme = FormColorTheme.Blue, }: FeedbackBlockProps): JSX.Element => { const { control, @@ -28,6 +33,10 @@ export const FeedbackBlock = ({ const handleFormSubmit = handleSubmit((inputs) => onSubmit(inputs)) + const colorScheme = useMemo(() => { + return `theme-${colorTheme}` as const + }, [colorTheme]) + return ( ( - + )} /> {errors.rating?.message} @@ -61,6 +75,7 @@ export const FeedbackBlock = ({ mt="1.5rem" variant="outline" type="submit" + colorScheme={colorScheme} isLoading={isSubmitting} > Submit feedback diff --git a/frontend/src/features/public-form/components/FormFields/FormFields.tsx b/frontend/src/features/public-form/components/FormFields/FormFields.tsx index 4d1af694d5..caae7a3316 100644 --- a/frontend/src/features/public-form/components/FormFields/FormFields.tsx +++ b/frontend/src/features/public-form/components/FormFields/FormFields.tsx @@ -1,11 +1,12 @@ import { useMemo } from 'react' import { FormProvider, SubmitHandler, useForm } from 'react-hook-form' -import { Stack } from '@chakra-ui/react' +import { Box, Stack } from '@chakra-ui/react' import { times } from 'lodash' import { BasicField, FormFieldDto } from '~shared/types/field' import { FormColorTheme, LogicDto } from '~shared/types/form' +import { useIsMobile } from '~hooks/useIsMobile' import Button from '~components/Button' import { FormFieldValues } from '~templates/Field' import { createTableRow } from '~templates/Field/Table/utils/createRow' @@ -27,6 +28,8 @@ export const FormFields = ({ colorTheme, onSubmit, }: FormFieldsProps): JSX.Element => { + const isMobile = useIsMobile() + // TODO: Inject default values is field is also prefilled. const augmentedFormFields = useMemo( () => formFields.map(augmentWithMyInfo), @@ -59,22 +62,28 @@ export const FormFields = ({ return (
- - + + + + + + - +
) diff --git a/frontend/src/features/public-form/components/FormFields/FormFieldsContainer.tsx b/frontend/src/features/public-form/components/FormFields/FormFieldsContainer.tsx index 2d9fcadb55..01ad6a9bbd 100644 --- a/frontend/src/features/public-form/components/FormFields/FormFieldsContainer.tsx +++ b/frontend/src/features/public-form/components/FormFields/FormFieldsContainer.tsx @@ -53,14 +53,7 @@ export const FormFieldsContainer = (): JSX.Element | null => { {isAuthRequired ? null : } - + {renderFields} {isAuthRequired ? null : } diff --git a/frontend/src/features/public-form/components/FormStartPage/FormHeader.tsx b/frontend/src/features/public-form/components/FormStartPage/FormHeader.tsx index f97922444d..d756f1925a 100644 --- a/frontend/src/features/public-form/components/FormStartPage/FormHeader.tsx +++ b/frontend/src/features/public-form/components/FormStartPage/FormHeader.tsx @@ -123,22 +123,33 @@ export const FormHeader = (): JSX.Element | null => { return ( <> - + - + {title ?? 'Loading title'} {estTimeString && ( - + - {estTimeString} + + {estTimeString} + )} {loggedInId ? ( diff --git a/frontend/src/features/public-form/components/PublicFormWrapper.tsx b/frontend/src/features/public-form/components/PublicFormWrapper.tsx index 5b637081c1..65c23049a6 100644 --- a/frontend/src/features/public-form/components/PublicFormWrapper.tsx +++ b/frontend/src/features/public-form/components/PublicFormWrapper.tsx @@ -22,7 +22,13 @@ export const PublicFormWrapper = ({ }, [form, isLoading]) return ( - + {children} ) diff --git a/frontend/src/features/verifiable-fields/components/VerifiableFieldContainer/VerifiableFieldContainer.tsx b/frontend/src/features/verifiable-fields/components/VerifiableFieldContainer/VerifiableFieldContainer.tsx index 9a0a8ec841..b176e64bf8 100644 --- a/frontend/src/features/verifiable-fields/components/VerifiableFieldContainer/VerifiableFieldContainer.tsx +++ b/frontend/src/features/verifiable-fields/components/VerifiableFieldContainer/VerifiableFieldContainer.tsx @@ -1,6 +1,7 @@ import { BiCheck } from 'react-icons/bi' import { Box, Stack } from '@chakra-ui/react' +import { FormColorTheme } from '~shared/types' import { FormFieldWithId } from '~shared/types/field' import Button from '~components/Button' @@ -24,6 +25,7 @@ export interface VerifiableFieldContainerProps */ export const VerifiableFieldContainer = ({ schema, + colorTheme = FormColorTheme.Blue, children, }: VerifiableFieldContainerProps): JSX.Element => { const { @@ -48,6 +50,7 @@ export const VerifiableFieldContainer = ({ isDisabled={isVfnBoxOpen || hasSignature} isLoading={isSendingOtp} onClick={handleVfnButtonClick} + colorScheme={`theme-${colorTheme}`} leftIcon={ hasSignature ? : undefined } diff --git a/frontend/src/templates/Field/Attachment/AttachmentField.tsx b/frontend/src/templates/Field/Attachment/AttachmentField.tsx index 6148935587..d60864a98e 100644 --- a/frontend/src/templates/Field/Attachment/AttachmentField.tsx +++ b/frontend/src/templates/Field/Attachment/AttachmentField.tsx @@ -2,6 +2,7 @@ import { useCallback, useMemo } from 'react' import { Controller, useFormContext } from 'react-hook-form' import { MB } from '~shared/constants/file' +import { FormColorTheme } from '~shared/types' import { VALID_EXTENSIONS } from '~shared/utils/file-validation' import { createAttachmentValidationRules } from '~utils/fieldValidation' @@ -19,6 +20,7 @@ export interface AttachmentFieldProps extends BaseFieldProps { */ export const AttachmentField = ({ schema, + colorTheme = FormColorTheme.Blue, }: AttachmentFieldProps): JSX.Element => { const fieldName = schema._id const validationRules = useMemo( @@ -47,6 +49,7 @@ export const AttachmentField = ({ render={({ field: { onChange, ...rest } }) => ( { - const styles = useMultiStyleConfig(CHECKBOX_THEME_KEY, {}) +export const CheckboxField = ({ + schema, + colorTheme = FormColorTheme.Blue, +}: CheckboxFieldProps): JSX.Element => { + const fieldColorScheme = useMemo( + () => `theme-${colorTheme}` as const, + [colorTheme], + ) + const styles = useMultiStyleConfig(CHECKBOX_THEME_KEY, { + colorScheme: fieldColorScheme, + }) const othersInputName = useMemo( () => `${schema._id}.${CHECKBOX_OTHERS_INPUT_KEY}` as const, @@ -70,6 +81,7 @@ export const CheckboxField = ({ schema }: CheckboxFieldProps): JSX.Element => { {schema.fieldOptions.map((o, idx) => ( { ))} {schema.othersRadioButton ? ( - + { isInvalid={!!get(errors, othersInputName)} > trigger(othersInputName)} {...register(checkboxInputName, validationRules)} /> diff --git a/frontend/src/templates/Field/Date/DateField.tsx b/frontend/src/templates/Field/Date/DateField.tsx index 458bd39d6e..bd48484ab5 100644 --- a/frontend/src/templates/Field/Date/DateField.tsx +++ b/frontend/src/templates/Field/Date/DateField.tsx @@ -1,6 +1,7 @@ import { useCallback, useMemo } from 'react' import { Controller, useFormContext } from 'react-hook-form' +import { FormColorTheme } from '~shared/types' import { DateSelectedValidation } from '~shared/types/field' import { @@ -21,7 +22,10 @@ export interface DateFieldProps extends BaseFieldProps { /** * @precondition Must have a parent `react-hook-form#FormProvider` component. */ -export const DateField = ({ schema }: DateFieldProps): JSX.Element => { +export const DateField = ({ + schema, + colorTheme = FormColorTheme.Blue, +}: DateFieldProps): JSX.Element => { const validationRules = useMemo( () => createDateValidationRules(schema), [schema], @@ -58,7 +62,11 @@ export const DateField = ({ schema }: DateFieldProps): JSX.Element => { name={schema._id} rules={validationRules} render={({ field }) => ( - + )} /> diff --git a/frontend/src/templates/Field/Dropdown/DropdownField.tsx b/frontend/src/templates/Field/Dropdown/DropdownField.tsx index d363d8ee8a..919f67d3a3 100644 --- a/frontend/src/templates/Field/Dropdown/DropdownField.tsx +++ b/frontend/src/templates/Field/Dropdown/DropdownField.tsx @@ -1,6 +1,8 @@ import { useMemo } from 'react' import { Controller, useFormContext } from 'react-hook-form' +import { FormColorTheme } from '~shared/types' + import { createDropdownValidationRules } from '~utils/fieldValidation' import { SingleSelect } from '~components/Dropdown/SingleSelect' @@ -14,7 +16,10 @@ export interface DropdownFieldProps extends BaseFieldProps { /** * @precondition Must have a parent `react-hook-form#FormProvider` component. */ -export const DropdownField = ({ schema }: DropdownFieldProps): JSX.Element => { +export const DropdownField = ({ + schema, + colorTheme = FormColorTheme.Blue, +}: DropdownFieldProps): JSX.Element => { const validationRules = useMemo( () => createDropdownValidationRules(schema), [schema], @@ -30,7 +35,11 @@ export const DropdownField = ({ schema }: DropdownFieldProps): JSX.Element => { name={schema._id} defaultValue="" render={({ field }) => ( - + )} /> diff --git a/frontend/src/templates/Field/Number/NumberField.tsx b/frontend/src/templates/Field/Number/NumberField.tsx index 27a6af0f07..67628f778d 100644 --- a/frontend/src/templates/Field/Number/NumberField.tsx +++ b/frontend/src/templates/Field/Number/NumberField.tsx @@ -1,6 +1,8 @@ import { useMemo } from 'react' import { Controller, useFormContext } from 'react-hook-form' +import { FormColorTheme } from '~shared/types' + import { createNumberValidationRules } from '~utils/fieldValidation' import NumberInput from '~components/NumberInput' @@ -11,7 +13,10 @@ export interface NumberFieldProps extends BaseFieldProps { schema: NumberFieldSchema } -export const NumberField = ({ schema }: NumberFieldProps): JSX.Element => { +export const NumberField = ({ + schema, + colorTheme = FormColorTheme.Blue, +}: NumberFieldProps): JSX.Element => { const validationRules = useMemo( () => createNumberValidationRules(schema), [schema], @@ -29,6 +34,7 @@ export const NumberField = ({ schema }: NumberFieldProps): JSX.Element => { { - const styles = useMultiStyleConfig(RADIO_THEME_KEY, {}) +export const RadioField = ({ + schema, + colorTheme = FormColorTheme.Blue, +}: RadioFieldProps): JSX.Element => { + const fieldColorScheme = useMemo( + () => `theme-${colorTheme}` as const, + [colorTheme], + ) + const styles = useMultiStyleConfig(RADIO_THEME_KEY, { + colorScheme: fieldColorScheme, + }) const othersInputName = useMemo( () => `${schema._id}.${RADIO_OTHERS_INPUT_KEY}` as const, @@ -66,6 +77,7 @@ export const RadioField = ({ schema }: RadioFieldProps): JSX.Element => { // radio themselves get the ref. render={({ field: { ref, onChange, value, ...rest } }) => ( { @@ -86,7 +98,10 @@ export const RadioField = ({ schema }: RadioFieldProps): JSX.Element => { ))} {schema.othersRadioButton ? ( - + Number(value), } -export const RatingField = ({ schema }: RatingFieldProps): JSX.Element => { +export const RatingField = ({ + schema, + colorTheme = FormColorTheme.Blue, +}: RatingFieldProps): JSX.Element => { const validationRules = useMemo( () => createRatingValidationRules(schema), [schema], @@ -50,6 +54,7 @@ export const RatingField = ({ schema }: RatingFieldProps): JSX.Element => { name={schema._id} render={({ field: { value, onChange, ...rest } }) => ( ( - ({ schema, handleSectionEnter }, ref) => { + ({ schema, colorTheme = FormColorTheme.Blue, handleSectionEnter }, ref) => { + const sectionColor = useMemo(() => { + switch (colorTheme) { + case FormColorTheme.Orange: + case FormColorTheme.Red: + return `theme-${colorTheme}.600` as const + default: + return `theme-${colorTheme}.500` as const + } + }, []) + return ( ( > {/* id given so app can scrolled to this section */} - + {schema.title} diff --git a/frontend/src/templates/Field/Section/SectionFieldContainer.tsx b/frontend/src/templates/Field/Section/SectionFieldContainer.tsx index 3c16fb898c..36993090d1 100644 --- a/frontend/src/templates/Field/Section/SectionFieldContainer.tsx +++ b/frontend/src/templates/Field/Section/SectionFieldContainer.tsx @@ -1,3 +1,5 @@ +import { FormColorTheme } from '~shared/types' + import { useFormSections } from '~features/public-form/components/FormFields/FormSectionsContext' import { BaseFieldProps } from '../FieldContainer' @@ -11,6 +13,7 @@ export interface SectionFieldContainerProps extends BaseFieldProps { export const SectionFieldContainer = ({ schema, + colorTheme = FormColorTheme.Blue, }: SectionFieldContainerProps): JSX.Element => { const { sectionRefs, setActiveSectionId } = useFormSections() @@ -18,6 +21,7 @@ export const SectionFieldContainer = ({ setActiveSectionId(schema._id)} /> ) diff --git a/frontend/src/templates/Field/Table/ColumnCell.tsx b/frontend/src/templates/Field/Table/ColumnCell.tsx index cb2287dada..4b2ca3827b 100644 --- a/frontend/src/templates/Field/Table/ColumnCell.tsx +++ b/frontend/src/templates/Field/Table/ColumnCell.tsx @@ -4,6 +4,7 @@ import { UseTableCellProps } from 'react-table' import { FormControl } from '@chakra-ui/react' import { get } from 'lodash' +import { FormColorTheme } from '~shared/types' import { BasicField, Column, @@ -28,17 +29,20 @@ export interface ColumnCellProps extends UseTableCellProps { schemaId: string columnSchema: ColumnDto + colorTheme: FormColorTheme } export interface FieldColumnCellProps { schema: ColumnDto /** Represents `{schemaId}.{rowIndex}.{columnId}` */ inputName: `${string}.${number}.${string}` + colorTheme: FormColorTheme } const ShortTextColumnCell = ({ schema, inputName, + colorTheme, }: FieldColumnCellProps) => { const rules = useMemo(() => createTextValidationRules(schema), [schema]) @@ -49,7 +53,13 @@ const ShortTextColumnCell = ({ control={control} name={inputName} rules={rules} - render={({ field }) => } + render={({ field }) => ( + + )} /> ) } @@ -57,6 +67,7 @@ const ShortTextColumnCell = ({ const DropdownColumnCell = ({ schema, inputName, + colorTheme, }: FieldColumnCellProps) => { const rules = useMemo(() => createDropdownValidationRules(schema), [schema]) @@ -66,7 +77,11 @@ const DropdownColumnCell = ({ rules={rules} defaultValue="" render={({ field }) => ( - + )} /> ) @@ -80,6 +95,7 @@ export const ColumnCell = ({ row, column, columnSchema, + colorTheme, }: ColumnCellProps): JSX.Element => { const isMobile = useIsMobile() const { errors } = useFormState({ name: schemaId }) @@ -93,16 +109,24 @@ export const ColumnCell = ({ switch (columnSchema.columnType) { case BasicField.ShortText: return ( - + ) case BasicField.Dropdown: return ( - + ) default: return null } - }, [columnSchema, inputName]) + }, [colorTheme, columnSchema, inputName]) return ( { +export const TableField = ({ + schema, + colorTheme = FormColorTheme.Blue, +}: TableFieldProps): JSX.Element => { const isMobile = useIsMobile() const columnsData = useMemo(() => { @@ -85,7 +90,7 @@ export const TableField = ({ schema }: TableFieldProps): JSX.Element => { {...getTableProps()} variant="column-stripe" size="sm" - colorScheme="primary" + colorScheme={`theme-${colorTheme}`} > {headerGroups.map((headerGroup) => ( @@ -117,6 +122,7 @@ export const TableField = ({ schema }: TableFieldProps): JSX.Element => { {cell.render('Cell', { schemaId: schema._id, columnSchema: schema.columns[j], + colorTheme, })} ))} diff --git a/frontend/src/templates/Field/YesNo/YesNoField.tsx b/frontend/src/templates/Field/YesNo/YesNoField.tsx index b88d0a8cf1..2cf11974c8 100644 --- a/frontend/src/templates/Field/YesNo/YesNoField.tsx +++ b/frontend/src/templates/Field/YesNo/YesNoField.tsx @@ -4,6 +4,8 @@ import { useMemo } from 'react' import { Controller, useFormContext } from 'react-hook-form' +import { FormColorTheme } from '~shared/types' + import { createBaseValidationRules } from '~/utils/fieldValidation' import YesNo from '~components/Field/YesNo' @@ -15,7 +17,10 @@ export interface YesNoFieldProps extends BaseFieldProps { schema: YesNoFieldSchema } -export const YesNoField = ({ schema }: YesNoFieldProps): JSX.Element => { +export const YesNoField = ({ + schema, + colorTheme = FormColorTheme.Blue, +}: YesNoFieldProps): JSX.Element => { const validationRules = useMemo( () => createBaseValidationRules(schema), [schema], @@ -29,7 +34,9 @@ export const YesNoField = ({ schema }: YesNoFieldProps): JSX.Element => { control={control} rules={validationRules} name={schema._id} - render={({ field }) => } + render={({ field }) => ( + + )} /> ) diff --git a/frontend/src/theme/components/Button.ts b/frontend/src/theme/components/Button.ts index 499a5ba9a7..cfabaed958 100644 --- a/frontend/src/theme/components/Button.ts +++ b/frontend/src/theme/components/Button.ts @@ -1,4 +1,8 @@ -import { getColor, SystemStyleFunction } from '@chakra-ui/theme-tools' +import { + getColor, + StyleFunctionProps, + SystemStyleFunction, +} from '@chakra-ui/theme-tools' import merge from 'lodash/merge' import { textStyles } from '../textStyles' @@ -13,19 +17,63 @@ export type ThemeButtonVariant = | 'link' | 'inputAttached' -const variantSolid: SystemStyleFunction = (props) => { - const { colorScheme: c } = props - let bg = `${c}.500` - let activeBg = `${c}.700` - let hoverBg = `${c}.600` - let focusBoxShadow = `0 0 0 4px var(--chakra-colors-${c}-300)` +const genVariantSolidColours = (c: string) => { + const defaultBackgrounds = { + bg: `${c}.500`, + activeBg: `${c}.700`, + hoverBg: `${c}.600`, + focusBoxShadow: `0 0 0 4px var(--chakra-colors-${c}-300)`, + } + switch (c) { + case 'success': { + return { + bg: `${c}.700`, + activeBg: `${c}.800`, + hoverBg: `${c}.800`, + focusBoxShadow: `0 0 0 4px var(--chakra-colors-${c}-400)`, + } + } + case 'theme-red': + case 'theme-orange': + case 'theme-yellow': { + return { + ...defaultBackgrounds, + bg: `${c}.600`, + activeBg: `${c}.800`, + hoverBg: `${c}.700`, + } + } + default: { + return defaultBackgrounds + } + } +} - if (c === 'success') { - bg = `${c}.700` - activeBg = `${c}.800` - hoverBg = `${c}.800` - focusBoxShadow = `0 0 0 4px var(--chakra-colors-${c}-400)` +const genVariantOutlineColours = ({ + colorScheme: c, + theme, +}: StyleFunctionProps) => { + switch (c) { + case 'theme-red': + case 'theme-orange': + case 'theme-yellow': { + return { + borderColor: `${c}.600` as const, + focusBorderColor: getColor(theme, `${c}.400`), + } + } + default: { + return { + borderColor: `${c}.500` as const, + focusBorderColor: getColor(theme, `${c}.300`), + } + } } +} + +const variantSolid: SystemStyleFunction = (props) => { + const { colorScheme: c } = props + const { bg, hoverBg, activeBg, focusBoxShadow } = genVariantSolidColours(c) return { bg, @@ -92,15 +140,16 @@ const variantClear: SystemStyleFunction = (props) => { const variantOutlineReverse: SystemStyleFunction = (props) => { const { colorScheme: c, variant } = props + const { borderColor, focusBorderColor } = genVariantOutlineColours(props) const showBorder = variant === 'outline' return { bg: 'white', px: '15px', - borderColor: showBorder ? `${c}.500` : 'white', - color: `${c}.500`, + borderColor: showBorder ? borderColor : 'white', + color: borderColor, _focus: { - boxShadow: `0 0 0 4px var(--chakra-colors-${c}-300)`, + boxShadow: `0 0 0 4px ${focusBorderColor}`, }, _disabled: { color: `${c}.300`, @@ -110,7 +159,7 @@ const variantOutlineReverse: SystemStyleFunction = (props) => { }, _active: { bg: `${c}.200`, - borderColor: showBorder ? `${c}.500` : `${c}.200`, + borderColor: showBorder ? borderColor : `${c}.200`, _disabled: { bg: 'white', borderColor: showBorder ? `${c}.300` : 'white', @@ -118,7 +167,7 @@ const variantOutlineReverse: SystemStyleFunction = (props) => { }, _hover: { bg: `${c}.100`, - borderColor: showBorder ? `${c}.500` : `${c}.100`, + borderColor: showBorder ? borderColor : `${c}.100`, _disabled: { bg: 'white', borderColor: showBorder ? `${c}.300` : 'white', diff --git a/frontend/src/theme/components/Checkbox.ts b/frontend/src/theme/components/Checkbox.ts index 9ba9e36007..993c4b9a1d 100644 --- a/frontend/src/theme/components/Checkbox.ts +++ b/frontend/src/theme/components/Checkbox.ts @@ -24,6 +24,7 @@ const baseStyle: PartsStyleFunction = ({ }) => ({ // Control is the box containing the check icon control: { + bg: 'white', borderRadius: '0.25rem', border: '0.125rem solid', borderColor: `${c}.500`, diff --git a/frontend/src/theme/components/Field/Attachment.ts b/frontend/src/theme/components/Field/Attachment.ts index f1d75179f8..4d81ef19b4 100644 --- a/frontend/src/theme/components/Field/Attachment.ts +++ b/frontend/src/theme/components/Field/Attachment.ts @@ -34,6 +34,7 @@ export const Attachment: ComponentMultiStyleConfig = { isDragActive, focusBorderColor: fc, errorBorderColor: ec, + colorScheme: c, theme, } = props @@ -49,9 +50,9 @@ export const Attachment: ComponentMultiStyleConfig = { justifyContent: 'center', cursor: 'pointer', border: '1px dashed', - borderColor: 'primary.700', + borderColor: `${c}.700`, borderRadius: '0.25rem', - bg: isDragActive ? 'primary.200' : 'neutral.100', + bg: isDragActive ? `${c}.200` : 'neutral.100', _invalid: { // Remove extra 1px of outline. borderColor: getColor(theme, ec), @@ -66,10 +67,10 @@ export const Attachment: ComponentMultiStyleConfig = { ...inputStyle._disabled, }, _hover: { - bg: 'primary.100', + bg: `${c}.100`, }, _active: { - bg: 'primary.200', + bg: `${c}.200`, }, }, } @@ -77,5 +78,6 @@ export const Attachment: ComponentMultiStyleConfig = { }, defaultProps: { ...Input.defaultProps, + colorScheme: 'primary', }, } diff --git a/frontend/src/theme/components/Field/Rating.ts b/frontend/src/theme/components/Field/Rating.ts index e45ce232a7..a747c7da19 100644 --- a/frontend/src/theme/components/Field/Rating.ts +++ b/frontend/src/theme/components/Field/Rating.ts @@ -10,7 +10,7 @@ const getOptionThemeColor = (colorScheme: string) => { case 'theme-red': case 'theme-orange': case 'theme-yellow': - return `${colorScheme}.700` + return `${colorScheme}.600` default: return `${colorScheme}.500` } diff --git a/frontend/src/theme/components/Menu.ts b/frontend/src/theme/components/Menu.ts index 270a94a723..d1afcd2bc0 100644 --- a/frontend/src/theme/components/Menu.ts +++ b/frontend/src/theme/components/Menu.ts @@ -27,18 +27,18 @@ const baseStyle: PartsStyleFunction = (props) => { fontWeight: '400', color: 'secondary.700', _hover: { - bg: 'primary.100', + bg: `${c}.100`, borderWidth: '0rem', }, _focus: { - bg: 'primary.100', + bg: `${c}.100`, boxShadow: `0 0 0 2px ${getColor(theme, fc)}`, _active: { - bg: 'primary.200', + bg: `${c}.200`, }, }, _active: { - bg: 'primary.200', + bg: `${c}.200`, fontWeight: 500, }, _disabled: { diff --git a/frontend/src/theme/foundations/colours.ts b/frontend/src/theme/foundations/colours.ts index 9b5651ea7f..fb69487f6b 100644 --- a/frontend/src/theme/foundations/colours.ts +++ b/frontend/src/theme/foundations/colours.ts @@ -22,6 +22,7 @@ export type ThemeColorScheme = export type FieldColorScheme = Extract< ThemeColorScheme, | 'primary' + | 'theme-blue' | 'theme-green' | 'theme-teal' | 'theme-purple'