diff --git a/react/CHANGELOG.md b/react/CHANGELOG.md
index eb950355..c49c3655 100644
--- a/react/CHANGELOG.md
+++ b/react/CHANGELOG.md
@@ -4,12 +4,21 @@ All notable changes to this project will be documented in this file. Dates are d
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
+#### [v1.24.0](https://github.com/opengovsg/design-system/compare/v1.23.0...v1.24.0)
+
+- feat: fix Input prefill style regression, add `isPrefilled` prop to Datepicker and Select [`#754`](https://github.com/opengovsg/design-system/pull/754)
+- chore: merge v1.23.0 back to main [`#747`](https://github.com/opengovsg/design-system/pull/747)
+- build: release v1.23.0 [`#746`](https://github.com/opengovsg/design-system/pull/746)
+
#### [v1.23.0](https://github.com/opengovsg/design-system/compare/v1.22.0...v1.23.0)
+> 20 August 2024
+
- fix!(DatePicker): add `renderInputElement` prop [`#745`](https://github.com/opengovsg/design-system/pull/745)
- chore: enable dual publish to GitHub [`#740`](https://github.com/opengovsg/design-system/pull/740)
- chore: merge latest v1.22.0 back to main [`#732`](https://github.com/opengovsg/design-system/pull/732)
- build: release v1.22.0 [`#731`](https://github.com/opengovsg/design-system/pull/731)
+- build: release v1.23.0 [`224b03c`](https://github.com/opengovsg/design-system/commit/224b03c263672eccb9a409309b4c549cb718b6f2)
#### [v1.22.0](https://github.com/opengovsg/design-system/compare/v1.21.0...v1.22.0)
diff --git a/react/package-lock.json b/react/package-lock.json
index 78713715..3ecbd217 100644
--- a/react/package-lock.json
+++ b/react/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@opengovsg/design-system-react",
- "version": "1.23.0",
+ "version": "1.24.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@opengovsg/design-system-react",
- "version": "1.23.0",
+ "version": "1.24.0",
"license": "SEE LICENSE IN LICENSE.md",
"dependencies": {
"@chakra-ui/utils": "^2.0.14",
diff --git a/react/package.json b/react/package.json
index 84a45393..89fc4d9f 100644
--- a/react/package.json
+++ b/react/package.json
@@ -1,6 +1,6 @@
{
"name": "@opengovsg/design-system-react",
- "version": "1.23.0",
+ "version": "1.24.0",
"description": "React components",
"homepage": "https://github.com/opengovsg/design-system/react#readme",
"bugs": "https://github.com/opengovsg/design-system/issues",
diff --git a/react/src/DatePicker/DatePicker.stories.tsx b/react/src/DatePicker/DatePicker.stories.tsx
index d659083b..9a16e0d8 100644
--- a/react/src/DatePicker/DatePicker.stories.tsx
+++ b/react/src/DatePicker/DatePicker.stories.tsx
@@ -62,6 +62,11 @@ FixedHeightCalendarPopover.args = {
isCalendarFixedHeight: true,
}
+export const Prefilled = Template.bind({})
+Prefilled.args = {
+ isPrefilled: true,
+}
+
export const SizeSmall = Template.bind({})
SizeSmall.args = {
size: 'sm',
diff --git a/react/src/DatePicker/DatePickerContext.tsx b/react/src/DatePicker/DatePickerContext.tsx
index a2f355f3..09a7f148 100644
--- a/react/src/DatePicker/DatePickerContext.tsx
+++ b/react/src/DatePicker/DatePickerContext.tsx
@@ -103,6 +103,7 @@ const useProvideDatePicker = ({
isReadOnly: isReadOnlyProp,
isRequired: isRequiredProp,
isInvalid: isInvalidProp,
+ isPrefilled,
locale,
allowManualInput = true,
allowInvalidDates = true,
@@ -260,6 +261,7 @@ const useProvideDatePicker = ({
const styles = useMultiStyleConfig('DatePicker', {
size,
colorScheme,
+ isPrefilled,
})
const placeholder = useMemo(
diff --git a/react/src/DatePicker/components/DatePickerInput.tsx b/react/src/DatePicker/components/DatePickerInput.tsx
index b89f95ce..6742c0f6 100644
--- a/react/src/DatePicker/components/DatePickerInput.tsx
+++ b/react/src/DatePicker/components/DatePickerInput.tsx
@@ -30,6 +30,7 @@ export const DatePickerInput = forwardRef<{}, 'input'>((_props, ref) => {
size,
inputPattern,
innerRef,
+ styles,
} = useDatePicker()
const mergedInputRef = useMergeRefs(inputRef, innerRef, ref)
@@ -71,6 +72,7 @@ export const DatePickerInput = forwardRef<{}, 'input'>((_props, ref) => {
onBlur={handleInputBlur}
onClick={handleInputClick}
isReadOnly={fcProps.isReadOnly || !allowManualInput}
+ sx={styles.field}
/>
) : (
((_props, ref) => {
inputMode="numeric"
placeholder={placeholder}
pattern={inputPattern}
+ sx={styles.field}
/>
)}
diff --git a/react/src/DatePicker/types.ts b/react/src/DatePicker/types.ts
index f67917a1..8e55fdf4 100644
--- a/react/src/DatePicker/types.ts
+++ b/react/src/DatePicker/types.ts
@@ -24,6 +24,10 @@ export interface DatePickerBaseProps
* @defaultValue `true`
*/
allowInvalidDates?: boolean
+ /**
+ * Whether the input is in a prefilled state.
+ */
+ isPrefilled?: boolean
/**
* Whether the calendar will close once a date is selected.
* @defaultValue `true`
diff --git a/react/src/DateRangePicker/DateRangePicker.stories.tsx b/react/src/DateRangePicker/DateRangePicker.stories.tsx
index f06645f8..380aa18c 100644
--- a/react/src/DateRangePicker/DateRangePicker.stories.tsx
+++ b/react/src/DateRangePicker/DateRangePicker.stories.tsx
@@ -57,6 +57,12 @@ DatePickerDisabled.args = {
defaultValue: [new Date('2001-01-01'), new Date('2002-01-03')],
}
+export const Prefilled = Template.bind({})
+Prefilled.args = {
+ isPrefilled: true,
+ defaultValue: [new Date('2001-01-01'), new Date('2002-01-03')],
+}
+
export const Mobile = Template.bind({})
Mobile.parameters = getMobileViewParameters()
diff --git a/react/src/DateRangePicker/DateRangePickerContext.tsx b/react/src/DateRangePicker/DateRangePickerContext.tsx
index 68605052..ca31bb5e 100644
--- a/react/src/DateRangePicker/DateRangePickerContext.tsx
+++ b/react/src/DateRangePicker/DateRangePickerContext.tsx
@@ -103,6 +103,7 @@ const useProvideDateRangePicker = ({
isReadOnly: isReadOnlyProp,
isRequired: isRequiredProp,
isInvalid: isInvalidProp,
+ isPrefilled,
locale,
allowManualInput = true,
allowInvalidDates = true,
@@ -333,6 +334,7 @@ const useProvideDateRangePicker = ({
const styles = useMultiStyleConfig('DateRangePicker', {
size,
colorScheme,
+ isPrefilled,
})
const placeholder = useMemo(
diff --git a/react/src/Input/Input.tsx b/react/src/Input/Input.tsx
index 8ab4910a..c6995222 100644
--- a/react/src/Input/Input.tsx
+++ b/react/src/Input/Input.tsx
@@ -32,7 +32,13 @@ export const Input = forwardRef((props, ref) => {
// Return normal input component if not success state.
if (!props.isSuccess) {
- return
+ return (
+
+ )
}
return (
diff --git a/react/src/MultiSelect/MultiSelect.stories.tsx b/react/src/MultiSelect/MultiSelect.stories.tsx
index d30132f5..78b56e18 100644
--- a/react/src/MultiSelect/MultiSelect.stories.tsx
+++ b/react/src/MultiSelect/MultiSelect.stories.tsx
@@ -103,6 +103,12 @@ DisabledWithSelection.args = {
values: ['What happens when the label is fairly long', 'Bat'],
}
+export const Prefilled = Template.bind({})
+Prefilled.args = {
+ isPrefilled: true,
+ values: ['What happens when the label is fairly long', 'Bat'],
+}
+
export const WithFixedItemHeight = Template.bind({})
WithFixedItemHeight.args = {
size: 'md',
diff --git a/react/src/MultiSelect/MultiSelectProvider.tsx b/react/src/MultiSelect/MultiSelectProvider.tsx
index 9c7c1719..bcb43d56 100644
--- a/react/src/MultiSelect/MultiSelectProvider.tsx
+++ b/react/src/MultiSelect/MultiSelectProvider.tsx
@@ -70,6 +70,10 @@ export interface MultiSelectProviderProps<
* If `true`, the selected items will take up the full width of the input container. Defaults to `false`.
*/
isStretchLayout?: boolean
+ /**
+ * Whether the input is in a prefilled state.
+ */
+ isPrefilled?: boolean
}
export const MultiSelectProvider = ({
items: rawItems,
@@ -81,6 +85,7 @@ export const MultiSelectProvider = ({
placeholder: placeholderProp,
clearButtonLabel = 'Clear selection',
isSearchable = true,
+ isPrefilled = false,
defaultIsOpen,
isInvalid: isInvalidProp,
isReadOnly: isReadOnlyProp,
@@ -297,6 +302,7 @@ export const MultiSelectProvider = ({
size,
isFocused: isFocused || isOpen,
isEmpty: selectedItems.length === 0,
+ isPrefilled,
})
const virtualListHeight = useMemo(() => {
diff --git a/react/src/SingleSelect/SingleSelect.stories.tsx b/react/src/SingleSelect/SingleSelect.stories.tsx
index d677a27e..9b28fe48 100644
--- a/react/src/SingleSelect/SingleSelect.stories.tsx
+++ b/react/src/SingleSelect/SingleSelect.stories.tsx
@@ -180,6 +180,12 @@ Disabled.args = {
isDisabled: true,
}
+export const Prefilled = Template.bind({})
+Prefilled.args = {
+ isPrefilled: true,
+ value: itemToValue(INITIAL_COMBOBOX_ITEMS[2]),
+}
+
export const FormInput: StoryFn = (args) => {
const [value, setValue] = useState(args.value)
diff --git a/react/src/SingleSelect/SingleSelectProvider.tsx b/react/src/SingleSelect/SingleSelectProvider.tsx
index 062eec53..3550dfae 100644
--- a/react/src/SingleSelect/SingleSelectProvider.tsx
+++ b/react/src/SingleSelect/SingleSelectProvider.tsx
@@ -39,6 +39,10 @@ export interface SingleSelectProviderProps<
/** Color scheme of component */
colorScheme?: ThemingProps<'SingleSelect'>['colorScheme']
fixedItemHeight?: number
+ /**
+ * Whether the input is in a prefilled state.
+ */
+ isPrefilled?: boolean
}
export const SingleSelectProvider = ({
items: rawItems,
@@ -51,6 +55,7 @@ export const SingleSelectProvider = ({
clearButtonLabel = 'Clear selection',
isClearable = true,
isSearchable = true,
+ isPrefilled = false,
initialIsOpen,
isInvalid: isInvalidProp,
isReadOnly: isReadOnlyProp,
@@ -234,6 +239,7 @@ export const SingleSelectProvider = ({
const styles = useMultiStyleConfig('SingleSelect', {
size,
isClearable,
+ isPrefilled,
colorScheme,
})
diff --git a/react/src/theme/components/DatePicker.ts b/react/src/theme/components/DatePicker.ts
index 9067377b..4d0992df 100644
--- a/react/src/theme/components/DatePicker.ts
+++ b/react/src/theme/components/DatePicker.ts
@@ -1,40 +1,52 @@
import { createMultiStyleConfigHelpers } from '@chakra-ui/react'
import { anatomy } from '@chakra-ui/theme-tools'
import { memoizedGet as get } from '@chakra-ui/utils'
+import omit from 'lodash/omit'
+
+import { Input } from './Input'
export const datepickerAnatomy = anatomy('datepicker').parts(
'header',
'inputButton',
'container',
'calendarButton',
+ 'field',
)
const { defineMultiStyleConfig, definePartsStyle } =
createMultiStyleConfigHelpers(datepickerAnatomy.keys)
const sizes = {
- xs: definePartsStyle({
+ xs: definePartsStyle((props) => ({
+ field: Input.sizes?.xs(props).field,
inputButton: {
fontSize: '1rem',
},
- }),
- sm: definePartsStyle({
+ })),
+ sm: definePartsStyle((props) => ({
+ field: Input.sizes?.sm(props).field,
inputButton: {
fontSize: '1.25rem',
},
- }),
- md: definePartsStyle({
+ })),
+ md: definePartsStyle((props) => ({
+ field: Input.sizes?.md(props).field,
inputButton: {
fontSize: '1.25rem',
},
- }),
+ })),
}
-const baseStyle = definePartsStyle(({ theme }) => {
- const themeTextStyles = get(theme, 'textStyles')
+const baseStyle = definePartsStyle((props) => {
+ const themeTextStyles = get(props.theme, 'textStyles')
+ const inputFieldStyle = omit(
+ Input.variants?.outline(props).field,
+ 'borderRadius',
+ )
return {
container: {
bg: 'utility.ui',
},
+ field: inputFieldStyle,
calendarButton: {
_active: {
zIndex: '1',
diff --git a/react/src/theme/components/DateRangePicker.ts b/react/src/theme/components/DateRangePicker.ts
index a6c4c1dc..136cb088 100644
--- a/react/src/theme/components/DateRangePicker.ts
+++ b/react/src/theme/components/DateRangePicker.ts
@@ -1,4 +1,5 @@
import { createMultiStyleConfigHelpers } from '@chakra-ui/react'
+import omit from 'lodash/omit'
import { DatePicker, datepickerAnatomy } from './DatePicker'
import { Input } from './Input'
@@ -40,19 +41,19 @@ const sizes = {
xs: definePartsStyle((props) => {
return {
fieldwrapper: Input.sizes?.xs(props).field,
- inputButton: DatePicker.sizes?.xs.inputButton,
+ inputButton: DatePicker.sizes?.xs(props).inputButton,
}
}),
sm: definePartsStyle((props) => {
return {
fieldwrapper: Input.sizes?.sm(props).field,
- inputButton: DatePicker.sizes?.sm.inputButton,
+ inputButton: DatePicker.sizes?.sm(props).inputButton,
}
}),
md: definePartsStyle((props) => {
return {
fieldwrapper: Input.sizes?.md(props).field,
- inputButton: DatePicker.sizes?.md.inputButton,
+ inputButton: DatePicker.sizes?.md(props).inputButton,
}
}),
}
@@ -64,7 +65,7 @@ const variants = {
export const DateRangePicker = defineMultiStyleConfig({
variants,
sizes,
- baseStyle: DatePicker.baseStyle,
+ baseStyle: (props) => omit(DatePicker.baseStyle?.(props), 'field'),
defaultProps: {
variant: 'outline',
size: 'md',