Skip to content

Commit

Permalink
feat(FluidDatePicker): implement FluidDatePicker (#12247)
Browse files Browse the repository at this point in the history
* feat(FluidDatePicker): scaffold out initial react files

* feat(FluidDatePicker): scaffold out more files

* style(FluidDatePicker): add more styles for FluidDatePicker

* style(FluidDatePicker): add single invalid styles

* style(FluidDatePicker): clean up invalid, warn states on all variants

* fix(FluidDatePicker): always show range icon in fluid state

* fix(FluidDatePicker): add invalid, warn icons to simple fluiddatepicker

* feat(FluidDatePicker): add invalid state to DatePicker

* test(FluidDatePicker): add e2e tests, update snapshots

* chore(FluidDatePicker): fix avt test name

* test(FluidDatePicker): add API tests

* chore(FluidForm): add FluidDatePicker to FluidForm story, style fixes

* chore(storybook): fix playground, remove test examples

* test(e2e): update id

* Update packages/react/src/components/FluidDatePicker/FluidDatePicker.stories.js

Co-authored-by: Taylor Jones <tay1orjones@users.noreply.github.com>

* Update packages/react/src/components/FluidDatePicker/FluidDatePicker.stories.js

Co-authored-by: Taylor Jones <tay1orjones@users.noreply.github.com>

* Update packages/react/src/components/FluidDatePicker/FluidDatePicker.stories.js

Co-authored-by: Taylor Jones <tay1orjones@users.noreply.github.com>

Co-authored-by: Taylor Jones <tay1orjones@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
3 people authored Nov 8, 2022
1 parent c51ce37 commit 5ee80eb
Show file tree
Hide file tree
Showing 26 changed files with 998 additions and 6 deletions.
67 changes: 67 additions & 0 deletions e2e/components/FluidDatePicker/FluidDatePicker-test.e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* Copyright IBM Corp. 2022
*
* This source code is licensed under the Apache-2.0 license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

const { expect, test } = require('@playwright/test');
const { themes } = require('../../test-utils/env');
const { snapshotStory, visitStory } = require('../../test-utils/storybook');

test.describe('FluidDatePicker', () => {
themes.forEach((theme) => {
test.describe(theme, () => {
test('fluid date picker (range) @vrt', async ({ page }) => {
await snapshotStory(page, {
component: 'FluidDatePicker',
id: 'experimental-unstable-fluiddatepicker--range-with-calendar',
theme,
});
});

test('fluid date picker (single) @vrt', async ({ page }) => {
await snapshotStory(page, {
component: 'FluidDatePicker',
id: 'experimental-unstable-fluiddatepicker--single',
theme,
});
});

test('fluid date picker (simple) @vrt', async ({ page }) => {
await snapshotStory(page, {
component: 'FluidDatePicker',
id: 'experimental-unstable-fluiddatepicker--simple',
theme,
});
});
});
});

test('accessibility-checker @avt', async ({ page }) => {
await visitStory(page, {
component: 'FluidDatePicker',
id: 'experimental-unstable-fluiddatepicker--range-with-calendar',
globals: {
theme: 'white',
},
});
await visitStory(page, {
component: 'FluidDatePicker',
id: 'experimental-unstable-fluiddatepicker--single',
globals: {
theme: 'white',
},
});
await visitStory(page, {
component: 'FluidDatePicker',
id: 'experimental-unstable-fluiddatepicker--simple',
globals: {
theme: 'white',
},
});
await expect(page).toHaveNoACViolations('FluidDatePicker');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Code generated by carbon-components-react. DO NOT EDIT.
//
// Copyright IBM Corp. 2018, 2018
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

@forward '@carbon/styles/scss/components/fluid-date-picker/fluid-date-picker';
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Code generated by carbon-components-react. DO NOT EDIT.
//
// Copyright IBM Corp. 2018, 2018
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

@forward '@carbon/styles/scss/components/fluid-date-picker';
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Code generated by carbon-components. DO NOT EDIT.
//
// Copyright IBM Corp. 2018, 2018
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

@forward '@carbon/styles/scss/components/fluid-date-picker/fluid-date-picker';
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Code generated by carbon-components. DO NOT EDIT.
//
// Copyright IBM Corp. 2018, 2018
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

@forward '@carbon/styles/scss/components/fluid-date-picker';
40 changes: 40 additions & 0 deletions packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2367,6 +2367,12 @@ Map {
"inline": Object {
"type": "bool",
},
"invalid": Object {
"type": "bool",
},
"invalidText": Object {
"type": "node",
},
"light": [Function],
"locale": Object {
"args": Array [
Expand Down Expand Up @@ -2501,6 +2507,12 @@ Map {
],
"type": "oneOfType",
},
"warn": Object {
"type": "bool",
},
"warnText": Object {
"type": "node",
},
},
"render": [Function],
},
Expand Down Expand Up @@ -9399,6 +9411,34 @@ Map {
},
},
},
"unstable__FluidDatePicker" => Object {
"$$typeof": Symbol(react.forward_ref),
"propTypes": Object {
"children": Object {
"type": "node",
},
"className": Object {
"type": "string",
},
"invalid": Object {
"type": "bool",
},
"invalidText": Object {
"type": "node",
},
"warn": Object {
"type": "bool",
},
"warnText": Object {
"type": "node",
},
},
"render": [Function],
},
"unstable__FluidDatePickerInput" => Object {
"$$typeof": Symbol(react.forward_ref),
"render": [Function],
},
"unstable__FluidDropdown" => Object {
"$$typeof": Symbol(react.forward_ref),
"propTypes": Object {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Code generated by @carbon/react. DO NOT EDIT.
//
// Copyright IBM Corp. 2018, 2018
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

@forward '@carbon/styles/scss/components/fluid-date-picker/fluid-date-picker';
9 changes: 9 additions & 0 deletions packages/react/scss/components/fluid-date-picker/_index.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Code generated by @carbon/react. DO NOT EDIT.
//
// Copyright IBM Corp. 2018, 2018
//
// This source code is licensed under the Apache-2.0 license found in the
// LICENSE file in the root directory of this source tree.
//

@forward '@carbon/styles/scss/components/fluid-date-picker';
2 changes: 2 additions & 0 deletions packages/react/src/__tests__/index-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ describe('Carbon Components React', () => {
"unstable_TextDirection",
"unstable__FluidComboBox",
"unstable__FluidComboBoxSkeleton",
"unstable__FluidDatePicker",
"unstable__FluidDatePickerInput",
"unstable__FluidDropdown",
"unstable__FluidDropdownSkeleton",
"unstable__FluidMultiSelect",
Expand Down
57 changes: 56 additions & 1 deletion packages/react/src/components/DatePicker/DatePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import PropTypes from 'prop-types';
import React, { useEffect, useRef } from 'react';
import React, { useContext, useEffect, useRef } from 'react';
import cx from 'classnames';
import flatpickr from 'flatpickr';
import l10n from 'flatpickr/dist/l10n/index';
Expand All @@ -18,6 +18,8 @@ import deprecate from '../../prop-types/deprecate';
import { match, keys } from '../../internal/keyboard';
import { usePrefix } from '../../internal/usePrefix';
import { useSavedCallback } from '../../internal/useSavedCallback';
import { FormContext } from '../FluidForm';
import { WarningFilled, WarningAltFilled } from '@carbon/icons-react';

// Weekdays shorthand for english locale
l10n.en.weekdays.shorthand.forEach((_day, index) => {
Expand Down Expand Up @@ -187,6 +189,10 @@ const DatePicker = React.forwardRef(function DatePicker(
disable,
enable,
inline,
invalid,
invalidText,
warn,
warnText,
light = false,
locale = 'en',
maxDate,
Expand All @@ -201,6 +207,7 @@ const DatePicker = React.forwardRef(function DatePicker(
ref
) {
const prefix = usePrefix();
const { isFluid } = useContext(FormContext);
const startInputField = useRef(null);
const endInputField = useRef(null);
const calendarRef = useRef(null);
Expand Down Expand Up @@ -467,9 +474,37 @@ const DatePicker = React.forwardRef(function DatePicker(
}
}, [value, prefix]);

let fluidError;
if (isFluid) {
if (invalid) {
fluidError = (
<>
<WarningFilled
className={`${prefix}--date-picker__icon ${prefix}--date-picker__icon--invalid`}
/>
<hr className={`${prefix}--date-picker__divider`} />
<div className={`${prefix}--form-requirement`}>{invalidText}</div>
</>
);
}

if (warn && !invalid) {
fluidError = (
<>
<WarningAltFilled
className={`${prefix}--date-picker__icon ${prefix}--date-picker__icon--warn`}
/>
<hr className={`${prefix}--date-picker__divider`} />
<div className={`${prefix}--form-requirement`}>{warnText}</div>
</>
);
}
}

return (
<div className={wrapperClasses} ref={ref} {...rest}>
<div className={datePickerClasses}>{childrenWithProps}</div>
{fluidError}
</div>
);
});
Expand Down Expand Up @@ -530,6 +565,16 @@ DatePicker.propTypes = {
*/
inline: PropTypes.bool,

/**
* Specify whether or not the control is invalid (Fluid only)
*/
invalid: PropTypes.bool,

/**
* Provide the text that is displayed when the control is in error state (Fluid Only)
*/
invalidText: PropTypes.node,

/**
* `true` to use the light version.
*/
Expand Down Expand Up @@ -654,6 +699,16 @@ DatePicker.propTypes = {
PropTypes.object,
PropTypes.number,
]),

/**
* Specify whether the control is currently in warning state (Fluid only)
*/
warn: PropTypes.bool,

/**
* Provide the text that is displayed when the control is in warning state (Fluid only)
*/
warnText: PropTypes.node,
};

export default DatePicker;
25 changes: 21 additions & 4 deletions packages/react/src/components/DatePickerInput/DatePickerInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
import { Calendar, WarningFilled, WarningAltFilled } from '@carbon/icons-react';
import cx from 'classnames';
import PropTypes from 'prop-types';
import React from 'react';
import React, { useContext } from 'react';
import { usePrefix } from '../../internal/usePrefix';
import { FormContext } from '../FluidForm';

const DatePickerInput = React.forwardRef(function DatePickerInput(props, ref) {
const {
Expand All @@ -32,6 +33,7 @@ const DatePickerInput = React.forwardRef(function DatePickerInput(props, ref) {
...rest
} = props;
const prefix = usePrefix();
const { isFluid } = useContext(FormContext);
const datePickerInputProps = {
id,
onChange: (event) => {
Expand Down Expand Up @@ -62,9 +64,12 @@ const DatePickerInput = React.forwardRef(function DatePickerInput(props, ref) {
const inputClasses = cx(`${prefix}--date-picker__input`, {
[`${prefix}--date-picker__input--${size}`]: size,
[`${prefix}--date-picker__input--invalid`]: invalid,
[`${prefix}--date-picker__input--warn`]: warn,
});
const containerClasses = cx(`${prefix}--date-picker-container`, {
[`${prefix}--date-picker--nolabel`]: !labelText,
[`${prefix}--date-picker--fluid--invalid`]: isFluid && invalid,
[`${prefix}--date-picker--fluid--warn`]: isFluid && warn,
});

const input = invalid ? (
Expand Down Expand Up @@ -95,16 +100,25 @@ const DatePickerInput = React.forwardRef(function DatePickerInput(props, ref) {
)}
<div className={wrapperClasses}>
{input}
{isFluid && <DatePickerIcon datePickerType={datePickerType} />}
<DatePickerIcon
datePickerType={datePickerType}
invalid={invalid}
warn={warn}
/>
</div>
{invalid && (
<div className={`${prefix}--form-requirement`}>{invalidText}</div>
<>
{isFluid && <hr className={`${prefix}--date-picker__divider`} />}
<div className={`${prefix}--form-requirement`}>{invalidText}</div>
</>
)}
{warn && (
<>
{isFluid && <hr className={`${prefix}--date-picker__divider`} />}
<div className={`${prefix}--form-requirement`}>{warnText}</div>
</>
)}
{warn && <div className={`${prefix}--form-requirement`}>{warnText}</div>}
{helperText && <div className={helperTextClasses}>{helperText}</div>}
</div>
);
Expand Down Expand Up @@ -211,9 +225,12 @@ DatePickerInput.propTypes = {

function DatePickerIcon({ datePickerType, invalid, warn }) {
const prefix = usePrefix();
const { isFluid } = useContext(FormContext);

if (datePickerType === 'simple' && !invalid && !warn) {
return null;
if (!isFluid) {
return null;
}
}

if (invalid) {
Expand Down
Loading

0 comments on commit 5ee80eb

Please sign in to comment.