refactor(forms): port game form to Chakra v3 with v4-style selects

- New FixedSelect wrapper over chakra-react-select v6 restoring the v4
  look everywhere: single gray.500 control border, flush addon chevron
  zone with rounded inner corners, hidden indicator separator, v4 option
  padding/type scale, gray subtle pills, brighter unselected hover
- GameForm: FormControl/InputGroup -> Field/Flex, Button
  colorScheme/isLoading -> colorPalette/loading, Stack spacing -> gap,
  Container container.md -> 768px, Steam Scrape row rebuilt as nowrap
  Flex, select wrappers de-bordered (control owns the border)
- formFields: Field/Checkbox/Switch shims in, required asterisk dropped
  to match legacy labels, Select/Creatable wrappers de-bordered,
  TS-typed select callbacks
This commit is contained in:
2026-09-06 10:29:41 -04:00
parent 4574dfb8f1
commit 7bdf42ac07
9 changed files with 269 additions and 109 deletions
+140
View File
@@ -0,0 +1,140 @@
import React from 'react'
import { Select as V6Select, CreatableSelect as V6Creatable } from 'chakra-react-select'
import { useColorModeValue } from './ui/color-mode'
// Shared styling that restores how these selects looked with Chakra v2 /
// chakra-react-select v4 (verified against the v4.9.1 source + old screenshots):
//
// - v4's control border resolved to the outer wrapper's gray.500 edge via
// `borderColor: inherit` (outer Box sets gray.500). v6 paints its own light
// edge (gray.100 in dark mode) on top, producing a double white+gray border.
// Fix universally: single gray.500 border on the control itself, transparent
// bg so wrapper bg shows through, no shadow, no padding so the chevron zone
// sits flush (v4 had padding:0 + overflow:hidden).
// - v4's chevron sat on a grey input-addon zone (gray.100 / whiteAlpha.300),
// flush right with rounded right corners matching the control.
// - v4's indicator separator was a subtle Divider, effectively invisible in
// the old screenshots; v6 hides it by default, so keep it hidden instead of
// rendering a prominent white line.
// - v4 multi-value pills defaulted to gray subtle tags (dark gray pill in dark
// mode), not bright blue. Defaults restored here; ActiveFilters tags pass
// blue explicitly and are unaffected.
function V6IndicatorSeparator() {
return null
}
function useSharedChakraStyles(extra: any) {
const zoneBg = useColorModeValue('gray.100', 'whiteAlpha.300')
const pillBg = useColorModeValue('gray.100', 'whiteAlpha.300')
const pillColor = useColorModeValue('gray.800', 'gray.100')
const optionHoverBg = useColorModeValue('gray.200', 'whiteAlpha.300')
return {
control: (provided: any) => ({
...provided,
borderColor: 'gray.500',
borderWidth: '1px',
borderStyle: 'solid',
background: 'transparent',
boxShadow: 'none',
padding: 0,
overflow: 'hidden',
}),
valueContainer: (provided: any, state: any) => ({
...provided,
paddingTop: '2px',
paddingBottom: '2px',
paddingLeft: state?.selectProps?.size === 'sm' ? '12px' : '16px',
paddingRight: '8px',
}),
indicatorsContainer: (provided: any) => ({
...provided,
padding: 0,
margin: 0,
}),
dropdownIndicator: (provided: any) => ({
...provided,
background: zoneBg,
alignSelf: 'stretch',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
margin: 0,
paddingLeft: '8px',
paddingRight: '8px',
borderWidth: 0,
borderRadius: 0,
borderTopRightRadius: 'md',
borderBottomRightRadius: 'md',
}),
option: (provided: any, state: any) => {
const size = state?.selectProps?.size === 'sm' ? 'sm' : state?.selectProps?.size === 'lg' ? 'lg' : 'md'
const v4 = {
sm: { fontSize: '14px', paddingLeft: '12.8px', paddingRight: '12.8px', paddingTop: '4.8px', paddingBottom: '4.8px' },
md: { fontSize: '16px', paddingLeft: '12.8px', paddingRight: '12.8px', paddingTop: '6.4px', paddingBottom: '6.4px' },
lg: { fontSize: '18px', paddingLeft: '16px', paddingRight: '16px', paddingTop: '8px', paddingBottom: '8px' },
}[size]
return {
...provided,
fontSize: v4.fontSize,
paddingLeft: v4.paddingLeft,
paddingRight: v4.paddingRight,
paddingTop: v4.paddingTop,
paddingBottom: v4.paddingBottom,
// v3 hover uses bg.emphasized/60 — near-invisible on dark surfaces.
// Brighten unselected hover in both modes; keep selected blue.
_highlighted: state?.isSelected
? provided._highlighted
: { bg: optionHoverBg },
}
},
multiValue: (provided: any) => ({
...provided,
background: pillBg,
color: pillColor,
borderRadius: 'md',
margin: '2px',
}),
multiValueLabel: (provided: any) => ({
...provided,
color: pillColor,
}),
multiValueRemove: (provided: any) => ({
...provided,
color: pillColor,
}),
...extra,
}
}
function mergeComponents(extra: any) {
return { IndicatorSeparator: V6IndicatorSeparator, ...extra }
}
export function Select(props: any) {
const { chakraStyles, components, tagColorPalette = 'gray', tagVariant = 'subtle', ...rest } = props
const mergedStyles = useSharedChakraStyles(chakraStyles)
return (
<V6Select
{...rest}
tagColorPalette={tagColorPalette}
tagVariant={tagVariant}
components={mergeComponents(components)}
chakraStyles={mergedStyles}
/>
)
}
export function CreatableSelect(props: any) {
const { chakraStyles, components, tagColorPalette = 'gray', tagVariant = 'subtle', ...rest } = props
const mergedStyles = useSharedChakraStyles(chakraStyles)
return (
<V6Creatable
{...rest}
tagColorPalette={tagColorPalette}
tagVariant={tagVariant}
components={mergeComponents(components)}
chakraStyles={mergedStyles}
/>
)
}
+43 -45
View File
@@ -21,17 +21,16 @@ import {
Box, Box,
Button, Button,
Container, Container,
FormControl, Flex,
FormLabel,
Heading, Heading,
InputGroup,
Spacer, Spacer,
Stack, Stack,
Switch,
Text, Text,
useColorModeValue,
} from '@chakra-ui/react' } from '@chakra-ui/react'
import {CreatableSelect,} from 'chakra-react-select' import {Field} from './ui/field'
import {Switch} from './ui/switch'
import {useColorModeValue} from './ui/color-mode'
import {CreatableSelect} from './FixedSelect'
import {adminMode} from '../stateManagement/userState' import {adminMode} from '../stateManagement/userState'
import {encode} from 'js-base64' import {encode} from 'js-base64'
import SingleFieldInput from './formFields/SingleFieldInput' import SingleFieldInput from './formFields/SingleFieldInput'
@@ -314,63 +313,64 @@ const GameForm = () => {
return ( return (
<> <>
<Container maxW="container.md" mt="10"> <Container maxW="768px" mt="10">
{id ? <Heading as="h1" size="xl">Editing {game.title}</Heading> : {id ? <Heading as="h1" size="xl">Editing {game.title}</Heading> :
<Heading as="h1" size="xl">Add a Game to the Database</Heading>} <Heading as="h1" size="xl">Add a Game to the Database</Heading>}
<form onSubmit={handleSubmit} style={{marginTop: '2rem'}}> <form onSubmit={handleSubmit} style={{marginTop: '2rem'}}>
<Stack spacing={[1, 5]} direction={{base: 'column', sm: 'row'}} justify={'flex-end'}> <Stack gap={[1, 5]} direction={{base: 'column', sm: 'row'}} justify={'flex-end'}>
<Button <Button
isLoading={submitLoading} loading={submitLoading}
colorScheme="blue" colorPalette="blue"
type="submit" type="submit"
data-name={"save"} data-name={"save"}
> >
Save Save
</Button> </Button>
<Button <Button
isLoading={moveOn} loading={moveOn}
colorScheme="green" colorPalette="green"
type="submit" type="submit"
data-name={"save-and-view"} data-name={"save-and-view"}
> >
Save and View Save and View
</Button> </Button>
</Stack> </Stack>
<InputGroup> <Flex gap={3} alignItems="center">
{!id || admin ? ( {!id || admin ? (
<Box flex="1">
<SingleFieldNumericInput label={'Steam ID'} textField={'steamId'} field={game.steamId} bg={bg} <SingleFieldNumericInput label={'Steam ID'} textField={'steamId'} field={game.steamId} bg={bg}
handleInputChange={handleInputChange} required={game.scrape}/> handleInputChange={handleInputChange} required={game.scrape}/>
</Box>
) : ''} ) : ''}
{!id && ( {!id && (
<FormControl display="flex" ml={'3'} alignItems="center"> <Flex alignItems="center" ml={'3'} flexShrink={0} gap={2}>
<FormLabel htmlFor="scrape" mb="0">Steam Scrape</FormLabel> <Text whiteSpace="nowrap">Steam Scrape</Text>
<Switch <Switch
isChecked={game.scrape} colorPalette="blue"
onChange={() => { checked={game.scrape}
onCheckedChange={() => {
handleToggle('scrape') handleToggle('scrape')
}} }}
name="scrape" name="scrape"
id="scrape" id="scrape"
/> />
</FormControl> </Flex>
)} )}
</InputGroup> </Flex>
{(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? ( {(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? (
<SingleFieldInput label={'Title'} textField={'title'} field={game.title} bg={bg} <SingleFieldInput label={'Title'} textField={'title'} field={game.title} bg={bg}
handleInputChange={handleInputChange} required={false}/> handleInputChange={handleInputChange} required={false}/>
) : ''} ) : ''}
<> <>
<FormControl mb="3"> <Field mb="3" label="Series">
<FormLabel>Series</FormLabel>
<Box <Box
bg={bg} bg={bg}
border="1px" rounded="md"
borderColor="gray.500" w="full">
rounded="md">
<CreatableSelect <CreatableSelect
name="series" name="series"
isClearable isClearable
onChange={(values) => { onChange={(values: any) => {
if (values === null) values = {value: '', label: ''} if (values === null) values = {value: '', label: ''}
if (values) { if (values) {
handleInputChange('series', values.value) handleInputChange('series', values.value)
@@ -380,20 +380,18 @@ const GameForm = () => {
value={{value: game.series, label: game.series}} value={{value: game.series, label: game.series}}
/> />
</Box> </Box>
</FormControl> </Field>
</> </>
{(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? ( {(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? (
<> <>
<SingleFieldInput label={'Front Image'} textField={'frontImage'} field={game.frontImage} <SingleFieldInput label={'Front Image'} textField={'frontImage'} field={game.frontImage}
bg={bg} bg={bg}
handleInputChange={handleInputChange} required={false}/> handleInputChange={handleInputChange} required={false}/>
<FormControl mb="3"> <Field mb="3" label="Screenshots">
<FormLabel>Screenshots</FormLabel>
<Box <Box
bg={bg} bg={bg}
border="1px" rounded="md"
borderColor="gray.500" w="full">
rounded="md">
<CreatableSelect <CreatableSelect
name="screenshots" name="screenshots"
isClearable isClearable
@@ -433,7 +431,7 @@ const GameForm = () => {
value={screenshots[0]?.value === '' ? [] : screenshots} value={screenshots[0]?.value === '' ? [] : screenshots}
/> />
</Box> </Box>
</FormControl> </Field>
</> </>
) : ''} ) : ''}
{(gameId === '' && !game.scrape) || (gameId.length >= 1) ? {(gameId === '' && !game.scrape) || (gameId.length >= 1) ?
@@ -453,14 +451,14 @@ const GameForm = () => {
</> </>
{(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? ( {(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? (
<Box mt="5" mb="5"> <Box mt="5" mb="5">
<FormLabel>Operating Systems</FormLabel> <Text fontWeight="medium" mb="2">Operating Systems</Text>
<Box <Box
bg={bg} bg={bg}
border="1px" borderWidth="1px" borderStyle="solid"
borderColor="gray.500" borderColor="gray.500"
rounded="md" rounded="md"
p="2"> p="2">
<Stack spacing={[1, 5]} direction={['column', 'row']}> <Stack gap={[1, 5]} direction={['column', 'row']}>
<CheckboxInput label={'Windows'} textField={'windows'} checked={game.os.windows} <CheckboxInput label={'Windows'} textField={'windows'} checked={game.os.windows}
defaultIsChecked={true} handleOSChange={handleOSChange}/> defaultIsChecked={true} handleOSChange={handleOSChange}/>
<CheckboxInput label={'Mac OSX'} textField={'mac'} checked={game.os.mac} <CheckboxInput label={'Mac OSX'} textField={'mac'} checked={game.os.mac}
@@ -518,9 +516,9 @@ const GameForm = () => {
</> </>
{(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? ( {(gameId === '' && !game.scrape) || (gameId.length >= 1 && admin) ? (
<> <>
<Text align="center" fontSize="xl" mt="10">System Requirements</Text> <Text textAlign="center" fontSize="xl" mt="10">System Requirements</Text>
<Box> <Box>
<Text fontSize="lg" align="center">Windows</Text> <Text fontSize="lg" textAlign="center">Windows</Text>
<SystemRequirementsTextareaInput label={'Windows Minimum'} <SystemRequirementsTextareaInput label={'Windows Minimum'}
textField={'systemRequirements.windows.minimum'} textField={'systemRequirements.windows.minimum'}
field={game.systemRequirements.windows.minimum} bg={bg} field={game.systemRequirements.windows.minimum} bg={bg}
@@ -532,7 +530,7 @@ const GameForm = () => {
bg={bg} bg={bg}
handleSystemRequirements={handleSystemRequirements} handleSystemRequirements={handleSystemRequirements}
rows={3}/> rows={3}/>
<Text fontSize="lg" align="center">Mac OSX</Text> <Text fontSize="lg" textAlign="center">Mac OSX</Text>
<SystemRequirementsTextareaInput label={'Mac OSX Minimum'} <SystemRequirementsTextareaInput label={'Mac OSX Minimum'}
textField={'systemRequirements.mac.minimum'} textField={'systemRequirements.mac.minimum'}
field={game.systemRequirements.mac.minimum} bg={bg} field={game.systemRequirements.mac.minimum} bg={bg}
@@ -543,7 +541,7 @@ const GameForm = () => {
field={game.systemRequirements.mac.recommended} bg={bg} field={game.systemRequirements.mac.recommended} bg={bg}
handleSystemRequirements={handleSystemRequirements} handleSystemRequirements={handleSystemRequirements}
rows={3}/> rows={3}/>
<Text fontSize="lg" align="center">Linux</Text> <Text fontSize="lg" textAlign="center">Linux</Text>
<SystemRequirementsTextareaInput label={'Linux Minimum'} <SystemRequirementsTextareaInput label={'Linux Minimum'}
textField={'systemRequirements.linux.minimum'} textField={'systemRequirements.linux.minimum'}
field={game.systemRequirements.linux.minimum} bg={bg} field={game.systemRequirements.linux.minimum} bg={bg}
@@ -558,18 +556,18 @@ const GameForm = () => {
</Box> </Box>
</> </>
) : ''} ) : ''}
<Stack spacing={[1, 5]} direction={{base: 'column', sm: 'row'}} align={{base: 'start'}}> <Stack gap={[1, 5]} direction={{base: 'column', sm: 'row'}} align={{base: 'start'}}>
<Button <Button
isLoading={submitLoading} loading={submitLoading}
colorScheme="blue" colorPalette="blue"
type="submit" type="submit"
data-name={"save"} data-name={"save"}
> >
Save Save
</Button> </Button>
<Button <Button
isLoading={moveOn} loading={moveOn}
colorScheme="green" colorPalette="green"
type="submit" type="submit"
data-name={"save-and-view"} data-name={"save-and-view"}
> >
@@ -579,7 +577,7 @@ const GameForm = () => {
<> <>
<Spacer/> <Spacer/>
<Button <Button
colorScheme="red" colorPalette="red"
onMouseDown={() => { onMouseDown={() => {
openState.set(true) openState.set(true)
}} }}
+7 -5
View File
@@ -1,5 +1,6 @@
import React from 'react' import React from 'react'
import { Checkbox, Text } from '@chakra-ui/react' import { Text } from '@chakra-ui/react'
import {Checkbox} from '../ui/checkbox'
interface Props { interface Props {
label: string label: string
@@ -12,15 +13,16 @@ interface Props {
const CheckboxInput = ({ label, textField, checked, defaultIsChecked, handleOSChange }: Props) => { const CheckboxInput = ({ label, textField, checked, defaultIsChecked, handleOSChange }: Props) => {
return ( return (
<Checkbox <Checkbox
colorPalette="blue"
defaultChecked={defaultIsChecked} defaultChecked={defaultIsChecked}
isChecked={checked} checked={checked}
onChange={() => { onCheckedChange={() => {
handleOSChange(textField) handleOSChange(textField)
}} }}
name={textField} name={textField}
spacing="1rem" gap="1rem"
><Text mt="1">{label}</Text></Checkbox> ><Text mt="1">{label}</Text></Checkbox>
) )
} }
export default CheckboxInput export default CheckboxInput
@@ -1,6 +1,7 @@
import React from 'react' import React from 'react'
import { Box, FormControl, FormLabel } from '@chakra-ui/react' import { Box } from '@chakra-ui/react'
import { CreatableSelect } from 'chakra-react-select' import { Field } from '../ui/field'
import { CreatableSelect } from '../FixedSelect'
interface Props { interface Props {
label: string label: string
@@ -13,13 +14,12 @@ interface Props {
const CreatableSelectInput = ({ label, textField, value, bg, handleInputChange, options}: Props) => { const CreatableSelectInput = ({ label, textField, value, bg, handleInputChange, options}: Props) => {
return ( return (
<FormControl mb="3"> <Field mb="3" label={label}>
<FormLabel>{label}</FormLabel>
<Box <Box
bg={bg} bg={bg}
border="1px" rounded="md"
borderColor="gray.500" w="full"
rounded="md"> >
<CreatableSelect <CreatableSelect
name={textField} name={textField}
isClearable isClearable
@@ -39,8 +39,8 @@ const CreatableSelectInput = ({ label, textField, value, bg, handleInputChange,
options={options} options={options}
/> />
</Box> </Box>
</FormControl> </Field>
) )
} }
export default CreatableSelectInput export default CreatableSelectInput
+8 -10
View File
@@ -1,6 +1,7 @@
import React from 'react' import React from 'react'
import {Box, FormControl, FormLabel} from '@chakra-ui/react' import {Box} from '@chakra-ui/react'
import {Select} from 'chakra-react-select' import { Field } from '../ui/field'
import {Select} from '../FixedSelect'
interface Props { interface Props {
label: string label: string
@@ -14,18 +15,15 @@ interface Props {
const SelectInput = ({label, textField, field, bg, handleAccessedBy, options, width = ''}: Props) => { const SelectInput = ({label, textField, field, bg, handleAccessedBy, options, width = ''}: Props) => {
return ( return (
<FormControl mb="3"> <Field mb="3" label={label}>
<FormLabel>{label}</FormLabel>
<Box <Box
bg={bg} bg={bg}
w={width} w={width || 'full'}
border="1px"
borderColor="gray.500"
rounded="md"> rounded="md">
<Select <Select
id={textField} id={textField}
name={textField} name={textField}
onChange={(values) => { onChange={(values: any) => {
if (values) handleAccessedBy(textField, values.value) if (values) handleAccessedBy(textField, values.value)
}} }}
options={options} options={options}
@@ -35,8 +33,8 @@ const SelectInput = ({label, textField, field, bg, handleAccessedBy, options, wi
}} }}
/> />
</Box> </Box>
</FormControl> </Field>
) )
} }
export default SelectInput export default SelectInput
@@ -1,5 +1,6 @@
import React from 'react' import React from 'react'
import { FormControl, FormLabel, Input } from '@chakra-ui/react' import { Input } from '@chakra-ui/react'
import { Field } from '../ui/field'
import { Data } from '../../models/game' import { Data } from '../../models/game'
interface Props { interface Props {
@@ -14,15 +15,14 @@ interface Props {
const SingleFieldInput = ({ label, textField, field, bg, handleInputChange, required }: Props) => { const SingleFieldInput = ({ label, textField, field, bg, handleInputChange, required }: Props) => {
return ( return (
<FormControl mb="3"> <Field mb="3" label={label}>
<FormLabel>{label}</FormLabel>
<Input <Input
id={textField} id={textField}
name={textField} name={textField}
bg={bg} bg={bg}
type="text" type="text"
border="1px" borderWidth="1px" borderStyle="solid"
borderColor="gray.500" borderColor={{ base: "gray.500", _invalid: "red.500" }}
rounded="md" rounded="md"
value={field} value={field}
required={required} required={required}
@@ -30,8 +30,8 @@ const SingleFieldInput = ({ label, textField, field, bg, handleInputChange, requ
handleInputChange(textField, e.target.value) handleInputChange(textField, e.target.value)
}} }}
/> />
</FormControl> </Field>
) )
} }
export default SingleFieldInput export default SingleFieldInput
@@ -1,39 +1,63 @@
import React from 'react' import React from "react";
import { FormControl, FormLabel, Input } from '@chakra-ui/react' import { Input } from "@chakra-ui/react";
import { Data } from '../../models/game' import { Field } from "../ui/field";
import { Data } from "../../models/game";
interface Props { interface Props {
label: string label: string;
textField: string textField: string;
field: string field: string;
bg: string bg: string;
handleInputChange: <G extends keyof Data>(name: string, value: Data[G]) => void handleInputChange: <G extends keyof Data>(
required: boolean name: string,
value: Data[G],
) => void;
required: boolean;
} }
const SingleFieldNumericInput = ({ label, textField, field, bg, handleInputChange, required }: Props) => { const SingleFieldNumericInput = ({
label,
textField,
field,
bg,
handleInputChange,
required,
}: Props) => {
const isValidSteamValue = (v: string) => {
const s = v.trim();
if (!s) return false;
if (/^\d+$/.test(s)) return true;
return s.includes("store.steampowered.com");
};
const showError = field.trim() !== "" && !isValidSteamValue(field);
return ( return (
<FormControl mb="3"> <Field
<FormLabel>{label}</FormLabel> mb="3"
label={label}
errorText="Enter a Steam App Id or a Steam App URL"
>
<Input <Input
id={textField} id={textField}
name={textField} name={textField}
bg={bg} bg={bg}
type="text" type="text"
inputMode="numeric" inputMode="text"
pattern="[0-9]*" aria-invalid={showError}
border="1px" placeholder="Steam Id or Steam URL"
borderColor="gray.500" borderWidth="1px"
borderStyle="solid"
borderColor={{ base: "gray.500", _invalid: "red.500" }}
rounded="md" rounded="md"
value={field} value={field}
required={required} required={required}
onChange={(e) => { onChange={(e) => {
handleInputChange(textField, e.target.value) handleInputChange(textField, e.target.value);
}} }}
/> />
</FormControl> </Field>
) );
} };
export default SingleFieldNumericInput export default SingleFieldNumericInput;
@@ -1,5 +1,5 @@
import React, {useMemo, useRef} from 'react' import React, {useMemo, useRef} from 'react'
import {FormControl, FormLabel} from '@chakra-ui/react' import {Field} from '../ui/field'
import JoditEditor from "jodit-react"; import JoditEditor from "jodit-react";
interface Props { interface Props {
@@ -24,18 +24,17 @@ const SystemRequirementsTextareaInput = ({label, textField, field, handleSystemR
); );
return ( return (
<FormControl mb="3"> <Field mb="3" label={label}>
<FormLabel>{label}</FormLabel>
<JoditEditor <JoditEditor
ref={editor} ref={editor}
value={field} value={field}
config={config} config={config}
onChange={(value) => { onChange={(value: string) => {
handleSystemRequirements(arrText[1], arrText[2], value) handleSystemRequirements(arrText[1], arrText[2], value)
}} }}
/> />
</FormControl> </Field>
) )
} }
export default SystemRequirementsTextareaInput export default SystemRequirementsTextareaInput
+5 -6
View File
@@ -1,5 +1,5 @@
import React, {useMemo, useRef} from 'react' import React, {useMemo, useRef} from 'react'
import { FormControl, FormLabel } from '@chakra-ui/react' import { Field } from '../ui/field'
import { Data } from '../../models/game' import { Data } from '../../models/game'
import JoditEditor from "jodit-react"; import JoditEditor from "jodit-react";
@@ -25,18 +25,17 @@ const TextareaInput = ({ label, textField, field, handleInputChange }: Props) =>
return ( return (
<FormControl mb="3"> <Field mb="3" label={label}>
<FormLabel>{label}</FormLabel>
<JoditEditor <JoditEditor
ref={editor} ref={editor}
value={field} value={field}
config={config} config={config}
onChange={(value) => { onChange={(value: string) => {
handleInputChange(textField, value) handleInputChange(textField, value)
}} }}
/> />
</FormControl> </Field>
) )
} }
export default TextareaInput export default TextareaInput