diff --git a/e2e/components/FluidTextInput/FluidTextInput-test.e2e.js b/e2e/components/FluidTextInput/FluidTextInput-test.e2e.js
new file mode 100644
index 000000000000..b0d752edd574
--- /dev/null
+++ b/e2e/components/FluidTextInput/FluidTextInput-test.e2e.js
@@ -0,0 +1,37 @@
+/**
+ * Copyright IBM Corp. 2016, 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.
+ */
+
+'use strict';
+
+const { expect, test } = require('@playwright/test');
+const { themes } = require('../../test-utils/env');
+const { snapshotStory, visitStory } = require('../../test-utils/storybook');
+
+test.describe('FluidTextInput', () => {
+ themes.forEach((theme) => {
+ test.describe(theme, () => {
+ test('fluid text input @vrt', async ({ page }) => {
+ await snapshotStory(page, {
+ component: 'FluidTextInput',
+ id: 'experimental-unstable-fluidtextinput--default',
+ theme,
+ });
+ });
+ });
+ });
+
+ test('accessibility-checker @avt', async ({ page }) => {
+ await visitStory(page, {
+ component: 'FluidTextInput',
+ id: 'experimental-unstable-fluidtextinput--default',
+ globals: {
+ theme: 'white',
+ },
+ });
+ await expect(page).toHaveNoACViolations('FluidTextInput');
+ });
+});
diff --git a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
index df56e8b322ee..13c08311100b 100644
--- a/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
+++ b/packages/react/__tests__/__snapshots__/PublicAPI-test.js.snap
@@ -9165,6 +9165,71 @@ Map {
},
},
},
+ "unstable__FluidTextInput" => Object {
+ "propTypes": Object {
+ "className": Object {
+ "type": "string",
+ },
+ "defaultValue": Object {
+ "args": Array [
+ Array [
+ Object {
+ "type": "string",
+ },
+ Object {
+ "type": "number",
+ },
+ ],
+ ],
+ "type": "oneOfType",
+ },
+ "disabled": Object {
+ "type": "bool",
+ },
+ "id": Object {
+ "isRequired": true,
+ "type": "string",
+ },
+ "invalid": Object {
+ "type": "bool",
+ },
+ "invalidText": Object {
+ "type": "node",
+ },
+ "labelText": Object {
+ "isRequired": true,
+ "type": "node",
+ },
+ "onChange": Object {
+ "type": "func",
+ },
+ "onClick": Object {
+ "type": "func",
+ },
+ "placeholder": Object {
+ "type": "string",
+ },
+ "value": Object {
+ "args": Array [
+ Array [
+ Object {
+ "type": "string",
+ },
+ Object {
+ "type": "number",
+ },
+ ],
+ ],
+ "type": "oneOfType",
+ },
+ "warn": Object {
+ "type": "bool",
+ },
+ "warnText": Object {
+ "type": "node",
+ },
+ },
+ },
"unstable_useContextMenu" => Object {},
"unstable_useFeatureFlag" => Object {},
"unstable_useFeatureFlags" => Object {},
diff --git a/packages/react/src/__tests__/index-test.js b/packages/react/src/__tests__/index-test.js
index c90af09ec018..62077eab9c9a 100644
--- a/packages/react/src/__tests__/index-test.js
+++ b/packages/react/src/__tests__/index-test.js
@@ -229,6 +229,7 @@ describe('Carbon Components React', () => {
"unstable_Pagination",
"unstable_Text",
"unstable_TextDirection",
+ "unstable__FluidTextInput",
"unstable_useContextMenu",
"unstable_useFeatureFlag",
"unstable_useFeatureFlags",
diff --git a/packages/react/src/components/FluidTextInput/FluidTextInput.js b/packages/react/src/components/FluidTextInput/FluidTextInput.js
new file mode 100644
index 000000000000..5fa57ed60f87
--- /dev/null
+++ b/packages/react/src/components/FluidTextInput/FluidTextInput.js
@@ -0,0 +1,96 @@
+/**
+ * Copyright IBM Corp. 2016, 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.
+ */
+
+import PropTypes from 'prop-types';
+import React from 'react';
+import classnames from 'classnames';
+import TextInput from '../TextInput';
+import { usePrefix } from '../../internal/usePrefix';
+import { FormContext } from '../FluidForm/FormContext';
+
+function FluidTextInput({ className, ...other }) {
+ const prefix = usePrefix();
+ const classNames = classnames(`${prefix}--text-input--fluid`, className);
+
+ return (
+
+
+
+ );
+}
+
+FluidTextInput.propTypes = {
+ /**
+ * Specify an optional className to be applied to the outer FluidForm wrapper
+ */
+ className: PropTypes.string,
+
+ /**
+ * Optionally provide the default value of the ``
+ */
+ defaultValue: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+
+ /**
+ * Specify whether the `` should be disabled
+ */
+ disabled: PropTypes.bool,
+
+ /**
+ * Specify a custom `id` for the ``
+ */
+ id: PropTypes.string.isRequired,
+
+ /**
+ * Specify whether the control is currently invalid
+ */
+ invalid: PropTypes.bool,
+
+ /**
+ * Provide the text that is displayed when the control is in an invalid state
+ */
+ invalidText: PropTypes.node,
+
+ /**
+ * Provide the text that will be read by a screen reader when visiting this
+ * control
+ */
+ labelText: PropTypes.node.isRequired,
+
+ /**
+ * Optionally provide an `onChange` handler that is called whenever ``
+ * is updated
+ */
+ onChange: PropTypes.func,
+
+ /**
+ * Optionally provide an `onClick` handler that is called whenever the
+ * `` is clicked
+ */
+ onClick: PropTypes.func,
+
+ /**
+ * Specify the placeholder attribute for the ``
+ */
+ placeholder: PropTypes.string,
+
+ /**
+ * Specify the value of the ``
+ */
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
+
+ /**
+ * Specify whether the control is currently in warning state
+ */
+ warn: PropTypes.bool,
+
+ /**
+ * Provide the text that is displayed when the control is in warning state
+ */
+ warnText: PropTypes.node,
+};
+
+export default FluidTextInput;
diff --git a/packages/react/src/components/FluidTextInput/FluidTextInput.stories.js b/packages/react/src/components/FluidTextInput/FluidTextInput.stories.js
new file mode 100644
index 000000000000..93d3beef886c
--- /dev/null
+++ b/packages/react/src/components/FluidTextInput/FluidTextInput.stories.js
@@ -0,0 +1,117 @@
+/**
+ * Copyright IBM Corp. 2016, 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.
+ */
+
+import React from 'react';
+import FluidTextInput from '../FluidTextInput';
+import {
+ ToggletipLabel,
+ Toggletip,
+ ToggletipButton,
+ ToggletipContent,
+} from '../Toggletip';
+import { Information } from '@carbon/icons-react';
+import './test.scss';
+
+export default {
+ title: 'Experimental/unstable__FluidTextInput',
+ component: FluidTextInput,
+};
+
+export const Default = () => (
+
+);
+
+const ToggleTip = (
+ <>
+ Label
+
+
+
+
+
+ Additional field information here.
+
+
+ >
+);
+
+export const DefaultWithTooltip = () => (
+
+);
+
+export const Playground = (args) => (
+
+
+
+);
+
+Playground.argTypes = {
+ playgroundWidth: {
+ control: { type: 'range', min: 300, max: 800, step: 50 },
+ defaultValue: 300,
+ },
+ className: {
+ control: {
+ type: 'text',
+ },
+ defaultValue: 'test-class',
+ },
+ defaultValue: {
+ control: {
+ type: 'text',
+ },
+ },
+ placeholder: {
+ control: {
+ type: 'text',
+ },
+ defaultValue: 'Placeholder text',
+ },
+ invalid: {
+ control: {
+ type: 'boolean',
+ },
+ defaultValue: false,
+ },
+ invalidText: {
+ control: {
+ type: 'text',
+ },
+ defaultValue:
+ 'Error message that is really long can wrap to more lines but should not be excessively long.',
+ },
+ disabled: {
+ control: {
+ type: 'boolean',
+ },
+ defaultValue: false,
+ },
+ labelText: {
+ control: {
+ type: 'text',
+ },
+ defaultValue: 'Label',
+ },
+ warn: {
+ control: {
+ type: 'boolean',
+ },
+ defaultValue: false,
+ },
+ warnText: {
+ control: {
+ type: 'text',
+ },
+ defaultValue:
+ 'Warning message that is really long can wrap to more lines but should not be excessively long.',
+ },
+ value: {
+ control: {
+ type: 'text',
+ },
+ },
+};
diff --git a/packages/react/src/components/FluidTextInput/__tests__/FluidTextInput-test.js b/packages/react/src/components/FluidTextInput/__tests__/FluidTextInput-test.js
new file mode 100644
index 000000000000..7162ffa631d3
--- /dev/null
+++ b/packages/react/src/components/FluidTextInput/__tests__/FluidTextInput-test.js
@@ -0,0 +1,292 @@
+/**
+ * Copyright IBM Corp. 2016, 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.
+ */
+
+import React from 'react';
+import FluidTextInput from '../FluidTextInput';
+import userEvent from '@testing-library/user-event';
+import { render, screen } from '@testing-library/react';
+import { FeatureFlags } from '../../FeatureFlags';
+
+const prefix = 'cds';
+
+describe('FluidTextInput', () => {
+ describe('renders as expected - Component API', () => {
+ it('should spread extra props onto the input element', () => {
+ render(
+
+ );
+
+ expect(screen.getByRole('textbox')).toHaveAttribute(
+ 'data-testid',
+ 'test-id'
+ );
+ });
+
+ it('should support a custom `className` prop on the outermost element', () => {
+ const { container } = render(
+
+
+
+ );
+
+ expect(container.firstChild).toHaveClass('custom-class');
+ });
+
+ it('should support a custom `className` prop on the input element (V10)', () => {
+ render(
+
+ );
+
+ expect(screen.getByRole('textbox')).toHaveClass('custom-class');
+ });
+
+ it('should respect defaultValue prop', () => {
+ render(
+
+ );
+
+ expect(screen.getByRole('textbox')).toHaveAttribute(
+ 'value',
+ 'This is default text'
+ );
+ });
+
+ it('should respect disabled prop', () => {
+ render(
+
+ );
+
+ expect(screen.getByRole('textbox')).toBeDisabled();
+ });
+
+ it('should respect id prop', () => {
+ render();
+
+ expect(screen.getByRole('textbox')).toHaveAttribute('id', 'input-1');
+ });
+
+ it('should respect invalid prop', () => {
+ const { container } = render(
+
+ );
+
+ const invalidIcon = container.querySelector(
+ `svg.${prefix}--text-input__invalid-icon`
+ );
+
+ expect(screen.getByRole('textbox')).toHaveAttribute('data-invalid');
+ expect(screen.getByRole('textbox')).toHaveClass(
+ `${prefix}--text-input--invalid`
+ );
+ expect(invalidIcon).toBeInTheDocument();
+ });
+
+ it('should respect invalidText prop', () => {
+ render(
+
+ );
+
+ expect(screen.getByText('This is invalid text')).toBeInTheDocument();
+ expect(screen.getByText('This is invalid text')).toHaveClass(
+ `${prefix}--form-requirement`
+ );
+ });
+
+ it('should respect labelText prop', () => {
+ render();
+
+ expect(screen.getByText('FluidTextInput label')).toBeInTheDocument();
+ expect(screen.getByText('FluidTextInput label')).toHaveClass(
+ `${prefix}--label`
+ );
+ });
+
+ it('should respect placeholder prop', () => {
+ render(
+
+ );
+
+ expect(
+ screen.getByPlaceholderText('Placeholder text')
+ ).toBeInTheDocument();
+ });
+
+ it('should respect type prop', () => {
+ render(
+
+ );
+
+ expect(screen.getByRole('textbox')).toHaveAttribute(`type`, 'text');
+ });
+
+ it('should respect value prop', () => {
+ render(
+
+ );
+
+ expect(screen.getByRole('textbox')).toHaveAttribute(
+ 'value',
+ 'This is a test value'
+ );
+ });
+
+ it('should respect warn prop', () => {
+ const { container } = render(
+
+ );
+
+ const warnIcon = container.querySelector(
+ `svg.${prefix}--text-input__invalid-icon--warning`
+ );
+
+ expect(screen.getByRole('textbox')).toHaveClass(
+ `${prefix}--text-input--warning`
+ );
+ expect(warnIcon).toBeInTheDocument();
+ });
+
+ it('should respect warnText prop', () => {
+ render(
+
+ );
+
+ expect(screen.getByText('This is warning text')).toBeInTheDocument();
+ expect(screen.getByText('This is warning text')).toHaveClass(
+ `${prefix}--form-requirement`
+ );
+ });
+ });
+
+ describe('behaves as expected - Component API', () => {
+ it('should respect onChange prop', () => {
+ const onChange = jest.fn();
+ render(
+
+ );
+
+ userEvent.type(screen.getByRole('textbox'), 'x');
+ expect(screen.getByRole('textbox')).toHaveValue('x');
+ expect(onChange).toHaveBeenCalledTimes(1);
+ expect(onChange).toHaveBeenCalledWith(
+ expect.objectContaining({
+ target: expect.any(Object),
+ })
+ );
+ });
+
+ it('should respect onClick prop', () => {
+ const onClick = jest.fn();
+ render(
+
+ );
+
+ userEvent.click(screen.getByRole('textbox'));
+ expect(onClick).toHaveBeenCalledTimes(1);
+ expect(onClick).toHaveBeenCalledWith(
+ expect.objectContaining({
+ target: expect.any(Object),
+ })
+ );
+ });
+
+ it('should not call `onClick` when the `` is clicked but disabled', () => {
+ const onClick = jest.fn();
+ render(
+
+ );
+
+ userEvent.click(screen.getByRole('textbox'));
+ expect(onClick).not.toHaveBeenCalled();
+ });
+
+ it('should respect readOnly prop', () => {
+ const onChange = jest.fn();
+ const onClick = jest.fn();
+ const { container } = render(
+
+ );
+
+ // Click events should fire
+ userEvent.click(screen.getByRole('textbox'));
+ expect(onClick).toHaveBeenCalledTimes(1);
+
+ // Change events should *not* fire
+ userEvent.type(screen.getByRole('textbox'), 'x');
+ expect(screen.getByRole('textbox')).not.toHaveValue('x');
+ expect(onChange).toHaveBeenCalledTimes(0);
+
+ // Should display the "read-only" icon
+ const icon = container.querySelector(
+ `svg.${prefix}--text-input__readonly-icon`
+ );
+ expect(icon).toBeInTheDocument();
+ });
+ });
+});
diff --git a/packages/react/src/components/FluidTextInput/index.js b/packages/react/src/components/FluidTextInput/index.js
new file mode 100644
index 000000000000..ad8946d3e7f9
--- /dev/null
+++ b/packages/react/src/components/FluidTextInput/index.js
@@ -0,0 +1,9 @@
+/**
+ * Copyright IBM Corp. 2016, 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.
+ */
+
+export default from './FluidTextInput';
+export FluidTextInput from './FluidTextInput';
diff --git a/packages/react/src/components/FluidTextInput/test.scss b/packages/react/src/components/FluidTextInput/test.scss
new file mode 100644
index 000000000000..39dd297f889b
--- /dev/null
+++ b/packages/react/src/components/FluidTextInput/test.scss
@@ -0,0 +1,11 @@
+.fluid-input-wrapper {
+ display: flex;
+ width: 100%;
+ justify-content: space-between;
+ margin-bottom: 2rem;
+}
+
+.fluid-input-wrapper > * {
+ width: 33%;
+ margin: 0 1rem;
+}
diff --git a/packages/react/src/index.js b/packages/react/src/index.js
index 56affb142734..9c0006811ab5 100644
--- a/packages/react/src/index.js
+++ b/packages/react/src/index.js
@@ -213,6 +213,7 @@ export {
useFeatureFlag as unstable_useFeatureFlag,
useFeatureFlags as unstable_useFeatureFlags,
} from './components/FeatureFlags';
+export { FluidTextInput as unstable__FluidTextInput } from './components/FluidTextInput';
export { Heading, Section } from './components/Heading';
export { IconButton } from './components/IconButton';
export { Layer, useLayer } from './components/Layer';
diff --git a/packages/styles/scss/components/_index.scss b/packages/styles/scss/components/_index.scss
index 532d1dc0a40b..715314a80f19 100644
--- a/packages/styles/scss/components/_index.scss
+++ b/packages/styles/scss/components/_index.scss
@@ -22,6 +22,7 @@
@use 'date-picker';
@use 'dropdown';
@use 'file-uploader';
+@use 'fluid-text-input';
@use 'form';
@use 'inline-loading';
@use 'link';
diff --git a/packages/styles/scss/components/fluid-text-input/_fluid-text-input.scss b/packages/styles/scss/components/fluid-text-input/_fluid-text-input.scss
new file mode 100644
index 000000000000..fd916cf0c8a3
--- /dev/null
+++ b/packages/styles/scss/components/fluid-text-input/_fluid-text-input.scss
@@ -0,0 +1,125 @@
+//
+// 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.
+//
+
+//-----------------------------
+// Fluid Text Input
+//-----------------------------
+@use '../../config' as *;
+@use '../../motion' as *;
+@use '../../spacing' as *;
+@use '../../theme' as *;
+@use '../../utilities/convert' as *;
+@use '../../utilities/focus-outline' as *;
+@use '../text-input';
+
+@mixin fluid-text-input {
+ .#{$prefix}--text-input--fluid.#{$prefix}--text-input-wrapper {
+ position: relative;
+ height: 100%;
+ background: $field;
+ transition: background-color $duration-fast-01 motion(standard, productive),
+ outline $duration-fast-01 motion(standard, productive);
+ }
+
+ .#{$prefix}--text-input--fluid .#{$prefix}--label {
+ position: absolute;
+ z-index: 1;
+ top: rem(13px);
+ left: $spacing-05;
+ display: flex;
+ height: rem(16px);
+ align-items: center;
+ margin: 0;
+ }
+
+ .#{$prefix}--text-input--fluid .#{$prefix}--form__helper-text {
+ display: none;
+ }
+
+ .#{$prefix}--text-input--fluid .#{$prefix}--text-input {
+ min-height: rem(64px);
+ padding: rem(32px) $spacing-05 rem(13px);
+ }
+
+ .#{$prefix}--text-input__divider,
+ .#{$prefix}--text-input--fluid .#{$prefix}--text-input__divider {
+ display: none;
+ }
+
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input__field-wrapper[data-invalid],
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input__field-wrapper--warning {
+ display: block;
+ }
+
+ .#{$prefix}--text-input--fluid input[data-invalid] {
+ outline: none;
+ }
+
+ .#{$prefix}--text-input--fluid .#{$prefix}--form-requirement {
+ padding: $spacing-03 rem(40px) $spacing-03 $spacing-05;
+ margin: 0;
+ }
+
+ .#{$prefix}--text-input--fluid .#{$prefix}--text-input--invalid,
+ .#{$prefix}--text-input--fluid .#{$prefix}--text-input--warning {
+ border-bottom: none;
+ }
+
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input--invalid
+ + .#{$prefix}--text-input__divider,
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input--warning
+ + .#{$prefix}--text-input__divider {
+ display: block;
+ border-style: solid;
+ border-color: $border-subtle;
+ border-bottom: none;
+ margin: 0 1rem;
+ }
+
+ .#{$prefix}--text-input--fluid .#{$prefix}--text-input__invalid-icon {
+ top: rem(80px);
+ }
+
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input__field-wrapper[data-invalid]
+ > .#{$prefix}--text-input--invalid,
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input__field-wrapper--warning
+ > .#{$prefix}--text-input--warning {
+ outline: none;
+ }
+
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input__field-wrapper--warning {
+ border-bottom: 1px solid $border-strong;
+ }
+
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input__field-wrapper[data-invalid]:not(:focus) {
+ @include focus-outline('invalid');
+ }
+
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input__field-wrapper[data-invalid]:focus-within,
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input__field-wrapper--warning:focus-within {
+ @include focus-outline('outline');
+ }
+
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input__field-wrapper[data-invalid]
+ > .#{$prefix}--text-input--invalid:focus,
+ .#{$prefix}--text-input--fluid
+ .#{$prefix}--text-input__field-wrapper--warning
+ > .#{$prefix}--text-input--warning:focus {
+ outline: none;
+ }
+}
diff --git a/packages/styles/scss/components/fluid-text-input/_index.scss b/packages/styles/scss/components/fluid-text-input/_index.scss
new file mode 100644
index 000000000000..a0619895a7bf
--- /dev/null
+++ b/packages/styles/scss/components/fluid-text-input/_index.scss
@@ -0,0 +1,11 @@
+//
+// 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 'fluid-text-input';
+@use 'fluid-text-input';
+
+@include fluid-text-input.fluid-text-input;
diff --git a/packages/styles/scss/components/text-input/_text-input.scss b/packages/styles/scss/components/text-input/_text-input.scss
index 04606f73cef2..7457b6228efc 100644
--- a/packages/styles/scss/components/text-input/_text-input.scss
+++ b/packages/styles/scss/components/text-input/_text-input.scss
@@ -248,6 +248,8 @@
@include skeleton;
}
+ // Deprecated -- Styles have been moved to `fluid-text-input.scss`
+ // V12 - Remove this block
//-----------------------------
// Fluid Text Input
//-----------------------------
@@ -263,6 +265,9 @@
z-index: 1;
top: rem(13px);
left: $spacing-05;
+ display: flex;
+ height: rem(16px);
+ align-items: center;
margin: 0;
}
@@ -281,7 +286,7 @@
}
.#{$prefix}--form--fluid .#{$prefix}--text-input--invalid,
- .#{$prefix}--form--fluid .#{$prefix}--text-input--warn {
+ .#{$prefix}--form--fluid .#{$prefix}--text-input--warning {
border-bottom: none;
}
@@ -289,7 +294,7 @@
.#{$prefix}--text-input--invalid
+ .#{$prefix}--text-input__divider,
.#{$prefix}--form--fluid
- .#{$prefix}--text-input--warn
+ .#{$prefix}--text-input--warning
+ .#{$prefix}--text-input__divider {
display: block;
border-style: solid;
@@ -302,15 +307,17 @@
top: rem(80px);
}
- // V11: Possibly deprecate
- .#{$prefix}--form--fluid .#{$prefix}--text-input-wrapper--light {
- background: $field-02;
- }
-
.#{$prefix}--form--fluid
.#{$prefix}--text-input__field-wrapper[data-invalid]
- > .#{$prefix}--text-input--invalid {
- @include focus-outline('reset');
+ > .#{$prefix}--text-input--invalid,
+ .#{$prefix}--form--fluid
+ .#{$prefix}--text-input__field-wrapper--warning
+ > .#{$prefix}--text-input--warning {
+ outline: none;
+ }
+
+ .#{$prefix}--form--fluid .#{$prefix}--text-input__field-wrapper--warning {
+ border-bottom: 1px solid $border-strong;
}
.#{$prefix}--form--fluid
@@ -319,11 +326,20 @@
}
.#{$prefix}--form--fluid
- .#{$prefix}--text-input__field-wrapper[data-invalid]
- > .#{$prefix}--text-input--invalid:focus {
+ .#{$prefix}--text-input__field-wrapper[data-invalid]:focus-within,
+ .#{$prefix}--form--fluid
+ .#{$prefix}--text-input__field-wrapper--warning:focus-within {
@include focus-outline('outline');
}
+ .#{$prefix}--form--fluid
+ .#{$prefix}--text-input__field-wrapper[data-invalid]
+ > .#{$prefix}--text-input--invalid:focus,
+ .#{$prefix}--form--fluid
+ .#{$prefix}--text-input__field-wrapper--warning
+ > .#{$prefix}--text-input--warning:focus {
+ outline: none;
+ }
//-----------------------------
// Inline Text Input
//-----------------------------