);
},
@@ -35,8 +38,11 @@ export const selectColumn = {
const updatedProps = useConvertIndeterminateProp(row.getToggleRowSelectedProps());
return (
-
-
+
+
);
},
diff --git a/src/Dropdown/Dropdown.scss b/src/Dropdown/Dropdown.scss
index cd3091a107..7982c3a2e2 100644
--- a/src/Dropdown/Dropdown.scss
+++ b/src/Dropdown/Dropdown.scss
@@ -38,10 +38,10 @@
}
.dropdown-toggle::after {
+ content: "";
border: 0;
border-style: solid;
border-width: .15rem .15rem 0 0;
- content: "";
height: .45rem;
margin-inline-start: .5em;
position: relative;
diff --git a/src/Dropdown/README.md b/src/Dropdown/README.md
index 014e8f672f..187fdfb182 100644
--- a/src/Dropdown/README.md
+++ b/src/Dropdown/README.md
@@ -11,9 +11,7 @@ categories:
- Navigation
status: 'Stable'
designStatus: 'Done'
-devStatus: 'TO DO'
-notes: |
- TODO: Remove subcomponent of deprecated implementation soon
+devStatus: 'Done'
---
@@ -120,94 +118,3 @@ You can use `Dropdown.Toggle` with [IconButton](/components/iconbutton) componen
```
-
-***
-
-## Dropdown.Deprecated
-
-```jsx live
-
-
- Search Engines
-
-
- Google
- DuckDuckGo
- Yahoo
-
-
-```
-
-### with icon element
-
-```jsx live
-
-
-
- Search Engines
-
-
- Google
- DuckDuckGo
- Yahoo
-
-
-```
-
-### (Deprecated) basic usage
-
-```jsx live
-
-```
-
-### (Deprecated) menu items as elements
-
-```jsx live
-Google,
- DuckDuckGo ,
- Yahoo ,
- ]}
-/>
-```
-
-### (Deprecated) with icon element
-
-```jsx live
- }
- menuItems={[
- {
- label: 'Google',
- href: 'https://google.com',
- },
- {
- label: 'DuckDuckGo',
- href: 'https://duckduckgo.com',
- },
- {
- label: 'Yahoo',
- href: 'https://yahoo.com',
- },
- ]}
-/>
-```
diff --git a/src/Dropdown/_variables.scss b/src/Dropdown/_variables.scss
index dfc4e9316f..ce24e03da5 100644
--- a/src/Dropdown/_variables.scss
+++ b/src/Dropdown/_variables.scss
@@ -2,32 +2,32 @@
//
// Dropdown menu container and contents.
-$dropdown-min-width: 18rem !default;
-$dropdown-padding-x: 0 !default;
-$dropdown-padding-y: .5rem !default;
-$dropdown-spacer: .125rem !default;
-$dropdown-font-size: $font-size-base !default;
-$dropdown-color: $body-color !default;
-$dropdown-bg: $white !default;
-$dropdown-border-color: rgba($black, .15) !default;
-$dropdown-border-radius: $border-radius !default;
-$dropdown-border-width: $border-width !default;
-$dropdown-inner-border-radius: calc(#{$dropdown-border-radius} - #{$dropdown-border-width}) !default;
-$dropdown-divider-bg: theme-color("gray", "background") !default;
-$dropdown-divider-margin-y: calc($spacer / 2) !default;
-$dropdown-box-shadow: 0 .5rem 1rem rgba($black, .175) !default;
+$dropdown-min-width: var(--pgn-size-dropdown-min-width) !default;
+$dropdown-padding-x: var(--pgn-spacing-dropdown-padding-x-base) !default;
+$dropdown-padding-y: var(--pgn-spacing-dropdown-padding-y-base) !default;
+$dropdown-spacer: var(--pgn-spacing-dropdown-spacer) !default;
+$dropdown-font-size: var(--pgn-typography-dropdown-font-size) !default;
+$dropdown-color: var(--pgn-color-dropdown-text) !default;
+$dropdown-bg: var(--pgn-color-dropdown-bg) !default;
+$dropdown-border-color: var(--pgn-color-dropdown-border) !default;
+$dropdown-border-radius: var(--pgn-size-dropdown-border-radius-base) !default;
+$dropdown-border-width: var(--pgn-size-dropdown-border-width) !default;
+$dropdown-inner-border-radius: var(--pgn-size-dropdown-border-radius-inner) !default;
+$dropdown-divider-bg: var(--pgn-color-dropdown-divider-bg) !default;
+$dropdown-divider-margin-y: var(--pgn-spacing-dropdown-divider-margin-y) !default;
+$dropdown-box-shadow: var(--pgn-elevation-dropdown-box-shadow) !default;
-$dropdown-link-color: theme-color("gray", "dark-text") !default;
-$dropdown-link-hover-color: darken(theme-color("gray", "dark-text"), 5%) !default;
-$dropdown-link-hover-bg: $light-300 !default;
+$dropdown-link-color: var(--pgn-color-dropdown-link-base) !default;
+$dropdown-link-hover-color: var(--pgn-color-dropdown-link-hover-base) !default;
+$dropdown-link-hover-bg: var(--pgn-color-dropdown-link-hover-bg) !default;
-$dropdown-link-active-color: $component-active-color !default;
-$dropdown-link-active-bg: $component-active-bg !default;
+$dropdown-link-active-color: var(--pgn-color-dropdown-link-active-base) !default;
+$dropdown-link-active-bg: var(--pgn-color-dropdown-link-active-bg) !default;
-$dropdown-link-disabled-color: theme-color("gray", "light-text") !default;
+$dropdown-link-disabled-color: var(--pgn-color-dropdown-link-disabled) !default;
-$dropdown-item-padding-y: .25rem !default;
-$dropdown-item-padding-x: 1rem !default;
+$dropdown-item-padding-y: var(--pgn-spacing-dropdown-padding-y-item) !default;
+$dropdown-item-padding-x: var(--pgn-spacing-dropdown-padding-x-item) !default;
-$dropdown-header-color: theme-color("gray", "light-text") !default;
-$dropdown-header-padding: $dropdown-padding-y $dropdown-item-padding-x !default;
+$dropdown-header-color: var(--pgn-color-dropdown-header) !default;
+$dropdown-header-padding: var(--pgn-spacing-dropdown-padding-header) !default;
diff --git a/src/Dropdown/deprecated/Dropdown.test.jsx b/src/Dropdown/deprecated/Dropdown.test.jsx
deleted file mode 100644
index da4bb6d769..0000000000
--- a/src/Dropdown/deprecated/Dropdown.test.jsx
+++ /dev/null
@@ -1,214 +0,0 @@
-import React from 'react';
-import { mount } from 'enzyme';
-import renderer from 'react-test-renderer';
-
-import Dropdown from './index';
-import Icon from '../../Icon';
-
-const menuContent = (
- <>
-
- Search Engines
-
-
- Google
- DuckDuckGo
- Yahoo
-
- >
-);
-
-const menuOpen = (isOpen, wrapper) => {
- expect(wrapper.find('.dropdown').hasClass('show')).toEqual(isOpen);
- expect(wrapper.find('button').prop('aria-expanded')).toEqual(isOpen);
- expect(wrapper.find('[aria-hidden=false]').exists()).toEqual(isOpen);
-};
-
-describe(' ', () => {
- describe('Rendering', () => {
- it('renders the happy path', () => {
- const tree = renderer.create((
-
- {menuContent}
-
- )).toJSON();
- expect(tree).toMatchSnapshot();
- });
-
- it('renders when there is html content in the trigger button', () => {
- const tree = renderer.create((
-
- {menuContent}
-
- )).toJSON();
- expect(tree).toMatchSnapshot();
- });
-
- it('renders with custom menu content', () => {
- const tree = renderer.create((
-
- Custom Content
-
- )).toJSON();
- expect(tree).toMatchSnapshot();
- });
- });
-
- describe('Mouse Interactions', () => {
- const app = document.createElement('div');
- document.body.appendChild(app);
-
- const wrapper = mount({menuContent} , { attachTo: app });
- const menuTrigger = wrapper.find('button');
- const menuContainer = wrapper.find('.dropdown-menu');
- const menuItems = wrapper.find('.dropdown-menu a');
-
- it('opens on trigger click', () => {
- menuTrigger.simulate('click'); // Open
- menuOpen(true, wrapper);
- });
-
- it('should focus on the first item after opening', () => {
- expect(menuItems.first().is(':focus')).toBe(true);
- });
-
- it('does not close on click inside the menu', () => {
- menuContainer.simulate('click'); // Do nothing
- menuOpen(true, wrapper);
- });
-
- it('closes on trigger click', () => {
- menuTrigger.simulate('click'); // Close
- menuOpen(false, wrapper);
- });
-
- it('should focus on the trigger button after closing', () => {
- expect(menuTrigger.is(':focus')).toBe(true);
- });
-
- it('closes on document click when open', () => {
- menuTrigger.simulate('click'); // Open
- menuOpen(true, wrapper);
- document.dispatchEvent(new MouseEvent('click'));
- wrapper.update(); // Let react re-render
- menuOpen(false, wrapper);
- });
- });
-
- describe('Keyboard Interactions', () => {
- // Note: menuContent has three items
- const app = document.createElement('div');
- document.body.appendChild(app);
-
- const wrapper = mount({menuContent} , { attachTo: app });
- const menuTrigger = wrapper.find('button');
- const menuContainer = wrapper.find('.dropdown-menu');
- const menuItems = wrapper.find('.dropdown-menu a');
-
- it('opens on click', () => {
- menuTrigger.simulate('click'); // Open
- menuOpen(true, wrapper);
- });
-
- it('should focus on the first item after opening', () => {
- expect(menuItems.first().is(':focus')).toBe(true);
- });
-
- it('should focus the next item after ArrowDown keyDown', () => {
- menuContainer.simulate('keyDown', { key: 'ArrowDown' });
- expect(menuItems.at(1).is(':focus')).toBe(true);
- });
-
- it('should focus the next item after Tab keyDown', () => {
- menuContainer.simulate('keyDown', { key: 'Tab' });
- expect(menuItems.at(2).is(':focus')).toBe(true);
- });
-
- it('should loop focus to the first item after Tab keyDown on last item', () => {
- menuContainer.simulate('keyDown', { key: 'Tab' });
- expect(menuItems.at(0).is(':focus')).toBe(true);
- });
-
- it('should loop focus to the last item after ArrowUp keyDown on first item', () => {
- menuContainer.simulate('keyDown', { key: 'ArrowUp' });
- expect(menuItems.at(2).is(':focus')).toBe(true);
- });
-
- it('should focus the previous item after Shift + Tab keyDown', () => {
- menuContainer.simulate('keyDown', { key: 'Tab', shiftKey: true });
- expect(menuItems.at(1).is(':focus')).toBe(true);
- });
-
- it('should close the menu on Escape keyDown', () => {
- menuContainer.simulate('keyDown', { key: 'Escape' });
- menuOpen(false, wrapper);
- });
-
- it('should focus on the trigger button after closing', () => {
- expect(menuTrigger.is(':focus')).toBe(true);
- });
- });
-
- describe('Backwards compatibility', () => {
- it('renders the basic usage', () => {
- const tree = renderer.create((
-
- )).toJSON();
- expect(tree).toMatchSnapshot();
- });
-
- it('renders menu items as elements', () => {
- const tree = renderer.create((
- Google,
- DuckDuckGo ,
- Yahoo ,
- ]}
- />
- )).toJSON();
- expect(tree).toMatchSnapshot();
- });
-
- it('renders with icon element', () => {
- const tree = renderer.create((
- }
- menuItems={[
- {
- label: 'Google',
- href: 'https://google.com',
- },
- {
- label: 'DuckDuckGo',
- href: 'https://duckduckgo.com',
- },
- {
- label: 'Yahoo',
- href: 'https://yahoo.com',
- },
- ]}
- />
- )).toJSON();
- expect(tree).toMatchSnapshot();
- });
- });
-});
diff --git a/src/Dropdown/deprecated/DropdownButton.jsx b/src/Dropdown/deprecated/DropdownButton.jsx
deleted file mode 100644
index c692aee437..0000000000
--- a/src/Dropdown/deprecated/DropdownButton.jsx
+++ /dev/null
@@ -1,52 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-// eslint-disable-next-line import/no-cycle
-import { Consumer } from './index';
-
-function DropdownButton({ children, className, ...other }) {
- return (
-
- {({
- buttonRef,
- isOpen,
- toggle,
- triggerId,
- }) => (
- {
- toggle(e);
- if (other.onClick) {
- other.onClick(e);
- }
- }}
- >
- {children}
-
- )}
-
- );
-}
-
-DropdownButton.propTypes = {
- children: PropTypes.node,
- className: PropTypes.string,
-};
-
-DropdownButton.defaultProps = {
- children: undefined,
- className: 'btn-light',
-};
-
-export default DropdownButton;
diff --git a/src/Dropdown/deprecated/DropdownItem.jsx b/src/Dropdown/deprecated/DropdownItem.jsx
deleted file mode 100644
index c83dad5d28..0000000000
--- a/src/Dropdown/deprecated/DropdownItem.jsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-
-function DropdownItem(props) {
- const {
- type, children, className, ...other
- } = props;
- return React.createElement(
- type,
- {
- ...other,
- className: classNames(
- 'dropdown-item',
- className,
- ),
- },
- children,
- );
-}
-
-DropdownItem.propTypes = {
- type: PropTypes.string,
- children: PropTypes.node,
- className: PropTypes.string,
-};
-
-DropdownItem.defaultProps = {
- type: 'a',
- children: undefined,
- className: null,
-};
-
-export default DropdownItem;
diff --git a/src/Dropdown/deprecated/DropdownMenu.jsx b/src/Dropdown/deprecated/DropdownMenu.jsx
deleted file mode 100644
index 105b76b510..0000000000
--- a/src/Dropdown/deprecated/DropdownMenu.jsx
+++ /dev/null
@@ -1,50 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-// eslint-disable-next-line import/no-cycle
-import { Consumer } from './index';
-
-function DropdownMenu({ children, ...other }) {
- return (
-
- {({
- handleMenuKeyDown,
- isOpen,
- menuRef,
- triggerId,
- }) => (
- /* eslint-disable-next-line jsx-a11y/interactive-supports-focus */
- {
- handleMenuKeyDown(e);
- if (other.onKeyDown) {
- other.onKeyDown(e);
- }
- }}
- >
- {children}
-
- )}
-
- );
-}
-
-DropdownMenu.propTypes = {
- children: PropTypes.node,
-};
-
-DropdownMenu.defaultProps = {
- children: undefined,
-};
-
-export default DropdownMenu;
diff --git a/src/Dropdown/deprecated/__snapshots__/Dropdown.test.jsx.snap b/src/Dropdown/deprecated/__snapshots__/Dropdown.test.jsx.snap
deleted file mode 100644
index 0a859c5a74..0000000000
--- a/src/Dropdown/deprecated/__snapshots__/Dropdown.test.jsx.snap
+++ /dev/null
@@ -1,229 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[` Backwards compatibility renders menu items as elements 1`] = `
-
-`;
-
-exports[` Backwards compatibility renders the basic usage 1`] = `
-
-`;
-
-exports[` Backwards compatibility renders with icon element 1`] = `
-
-
-
- Search Engines
-
-
-
-`;
-
-exports[` Rendering renders the happy path 1`] = `
-
-`;
-
-exports[` Rendering renders when there is html content in the trigger button 1`] = `
-
-`;
-
-exports[` Rendering renders with custom menu content 1`] = `
-
- Custom Content
-
-`;
diff --git a/src/Dropdown/deprecated/index.jsx b/src/Dropdown/deprecated/index.jsx
deleted file mode 100644
index b8c1fed8a7..0000000000
--- a/src/Dropdown/deprecated/index.jsx
+++ /dev/null
@@ -1,222 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-// eslint-disable-next-line import/no-cycle
-import DropdownButton from './DropdownButton';
-// eslint-disable-next-line import/no-cycle
-import DropdownMenu from './DropdownMenu';
-import DropdownItem from './DropdownItem';
-
-import withDeprecatedProps, { DeprTypes } from '../../withDeprecatedProps';
-
-const { Provider, Consumer } = React.createContext();
-
-class Dropdown extends React.Component {
- // eslint-disable-next-line react/sort-comp
- static idCounter = 0; // For creating unique ids
-
- constructor(props) {
- super(props);
- this.state = {
- open: false,
- };
-
- // Used for aria labelling. Increment the id counter so the next id can be unique
- this.uniqueId = Dropdown.idCounter;
- Dropdown.idCounter += 1;
- this.triggerId = `pgn__dropdown-trigger-${this.uniqueId}`;
-
- this.containerRef = React.createRef();
- this.menuRef = React.createRef();
- this.buttonRef = React.createRef();
- }
-
- componentDidUpdate(prevProps, prevState) {
- if (prevState.open !== this.state.open) {
- if (this.state.open) {
- this.focusFirst();
- } else {
- this.buttonRef.current.focus();
- }
- }
- }
-
- componentWillUnmount() {
- document.removeEventListener('click', this.handleDocumentClick, true);
- }
-
- getFocusableElements() {
- const selector = 'button:not([disabled]), [href]:not([disabled]), input:not([disabled]), select:not([disabled]), textarea:not([disabled]), [tabindex]:not([tabindex="-1"]):not([disabled])';
- return Array.from(this.menuRef.current.querySelectorAll(selector));
- }
-
- handleDocumentClick = (e) => {
- if (this.containerRef.current.contains(e.target) && this.containerRef.current !== e.target) {
- return;
- }
- if (this.state.open) {
- this.close();
- }
- };
-
- handleMenuKeyDown = (e) => {
- switch (e.key) {
- case 'ArrowUp':
- e.preventDefault();
- this.focusPrevious();
- break;
- case 'ArrowDown':
- e.preventDefault();
- this.focusNext();
- break;
- case 'Tab':
- e.preventDefault();
- if (e.shiftKey) {
- this.focusPrevious();
- } else {
- this.focusNext();
- }
- break;
- case 'Escape':
- e.stopPropagation();
- this.close();
- break;
- default:
- break;
- }
- };
-
- toggle = () => {
- if (this.state.open) {
- this.close();
- } else {
- this.open();
- }
- };
-
- close() {
- document.removeEventListener('click', this.handleDocumentClick, true);
- this.setState({
- open: false,
- });
- }
-
- open() {
- // adding event listener here so the user can close dropdown on click outside of the dropdown
- document.addEventListener('click', this.handleDocumentClick, true);
- this.setState({
- open: true,
- });
- }
-
- focusFirst() {
- const focusableElements = this.getFocusableElements();
- if (focusableElements.length) { focusableElements[0].focus(); }
- }
-
- focusNext() {
- const allFocusableElements = this.getFocusableElements();
- if (allFocusableElements.length === 0) { return; }
- const activeIndex = allFocusableElements.indexOf(document.activeElement);
- const nextIndex = (activeIndex + 1) % allFocusableElements.length;
- allFocusableElements[nextIndex].focus();
- }
-
- focusPrevious() {
- const allFocusableElements = this.getFocusableElements();
- if (allFocusableElements.length === 0) { return; }
- const activeIndex = allFocusableElements.indexOf(document.activeElement);
- const previousIndex = ((activeIndex - 1) + allFocusableElements.length) % allFocusableElements.length;
- allFocusableElements[previousIndex].focus();
- }
-
- render() {
- const { children, ...other } = this.props;
-
- return (
-
- );
- }
-}
-
-Dropdown.propTypes = {
- children: PropTypes.node.isRequired,
-};
-
-Dropdown.Item = DropdownItem;
-Dropdown.Button = DropdownButton;
-Dropdown.Menu = DropdownMenu;
-
-const DropdownWithDeprecatedProps = withDeprecatedProps(Dropdown, 'Dropdown', {
- menuItems: {
- deprType: DeprTypes.MOVED_AND_FORMAT,
- message: 'They should be components sent as children.',
- newName: 'children',
- transform: (menuItems, allProps) => {
- if (!Array.isArray(menuItems)) { return null; }
- return (
- <>
-
- {React.isValidElement(allProps.iconElement) ? allProps.iconElement : null }
- {allProps.title}
-
-
- {menuItems.map((menuItem, i) => {
- /* eslint-disable react/no-array-index-key */
- if (React.isValidElement(menuItem)) {
- return React.cloneElement(menuItem, {
- className: 'dropdown-item',
- key: i,
- });
- }
- return {menuItem.label} ;
- /* eslint-enable react/no-array-index-key */
- })}
-
- >
- );
- },
- },
- title: {
- deprType: DeprTypes.REMOVED,
- message: 'It should be specified inside the Dropdown.Button component',
- },
- buttonType: {
- deprType: DeprTypes.REMOVED,
- message: 'It should be specified as a className prop',
- },
- iconElement: {
- deprType: DeprTypes.REMOVED,
- message: 'It should be specified inside the buttonContent prop.',
- },
-});
-
-DropdownWithDeprecatedProps.propTypes = Dropdown.propTypes;
-DropdownWithDeprecatedProps.defaultProps = Dropdown.defaultProps;
-DropdownWithDeprecatedProps.Item = Dropdown.Item;
-DropdownWithDeprecatedProps.Button = Dropdown.Button;
-DropdownWithDeprecatedProps.Menu = Dropdown.Menu;
-
-export { Provider, Consumer };
-export default DropdownWithDeprecatedProps;
diff --git a/src/Dropdown/index.jsx b/src/Dropdown/index.jsx
index e1eebd64f0..88f10fad20 100644
--- a/src/Dropdown/index.jsx
+++ b/src/Dropdown/index.jsx
@@ -5,7 +5,6 @@ import BaseDropdown from 'react-bootstrap/Dropdown';
import DropdownMenu from 'react-bootstrap/DropdownMenu';
import BaseDropdownItem from 'react-bootstrap/DropdownItem';
import BaseDropdownToggle from 'react-bootstrap/DropdownToggle';
-import DropdownDeprecated from './deprecated';
import {
Button,
IconButton,
@@ -136,7 +135,6 @@ Dropdown.Item.defaultProps = {
className: undefined,
};
-Dropdown.Deprecated = DropdownDeprecated;
Dropdown.Toggle = DropdownToggle;
Dropdown.Menu = DropdownMenu;
Dropdown.Header = BaseDropdown.Header;
diff --git a/src/Dropzone/Dropzone.scss b/src/Dropzone/Dropzone.scss
index e804efeff4..5c892fda89 100644
--- a/src/Dropzone/Dropzone.scss
+++ b/src/Dropzone/Dropzone.scss
@@ -6,24 +6,24 @@
align-items: center;
min-height: 200px;
padding: $dropzone-padding;
- border: $dropzone-border-default;
+ border: $dropzone-border-default dashed $dropzone-border-color-default;
box-sizing: border-box;
cursor: pointer;
&:hover {
- border: $dropzone-border-hover;
+ border: $dropzone-border-hover solid $dropzone-border-color-hover;
}
&:focus {
- border: $dropzone-border-focus;
+ border: $dropzone-border-focus solid $dropzone-border-color-focus;
}
&.pgn__dropzone-validation-error {
- border: $dropzone-border-error;
+ border: $dropzone-border-error solid $dropzone-border-color-error;
}
&.pgn__dropzone-active {
- border: $dropzone-border-active;
+ border: $dropzone-border-active solid $dropzone-border-color-active;
}
}
diff --git a/src/Dropzone/_variables.scss b/src/Dropzone/_variables.scss
index ee7caed6a4..6a107a5088 100644
--- a/src/Dropzone/_variables.scss
+++ b/src/Dropzone/_variables.scss
@@ -1,9 +1,14 @@
-$dropzone-padding: 1.5rem !default;
-$dropzone-border-default: 1px dashed $gray-500 !default;
-$dropzone-border-hover: 2px solid $info-300 !default;
-$dropzone-border-focus: 2px solid $info-300 !default;
-$dropzone-border-active: 2px solid $primary-500 !default;
-$dropzone-border-error: 2px solid $danger-300 !default;
-$dropzone-error-wrapper-color: $danger-500 !default;
-$dropzone-restriction-msg-font-size: $x-small-font-size !default;
-$dropzone-restriction-msg-color: $gray-500 !default;
+$dropzone-padding: var(--pgn-spacing-dropzone-padding) !default;
+$dropzone-border-default: var(--pgn-spacing-dropzone-border-base) !default;
+$dropzone-border-hover: var(--pgn-spacing-dropzone-border-hover) !default;
+$dropzone-border-focus: var(--pgn-spacing-dropzone-border-focus) !default;
+$dropzone-border-active: var(--pgn-spacing-dropzone-border-active) !default;
+$dropzone-border-error: var(--pgn-spacing-dropzone-border-error) !default;
+$dropzone-error-wrapper-color: var(--pgn-color-dropzone-error-wrapper) !default;
+$dropzone-restriction-msg-font-size: var(--pgn-typography-dropzone-restriction-msg-font-size) !default;
+$dropzone-restriction-msg-color: var(--pgn-color-dropzone-restriction-msg) !default;
+$dropzone-border-color-default: var(--pgn-color-dropzone-border-base) !default;
+$dropzone-border-color-hover: var(--pgn-color-dropzone-border-hover) !default;
+$dropzone-border-color-focus: var(--pgn-color-dropzone-border-focus) !default;
+$dropzone-border-color-active: var(--pgn-color-dropzone-border-active) !default;
+$dropzone-border-color-error: var(--pgn-color-dropzone-border-error) !default;
diff --git a/src/Dropzone/tests/__snapshots__/DefaultContent.test.jsx.snap b/src/Dropzone/tests/__snapshots__/DefaultContent.test.jsx.snap
index f28f6f9725..5494d592d4 100644
--- a/src/Dropzone/tests/__snapshots__/DefaultContent.test.jsx.snap
+++ b/src/Dropzone/tests/__snapshots__/DefaultContent.test.jsx.snap
@@ -10,6 +10,7 @@ Array [
>
diff --git a/src/Dropzone/tests/__snapshots__/Dropzone.test.jsx.snap b/src/Dropzone/tests/__snapshots__/Dropzone.test.jsx.snap
index a42fd297d6..8fa5c7e687 100644
--- a/src/Dropzone/tests/__snapshots__/Dropzone.test.jsx.snap
+++ b/src/Dropzone/tests/__snapshots__/Dropzone.test.jsx.snap
@@ -38,6 +38,7 @@ exports[` successfully renders 1`] = `
>
successfully renders 1`] = `
>
diff --git a/src/Fieldset/Fieldset.scss b/src/Fieldset/Fieldset.scss
deleted file mode 100644
index 5e039319ad..0000000000
--- a/src/Fieldset/Fieldset.scss
+++ /dev/null
@@ -1,12 +0,0 @@
-.paragon-fieldset {
- margin-bottom: $spacer * 1.5;
-
- .form-control {
- height: auto;
- }
-
- fieldset legend {
- width: auto;
- margin-bottom: 0;
- }
-}
diff --git a/src/Fieldset/Fieldset.test.jsx b/src/Fieldset/Fieldset.test.jsx
deleted file mode 100644
index d852268a00..0000000000
--- a/src/Fieldset/Fieldset.test.jsx
+++ /dev/null
@@ -1,105 +0,0 @@
-import React from 'react';
-import { mount } from 'enzyme';
-
-import Fieldset from './index';
-import newId from '../utils/newId';
-import ValidationMessage from '../ValidationMessage';
-import Variant from '../utils/constants';
-
-const dangerVariant = {
- status: Variant.status.DANGER,
-};
-const id = 'input1';
-const legend = 'A Fieldset';
-const invalidMessage = 'This is invalid!';
-const children = 'Input goes here';
-const variant = {
- status: Variant.status.INFO,
-};
-const variantIconDescription = 'Error';
-
-const baseProps = {
- className: '',
- id,
- isValid: true,
- legend,
- invalidMessage,
- variant,
- variantIconDescription,
-};
-
-const mockedNextId = 'fieldset1';
-
-// Cannot reference variables inside of a jest mock function: https://github.com/facebook/jest/issues/2567
-jest.mock('../utils/newId', () => jest.fn().mockReturnValue('fieldset1'));
-
-describe('Fieldset', () => {
- let wrapper;
-
- beforeEach(() => {
- const props = {
- ...baseProps,
- };
- wrapper = mount({children} );
- });
- it('renders', () => {
- const fieldset = wrapper.find('fieldset.form-control');
- expect(fieldset.exists()).toEqual(true);
- expect(fieldset.hasClass('is-invalid-nodanger')).toEqual(true);
- expect(fieldset.prop('aria-describedby')).toEqual(`error-${id}`);
- const legendElem = fieldset.find('legend');
- expect(legendElem.text()).toEqual(legend);
- expect(fieldset.text()).toEqual(legend + children);
- const feedback = wrapper.find(ValidationMessage);
- expect(feedback.prop('id')).toEqual(`error-${id}`);
- });
- it('renders with auto-generated id if not specified', () => {
- const props = {
- ...baseProps,
- id: undefined,
- };
- wrapper = mount( );
- const feedback = wrapper.find(ValidationMessage);
- expect(feedback.prop('id')).toEqual('error-fieldset1');
- });
- it('renders invalidMessage when isValid is false', () => {
- wrapper.setProps({ isValid: false });
- const feedback = wrapper.find(ValidationMessage);
- expect(feedback.prop('invalidMessage')).toEqual(invalidMessage);
- });
- it('renders with danger variant when isValid is false and variant is DANGER', () => {
- wrapper.setProps({ isValid: false, variant: dangerVariant });
- const feedback = wrapper.find(ValidationMessage);
- expect(feedback.hasClass('invalid-feedback-nodanger')).toEqual(false);
- expect(feedback.prop('variantIconDescription')).toEqual(variantIconDescription);
- expect(feedback.prop('invalidMessage')).toEqual(invalidMessage);
- expect(feedback.prop('variant')).toEqual(dangerVariant);
- });
- it('receives new id when a valid one is passed to props', () => {
- const nextId = 'new-id';
- let fieldset = wrapper.find('fieldset.form-control');
- let feedback = wrapper.find(ValidationMessage);
- expect(fieldset.prop('aria-describedby')).toEqual(`error-${id}`);
- expect(feedback.prop('id')).toEqual(`error-${id}`);
-
- wrapper.setProps({ id: nextId });
- fieldset = wrapper.find('fieldset.form-control');
- feedback = wrapper.find(ValidationMessage);
- expect(fieldset.prop('aria-describedby')).toEqual(`error-${nextId}`);
- expect(feedback.prop('id')).toEqual(`error-${nextId}`);
- });
- it('auto-generates new id when an invalid one is passed to props', () => {
- const nextId = '';
- let fieldset = wrapper.find('fieldset.form-control');
- let feedback = wrapper.find(ValidationMessage);
- expect(fieldset.prop('aria-describedby')).toEqual(`error-${id}`);
- expect(feedback.prop('id')).toEqual(`error-${id}`);
-
- wrapper.setProps({ id: nextId });
- expect(newId).toHaveBeenCalledWith('fieldset');
- fieldset = wrapper.find('fieldset.form-control');
- feedback = wrapper.find(ValidationMessage);
- expect(fieldset.prop('aria-describedby')).toEqual(`error-${mockedNextId}`);
- expect(feedback.prop('id')).toEqual(`error-${mockedNextId}`);
- });
-});
diff --git a/src/Fieldset/README.md b/src/Fieldset/README.md
deleted file mode 100644
index e180bf1e64..0000000000
--- a/src/Fieldset/README.md
+++ /dev/null
@@ -1,146 +0,0 @@
----
-title: 'Fieldset'
-type: 'component'
-components:
-- Fieldset
-categories:
-- Forms (deprecated)
-status: 'Deprecate Soon'
-designStatus: 'TBD'
-devStatus: 'To Do'
-notes: |
- Unneeded. Used in one place (studio-frontend/src/components/EditImageModal/index.jsx)
----
-
-## basic usage
-
-```jsx live
-
-```
-
-## invalid
-
-```jsx live
-
-```
-
-## invalid with danger theme
-
-```jsx live
-
-```
-
-## Validated Form
-
-```jsx live
-class ValidatedForm extends React.Component {
- constructor(props) {
- super(props);
- this.firstInputRef = null;
- this.secondInputRef = null;
-
- this.state = {
- isValid: true,
- };
-
- this.handleSubmit = this.handleSubmit.bind(this);
- }
-
- handleSubmit(event) {
- if (
- this.firstInputRef.value.length === 0 &&
- this.secondInputRef.value.length === 0
- ) {
- this.setState({
- isValid: false,
- });
- } else {
- this.setState({
- isValid: true,
- });
- }
- event.preventDefault();
- }
-
- render() {
- return (
-
- );
- }
-}
-```
diff --git a/src/Fieldset/index.jsx b/src/Fieldset/index.jsx
deleted file mode 100644
index 56905a46d0..0000000000
--- a/src/Fieldset/index.jsx
+++ /dev/null
@@ -1,106 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-
-import newId from '../utils/newId';
-
-import ValidationMessage from '../ValidationMessage/index';
-import Variant from '../utils/constants';
-
-const inputProps = {
- legend: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
-
- children: PropTypes.node,
- className: PropTypes.string,
- id: PropTypes.string,
- isValid: PropTypes.bool,
- invalidMessage: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
- variant: PropTypes.shape({
- status: PropTypes.oneOf(Object.keys(Variant.status).map(k => Variant.status[k])),
- }),
- variantIconDescription: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
-};
-
-const defaultProps = {
- children: null,
- className: undefined,
- id: '',
- isValid: true,
- invalidMessage: '',
- variant: {
- status: Variant.status.INFO,
- },
- variantIconDescription: '',
-};
-
-class Fieldset extends React.Component {
- constructor(props) {
- super(props);
- this.state = { id: props.id || newId('fieldset') };
- }
-
- static getDerivedStateFromProps(nextProps, prevState) {
- if (nextProps.id !== prevState.id) {
- return { id: nextProps.id || newId('fieldset') };
- }
-
- return null;
- }
-
- getVariantClassName() {
- const { variant } = this.props;
- let className;
-
- switch (variant.status) {
- case Variant.status.INFO:
- className = 'is-invalid-nodanger';
- break;
- default:
- break;
- }
-
- return className;
- }
-
- render() {
- const {
- className,
- children,
- variantIconDescription,
- invalidMessage,
- isValid,
- legend,
- variant,
- } = this.props;
- const errorId = `error-${this.state.id}`;
- return (
-
-
- {legend}
- {children}
-
-
-
- );
- }
-}
-
-Fieldset.propTypes = inputProps;
-Fieldset.defaultProps = defaultProps;
-
-export default Fieldset;
diff --git a/src/Figure/README.md b/src/Figure/README.md
index b9020b241c..9e318c4658 100644
--- a/src/Figure/README.md
+++ b/src/Figure/README.md
@@ -23,7 +23,7 @@ notes: |
Nulla vitae elit libero, a pharetra augue mollis interdum.
diff --git a/src/Form/README.md b/src/Form/README.md
index c7ec6f7ac5..6970340abf 100644
--- a/src/Form/README.md
+++ b/src/Form/README.md
@@ -75,17 +75,8 @@ notes: |
-
-
+ Check this switch
+ disabled switch
@@ -103,7 +94,7 @@ notes: |
-
+ Check me out
@@ -166,21 +157,12 @@ notes: |
-
-
+ Check this switch
+ disabled switch
-
+ Check me out
diff --git a/src/Form/_Form.scss b/src/Form/_Form.scss
index 6d42e7dccd..d4ee1070e0 100644
--- a/src/Form/_Form.scss
+++ b/src/Form/_Form.scss
@@ -1,14 +1,11 @@
@import "variables";
-@import "~bootstrap/scss/forms";
+@import "bootstrap-forms";
@import "~bootstrap/scss/input-group";
-@import "~bootstrap/scss/custom-forms";
+@import "bootstrap-custom-forms";
@import "mixins";
@import "FormText";
@import "FormControlSet";
-$form-control-icon-width: 32px !default;
-$select-icon-padding: .5625rem !default;
-
// A form input state used by the now deprecate Fieldset and asInput
// we can remove this when they are deleted.
.form-control.is-invalid.is-invalid-nodanger {
@@ -117,13 +114,13 @@ $select-icon-padding: .5625rem !default;
&.pgn__form-control-decorator-leading {
inset-inline-start: 0;
padding-inline-start: $input-padding-x;
- padding-inline-end: calc($input-padding-x / 2);
+ padding-inline-end: calc(#{$input-padding-x} / 2);
}
&.pgn__form-control-decorator-trailing {
inset-inline-end: 0;
- padding-inline-start: calc($input-padding-x / 2);
- padding-inline-end: calc(#{$input-padding-y-sm} - #{2 * $input-border-width});
+ padding-inline-start: calc(#{$input-padding-x} / 2);
+ padding-inline-end: calc(#{$input-padding-y-sm} - calc(2 * #{$input-border-width}));
}
.pgn__form-control-decorator-group-lg & {
@@ -137,7 +134,7 @@ $select-icon-padding: .5625rem !default;
&.pgn__form-control-decorator-trailing {
padding-left: calc($input-padding-x-lg / 2);
- padding-right: calc(#{$input-padding-y} - #{2 * $input-border-width});
+ padding-right: calc(#{$input-padding-y} - (2 * $input-border-width));
}
}
@@ -152,7 +149,7 @@ $select-icon-padding: .5625rem !default;
&.pgn__form-control-decorator-trailing {
padding-left: calc($input-padding-x-sm / 2);
- padding-right: calc(#{$input-padding-y-sm} - #{2 * $input-border-width});
+ padding-right: calc($input-padding-y-sm - (2 * $input-border-width));
}
}
@@ -198,7 +195,7 @@ $select-icon-padding: .5625rem !default;
// Prevent background-color from being output as "transparent"
// Firefox doesn't handle the first animation well from transparent to
// a color. Adding an alpha channel smooths it out.
- background-color: rgba($input-bg, .01);
+ background-color: $form-control-floating-label-text-bg;
white-space: nowrap;
max-width: 75vw;
display: block;
@@ -215,7 +212,7 @@ $select-icon-padding: .5625rem !default;
transform: translateX(#{$form-control-icon-width});
[dir="rtl"] & {
- transform: translateX(#{-$form-control-icon-width});
+ transform: translateX(calc(-1 * #{$form-control-icon-width}));
}
}
}
@@ -319,7 +316,7 @@ $select-icon-padding: .5625rem !default;
}
select.form-control {
- padding-inline-end: 2rem + $select-icon-padding;
+ padding-inline-end: calc(#{$select-icon-padding} + 2rem);
background-image: $custom-select-indicator;
background-position: right $select-icon-padding center;
background-repeat: no-repeat;
@@ -365,7 +362,9 @@ select.form-control {
height: $custom-control-indicator-size;
width: $custom-control-indicator-size;
background-color: $custom-control-indicator-bg;
- border: solid $custom-control-indicator-border-width $custom-control-indicator-border-color;
+ border:
+ solid $custom-control-indicator-border-width
+ $custom-control-indicator-border-color;
border-radius: $custom-checkbox-indicator-border-radius;
margin-inline-end: $custom-control-gutter;
background-position: center;
@@ -410,10 +409,10 @@ select.form-control {
&:focus::before {
content: "";
position: absolute;
- top: -$form-check-position-axis;
- right: -$form-check-position-axis;
- bottom: -$form-check-position-axis;
- left: -$form-check-position-axis;
+ top: calc(#{$form-check-position-axis} * -1);
+ right: calc(#{$form-check-position-axis} * -1);
+ bottom: calc(#{$form-check-position-axis} * -1);
+ left: calc(#{$form-check-position-axis} * -1);
border: $form-check-border-width solid $input-focus-border-color;
border-radius: $form-check-focus-border-radius;
}
diff --git a/src/Form/_bootstrap-custom-forms.scss b/src/Form/_bootstrap-custom-forms.scss
new file mode 100644
index 0000000000..33713d234e
--- /dev/null
+++ b/src/Form/_bootstrap-custom-forms.scss
@@ -0,0 +1,553 @@
+// Embedded icons from Open Iconic.
+// Released under MIT and copyright 2014 Waybury.
+// https://useiconic.com/open
+
+
+// Checkboxes and radios
+//
+// Base class takes care of all the key behavioral aspects.
+
+.custom-control {
+ position: relative;
+ z-index: 1;
+ display: block;
+ min-height: calc(#{$font-size-base} * #{$line-height-base});
+ padding-left: calc(#{$custom-control-gutter} + #{$custom-control-indicator-size});
+ print-color-adjust: exact; // Keep themed appearance for print
+}
+
+.custom-control-inline {
+ display: inline-flex;
+ margin-right: $custom-control-spacer-x;
+}
+
+.custom-control-input {
+ position: absolute;
+ left: 0;
+ z-index: -1; // Put the input behind the label so it doesn't overlay text
+ width: $custom-control-indicator-size;
+ height: calc((#{$font-size-base} * #{$line-height-base} + #{$custom-control-indicator-size}) * .5);
+ opacity: 0;
+
+ &:checked ~ .custom-control-label::before {
+ color: $custom-control-indicator-checked-color;
+ border-color: $custom-control-indicator-checked-border-color;
+
+ @include gradient-bg($custom-control-indicator-checked-bg);
+ @include box-shadow($custom-control-indicator-checked-box-shadow);
+ }
+
+ &:focus ~ .custom-control-label::before {
+ // the mixin is not used here to make sure there is feedback
+ @if $enable-shadows {
+ box-shadow: $input-box-shadow, $custom-control-indicator-focus-box-shadow;
+ }
+
+ @else {
+ box-shadow: $custom-control-indicator-focus-box-shadow;
+ }
+ }
+
+ &:focus:not(:checked) ~ .custom-control-label::before {
+ border-color: $custom-control-indicator-focus-border-color;
+ }
+
+ &:not(:disabled):active ~ .custom-control-label::before {
+ color: $custom-control-indicator-active-color;
+ background-color: $custom-control-indicator-active-bg;
+ border-color: $custom-control-indicator-active-border-color;
+
+ @include box-shadow($custom-control-indicator-active-box-shadow);
+ }
+
+ // Use [disabled] and :disabled to work around https://github.com/twbs/bootstrap/issues/28247
+ &[disabled],
+ &:disabled {
+ ~ .custom-control-label {
+ color: $custom-control-label-disabled-color;
+
+ &::before {
+ background-color: $custom-control-indicator-disabled-bg;
+ }
+ }
+ }
+}
+
+// Custom control indicators
+//
+// Build the custom controls out of pseudo-elements.
+
+.custom-control-label {
+ position: relative;
+ margin-bottom: 0;
+ color: $custom-control-label-color;
+ vertical-align: top;
+ cursor: $custom-control-cursor;
+
+ // Background-color and (when enabled) gradient
+ &::before {
+ content: "";
+ position: absolute;
+ top: calc((#{$font-size-base} * #{$line-height-base} - #{$custom-control-indicator-size}) * .5);
+ left: -($custom-control-gutter + $custom-control-indicator-size);
+ display: block;
+ width: $custom-control-indicator-size;
+ height: $custom-control-indicator-size;
+ pointer-events: none;
+ background-color: $custom-control-indicator-bg;
+ border: $custom-control-indicator-border-width solid $custom-control-indicator-border-color;
+
+ @include box-shadow($custom-control-indicator-box-shadow);
+ }
+
+ // Foreground (icon)
+ &::after {
+ content: "";
+ position: absolute;
+ top: calc((#{$font-size-base} * #{$line-height-base} - #{$custom-control-indicator-size}) * .5);
+ left: -($custom-control-gutter + $custom-control-indicator-size);
+ display: block;
+ width: $custom-control-indicator-size;
+ height: $custom-control-indicator-size;
+ background: 50% / #{$custom-control-indicator-bg-size} no-repeat;
+ }
+}
+
+
+// Checkboxes
+//
+// Tweak just a few things for checkboxes.
+
+.custom-checkbox {
+ .custom-control-label::before {
+ @include border-radius($custom-checkbox-indicator-border-radius);
+ }
+
+ .custom-control-input:checked ~ .custom-control-label {
+ &::after {
+ background-image: escape-svg($custom-checkbox-indicator-icon-checked);
+ }
+ }
+
+ .custom-control-input:indeterminate ~ .custom-control-label {
+ &::before {
+ border-color: $custom-checkbox-indicator-indeterminate-border-color;
+
+ @include gradient-bg($custom-checkbox-indicator-indeterminate-bg);
+ @include box-shadow($custom-checkbox-indicator-indeterminate-box-shadow);
+ }
+
+ &::after {
+ background-image: escape-svg($custom-checkbox-indicator-icon-indeterminate);
+ }
+ }
+
+ .custom-control-input:disabled {
+ &:checked ~ .custom-control-label::before {
+ @include gradient-bg($custom-control-indicator-checked-disabled-bg);
+ }
+
+ &:indeterminate ~ .custom-control-label::before {
+ @include gradient-bg($custom-control-indicator-checked-disabled-bg);
+ }
+ }
+}
+
+// Radios
+//
+// Tweak just a few things for radios.
+
+.custom-radio {
+ .custom-control-label::before {
+ // stylelint-disable-next-line property-disallowed-list
+ border-radius: $custom-radio-indicator-border-radius;
+ }
+
+ .custom-control-input:checked ~ .custom-control-label {
+ &::after {
+ background-image: escape-svg($custom-radio-indicator-icon-checked);
+ }
+ }
+
+ .custom-control-input:disabled {
+ &:checked ~ .custom-control-label::before {
+ @include gradient-bg($custom-control-indicator-checked-disabled-bg);
+ }
+ }
+}
+
+
+// switches
+//
+// Tweak a few things for switches
+
+.custom-switch {
+ padding-left: calc(#{$custom-switch-width} + #{$custom-control-gutter});
+
+ .custom-control-label {
+ &::before {
+ left: calc(-1 * (#{$custom-switch-width} + #{$custom-control-gutter}));
+ width: $custom-switch-width;
+ pointer-events: all;
+ // stylelint-disable-next-line property-disallowed-list
+ border-radius: $custom-switch-indicator-border-radius;
+ }
+
+ &::after {
+ // stylelint-disable-next-line max-line-length
+ top: calc(calc((#{$font-size-base} * #{$line-height-base} - #{$custom-control-indicator-size}) * .5) + calc(#{$custom-control-indicator-border-width} * 2));
+ // stylelint-disable-next-line max-line-length
+ left: calc(calc(-1 * (#{$custom-switch-width} + #{$custom-control-gutter})) + calc(#{$custom-control-indicator-border-width} * 2));
+ width: $custom-switch-indicator-size;
+ height: $custom-switch-indicator-size;
+ background-color: $custom-control-indicator-border-color;
+ // stylelint-disable-next-line property-disallowed-list
+ border-radius: $custom-switch-indicator-border-radius;
+ transition: transform .15s ease-in-out, $custom-forms-transition;
+ }
+ }
+
+ .custom-control-input:checked ~ .custom-control-label {
+ &::after {
+ background-color: $custom-control-indicator-bg;
+ transform: translateX(calc(#{$custom-switch-width} - #{$custom-control-indicator-size}));
+ }
+ }
+
+ .custom-control-input:disabled {
+ &:checked ~ .custom-control-label::before {
+ @include gradient-bg($custom-control-indicator-checked-disabled-bg);
+ }
+ }
+}
+
+
+// Select
+//
+// Replaces the browser default select with a custom one, mostly pulled from
+// https://primer.github.io/.
+//
+
+.custom-select {
+ display: inline-block;
+ width: 100%;
+ height: $custom-select-height;
+ // stylelint-disable-next-line max-line-length
+ padding: $custom-select-padding-y ($custom-select-padding-x + $custom-select-indicator-padding) $custom-select-padding-y $custom-select-padding-x;
+ font-family: $custom-select-font-family;
+ font-weight: $custom-select-font-weight;
+ line-height: $custom-select-line-height;
+ color: $custom-select-color;
+ vertical-align: middle;
+ background: $custom-select-bg $custom-select-background;
+ border: $custom-select-border-width solid $custom-select-border-color;
+ appearance: none;
+
+ @include font-size($custom-select-font-size);
+ @include border-radius($custom-select-border-radius,0);
+ @include box-shadow($custom-select-box-shadow);
+
+ &:focus {
+ border-color: $custom-select-focus-border-color;
+ outline: 0;
+
+ @if $enable-shadows {
+ @include box-shadow($custom-select-box-shadow, $custom-select-focus-box-shadow);
+ }
+
+ @else {
+ // Avoid using mixin so we can pass custom focus shadow properly
+ box-shadow: $custom-select-focus-box-shadow;
+ }
+
+ &::-ms-value {
+ // For visual consistency with other platforms/browsers,
+ // suppress the default white text on blue background highlight given to
+ // the selected option text when the (still closed) receives focus
+ // in IE and (under certain conditions) Edge.
+ // See https://github.com/twbs/bootstrap/issues/19398.
+ color: $input-color;
+ background-color: $input-bg;
+ }
+ }
+
+ &[multiple],
+ &[size]:not([size="1"]) {
+ height: auto;
+ padding-right: $custom-select-padding-x;
+ background-image: none;
+ }
+
+ &:disabled {
+ color: $custom-select-disabled-color;
+ background-color: $custom-select-disabled-bg;
+ }
+
+ // Hides the default caret in IE11
+ &::-ms-expand {
+ display: none;
+ }
+
+ // Remove outline from select box in FF
+ &:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 $custom-select-color;
+ }
+}
+
+.custom-select-sm {
+ height: $custom-select-height-sm;
+ padding-top: $custom-select-padding-y-sm;
+ padding-bottom: $custom-select-padding-y-sm;
+ padding-left: $custom-select-padding-x-sm;
+
+ @include font-size($custom-select-font-size-sm);
+}
+
+.custom-select-lg {
+ height: $custom-select-height-lg;
+ padding-top: $custom-select-padding-y-lg;
+ padding-bottom: $custom-select-padding-y-lg;
+ padding-left: $custom-select-padding-x-lg;
+
+ @include font-size($custom-select-font-size-lg);
+}
+
+
+// File
+//
+// Custom file input.
+
+.custom-file {
+ position: relative;
+ display: inline-block;
+ width: 100%;
+ height: $custom-file-height;
+ margin-bottom: 0;
+}
+
+.custom-file-input {
+ position: relative;
+ z-index: 2;
+ width: 100%;
+ height: $custom-file-height;
+ margin: 0;
+ overflow: hidden;
+ opacity: 0;
+
+ &:focus ~ .custom-file-label {
+ border-color: $custom-file-focus-border-color;
+ box-shadow: $custom-file-focus-box-shadow;
+ }
+
+ // Use [disabled] and :disabled to work around https://github.com/twbs/bootstrap/issues/28247
+ &[disabled] ~ .custom-file-label,
+ &:disabled ~ .custom-file-label {
+ background-color: $custom-file-disabled-bg;
+ }
+
+ @each $lang, $value in $custom-file-text {
+ &:lang(#{$lang}) ~ .custom-file-label::after {
+ content: $value;
+ }
+ }
+
+ ~ .custom-file-label[data-browse]::after {
+ content: attr(data-browse);
+ }
+}
+
+.custom-file-label {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index: 1;
+ height: $custom-file-height;
+ padding: $custom-file-padding-y $custom-file-padding-x;
+ overflow: hidden;
+ font-family: $custom-file-font-family;
+ font-weight: $custom-file-font-weight;
+ line-height: $custom-file-line-height;
+ color: $custom-file-color;
+ background-color: $custom-file-bg;
+ border: $custom-file-border-width solid $custom-file-border-color;
+
+ @include border-radius($custom-file-border-radius);
+ @include box-shadow($custom-file-box-shadow);
+
+ &::after {
+ content: "Browse";
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 3;
+ display: block;
+ height: $custom-file-height-inner;
+ padding: $custom-file-padding-y $custom-file-padding-x;
+ line-height: $custom-file-line-height;
+ color: $custom-file-button-color;
+ border-left: inherit;
+
+ @include gradient-bg($custom-file-button-bg);
+ @include border-radius(0 $custom-file-border-radius $custom-file-border-radius 0);
+ }
+}
+
+// Range
+//
+// Style range inputs the same across browsers. Vendor-specific rules for pseudo
+// elements cannot be mixed. As such, there are no shared styles for focus or
+// active states on prefixed selectors.
+
+.custom-range {
+ width: 100%;
+ height: calc($custom-range-thumb-height + calc(#{$custom-range-thumb-focus-box-shadow-width} * 2));
+ padding: 0; // Need to reset padding
+ background-color: transparent;
+ appearance: none;
+
+ &:focus {
+ outline: 0;
+
+ // Pseudo-elements must be split across multiple rulesets to have an effect.
+ // No box-shadow() mixin for focus accessibility.
+ &::-webkit-slider-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }
+ &::-moz-range-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }
+ &::-ms-thumb { box-shadow: $custom-range-thumb-focus-box-shadow; }
+ }
+
+ &::-moz-focus-outer {
+ border: 0;
+ }
+
+ &::-webkit-slider-thumb {
+ width: $custom-range-thumb-width;
+ height: $custom-range-thumb-height;
+ margin-top: calc((#{$custom-range-track-height} - #{$custom-range-thumb-height}) * .5); // Webkit specific
+ border: $custom-range-thumb-border;
+ appearance: none;
+ transition: $custom-forms-transition;
+
+ @include gradient-bg($custom-range-thumb-bg);
+ @include border-radius($custom-range-thumb-border-radius);
+ @include box-shadow($custom-range-thumb-box-shadow);
+
+ &:active {
+ @include gradient-bg($custom-range-thumb-active-bg);
+ }
+ }
+
+ &::-webkit-slider-runnable-track {
+ width: $custom-range-track-width;
+ height: $custom-range-track-height;
+ color: transparent; // Why?
+ cursor: $custom-range-track-cursor;
+ background-color: $custom-range-track-bg;
+ border-color: transparent;
+
+ @include border-radius($custom-range-track-border-radius);
+ @include box-shadow($custom-range-track-box-shadow);
+ }
+
+ &::-moz-range-thumb {
+ width: $custom-range-thumb-width;
+ height: $custom-range-thumb-height;
+ border: $custom-range-thumb-border;
+ appearance: none;
+ transition: $custom-forms-transition;
+
+ @include gradient-bg($custom-range-thumb-bg);
+ @include border-radius($custom-range-thumb-border-radius);
+ @include box-shadow($custom-range-thumb-box-shadow);
+
+ &:active {
+ @include gradient-bg($custom-range-thumb-active-bg);
+ }
+ }
+
+ &::-moz-range-track {
+ width: $custom-range-track-width;
+ height: $custom-range-track-height;
+ color: transparent;
+ cursor: $custom-range-track-cursor;
+ background-color: $custom-range-track-bg;
+ border-color: transparent; // Firefox specific?
+
+ @include border-radius($custom-range-track-border-radius);
+ @include box-shadow($custom-range-track-box-shadow);
+ }
+
+ &::-ms-thumb {
+ width: $custom-range-thumb-width;
+ height: $custom-range-thumb-height;
+ margin-top: 0; // Edge specific
+ margin-right: $custom-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden.
+ margin-left: $custom-range-thumb-focus-box-shadow-width; // Workaround that overflowed box-shadow is hidden.
+ border: $custom-range-thumb-border;
+ appearance: none;
+ transition: $custom-forms-transition;
+
+ @include gradient-bg($custom-range-thumb-bg);
+ @include border-radius($custom-range-thumb-border-radius);
+ @include box-shadow($custom-range-thumb-box-shadow);
+
+ &:active {
+ @include gradient-bg($custom-range-thumb-active-bg);
+ }
+ }
+
+ &::-ms-track {
+ width: $custom-range-track-width;
+ height: $custom-range-track-height;
+ color: transparent;
+ cursor: $custom-range-track-cursor;
+ background-color: transparent;
+ border-color: transparent;
+ border-width: calc(#{$custom-range-thumb-height} * .5);
+
+ @include box-shadow($custom-range-track-box-shadow);
+ }
+
+ &::-ms-fill-lower {
+ background-color: $custom-range-track-bg;
+
+ @include border-radius($custom-range-track-border-radius);
+ }
+
+ &::-ms-fill-upper {
+ margin-right: 15px; // arbitrary?
+ background-color: $custom-range-track-bg;
+
+ @include border-radius($custom-range-track-border-radius);
+ }
+
+ &:disabled {
+ &::-webkit-slider-thumb {
+ background-color: $custom-range-thumb-disabled-bg;
+ }
+
+ &::-webkit-slider-runnable-track {
+ cursor: default;
+ }
+
+ &::-moz-range-thumb {
+ background-color: $custom-range-thumb-disabled-bg;
+ }
+
+ &::-moz-range-track {
+ cursor: default;
+ }
+
+ &::-ms-thumb {
+ background-color: $custom-range-thumb-disabled-bg;
+ }
+ }
+}
+
+.custom-control-label::before,
+.custom-file-label,
+.custom-select {
+ transition: $custom-forms-transition;
+}
diff --git a/src/Form/_bootstrap-forms.scss b/src/Form/_bootstrap-forms.scss
new file mode 100644
index 0000000000..1281d91101
--- /dev/null
+++ b/src/Form/_bootstrap-forms.scss
@@ -0,0 +1,374 @@
+@import "mixins";
+// stylelint-disable selector-no-qualifying-type
+
+//
+// Textual form controls
+//
+
+.form-control {
+ display: block;
+ width: 100%;
+ height: $input-height;
+ padding: $input-padding-y $input-padding-x;
+ font-family: $input-font-family;
+
+ @include font-size($input-font-size);
+
+ font-weight: $input-font-weight;
+ line-height: $input-line-height;
+ color: $input-color;
+ background-color: $input-bg;
+ background-clip: padding-box;
+ border: $input-border-width solid $input-border-color;
+ transition: $input-transition;
+
+ // Note: This has no effect on s in some browsers, due to the limited stylability of ``s in CSS.
+ @include border-radius($input-border-radius, 0);
+ @include box-shadow($input-box-shadow);
+
+ // Unstyle the caret on ``s in IE10+.
+ &::-ms-expand {
+ background-color: transparent;
+ border: 0;
+ }
+
+ // Customize the `:focus` state to imitate native WebKit styles.
+ @include form-control-focus($ignore-warning: true);
+
+ // Placeholder
+ &::placeholder {
+ color: $input-placeholder-color;
+ // Override Firefox's unusual default opacity; see https://github.com/twbs/bootstrap/pull/11526.
+ opacity: 1;
+ }
+
+ // Disabled and read-only inputs
+ //
+ // HTML5 says that controls under a fieldset > legend:first-child won't be
+ // disabled if the fieldset is disabled. Due to implementation difficulty, we
+ // don't honor that edge case; we style them as disabled anyway.
+ &:disabled,
+ &[readonly] {
+ background-color: $input-disabled-bg;
+ // iOS fix for unreadable disabled content; see https://github.com/twbs/bootstrap/issues/11655.
+ opacity: 1;
+ }
+}
+
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+ &.form-control {
+ appearance: none; // Fix appearance for date inputs in Safari
+ }
+}
+
+select.form-control {
+ // Remove select outline from select box in FF
+ &:-moz-focusring {
+ color: transparent;
+ text-shadow: 0 0 0 $input-color;
+ }
+
+ &:focus::-ms-value {
+ // Suppress the nested default white text on blue background highlight given to
+ // the selected option text when the (still closed) receives focus
+ // in IE and (under certain conditions) Edge, as it looks bad and cannot be made to
+ // match the appearance of the native widget.
+ // See https://github.com/twbs/bootstrap/issues/19398.
+ color: $input-color;
+ background-color: $input-bg;
+ }
+}
+
+// Make file inputs better match text inputs by forcing them to new lines.
+.form-control-file,
+.form-control-range {
+ display: block;
+ width: 100%;
+}
+
+
+//
+// Labels
+//
+
+// For use with horizontal and inline forms, when you need the label (or legend)
+// text to align with the form controls.
+.col-form-label {
+ padding-top: calc(#{$input-padding-y} + #{$input-border-width});
+ padding-bottom: calc(#{$input-padding-y} + #{$input-border-width});
+ margin-bottom: 0; // Override the `/` default
+
+ @include font-size(inherit); // Override the `` default
+
+ line-height: $input-line-height;
+}
+
+.col-form-label-lg {
+ padding-top: calc(#{$input-padding-y-lg} + #{$input-border-width});
+ padding-bottom: calc(#{$input-padding-y-lg} + #{$input-border-width});
+
+ @include font-size($input-font-size-lg);
+
+ line-height: $input-line-height-lg;
+}
+
+.col-form-label-sm {
+ padding-top: calc(#{$input-padding-y-sm} + #{$input-border-width});
+ padding-bottom: calc(#{$input-padding-y-sm} + #{$input-border-width});
+
+ @include font-size($input-font-size-sm);
+
+ line-height: $input-line-height-sm;
+}
+
+
+// Readonly controls as plain text
+//
+// Apply class to a readonly input to make it appear like regular plain
+// text (without any border, background color, focus indicator)
+
+.form-control-plaintext {
+ display: block;
+ width: 100%;
+ padding: $input-padding-y 0;
+ margin-bottom: 0; // match inputs if this class comes on inputs with default margins
+
+ @include font-size($input-font-size);
+
+ line-height: $input-line-height;
+ color: $input-plaintext-color;
+ background-color: transparent;
+ border: solid transparent;
+ border-width: $input-border-width 0;
+
+ &.form-control-sm,
+ &.form-control-lg {
+ padding-right: 0;
+ padding-left: 0;
+ }
+}
+
+
+// Form control sizing
+//
+// Build on `.form-control` with modifier classes to decrease or increase the
+// height and font-size of form controls.
+//
+// Repeated in `_input_group.scss` to avoid Sass extend issues.
+
+.form-control-sm {
+ height: $input-height-sm;
+ padding: $input-padding-y-sm $input-padding-x-sm;
+
+ @include font-size($input-font-size-sm);
+
+ line-height: $input-line-height-sm;
+
+ @include border-radius($input-border-radius-sm);
+}
+
+.form-control-lg {
+ height: $input-height-lg;
+ padding: $input-padding-y-lg $input-padding-x-lg;
+
+ @include font-size($input-font-size-lg);
+
+ line-height: $input-line-height-lg;
+
+ @include border-radius($input-border-radius-lg);
+}
+
+// stylelint-disable-next-line no-duplicate-selectors
+select.form-control {
+ &[size],
+ &[multiple] {
+ height: auto;
+ }
+}
+
+textarea.form-control {
+ height: auto;
+}
+
+// Form groups
+//
+// Designed to help with the organization and spacing of vertical forms. For
+// horizontal forms, use the predefined grid classes.
+
+.form-group {
+ margin-bottom: $form-group-margin-bottom;
+}
+
+.form-text {
+ display: block;
+ margin-top: $form-text-margin-top;
+}
+
+
+// Form grid
+//
+// Special replacement for our grid system's `.row` for tighter form layouts.
+
+.form-row {
+ display: flex;
+ flex-wrap: wrap;
+ margin-right: calc(-1 * #{$form-grid-gutter-width} * .5);
+ margin-left: calc(-1 * #{$form-grid-gutter-width} * .5);
+
+ > .col,
+ > [class*="col-"] {
+ padding-right: calc(#{$form-grid-gutter-width} * .5);
+ padding-left: calc(#{$form-grid-gutter-width} * .5);
+ }
+}
+
+
+// Checkboxes and radios
+//
+// Indent the labels to position radios/checkboxes as hanging controls.
+
+.form-check {
+ position: relative;
+ display: block;
+ padding-left: $form-check-input-gutter;
+}
+
+.form-check-input {
+ position: absolute;
+ margin-top: $form-check-input-margin-y;
+ margin-left: calc(-1 * #{$form-check-input-gutter});
+
+ // Use [disabled] and :disabled for workaround https://github.com/twbs/bootstrap/issues/28247
+ &[disabled] ~ .form-check-label,
+ &:disabled ~ .form-check-label {
+ color: $text-muted;
+ }
+}
+
+.form-check-label {
+ margin-bottom: 0; // Override default `` bottom margin
+}
+
+.form-check-inline {
+ display: inline-flex;
+ align-items: center;
+ padding-left: 0; // Override base .form-check
+ margin-right: $form-check-inline-margin-x;
+
+ // Undo .form-check-input defaults and add some `margin-right`.
+ .form-check-input {
+ position: static;
+ margin-top: 0;
+ margin-right: $form-check-inline-input-margin-x;
+ margin-left: 0;
+ }
+}
+
+
+// Form validation
+//
+// Provide feedback to users when form field values are valid or invalid. Works
+// primarily for client-side validation via scoped `:invalid` and `:valid`
+// pseudo-classes but also includes `.is-invalid` and `.is-valid` classes for
+// server side validation.
+
+@each $state, $data in $form-validation-states {
+ @include form-validation-state(
+ $state,
+ map-get($data, color),
+ map-get($data, icon),
+ map-get($data, tooltip-color),
+ map-get($data, tooltip-bg),
+ map-get($data, focus-box-shadow-color),
+ map-get($data, checked-color)
+ );
+}
+
+// Inline forms
+//
+// Make forms appear inline(-block) by adding the `.form-inline` class. Inline
+// forms begin stacked on extra small (mobile) devices and then go inline when
+// viewports reach <768px.
+//
+// Requires wrapping inputs and labels with `.form-group` for proper display of
+// default HTML form controls and our custom form controls (e.g., input groups).
+
+.form-inline {
+ display: flex;
+ flex-flow: row wrap;
+ align-items: center; // Prevent shorter elements from growing to same height as others (e.g.,
+ // small buttons growing to normal sized button height)
+
+ // Because we use flex, the initial sizing of checkboxes is collapsed and
+ // doesn't occupy the full-width (which is what we want for xs grid tier),
+ // so we force that here.
+ .form-check {
+ width: 100%;
+ }
+
+ // Kick in the inline
+ @include media-breakpoint-up(sm) {
+ label {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-bottom: 0;
+ }
+
+ // Inline-block all the things for "inline"
+ .form-group {
+ display: flex;
+ flex: 0 0 auto;
+ flex-flow: row wrap;
+ align-items: center;
+ margin-bottom: 0;
+ }
+
+ // Allow folks to *not* use `.form-group`
+ .form-control {
+ display: inline-block;
+ width: auto; // Prevent labels from stacking above inputs in `.form-group`
+ vertical-align: middle;
+ }
+
+ // Make static controls behave like regular ones
+ .form-control-plaintext {
+ display: inline-block;
+ }
+
+ .input-group,
+ .custom-select {
+ width: auto;
+ }
+
+ // Remove default margin on radios/checkboxes that were used for stacking, and
+ // then undo the floating of radios and checkboxes to match.
+ .form-check {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ width: auto;
+ padding-left: 0;
+ }
+
+ .form-check-input {
+ position: relative;
+ flex-shrink: 0;
+ margin-top: 0;
+ margin-right: $form-check-input-margin-x;
+ margin-left: 0;
+ }
+
+ .custom-control {
+ align-items: center;
+ justify-content: center;
+ }
+
+ .custom-control-label {
+ margin-bottom: 0;
+ }
+ }
+}
diff --git a/src/Form/_mixins.scss b/src/Form/_mixins.scss
index bce3eb1276..25cae85754 100644
--- a/src/Form/_mixins.scss
+++ b/src/Form/_mixins.scss
@@ -3,7 +3,7 @@
$padding-y,
$line-height,
$font-size,
- $border-width
+ $label-initial-border-width
) {
padding: 0 $padding-x;
@@ -19,12 +19,227 @@
$padding-y,
$line-height,
$font-size,
- $border-width
+ $label-float-border-width
) {
.pgn__form-control-floating-label-text {
$half-leading: calc(($line-height - .8) / 2);
$percent-height-minus-no-bottom-leading: calc((($line-height - $half-leading) / $line-height) * 100%);
- transform: translateY(-$padding-y) scale(.75) translateY(-$percent-height-minus-no-bottom-leading);
+ transform:
+ translateY(calc($padding-y * -1)) scale(.75)
+ translateY(calc($percent-height-minus-no-bottom-leading * -1));
+ }
+}
+
+
+// Form control focus state
+//
+// Generate a customized focus state and for any input with the specified color,
+// which defaults to the `$input-focus-border-color` variable.
+//
+// We highly encourage you to not customize the default value, but instead use
+// this to tweak colors on an as-needed basis. This aesthetic change is based on
+// WebKit's default styles, but applicable to a wider range of browsers. Its
+// usability and accessibility should be taken into account with any change.
+//
+// Example usage: change the default blue border and shadow to white for better
+// contrast against a dark gray background.
+@mixin form-control-focus($ignore-warning: false) {
+ &:focus {
+ color: $input-focus-color;
+ background-color: $input-focus-bg;
+ border-color: $input-focus-border-color;
+ outline: 0;
+
+ @if $enable-shadows {
+ @include box-shadow($input-box-shadow, $input-focus-box-shadow);
+ }
+
+ @else {
+ // Avoid using mixin so we can pass custom focus shadow properly
+ box-shadow: $input-focus-box-shadow;
+ }
+ }
+
+ @include deprecate("The `form-control-focus()` mixin", "v4.4.0", "v5", $ignore-warning);
+}
+
+// This mixin uses an `if()` technique to be compatible with Dart Sass
+// See https://github.com/sass/sass/issues/1873#issuecomment-152293725 for more details
+@mixin form-validation-state-selector($state) {
+ @if ($state == "valid" or $state == "invalid") {
+ .was-validated #{if(&, "&", "")}:#{$state},
+ #{if(&, "&", "")}.is-#{$state} {
+ @content;
+ }
+ }
+
+ @else {
+ #{if(&, "&", "")}.is-#{$state} {
+ @content;
+ }
+ }
+}
+
+@mixin form-validation-state(
+ $state, $color, $icon, $tooltip-color,
+ $tooltip-bg, $focus-box-shadow-color, $checked-border-color
+) {
+ .#{$state}-feedback {
+ display: none;
+ width: 100%;
+ margin-top: $form-feedback-margin-top;
+
+ @include font-size($form-feedback-font-size);
+
+ color: $color;
+ }
+
+ .#{$state}-tooltip {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 5;
+ display: none;
+ max-width: 100%; // Contain to parent when possible
+ padding: $form-feedback-tooltip-padding-y $form-feedback-tooltip-padding-x;
+ margin-top: .1rem;
+
+ @include font-size($form-feedback-tooltip-font-size);
+
+ line-height: $form-feedback-tooltip-line-height;
+ color: $tooltip-color;
+ background-color: $tooltip-bg;
+
+ @include border-radius($form-feedback-tooltip-border-radius);
+
+ // See https://github.com/twbs/bootstrap/pull/31557
+ // Align tooltip to form elements
+ .form-row > .col > &,
+ .form-row > [class*="col-"] > & {
+ left: calc(#{$form-grid-gutter-width} * .5);
+ }
+ }
+
+ @include form-validation-state-selector($state) {
+ ~ .#{$state}-feedback,
+ ~ .#{$state}-tooltip {
+ display: block;
+ }
+ }
+
+ .form-control {
+ @include form-validation-state-selector($state) {
+ border-color: $color;
+
+ @if $enable-validation-icons {
+ padding-right: $input-height-inner !important; // stylelint-disable-line declaration-no-important
+ background-image: $icon;
+ background-repeat: no-repeat;
+ background-position: right $input-height-inner-quarter center;
+ background-size: $input-height-inner-half $input-height-inner-half;
+ }
+
+ &:focus {
+ border-color: $color;
+ box-shadow: 0 0 0 $input-focus-width $focus-box-shadow-color;
+ }
+ }
+ }
+
+ // stylelint-disable-next-line selector-no-qualifying-type
+ select.form-control {
+ @include form-validation-state-selector($state) {
+ @if $enable-validation-icons {
+ padding-right: calc(#{$input-padding-x} * 4) !important; // stylelint-disable-line declaration-no-important
+ background-position: right calc(#{$input-padding-x} * 2) center;
+ }
+ }
+ }
+
+ // stylelint-disable-next-line selector-no-qualifying-type
+ textarea.form-control {
+ @include form-validation-state-selector($state) {
+ @if $enable-validation-icons {
+ padding-right: $input-height-inner;
+ background-position: top $input-height-inner-quarter right $input-height-inner-quarter;
+ }
+ }
+ }
+
+ .custom-select {
+ @include form-validation-state-selector($state) {
+ border-color: $color;
+
+ @if $enable-validation-icons {
+ padding-right: $custom-select-feedback-icon-padding-right !important;
+ // stylelint-disable-next-line max-line-length
+ background: $custom-select-background, $custom-select-bg $icon $custom-select-feedback-icon-position / $custom-select-feedback-icon-size no-repeat;
+ }
+
+ &:focus {
+ border-color: $color;
+ box-shadow: 0 0 0 $input-focus-width $focus-box-shadow-color;
+ }
+ }
+ }
+
+ .form-check-input {
+ @include form-validation-state-selector($state) {
+ ~ .form-check-label {
+ color: $color;
+ }
+
+ ~ .#{$state}-feedback,
+ ~ .#{$state}-tooltip {
+ display: block;
+ }
+ }
+ }
+
+ .custom-control-input {
+ @include form-validation-state-selector($state) {
+ ~ .custom-control-label {
+ color: $color;
+
+ &::before {
+ border-color: $color;
+ }
+ }
+
+ &:checked {
+ ~ .custom-control-label::before {
+ border-color: $checked-border-color;
+
+ @include gradient-bg($checked-border-color);
+ }
+ }
+
+ &:focus {
+ ~ .custom-control-label::before {
+ box-shadow: 0 0 0 $input-focus-width $focus-box-shadow-color;
+ }
+
+ &:not(:checked) ~ .custom-control-label::before {
+ border-color: $color;
+ }
+ }
+ }
+ }
+
+ // custom file
+ .custom-file-input {
+ @include form-validation-state-selector($state) {
+ ~ .custom-file-label {
+ border-color: $color;
+ }
+
+ &:focus {
+ ~ .custom-file-label {
+ border-color: $color;
+ box-shadow: 0 0 0 $input-focus-width $focus-box-shadow-color;
+ }
+ }
+ }
}
}
diff --git a/src/Form/_variables.scss b/src/Form/_variables.scss
index 8f8b6a01b9..f9213a5c53 100644
--- a/src/Form/_variables.scss
+++ b/src/Form/_variables.scss
@@ -1,234 +1,244 @@
-$input-padding-y: $input-btn-padding-y !default;
-$input-padding-x: $input-btn-padding-x !default;
-$input-font-family: $input-btn-font-family !default;
-$input-font-size: $input-btn-font-size !default;
-$input-font-weight: $font-weight-base !default;
-$input-line-height: $input-btn-line-height !default;
-
-$input-padding-y-sm: $input-btn-padding-y-sm !default;
-$input-padding-x-sm: $input-btn-padding-x-sm !default;
-$input-font-size-sm: $input-btn-font-size-sm !default;
-$input-line-height-sm: $input-btn-line-height-sm !default;
-
-$input-padding-y-lg: $input-btn-padding-y-lg !default;
-$input-padding-x-lg: $input-btn-padding-x-lg !default;
-$input-font-size-lg: $input-btn-font-size-lg !default;
-$input-line-height-lg: $input-btn-line-height-lg !default;
-
-$input-bg: $white !default;
-$input-disabled-bg: theme-color("gray", "background") !default;
-
-$input-color: theme-color("gray", "text") !default;
-$input-border-color: $gray-500 !default;
-$input-border-width: $input-btn-border-width !default;
-$input-box-shadow: inset 0 1px 1px rgba($black, .075) !default;
-
-$input-border-radius: $border-radius !default;
-$input-border-radius-lg: $border-radius-lg !default;
-$input-border-radius-sm: $border-radius-sm !default;
-
-$input-focus-bg: $input-bg !default;
-$input-focus-border-color: $component-active-bg !default;
-$input-focus-color: $input-color !default;
-$input-focus-width: 1px !default;
-$input-focus-box-shadow: $input-btn-focus-box-shadow !default;
-
-$input-placeholder-color: theme-color("gray", "light-text") !default;
-$input-plaintext-color: $body-color !default;
-
-$input-height-border: $input-border-width * 2 !default;
-
-$input-height-inner: calc(#{$input-line-height * 1em} + #{$input-padding-y * 2}) !default;
-$input-height-inner-half: calc(#{$input-line-height * .5em} + #{$input-padding-y}) !default;
-$input-height-inner-quarter: calc(#{$input-line-height * .25em} + #{calc($input-padding-y / 2)}) !default;
-
-$input-height: calc(
- #{$input-line-height * 1em} + #{$input-padding-y * 2} + #{$input-height-border}
-) !default;
-$input-height-sm: calc(
- #{$input-line-height-sm * 1em} + #{$input-btn-padding-y-sm * 2} + #{$input-height-border}
-) !default;
-$input-height-lg: calc(
- #{$input-line-height-lg * 1em} + #{$input-btn-padding-y-lg * 2} + #{$input-height-border}
-) !default;
+$input-padding-y: var(--pgn-spacing-form-input-padding-y-base) !default;
+$input-padding-x: var(--pgn-spacing-form-input-padding-x-base) !default;
+$input-font-family: var(--pgn-typography-form-input-font-family) !default;
+$input-font-size: var(--pgn-typography-form-input-font-size-base) !default;
+$input-font-weight: var(--pgn-typography-form-input-font-weight) !default;
+$input-line-height: var(--pgn-typography-form-input-line-height-base) !default;
-$input-hover-width: 1px !default;
-$input-transition: border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+$input-padding-y-sm: var(--pgn-spacing-form-input-padding-y-sm) !default;
+$input-padding-x-sm: var(--pgn-spacing-form-input-padding-x-sm) !default;
+$input-font-size-sm: var(--pgn-typography-form-input-font-size-sm) !default;
+$input-line-height-sm: var(--pgn-typography-form-input-line-height-sm) !default;
-$form-text-margin-top: .25rem !default;
+$input-padding-y-lg: var(--pgn-spacing-form-input-padding-y-lg) !default;
+$input-padding-x-lg: var(--pgn-spacing-form-input-padding-x-lg) !default;
+$input-font-size-lg: var(--pgn-typography-form-input-font-size-lg) !default;
+$input-line-height-lg: var(--pgn-typography-form-input-line-height-lg) !default;
-$form-check-input-gutter: 1.25rem !default;
-$form-check-input-margin-y: .3rem !default;
-$form-check-input-margin-x: .25rem !default;
+$input-bg: var(--pgn-color-form-input-bg-base) !default;
+$input-disabled-bg: var(--pgn-color-form-input-bg-disabled) !default;
-$form-check-inline-margin-x: .75rem !default;
-$form-check-inline-input-margin-x: .3125rem !default;
+$input-color: var(--pgn-color-form-input-base) !default;
+$input-border-color: var(--pgn-color-form-input-border) !default;
+$input-border-width: var(--pgn-size-form-input-width-border) !default;
+$input-box-shadow: var(--pgn-elevation-form-input-base) !default;
-$form-check-position-axis: .375rem !default;
-$form-check-focus-border-radius: .0625rem !default;
-$form-check-border-width: .125rem !default;
+$input-border-radius: var(--pgn-size-form-input-radius-border-base) !default;
+$input-border-radius-lg: var(--pgn-size-form-input-radius-border-lg) !default;
+$input-border-radius-sm: var(--pgn-size-form-input-radius-border-sm) !default;
-$form-grid-gutter-width: 10px !default;
-$form-group-margin-bottom: 1rem !default;
+$input-focus-bg: var(--pgn-color-form-input-focus-bg) !default;
+$input-focus-border-color: var(--pgn-color-form-input-focus-border) !default;
+$input-focus-color: var(--pgn-color-form-input-focus-base) !default;
+$input-focus-width: var(--pgn-size-form-input-width-focus) !default;
+$input-focus-box-shadow: var(--pgn-elevation-form-input-focus) !default;
-$input-group-addon-color: $input-color !default;
-$input-group-addon-bg: theme-color("gray", "background") !default;
-$input-group-addon-border-color: $input-border-color !default;
+$input-placeholder-color: var(--pgn-color-form-input-placeholder) !default;
+$input-plaintext-color: var(--pgn-color-form-input-plaintext) !default;
-$custom-forms-transition: background-color .15s ease-in-out,
- border-color .15s ease-in-out, box-shadow .15s ease-in-out !default;
+$input-height-border: var(--pgn-size-form-input-height-border) !default;
-$custom-control-gutter: .5rem !default;
-$custom-control-spacer-x: 1rem !default;
-$custom-control-cursor: null !default;
+$input-height-inner: var(--pgn-size-form-input-height-inner-base) !default;
+$input-height-inner-half: var(--pgn-size-form-input-height-inner-half) !default;
+$input-height-inner-quarter: var(--pgn-size-form-input-height-inner-quarter) !default;
-$custom-control-indicator-size: 1.25rem !default;
-$custom-control-indicator-bg: $input-bg !default;
+$input-height: var(--pgn-size-form-input-height-base) !default;
+$input-height-sm: var(--pgn-size-form-input-height-sm) !default;
+$input-height-lg: var(--pgn-size-form-input-height-lg) !default;
-$custom-control-indicator-bg-size: 100% !default;
-$custom-control-indicator-box-shadow: $input-box-shadow !default;
-$custom-control-indicator-border-color: $gray-700 !default;
-$custom-control-indicator-border-width: 2px !default;
+$input-hover-width: var(--pgn-size-form-input-width-hover) !default;
+$input-transition: var(--pgn-transition-form-input) !default;
-$custom-control-label-color: null !default;
-$custom-control-indicator-disabled-bg: $input-disabled-bg !default;
-$custom-control-label-disabled-color: theme-color("gray", "light-text") !default;
+$form-text-margin-top: var(--pgn-spacing-form-text-margin-top) !default;
-$custom-control-indicator-checked-color: $component-active-bg !default;
-$custom-control-indicator-checked-bg: $component-active-bg !default;
-$custom-control-indicator-checked-disabled-bg: rgba($primary, .5) !default;
-$custom-control-indicator-checked-box-shadow: none !default;
-$custom-control-indicator-checked-border-color: $custom-control-indicator-checked-bg !default;
+$form-check-input-gutter: var(--pgn-spacing-form-input-check-gutter) !default;
+$form-check-input-margin-y: var(--pgn-spacing-form-input-check-margin-y) !default;
+$form-check-input-margin-x: var(--pgn-spacing-form-input-check-margin-x-base) !default;
-$custom-control-indicator-focus-box-shadow: 0 0 0 4px rgba(0, 0, 0, .1) !default;
-$custom-control-indicator-focus-border-color: $input-focus-border-color !default;
+$form-check-inline-margin-x: var(--pgn-spacing-form-check-inline-margin-x) !default;
+$form-check-inline-input-margin-x: var(--pgn-spacing-form-input-check-margin-x-inline) !default;
-$custom-control-indicator-active-color: $component-active-color !default;
-$custom-control-indicator-active-bg: $component-active-bg !default;
-$custom-control-indicator-active-box-shadow: none !default;
-$custom-control-indicator-active-border-color: $custom-control-indicator-active-bg !default;
-$custom-checkbox-indicator-border-radius: 0 !default;
-$custom-checkbox-indicator-icon-checked: str-replace(url("data:image/svg+xml, "), "#", "%23") !default;
+$form-check-position-axis: var(--pgn-spacing-form-check-position-axis) !default;
+$form-check-focus-border-radius: var(--pgn-size-form-border-radius-check-focus) !default;
+$form-check-border-width: var(--pgn-size-form-border-radius-width) !default;
-$custom-checkbox-indicator-indeterminate-bg: $component-active-bg !default;
-$custom-checkbox-indicator-indeterminate-color: $custom-control-indicator-checked-color !default;
-$custom-checkbox-indicator-icon-indeterminate: str-replace(url("data:image/svg+xml, "), "#", "%23") !default;
-$custom-checkbox-indicator-indeterminate-box-shadow: none !default;
-$custom-checkbox-indicator-indeterminate-border-color: $custom-checkbox-indicator-indeterminate-bg !default;
+$form-grid-gutter-width: var(--pgn-size-form-grid-gutter-width) !default;
+$form-group-margin-bottom: var(--pgn-spacing-form-group-margin-bottom) !default;
-$custom-radio-indicator-border-radius: 50% !default;
-$custom-radio-indicator-icon-checked: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-bg}'/%3e%3c/svg%3e"), "#", "%23") !default;
+$input-group-addon-color: var(--pgn-color-form-input-group-addon-base) !default;
+$input-group-addon-bg: var(--pgn-color-form-input-group-addon-bg) !default;
+$input-group-addon-border-color: var(--pgn-color-form-input-group-addon-border) !default;
-$custom-switch-indicator-icon-off: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-checked-bg}'/%3e%3c/svg%3e"), "#", "%23") !default;
-$custom-switch-indicator-icon-on: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3e%3ccircle r='3' fill='#{$custom-control-indicator-active-color}'/%3e%3c/svg%3e"), "#", "%23") !default;
-$custom-switch-width: $custom-control-indicator-size * 1.75 !default;
-$custom-switch-indicator-border-radius: calc($custom-control-indicator-size / 2) !default;
-$custom-switch-indicator-size: calc(
- #{$custom-control-indicator-size} - #{$custom-control-indicator-border-width * 4}
-) !default;
-$custom-switch-indicator-checked-bg: theme-color("success") !default;
+$custom-forms-transition: var(--pgn-transition-form-control) !default;
+
+$custom-control-gutter: var(--pgn-spacing-form-control-gutter) !default;
+$custom-control-spacer-x: var(--pgn-spacing-form-control-spacer-x) !default;
+$custom-control-cursor: var(--pgn-other-form-control-cursor) !default;
+
+$custom-control-indicator-size: var(--pgn-size-form-control-indicator-base) !default;
+$custom-control-indicator-bg: var(--pgn-color-form-control-indicator-bg-base) !default;
+
+$custom-control-indicator-bg-size: var(--pgn-size-form-control-indicator-bg) !default;
+$custom-control-indicator-box-shadow: var(--pgn-elevation-form-control-indicator-base) !default;
+$custom-control-indicator-border-color: var(--pgn-color-form-control-indicator-border) !default;
+$custom-control-indicator-border-width: var(--pgn-size-form-control-indicator-border-width) !default;
+
+$custom-control-label-color: var(--pgn-color-form-control-label-base) !default;
+$custom-control-indicator-disabled-bg: var(--pgn-color-form-control-indicator-bg-disabled) !default;
+$custom-control-label-disabled-color: var(--pgn-color-form-control-label-disabled) !default;
+
+$custom-control-indicator-checked-color: var(--pgn-color-form-control-indicator-checked-base) !default;
+$custom-control-indicator-checked-bg: var(--pgn-color-form-control-indicator-checked-bg-base) !default;
+$custom-control-indicator-checked-disabled-bg: var(--pgn-color-form-control-indicator-checked-bg-disabled) !default;
+
+// stylelint-disable-next-line max-line-length
+$custom-control-indicator-checked-box-shadow: var(--pgn-elevation-form-control-indicator-checked-base) !default;
+
+// stylelint-disable-next-line max-line-length
+$custom-control-indicator-checked-border-color: var(--pgn-color-form-control-indicator-checked-border-base) !default;
+
+$custom-control-indicator-focus-box-shadow: var(--pgn-elevation-form-control-indicator-checked-focus) !default;
+
+// stylelint-disable-next-line max-line-length
+$custom-control-indicator-focus-border-color: var(--pgn-color-form-control-indicator-checked-border-focus) !default;
-$custom-select-padding-y: $input-padding-y !default;
-$custom-select-padding-x: $input-padding-x !default;
-$custom-select-font-family: $input-font-family !default;
-$custom-select-font-size: $input-font-size !default;
-$custom-select-height: $input-height !default;
+$custom-control-indicator-active-color: var(--pgn-color-form-control-indicator-active-base) !default;
+$custom-control-indicator-active-bg: var(--pgn-color-form-control-indicator-active-bg) !default;
+$custom-control-indicator-active-box-shadow: var(--pgn-elevation-form-control-indicator-active) !default;
+$custom-control-indicator-active-border-color: var(--pgn-color-form-control-indicator-active-border) !default;
+$custom-checkbox-indicator-border-radius: var(--pgn-size-form-control-border-checkbox-indicator-radius) !default;
+$custom-checkbox-indicator-icon-checked: var(--pgn-other-content-form-control-checkbox-indicator-icon-checked) !default;
+
+$custom-checkbox-indicator-indeterminate-bg: var(--pgn-color-form-control-checkbox-indicator-indeterminate-bg) !default;
+
+// stylelint-disable-next-line max-line-length
+$custom-checkbox-indicator-indeterminate-color: var(--pgn-color-form-control-checkbox-indicator-indeterminate-base) !default;
+
+// stylelint-disable-next-line max-line-length
+$custom-checkbox-indicator-icon-indeterminate: var(--pgn-other-content-form-control-checkbox-indicator-indeterminate-icon) !default;
+
+// stylelint-disable-next-line max-line-length
+$custom-checkbox-indicator-indeterminate-box-shadow: var(--pgn-elevation-form-control-checkbox-indicator-indeterminate) !default;
+
+// stylelint-disable-next-line max-line-length
+$custom-checkbox-indicator-indeterminate-border-color: var(--pgn-color-form-control-checkbox-indicator-indeterminate-border) !default;
+
+$custom-radio-indicator-border-radius: var(--pgn-size-form-control-border-radio-indicator-radius) !default;
+$custom-radio-indicator-icon-checked: var(--pgn-other-content-form-control-radio-indicator-icon-checked) !default;
+
+$custom-switch-indicator-icon-off: var(--pgn-other-content-form-control-switch-indicator-icon-off) !default;
+$custom-switch-indicator-icon-on: var(--pgn-other-content-form-control-switch-indicator-icon-on) !default;
+$custom-switch-width: var(--pgn-size-form-control-switch-width) !default;
+$custom-switch-indicator-border-radius: var(--pgn-size-form-control-switch-indicator-border-radius) !default;
+$custom-switch-indicator-size: var(--pgn-size-form-control-switch-indicator-base) !default;
+$custom-switch-indicator-checked-bg: var(--pgn-color-form-control-switch-indicator-checked-bg) !default;
+
+$custom-select-padding-y: var(--pgn-spacing-form-control-select-padding-y-base) !default;
+$custom-select-padding-x: var(--pgn-spacing-form-control-select-padding-x-base) !default;
+$custom-select-font-family: var(--pgn-typography-form-control-select-font-family) !default;
+$custom-select-font-size: var(--pgn-typography-form-control-select-font-size-base) !default;
+$custom-select-height: var(--pgn-size-form-control-select-height-base) !default;
// Extra padding to account for the presence of the background-image based indicator
-$custom-select-indicator-padding: 1rem !default;
-$custom-select-font-weight: $input-font-weight !default;
-$custom-select-line-height: $input-line-height !default;
-$custom-select-color: $input-color !default;
-$custom-select-disabled-color: theme-color("gray", "light-text") !default;
-$custom-select-bg: $input-bg !default;
-$custom-select-disabled-bg: theme-color("gray", "background") !default;
-$custom-select-bg-size: 24px 24px !default; // In pixels because image dimensions
-$custom-select-indicator-color: theme-color("gray", "hover") !default;
-
-$custom-select-indicator: str-replace(url('data:image/svg+xml, '), "#", "%23") !default;
+$custom-select-indicator-padding: var(--pgn-spacing-form-control-select-indicator-padding) !default;
+$custom-select-font-weight: var(--pgn-typography-form-control-select-font-weight) !default;
+$custom-select-line-height: var(--pgn-typography-form-control-select-line-height) !default;
+$custom-select-color: var(--pgn-color-form-control-select-base) !default;
+$custom-select-disabled-color: var(--pgn-color-form-control-select-disabled) !default;
+$custom-select-bg: var(--pgn-color-form-control-select-bg-base) !default;
+$custom-select-disabled-bg: var(--pgn-color-form-control-select-bg-disabled) !default;
+$custom-select-bg-size: var(--pgn-color-form-control-select-bg-size) !default;
+$custom-select-indicator-color: var(--pgn-color-form-control-select-indicator-base) !default;
+
+$custom-select-indicator: var(--pgn-other-content-form-control-select-indicator-icon) !default;
// Used so we can have multiple background elements (e.g., arrow and feedback icon)
-$custom-select-background: $custom-select-indicator no-repeat right
- $input-padding-y center / $custom-select-bg-size !default;
-
-$custom-select-feedback-icon-padding-right: calc(
- (1em + #{2 * $custom-select-padding-y}) * 3 / 4 + #{$custom-select-padding-x + $custom-select-indicator-padding}
-) !default;
-$custom-select-feedback-icon-position: center right
- ($custom-select-padding-x + $custom-select-indicator-padding) !default;
-$custom-select-feedback-icon-size: $input-height-inner-half $input-height-inner-half !default;
-
-$custom-select-border-width: $input-border-width !default;
-$custom-select-border-color: $input-border-color !default;
-$custom-select-border-radius: $border-radius !default;
-$custom-select-box-shadow: inset 0 1px 2px rgba($black, .075) !default;
-
-$custom-select-focus-border-color: $input-focus-border-color !default;
-$custom-select-focus-width: $input-focus-width !default;
-$custom-select-focus-box-shadow: $input-btn-focus-box-shadow !default;
-
-$custom-select-padding-y-sm: $input-padding-y-sm !default;
-$custom-select-padding-x-sm: $input-padding-x-sm !default;
-$custom-select-font-size-sm: $input-font-size-sm !default;
-$custom-select-height-sm: $input-height-sm !default;
-
-$custom-select-padding-y-lg: $input-padding-y-lg !default;
-$custom-select-padding-x-lg: $input-padding-x-lg !default;
-$custom-select-font-size-lg: $input-font-size-lg !default;
-$custom-select-height-lg: $input-height-lg !default;
-
-$custom-range-track-width: 100% !default;
-$custom-range-track-height: .5rem !default;
-$custom-range-track-cursor: pointer !default;
-$custom-range-track-bg: theme-color("gray", "graphic") !default;
-$custom-range-track-border-radius: 1rem !default;
-$custom-range-track-box-shadow: inset 0 .25rem .25rem rgba($black, .1) !default;
-
-$custom-range-thumb-width: 1rem !default;
-$custom-range-thumb-height: $custom-range-thumb-width !default;
-$custom-range-thumb-bg: $component-active-bg !default;
-$custom-range-thumb-border: 0 !default;
-$custom-range-thumb-border-radius: 1rem !default;
-$custom-range-thumb-box-shadow: 0 .1rem .25rem rgba($black, .1) !default;
-$custom-range-thumb-focus-box-shadow: 0 0 0 1px $body-bg, $input-focus-box-shadow !default;
-$custom-range-thumb-focus-box-shadow-width: $input-focus-width !default; // For focus box shadow issue in IE/Edge
-$custom-range-thumb-active-bg: lighten($component-active-bg, 35%) !default;
-$custom-range-thumb-disabled-bg: theme-color("gray", "default") !default;
-
-$custom-file-height: $input-height !default;
-$custom-file-height-inner: $input-height-inner !default;
-$custom-file-focus-border-color: $input-focus-border-color !default;
-$custom-file-focus-box-shadow: $input-focus-box-shadow !default;
-$custom-file-disabled-bg: $input-disabled-bg !default;
-
-$custom-file-padding-y: $input-padding-y !default;
-$custom-file-padding-x: $input-padding-x !default;
-$custom-file-line-height: $input-line-height !default;
-$custom-file-font-family: $input-font-family !default;
-$custom-file-font-weight: $input-font-weight !default;
-$custom-file-color: $input-color !default;
-$custom-file-bg: $input-bg !default;
-$custom-file-border-width: $input-border-width !default;
-$custom-file-border-color: $input-border-color !default;
-$custom-file-border-radius: $input-border-radius !default;
-$custom-file-box-shadow: $input-box-shadow !default;
-$custom-file-button-color: $custom-file-color !default;
-$custom-file-button-bg: $input-group-addon-bg !default;
+$custom-select-background: var(--pgn-other-content-form-control-select-bg) !default;
+
+$custom-select-feedback-icon-padding-right: var(--pgn-spacing-form-control-select-feedback-icon-padding-right) !default;
+$custom-select-feedback-icon-position: var(--pgn-spacing-form-control-select-feedback-icon-position) !default;
+$custom-select-feedback-icon-size: var(--pgn-size-form-control-select-feedback-icon) !default;
+
+$custom-select-border-width: var(--pgn-size-form-control-select-border-width-base) !default;
+$custom-select-border-color: var(--pgn-color-form-control-select-border-base) !default;
+$custom-select-border-radius: var(--pgn-size-form-control-select-border-radius) !default;
+$custom-select-box-shadow: var(--pgn-elevation-form-control-select-border-base) !default;
+
+$custom-select-focus-border-color: var(--pgn-color-form-control-select-border-focus) !default;
+$custom-select-focus-width: var(--pgn-size-form-control-select-border-width-focus) !default;
+$custom-select-focus-box-shadow: var(--pgn-elevation-form-control-select-border-focus) !default;
+
+$custom-select-padding-y-sm: var(--pgn-spacing-form-control-select-padding-y-sm) !default;
+$custom-select-padding-x-sm: var(--pgn-spacing-form-control-select-padding-x-sm) !default;
+$custom-select-font-size-sm: var(--pgn-typography-form-control-select-font-size-sm) !default;
+$custom-select-height-sm: var(--pgn-size-form-control-select-height-sm) !default;
+
+$custom-select-padding-y-lg: var(--pgn-spacing-form-control-select-padding-y-lg) !default;
+$custom-select-padding-x-lg: var(--pgn-spacing-form-control-select-padding-x-lg) !default;
+$custom-select-font-size-lg: var(--pgn-typography-form-control-select-font-size-lg) !default;
+$custom-select-height-lg: var(--pgn-size-form-control-select-height-lg) !default;
+
+$custom-range-track-width: var(--pgn-size-form-control-range-track-width) !default;
+$custom-range-track-height: var(--pgn-size-form-control-range-track-height) !default;
+$custom-range-track-cursor: var(--pgn-other-form-control-range-track-cursor) !default;
+$custom-range-track-bg: var(--pgn-color-form-control-range-track-bg) !default;
+$custom-range-track-border-radius: var(--pgn-size-form-control-range-track-border-radius) !default;
+$custom-range-track-box-shadow: var(--pgn-elevation-form-control-range-track) !default;
+
+$custom-range-thumb-width: var(--pgn-size-form-control-range-thumb-width) !default;
+$custom-range-thumb-height: var(--pgn-size-form-control-range-thumb-height) !default;
+$custom-range-thumb-bg: var(--pgn-color-form-control-range-thumb-bg-base) !default;
+$custom-range-thumb-border: var(--pgn-size-form-control-range-thumb-border-base) !default;
+$custom-range-thumb-border-radius: var(--pgn-size-form-control-range-thumb-border-radius) !default;
+$custom-range-thumb-box-shadow: var(--pgn-elevation-form-control-range-thumb-base) !default;
+$custom-range-thumb-focus-box-shadow: var(--pgn-elevation-form-control-range-thumb-focus) !default;
+$custom-range-thumb-focus-box-shadow-width: var(--pgn-size-form-control-range-thumb-focus-width) !default;
+$custom-range-thumb-active-bg: var(--pgn-color-form-control-range-thumb-bg-active) !default;
+$custom-range-thumb-disabled-bg: var(--pgn-color-form-control-range-thumb-bg-disabled) !default;
+
+$custom-file-height: var(--pgn-size-form-control-file-height-base) !default;
+$custom-file-height-inner: var(--pgn-size-form-control-file-height-inner) !default;
+$custom-file-focus-border-color: var(--pgn-color-form-control-file-border-focus) !default;
+$custom-file-focus-box-shadow: var(--pgn-elevation-form-control-file-focus) !default;
+$custom-file-disabled-bg: var(--pgn-color-form-control-file-bg-disabled) !default;
+
+$custom-file-padding-y: var(--pgn-spacing-form-control-file-padding-y) !default;
+$custom-file-padding-x: var(--pgn-spacing-form-control-file-padding-x) !default;
+$custom-file-line-height: var(--pgn-typography-form-control-file-line-height) !default;
+$custom-file-font-family: var(--pgn-typography-form-control-file-font-family) !default;
+$custom-file-font-weight: var(--pgn-typography-form-control-file-font-weight) !default;
+$custom-file-color: var(--pgn-color-form-control-file-base) !default;
+$custom-file-bg: var(--pgn-color-form-control-file-bg-base) !default;
+$custom-file-border-width: var(--pgn-size-form-control-file-width) !default;
+$custom-file-border-color: var(--pgn-color-form-control-file-border-base) !default;
+$custom-file-border-radius: var(--pgn-size-form-control-file-border-radius) !default;
+$custom-file-box-shadow: var(--pgn-elevation-form-control-file-base) !default;
+$custom-file-button-color: var(--pgn-color-form-control-file-button-base) !default;
+$custom-file-button-bg: var(--pgn-color-form-control-file-button-bg) !default;
$custom-file-text: (
en: "Browse"
) !default;
// Form validation
-$form-feedback-margin-top: $form-text-margin-top !default;
-$form-feedback-font-size: $small-font-size !default;
-$form-feedback-valid-color: theme-color("success") !default;
-$form-feedback-invalid-color: theme-color("danger") !default;
+$form-feedback-margin-top: var(--pgn-spacing-form-control-select-feedback-margin-top) !default;
+$form-feedback-font-size: var(--pgn-typography-form-feedback-font-size) !default;
+$form-feedback-valid-color: var(--pgn-color-form-feedback-valid) !default;
+$form-feedback-invalid-color: var(--pgn-color-form-feedback-invalid) !default;
+
+$form-feedback-tooltip-valid-color: var(--pgn-color-form-feedback-tooltip-valid) !default;
+$form-feedback-tooltip-valid-bg: var(--pgn-color-form-feedback-tooltip-bg-valid) !default;
+$form-feedback-tooltip-invalid-bg: var(--pgn-color-form-feedback-tooltip-bg-invalid) !default;
+
+$form-feedback-focus-box-shadow-valid-color: var(--pgn-color-form-feedback-tooltip-box-shadow-focus-valid) !default;
+$form-feedback-focus-box-shadow-invalid-color: var(--pgn-color-form-feedback-tooltip-box-shadow-focus-invalid) !default;
+$form-feedback-checked-valid-color: var(--pgn-color-form-feedback-checked-valid) !default;
+$form-feedback-checked-invalid-color: var(--pgn-color-form-feedback-checked-invalid) !default;
-$form-feedback-icon-valid-color: $form-feedback-valid-color !default;
-$form-feedback-icon-valid: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3e%3cpath fill='#{$form-feedback-icon-valid-color}' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3e%3c/svg%3e"), "#", "%23") !default;
-$form-feedback-icon-invalid-color: $form-feedback-invalid-color !default;
-$form-feedback-icon-invalid: str-replace(url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='#{$form-feedback-icon-invalid-color}' viewBox='-2 -2 7 7'%3e%3cpath stroke='#{$form-feedback-icon-invalid-color}' d='M0 0l3 3m0-3L0 3'/%3e%3ccircle r='.5'/%3e%3ccircle cx='3' r='.5'/%3e%3ccircle cy='3' r='.5'/%3e%3ccircle cx='3' cy='3' r='.5'/%3e%3c/svg%3E"), "#", "%23") !default;
+$form-feedback-icon-valid-color: var(--pgn-color-form-feedback-icon-valid) !default;
+$form-feedback-icon-valid: var(--pgn-other-content-form-feedback-icon-valid) !default;
+$form-feedback-icon-invalid-color: var(--pgn-color-form-feedback-icon-invalid) !default;
+$form-feedback-icon-invalid: var(--pgn-other-content-form-feedback-icon-invalid) !default;
$form-validation-states: () !default;
// stylelint-disable-next-line scss/dollar-variable-default
@@ -236,26 +246,37 @@ $form-validation-states: map-merge(
(
"valid": (
"color": $form-feedback-valid-color,
- "icon": $form-feedback-icon-valid
+ "icon": $form-feedback-icon-valid,
+ "tooltip-color": $form-feedback-tooltip-valid-color,
+ "tooltip-bg": $form-feedback-tooltip-valid-bg,
+ "focus-box-shadow-color": $form-feedback-focus-box-shadow-valid-color,
+ "checked-color": $form-feedback-checked-valid-color
),
"invalid": (
"color": $form-feedback-invalid-color,
- "icon": $form-feedback-icon-invalid
+ "icon": $form-feedback-icon-invalid,
+ "tooltip-bg": $form-feedback-tooltip-invalid-bg,
+ "focus-box-shadow-color": $form-feedback-focus-box-shadow-invalid-color,
+ "checked-color": $form-feedback-checked-invalid-color
),
),
$form-validation-states
);
// Form tooltips must come after regular tooltips
-$form-feedback-tooltip-padding-y: .25rem !default;
-$form-feedback-tooltip-padding-x: .5rem !default;
-$form-feedback-tooltip-font-size: $font-size-sm !default;
-$form-feedback-tooltip-line-height: $line-height-base !default;
-$form-feedback-tooltip-opacity: .9 !default;
-$form-feedback-tooltip-border-radius: $border-radius !default;
-
-$form-autosuggest-icon-width: 2.4rem;
-$form-autosuggest-icon-height: $form-autosuggest-icon-width;
-$form-autosuggest-spinner-width: 1.25rem;
-$form-autosuggest-spinner-height: $form-autosuggest-spinner-width;
-$form-autosuggest-border-width: .125rem;
+$form-feedback-tooltip-padding-y: var(--pgn-spacing-form-control-select-feedback-tooltip-padding-y) !default;
+$form-feedback-tooltip-padding-x: var(--pgn-spacing-form-control-select-feedback-tooltip-padding-x) !default;
+$form-feedback-tooltip-font-size: var(--pgn-typography-form-feedback-tooltip-font-size) !default;
+$form-feedback-tooltip-line-height: var(--pgn-typography-form-feedback-tooltip-line-height) !default;
+$form-feedback-tooltip-opacity: var(--pgn-other-form-feedback-tooltip-opacity) !default;
+$form-feedback-tooltip-border-radius: var(--pgn-size-form-feedback-tooltip-border-radius) !default;
+
+$form-control-icon-width: var(--pgn-size-form-control-icon-width) !default;
+$select-icon-padding: var(--pgn-spacing-form-control-select-icon-padding) !default;
+
+$form-autosuggest-icon-width: var(--pgn-size-form-autosuggest-icon-width) !default;
+$form-autosuggest-icon-height: var(--pgn-size-form-autosuggest-icon-height) !default;
+$form-autosuggest-spinner-width: var(--pgn-size-form-autosuggest-spinner-width) !default;
+$form-autosuggest-spinner-height: var(--pgn-size-form-autosuggest-spinner-height) !default;
+$form-autosuggest-border-width: var(--pgn-size-form-autosuggest-border-width) !default;
+$form-control-floating-label-text-bg: var(--pgn-color-form-control-label-floating-text) !default;
diff --git a/src/Form/fieldUtils.js b/src/Form/fieldUtils.js
index 031e684560..4e0b3cc1f3 100644
--- a/src/Form/fieldUtils.js
+++ b/src/Form/fieldUtils.js
@@ -20,8 +20,8 @@ const callAllHandlers = (...handlers) => {
};
const useHasValue = ({ defaultValue, value }) => {
- const [hasUncontrolledValue, setHasUncontrolledValue] = useState(!!defaultValue);
- const hasValue = !!value || hasUncontrolledValue;
+ const [hasUncontrolledValue, setHasUncontrolledValue] = useState(!!defaultValue || defaultValue === 0);
+ const hasValue = !!value || value === 0 || hasUncontrolledValue;
const handleInputEvent = (e) => setHasUncontrolledValue(e.target.value);
return [hasValue, handleInputEvent];
};
diff --git a/src/Form/form-radio.mdx b/src/Form/form-radio.mdx
index a7ea1060e7..72abcbb3ec 100644
--- a/src/Form/form-radio.mdx
+++ b/src/Form/form-radio.mdx
@@ -143,9 +143,9 @@ This is supported, but not recommended.
```jsx live
<>
- Red
- Green
- Blue
- Cyan
+ Red
+ Green
+ Blue
+ Cyan
>
```
\ No newline at end of file
diff --git a/src/Icon/_variables.scss b/src/Icon/_variables.scss
index fb5072cf10..ab409d7a59 100644
--- a/src/Icon/_variables.scss
+++ b/src/Icon/_variables.scss
@@ -1,6 +1,6 @@
// Icons sizes
-$icon-inline: .8em !default;
-$icon-sm: 1.25rem !default;
-$icon-md: 1.5rem !default;
-$icon-lg: 1.75rem !default;
+$icon-inline: var(--pgn-size-icon-inline) !default;
+$icon-sm: var(--pgn-size-icon-sm) !default;
+$icon-md: var(--pgn-size-icon-md) !default;
+$icon-lg: var(--pgn-size-icon-lg) !default;
diff --git a/src/IconButton/IconButton.scss b/src/IconButton/IconButton.scss
index 3843925ed6..6bc65cc2c6 100644
--- a/src/IconButton/IconButton.scss
+++ b/src/IconButton/IconButton.scss
@@ -1,20 +1,4 @@
-$icon-button-colors: (
- "primary": $primary,
- "secondary": $secondary,
- "brand": $brand,
- "success": $success,
- "warning": $warning,
- "danger": $danger,
- "light": $light,
- "dark": $dark,
- "black": $black,
-) !default;
-$btn-icon-diameter-md: 2.75rem !default;
-$btn-icon-diameter-sm: 2.25rem !default;
-$btn-icon-diameter-inline: calc(#{$line-height-base}em + .1em) !default;
-
-$btn-icon-bg: transparent !default;
-$btn-icon-accent-color: white !default;
+@import "variables";
@mixin btn-icon-size($icon-size) {
width: $icon-size;
@@ -64,6 +48,8 @@ $btn-icon-accent-color: white !default;
display: inline-flex;
justify-content: center;
border: none;
+ background-color: $btn-icon-bg;
+ color: $btn-icon-accent-color;
&.btn-icon-sm {
@include btn-icon-size($btn-icon-diameter-sm);
diff --git a/src/IconButton/_variables.scss b/src/IconButton/_variables.scss
new file mode 100644
index 0000000000..2555fff414
--- /dev/null
+++ b/src/IconButton/_variables.scss
@@ -0,0 +1,29 @@
+$btn-icon-diameter-md: var(--pgn-size-icon-button-diameter-md) !default;
+$btn-icon-diameter-sm: var(--pgn-size-icon-button-diameter-sm) !default;
+$btn-icon-diameter-inline: var(--pgn-size-icon-button-diameter-inline) !default;
+
+$btn-icon-bg: var(--pgn-color-icon-button-bg) !default;
+$btn-icon-accent-color: var(--pgn-color-icon-button-accent) !default;
+
+$btn-icon-primary: var(--pgn-color-icon-button-primary) !default;
+$btn-icon-secondary: var(--pgn-color-icon-button-secondary) !default;
+$btn-icon-brand: var(--pgn-color-icon-button-brand) !default;
+$btn-icon-success: var(--pgn-color-icon-button-success) !default;
+$btn-icon-warning: var(--pgn-color-icon-button-warning) !default;
+$btn-icon-danger: var(--pgn-color-icon-button-danger) !default;
+$btn-icon-light: var(--pgn-color-icon-button-light) !default;
+$btn-icon-dark: var(--pgn-color-icon-button-dark) !default;
+$btn-icon-black: var(--pgn-color-icon-button-black) !default;
+
+
+$icon-button-colors: (
+ "primary": $btn-icon-primary,
+ "secondary": $btn-icon-secondary,
+ "brand": $btn-icon-brand,
+ "success": $btn-icon-success,
+ "warning": $btn-icon-warning,
+ "danger": $btn-icon-danger,
+ "light": $btn-icon-light,
+ "dark": $btn-icon-dark,
+ "black": $btn-icon-black,
+) !default;
diff --git a/src/Image/Image.scss b/src/Image/Image.scss
index 9f37499cb6..410d7d57a1 100644
--- a/src/Image/Image.scss
+++ b/src/Image/Image.scss
@@ -1,2 +1,55 @@
@import "variables";
-@import "~bootstrap/scss/images";
+
+@mixin img-fluid() {
+ // Part 1: Set a maximum relative to the parent
+ max-width: 100%;
+ // Part 2: Override the height to auto, otherwise images will be stretched
+ // when setting a width and height attribute on the img element.
+ height: auto;
+}
+
+// Responsive images (ensure images don't scale beyond their parents)
+//
+// This is purposefully opt-in via an explicit class rather than being the default for all ` `s.
+// We previously tried the "images are responsive by default" approach in Bootstrap v2,
+// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)
+// which weren't expecting the images within themselves to be involuntarily resized.
+// See also https://github.com/twbs/bootstrap/issues/18178
+.img-fluid {
+ @include img-fluid();
+}
+
+
+// Image thumbnails
+.img-thumbnail {
+ padding: $thumbnail-padding;
+ background-color: $thumbnail-bg;
+ border: $thumbnail-border-width solid $thumbnail-border-color;
+
+ @include border-radius($thumbnail-border-radius);
+ @include box-shadow($thumbnail-box-shadow);
+
+ // Keep them at most 100% wide
+ @include img-fluid();
+}
+
+//
+// Figures
+//
+
+.figure {
+ // Ensures the caption's text aligns with the image.
+ display: inline-block;
+}
+
+.figure-img {
+ margin-bottom: calc(#{$spacer} * .5);
+ line-height: 1;
+}
+
+.figure-caption {
+ color: $figure-caption-color;
+
+ @include font-size($figure-caption-font-size);
+}
+
diff --git a/src/Image/README.md b/src/Image/README.md
index 1ee067d3d7..6689b77786 100644
--- a/src/Image/README.md
+++ b/src/Image/README.md
@@ -24,19 +24,19 @@ notes: |
<>
@@ -46,7 +46,7 @@ notes: |
## Fluid Sizing
```jsx live
-
+
```
diff --git a/src/Image/_variables.scss b/src/Image/_variables.scss
index 9de7935300..5fec1450e7 100644
--- a/src/Image/_variables.scss
+++ b/src/Image/_variables.scss
@@ -1,13 +1,13 @@
// Image thumbnails
-$thumbnail-padding: .25rem !default;
-$thumbnail-bg: $body-bg !default;
-$thumbnail-border-width: $border-width !default;
-$thumbnail-border-color: theme-color("gray", "border") !default;
-$thumbnail-border-radius: $border-radius !default;
-$thumbnail-box-shadow: 0 1px 2px rgba($black, .075) !default;
+$thumbnail-padding: var(--pgn-spacing-image-thumbnail-padding) !default;
+$thumbnail-bg: var(--pgn-color-image-thumbnail-bg) !default;
+$thumbnail-border-width: var(--pgn-size-image-thumbnail-border-width) !default;
+$thumbnail-border-color: var(--pgn-color-image-thumbnail-border) !default;
+$thumbnail-border-radius: var(--pgn-size-image-thumbnail-border-radius) !default;
+$thumbnail-box-shadow: var(--pgn-elevation-image-thumbnail-box-shadow) !default;
// Figures
-$figure-caption-font-size: 90% !default;
-$figure-caption-color: theme-color("gray", "light-text") !default;
+$figure-caption-font-size: var(--pgn-typography-image-figure-caption-font-size) !default;
+$figure-caption-color: var(--pgn-color-image-figure-caption) !default;
diff --git a/src/Input/README.md b/src/Input/README.md
deleted file mode 100644
index 1d0205d63b..0000000000
--- a/src/Input/README.md
+++ /dev/null
@@ -1,74 +0,0 @@
----
-title: 'Input'
-type: 'component'
-components:
-- Input
-categories:
-- Forms (deprecated)
-status: 'Deprecate Soon'
-designStatus: 'Done'
-devStatus: 'Done'
-notes: |
- Replaced by Form.Control
----
-
-A component for all user input. It is responsible for rendering select, textarea, and inputs of any type with the appropriate bootstrap class name.
-
-Extra props supplied to Input will be passed through to the html node.
-
-## Text
-
-```jsx live
-
-```
-
-## Select
-
-```jsx live
-
-```
-
-## Textarea
-
-```jsx live
-
-```
-
-## Date
-
-```jsx live
-
-```
-
-### File
-
-```jsx live
-
-```
-
-### Range
-
-```jsx live
-
-```
diff --git a/src/Input/__snapshots__/input.test.jsx.snap b/src/Input/__snapshots__/input.test.jsx.snap
deleted file mode 100644
index 1192de149d..0000000000
--- a/src/Input/__snapshots__/input.test.jsx.snap
+++ /dev/null
@@ -1,53 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[` rendering properly renders groups 1`] = `
-
-
- Foo Bar
-
-
- Bar foo
-
-
- FoBaro
-
-
- Farboo
-
-
-
- Foov Bar
-
-
- Barv foo
-
-
- FoBarov
-
-
- Farboov
-
-
-
-`;
diff --git a/src/Input/index.jsx b/src/Input/index.jsx
deleted file mode 100644
index 14e235e7ea..0000000000
--- a/src/Input/index.jsx
+++ /dev/null
@@ -1,151 +0,0 @@
-import React from 'react';
-import classNames from 'classnames';
-import PropTypes from 'prop-types';
-
-class Input extends React.Component {
- componentDidMount() {
- if (process.env.NODE_ENV === 'development') {
- this.checkHasLabel();
- }
- }
-
- getHTMLTagForType() {
- const { type } = this.props;
- if (type === 'select' || type === 'textarea') { return type; }
- return 'input';
- }
-
- getClassNameForType() {
- switch (this.props.type) {
- case 'file':
- return 'form-control-file';
- case 'checkbox':
- case 'radio':
- return 'form-check-input';
- default:
- return 'form-control';
- }
- }
-
- setRef(forwardedRef) {
- // In production just return the optional forwardedRef
- if (process.env.NODE_ENV !== 'development') { return forwardedRef; }
-
- return (element) => {
- if (forwardedRef) { forwardedRef.current = element; } // eslint-disable-line no-param-reassign
- this.inputEl = element;
- };
- }
-
- checkHasLabel() {
- if (this.inputEl.labels.length > 0) { return; }
- if (this.inputEl.getAttribute('aria-label') !== null) { return; }
- if (this.inputEl.getAttribute('aria-labelledby') !== null) { return; }
-
- if (console) {
- // eslint-disable-next-line no-console
- console.warn('Input[a11y]: There is no associated label for this Input');
- }
- }
-
- renderOptions(options) {
- return options.map((option) => {
- const {
- value,
- label,
- group,
- ...attributes
- } = option;
-
- if (group) {
- return (
-
- {this.renderOptions(group)}
-
- );
- }
- return (
-
- {label}
-
- );
- }, this);
- }
-
- render() {
- const {
- type,
- className,
- options,
- forwardedRef, // eslint-disable-line react/prop-types
- ...attributes // eslint-disable-line react/prop-types
- } = this.props;
-
- const htmlTag = this.getHTMLTagForType();
- const htmlProps = {
- className: classNames(this.getClassNameForType(), className),
- type: htmlTag === 'input' ? type : undefined,
- ...attributes,
- ref: this.setRef(forwardedRef),
- };
- const htmlChildren = type === 'select' ? this.renderOptions(options) : null;
-
- return React.createElement(htmlTag, htmlProps, htmlChildren);
- }
-}
-
-Input.propTypes = {
- /** specifies the type of component.
- * One of select, textarea, or any valid type for an html input tag. */
- type: PropTypes.oneOf([
- 'textarea',
- 'select',
- 'checkbox',
- 'color',
- 'date',
- 'datetime',
- 'datetime-local',
- 'email',
- 'file',
- 'hidden',
- 'image',
- 'month',
- 'number',
- 'password',
- 'radio',
- 'range',
- 'reset',
- 'search',
- 'submit',
- 'tel',
- 'text',
- 'time',
- 'url',
- 'week',
- ]).isRequired,
- /** specifies the className in addition to a bootstrap class name. */
- className: PropTypes.string,
- /** should be used to specify the options of an Input of type select */
- options: PropTypes.arrayOf(PropTypes.shape({
- label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- disabled: PropTypes.bool,
- group: PropTypes.arrayOf(PropTypes.shape({
- label: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
- disabled: PropTypes.bool,
- })),
- })),
-};
-
-Input.defaultProps = {
- className: undefined,
- options: [],
-};
-
-// eslint-disable-next-line react/no-multi-comp
-const InputWithRefForwarding = React.forwardRef((props, ref) => (
-
-));
-
-export default InputWithRefForwarding;
diff --git a/src/Input/input.test.jsx b/src/Input/input.test.jsx
deleted file mode 100644
index 8cd7a9fcaa..0000000000
--- a/src/Input/input.test.jsx
+++ /dev/null
@@ -1,84 +0,0 @@
-import React from 'react';
-import { mount } from 'enzyme';
-import renderer from 'react-test-renderer';
-
-import Input from './index';
-
-describe(' ', () => {
- const label = 'label';
- const name = 'name';
- const className = 'input';
- const props = {
- label,
- name,
- className,
- };
- const types = [
- 'textarea',
- 'select',
- 'checkbox',
- 'color',
- 'date',
- 'datetime',
- 'datetime-local',
- 'email',
- 'file',
- 'hidden',
- 'image',
- 'month',
- 'number',
- 'password',
- 'radio',
- 'range',
- 'reset',
- 'search',
- 'submit',
- 'tel',
- 'text',
- 'time',
- 'url',
- 'week',
- ];
-
- const groupInput = (
-
- );
-
- describe('rendering', () => {
- it('should render with forwardRef', () => {
- const wrapper = mount( );
- expect(wrapper.find(React.forwardRef)).toBeTruthy();
- });
-
- it('should render each input type', () => {
- types.forEach((type) => {
- const wrapper = mount( );
- const input = wrapper.find('Input.input');
- expect(input.prop('type')).toEqual(type);
- });
- });
-
- it('properly renders groups', () => {
- const tree = renderer.create(groupInput).toJSON();
- expect(tree).toMatchSnapshot();
- });
- });
-});
diff --git a/src/InputSelect/README.md b/src/InputSelect/README.md
deleted file mode 100644
index d1d99c30cc..0000000000
--- a/src/InputSelect/README.md
+++ /dev/null
@@ -1,136 +0,0 @@
----
-title: 'InputSelect'
-type: 'component'
-components:
-- InputSelect
-categories:
-- Forms (deprecated)
-status: 'Deprecate Soon'
-designStatus: 'TBD'
-devStatus: 'To Do'
-notes: |
- Replaced by Input and ValidationFormGroup
----
-
-## basic usage
-
-```jsx live
-
-```
-
-## separate labels and values
-
-```jsx live
-
-```
-
-## separate option groups
-
-```jsx live
-
-```
-
-## with validation
-
-```jsx live
- {
- let feedback = { isValid: true };
- if (!value) {
- feedback = {
- isValid: false,
- validationMessage: 'Please make a selection.',
- };
- }
- return feedback;
- }}
-/>
-```
-
-## disabled usage
-
-```jsx live
-
-```
-
-## with disabled option
-
-```jsx live
-
-```
diff --git a/src/InputSelect/index.jsx b/src/InputSelect/index.jsx
deleted file mode 100644
index 3f3a25a417..0000000000
--- a/src/InputSelect/index.jsx
+++ /dev/null
@@ -1,92 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-
-import asInput from '../asInput';
-import withDeprecatedProps, { DeprTypes } from '../withDeprecatedProps';
-
-class Select extends React.Component {
- static getOption(option, i) {
- const { disabled } = option;
- let { label, value } = option;
-
- if (typeof option === 'string') {
- label = option;
- value = option;
- }
-
- return (
-
- {label}
-
- );
- }
-
- getOptions() {
- return this.props.options.map((option, i) => {
- let section;
- if (option.options) {
- const groupOpts = option.options.map((opt, j) => Select.getOption(opt, j));
- section = (
-
- {groupOpts}
-
- );
- } else {
- section = Select.getOption(option, i);
- }
- return section;
- });
- }
-
- render() {
- const {
- className,
- inputRef,
- ...others
- } = this.props;
- const options = this.getOptions();
-
- return (
-
- {options}
-
- );
- }
-}
-
-Select.propTypes = {
- className: PropTypes.string,
- inputRef: PropTypes.oneOfType([
- PropTypes.func,
- PropTypes.shape({ current: PropTypes.instanceOf(PropTypes.element) }),
- ]),
- options: PropTypes.oneOfType([
- PropTypes.arrayOf(PropTypes.string),
- PropTypes.arrayOf(PropTypes.shape({})),
- ]).isRequired,
-};
-
-Select.defaultProps = {
- className: undefined,
- inputRef: undefined,
-};
-
-const InputSelect = asInput(withDeprecatedProps(Select, 'InputSelect', {
- className: {
- deprType: DeprTypes.FORMAT,
- expect: value => typeof value === 'string',
- transform: value => (Array.isArray(value) ? value.join(' ') : value),
- message: 'It should be a string.',
- },
-}));
-
-export default InputSelect;
diff --git a/src/InputText/InputText.test.jsx b/src/InputText/InputText.test.jsx
deleted file mode 100644
index 47720327a2..0000000000
--- a/src/InputText/InputText.test.jsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import React from 'react';
-import { mount } from 'enzyme';
-
-import InputText from './index';
-
-describe(' ', () => {
- const label = 'label';
- const name = 'name';
- const props = {
- label,
- name,
- };
-
- describe('rendering', () => {
- it('should render with default type when type is not defined', () => {
- const wrapper = mount( );
- expect(wrapper.find('input')).toHaveLength(1);
-
- const input = wrapper.find('input').at(0);
- expect(input.prop('type')).toEqual('text');
- });
-
- it('should render with default type when type is defined as undefined', () => {
- const wrapper = mount( );
- expect(wrapper.find('input')).toHaveLength(1);
-
- const input = wrapper.find('input').at(0);
- expect(input.prop('type')).toEqual('text');
- });
-
- it('should render with default type when type is defined as null', () => {
- const wrapper = mount( );
- expect(wrapper.find('input')).toHaveLength(1);
-
- const input = wrapper.find('input').at(0);
- expect(input.prop('type')).toEqual('text');
- });
-
- it('should render with specified type when type is defined', () => {
- const type = 'foobar';
- const wrapper = mount( );
- expect(wrapper.find('input')).toHaveLength(1);
-
- const input = wrapper.find('input').at(0);
- expect(input.prop('type')).toEqual(type);
- });
-
- it('should render with the autocomplete property if set', () => {
- const wrapper = mount( );
- expect(wrapper.find('input')).toHaveLength(1);
-
- const input = wrapper.find('input').at(0);
- expect(input.prop('autoComplete')).toEqual('off');
- });
-
- it('should render with custom classNames if set', () => {
- const wrapper = mount( );
- expect(wrapper.find('input')).toHaveLength(1);
-
- const input = wrapper.find('input').at(0);
- expect(input.prop('type')).toEqual('text');
- expect(input.hasClass('first')).toEqual(true);
- expect(input.hasClass('last')).toEqual(true);
- });
-
- it('should not be readOnly if the readOnly property is not set', () => {
- const wrapper = mount( );
- expect(wrapper.props().readOnly).toBeUndefined();
- });
-
- it('should render with the readOnly property if set', () => {
- const wrapper = mount( );
- expect(wrapper.props().readOnly).toEqual(true);
- });
- });
-});
diff --git a/src/InputText/README.md b/src/InputText/README.md
deleted file mode 100644
index 60ec59d5b4..0000000000
--- a/src/InputText/README.md
+++ /dev/null
@@ -1,293 +0,0 @@
----
-title: 'InputText'
-type: 'component'
-components:
-- InputText
-categories:
-- Forms (deprecated)
-status: 'Deprecate Soon'
-designStatus: 'TBD'
-devStatus: 'To Do'
-notes: |
- Replaced by Input and ValidationFormGroup
----
-
-## minimal usage
-
-```jsx live
-
-```
-
-## read only
-
-```jsx live
-
-```
-
-## validation
-
-```jsx live
- {
- let feedback = { isValid: true };
- if (value.length < 3) {
- feedback = {
- isValid: false,
- validationMessage: 'Username must be at least 3 characters in length.',
- };
- }
- return feedback;
- }}
-/>
-```
-
-### validation with danger theme
-
-```jsx live
- {
- let feedback = { isValid: true };
- if (value.length < 3) {
- feedback = {
- isValid: false,
- validationMessage: 'Username must be at least 3 characters in length.',
- dangerIconDescription: 'Error',
- };
- }
- return feedback;
- }}
- themes={['danger']}
-/>
-```
-
-### label as element
-
-```jsx live
-Element}
- value="Label is wrapped in language span"
-/>
-```
-
-### focus test
-
-```jsx live
-class FocusInputWrapper extends React.Component {
- constructor(props) {
- super(props);
- this.state = { open: true };
-
- this.resetStatusAlertWrapperState = this.resetStatusAlertWrapperState.bind(
- this,
- );
- }
-
- resetStatusAlertWrapperState() {
- this.setState({ open: false });
- this.inputForm.focus();
- }
-
- render() {
- return (
-
-
- {
- this.inputForm = input;
- }}
- />
-
- );
- }
-}
-```
-
-### different textual input types
-
-```jsx live
-
-```
-
-### price with step
-
-```jsx live
-
-```
-
-### displayed inline
-
-```jsx live
-
-```
-
-### with input group addons
-
-```jsx live
- }
- />
- {'@example.com'} }
- />
- {'$'}