diff --git a/components/AutoComplete/AutoComplete.module.css b/components/AutoComplete/AutoComplete.module.css
index 745ef6df..965e1801 100644
--- a/components/AutoComplete/AutoComplete.module.css
+++ b/components/AutoComplete/AutoComplete.module.css
@@ -1,6 +1,6 @@
:root {
- --max-items-visibility: 7;
- --item-height: 44px;
+ --max-items-visibility-autocomplete: 7;
+ --item-height-autocomplete: 44px;
--dropitem-font-size: calc(var(--qtm-base-font-size) * 0.875);
}
@@ -52,7 +52,7 @@
border-radius: 4px;
box-sizing: border-box;
list-style: none;
- max-height: calc(var(--item-height) * var(--max-items-visibility));
+ max-height: calc(var(--item-height-autocomplete) * var(--max-items-visibility-autocomplete));
overflow: auto;
padding: 0;
position: absolute;
@@ -68,7 +68,7 @@
justify-content: space-between;
box-sizing: border-box;
cursor: pointer;
- height: var(--item-height);
+ height: var(--item-height-autocomplete);
color: var(--qtm-colors-neutral-700);
font-size: var(--dropitem-font-size);
background-color: var(--qtm-colors-neutral-0);
diff --git a/components/Dropdown/Dropdown.jsx b/components/Dropdown/Dropdown.jsx
index 3943816f..1d69ffe4 100644
--- a/components/Dropdown/Dropdown.jsx
+++ b/components/Dropdown/Dropdown.jsx
@@ -1,10 +1,9 @@
import { useState, forwardRef } from 'react';
import PropTypes from 'prop-types';
-import styled, { css } from 'styled-components';
import Downshift from 'downshift';
+import classNames from 'classnames';
import Icon from '../Icon/Icon';
-import { FieldGroup, shadow, createUniqId, normalizeChars } from '../shared';
-import { colors, spacing, baseFontSize } from '../shared/theme';
+import { FieldGroup, createUniqId, normalizeChars } from '../shared';
import {
InputLabel,
@@ -14,15 +13,12 @@ import {
HelperText,
} from '../Input/sub-components';
import { useTextInputClass } from '../Input/sub-components/TextInput';
+import styles from './Dropdown.module.css';
const uniqId = createUniqId('dropdown-');
-const ITEM_HEIGHT = '44px';
const MAX_ITEMS_VISIBILITY = 7;
-const DROPITEM_FONT_SIZE = baseFontSize * 0.875;
-const DROPITEM_IMAGE_SIZE = '24px';
-const ICON_DEFAULT_SIZE = `${baseFontSize * 1.5}px`;
-const DropButtonBase = forwardRef(
+const DropButton = forwardRef(
(
{ children, className, hasDefaultValue, hasLabel, skin, error, ...rest },
ref,
@@ -42,173 +38,15 @@ const DropButtonBase = forwardRef(
);
},
);
-const propsNotContainedInDropButtonBase = ['text'];
-const DropButton = styled(DropButtonBase).withConfig({
- shouldForwardProp: (prop) =>
- !propsNotContainedInDropButtonBase.includes(prop),
-})`
- align-items: center;
- cursor: pointer;
- display: flex;
- justify-content: space-between;
- text-align: left;
-
- ${({ text }) => `
- ${!text ? 'flex-direction: row-reverse;' : ''}
- color: inherit;
- `};
-`;
-
-const propsNotContainedInInput = ['theme', 'autocomplete'];
-
-const DropInput = styled(TextInput).withConfig({
- shouldForwardProp: (prop) => !propsNotContainedInInput.includes(prop),
-})`
- align-items: center;
- cursor: pointer;
- display: flex;
- justify-content: space-between;
- text-align: left;
-
- ${({
- text,
- autocomplete,
- theme: {
- spacing: { xsmall, medium, xxxlarge },
- },
- }) => `
- ${
- autocomplete
- ? `padding: ${xsmall}px ${xxxlarge}px ${xsmall}px ${medium}px;`
- : ''
- }
- ${!text ? 'flex-direction: row-reverse;' : ''}
- color: inherit;
- `};
-`;
-
-const ArrowIcon = styled(Icon)`
- pointer-events: none;
- width: ${ICON_DEFAULT_SIZE};
-
- ${({ selectedItem }) =>
- !selectedItem &&
- `
- color: inherit;
- `}
-`;
-
-const DropList = styled.ul`
- border-radius: 4px;
- box-sizing: border-box;
- list-style: none;
- max-height: calc(${ITEM_HEIGHT} * ${MAX_ITEMS_VISIBILITY});
- overflow: auto;
- padding: 0;
- position: absolute;
- width: 100%;
- z-index: 9999;
-
- ${({ theme }) => {
- const {
- spacing: { xxsmall },
- colors: { neutral },
- } = theme;
-
- return css`
- background-color: ${neutral[0]};
- color: ${neutral[700]};
- margin-top: ${xxsmall}px;
- ${shadow(5, neutral[300])({ theme })};
- `;
- }}
-`;
-
-const CheckIcon = styled(Icon).attrs({
- name: 'check',
-})`
- ${({
- selectedItem,
- theme: {
- colors: {
- primary: { 700: primary700 },
- },
- },
- }) =>
- !selectedItem &&
- `
- color: ${primary700};
- `}
-`;
-
-const DropItem = styled.li`
- display: flex;
- align-items: center;
- justify-content: space-between;
- box-sizing: border-box;
- cursor: pointer;
- min-height: 42px;
- ${({
- theme: {
- spacing: { xsmall, medium },
- colors: {
- neutral: { 0: neutral0 },
- },
- },
- }) => `
- font-size: ${DROPITEM_FONT_SIZE}px;
- background-color: ${neutral0};
- padding: ${xsmall}px ${medium}px;
- `}
- &[aria-selected= 'true' ] {
- ${({
- theme: {
- colors: {
- neutral: { 100: neutral100 },
- },
- },
- }) => `
- background-color: ${neutral100};
- `}
- }
-
- ${({ isSelected }) =>
- isSelected &&
- `
- display: flex;
- justify-content: space-between;
- `}
-`;
-
-const DropContainer = styled.div`
- position: relative;
-`;
-
-const SelectedItemLabel = styled.span`
- ${({
- theme: {
- colors: {
- primary: { 700: primary700 },
- },
- },
- }) => `
- color: ${primary700}
- `}
-`;
-
-const DropItemImage = styled.img`
- width: ${DROPITEM_IMAGE_SIZE};
- height: ${DROPITEM_IMAGE_SIZE};
- margin-left: ${spacing.xsmall}px;
-`;
-
-DropInput.displayName = 'DropInput';
-DropItem.displayName = 'DropItem';
-ArrowIcon.displayName = 'ArrowIcon';
-SelectedItemLabel.displayName = 'SelectedItemLabel';
-DropItemImage.displayName = 'DropItemImage';
-DropContainer.displayName = 'DropContainer';
+const DropContainer = forwardRef(({ children, className, ...rest }, ref) => {
+ const dropContainerClass = classNames(styles['drop-container'], className);
+ return (
+
+ {children}
+
+ );
+});
const _getValue = (item) => (item ? item.value || item.label || item : '');
const _getLabel = (item) => (item ? item.label || item.value || item : '');
@@ -224,48 +62,59 @@ const itemPropType = PropTypes.oneOfType([
}),
]);
-const List = ({ theme, items, selectedItem = null, getItemProps }) => (
-
- {items.map((item) => (
-
- {_isEqual(selectedItem, item) ? (
- <>
-
- {_getLabel(item)}
-
+const List = ({ items, selectedItem = null, getItemProps }) => {
+ const imageItemClass = classNames(styles['drop-image-item']);
+ const checkIconClass = classNames(styles['check-icon-without-selected-item']);
+ const dropListClass = classNames(styles['drop-list']);
+ const itemClass = classNames(styles['drop-item']);
+ const itemSelectedLabelClass = classNames(
+ styles['drop-item-item-selected-label'],
+ );
- {_getImage(item) ? (
-
- ) : (
-
- )}
- >
- ) : (
- <>
- {_getLabel(item)}
- {_getImage(item) && (
-
- )}
- >
- )}
-
- ))}
-
-);
+ return (
+
+ {items.map((item) => (
+ -
+ {_isEqual(selectedItem, item) ? (
+ <>
+ {_getLabel(item)}
+
+ {_getImage(item) ? (
+
+ ) : (
+
+ )}
+ >
+ ) : (
+ <>
+ {_getLabel(item)}
+ {_getImage(item) && (
+
+ )}
+ >
+ )}
+
+ ))}
+
+ );
+};
List.propTypes = {
selectedItem: itemPropType,
- theme: PropTypes.shape({
- colors: PropTypes.object,
- spacing: PropTypes.object,
- }).isRequired,
items: PropTypes.arrayOf(itemPropType).isRequired,
getItemProps: PropTypes.func.isRequired,
};
@@ -281,7 +130,6 @@ const Dropdown = ({
selectedItem = null,
onChange = () => {},
autocomplete = false,
- theme = { colors, spacing, baseFontSize },
id = '',
name = '',
ignoreSpecialChars = false,
@@ -289,6 +137,14 @@ const Dropdown = ({
...rest
}) => {
const _buttonLabel = selectedItem ? _getLabel(selectedItem) : placeholder;
+ const dropdownButtonClass = classNames(styles['dropdown-button'], {
+ [styles['without-text']]: !_buttonLabel,
+ });
+ const dropdownInputClass = classNames(styles['dropdown-input'], {
+ [styles['without-text']]: !_buttonLabel,
+ [styles['dropdown-input-autocomplete']]: autocomplete,
+ });
+ const arrowIconClass = classNames(styles['arrow-icon']);
const _highlightedReducer = ({ selectedItem: selected }, changes) => {
if (changes.isOpen !== undefined && changes.isOpen) {
@@ -342,7 +198,7 @@ const Dropdown = ({
const filteredInput = isOpen ? inputFilter(inputValue) : [];
return (
-
+
{label && (
{autocomplete ? (
<>
-
-
+
@@ -384,7 +240,6 @@ const Dropdown = ({
{filteredInput.length > 0 && (
@@ -396,22 +251,21 @@ const Dropdown = ({
{...getToggleButtonProps()}
disabled={disabled}
error={error}
- text={_buttonLabel}
hasLabel={hasLabel}
skin={skin}
id={_id}
+ className={dropdownButtonClass}
>
{_buttonLabel}
-
{isOpen && (
@@ -449,11 +303,6 @@ Dropdown.propTypes = {
onChange: PropTypes.func,
/** A list of string or objects with value and label keys */
items: PropTypes.arrayOf(itemPropType),
- theme: PropTypes.shape({
- colors: PropTypes.object,
- spacing: PropTypes.object,
- baseFontSize: PropTypes.number,
- }),
ignoreSpecialChars: PropTypes.bool,
skin: PropTypes.oneOf(['default', 'dark']),
};
diff --git a/components/Dropdown/Dropdown.module.css b/components/Dropdown/Dropdown.module.css
new file mode 100644
index 00000000..935305b0
--- /dev/null
+++ b/components/Dropdown/Dropdown.module.css
@@ -0,0 +1,100 @@
+:root {
+ --max-items-visibility-dropdown: 7;
+ --item-height-dropdown: 44px;
+
+ --qtm-shadow-umbra-neutral-300-color: rgba(224, 224, 224, var(--qtm-shadow-umbra-opacity));
+ --qtm-shadow-penumbra-neutral-300-color: rgba(224, 224, 224, var(--qtm-shadow-penumbra-opacity));
+ --qtm-shadow-ambient-neutral-300-color: rgba(224, 224, 224, var(--qtm-shadow-ambient-opacity));
+
+ --shadow-5-neutral-300:
+ 0px 3px 5px -1px var(--qtm-shadow-umbra-neutral-300-color),
+ 0px 5px 8px 0px var(--qtm-shadow-penumbra-neutral-300-color),
+ 0px 1px 14px 0px var(--qtm-shadow-ambient-neutral-300-color);
+}
+
+.dropdown-button {
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+ justify-content: space-between;
+ text-align: left;
+ color: inherit;
+}
+
+.without-text {
+ flex-direction: row-reverse;
+}
+
+.dropdown-input {
+ align-items: center;
+ cursor: pointer;
+ display: flex;
+ justify-content: space-between;
+ text-align: left;
+ color: inherit;
+}
+
+.dropdown-input-autocomplete {
+ padding: var(--qtm-spacing-xsmall) var(--qtm-spacing-xxxlarge) var(--qtm-spacing-xsmall) var(--qtm-spacing-medium);
+}
+
+.arrow-icon {
+ pointer-events: none;
+ width: calc(var(--qtm-base-font-size) * 1.5);
+ color: inherit;
+}
+
+.check-icon-without-selected-item {
+ color: var(--qtm-colors-primary-700);
+}
+
+.drop-container {
+ position: relative;
+}
+
+.drop-list {
+ border-radius: 4px;
+ box-sizing: border-box;
+ list-style: none;
+ max-height: calc(var(--item-height-dropdown) * var(--max-items-visibility-dropdown));
+ overflow: auto;
+ padding: 0;
+ position: absolute;
+ width: 100%;
+ z-index: 9999;
+ background-color: var(--qtm-colors-neutral-0);
+ color: var(--qtm-colors-neutral-700);
+ margin-top: var(--qtm-spacing-xxsmall);
+ box-shadow: var(--shadow-5-neutral-300);
+}
+
+.drop-image-item {
+ width: 24px;
+ height: 24px;
+ margin-left: var(--qtm-spacing-xsmall);
+}
+
+.drop-item {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ box-sizing: border-box;
+ cursor: pointer;
+ min-height: 42px;
+ font-size: calc(var(--qtm-base-font-size) * 0.875);
+ background-color: var(--qtm-colors-neutral-0);
+ padding: var(--qtm-spacing-xsmall) var(--qtm-spacing-medium);
+}
+
+.drop-item[aria-selected='true'] {
+ background-color: var(--qtm-colors-neutral-100);
+}
+
+.drop-item-item-selected {
+ display: flex;
+ justify-content: space-between;
+}
+
+.drop-item-item-selected-label {
+ color: var(--qtm-colors-primary-700);
+}
\ No newline at end of file
diff --git a/components/Dropdown/__snapshots__/Dropdown.unit.test.jsx.snap b/components/Dropdown/__snapshots__/Dropdown.unit.test.jsx.snap
index 4c385e03..226f26ee 100644
--- a/components/Dropdown/__snapshots__/Dropdown.unit.test.jsx.snap
+++ b/components/Dropdown/__snapshots__/Dropdown.unit.test.jsx.snap
@@ -25,31 +25,22 @@ exports[`Dropdown component should match the snapshot 1`] = `
width: 100%;
}
-.c1 {
- -webkit-align-items: center;
- -webkit-box-align: center;
- -ms-flex-align: center;
+.Dropdown-module__dropdown-button___DZE6T {
align-items: center;
+ color: inherit;
cursor: pointer;
- display: -webkit-box;
- display: -webkit-flex;
- display: -ms-flexbox;
display: flex;
- -webkit-box-pack: justify;
- -webkit-justify-content: space-between;
- -ms-flex-pack: justify;
justify-content: space-between;
text-align: left;
- color: inherit;
}
-.c2 {
- pointer-events: none;
- width: 24px;
+.Dropdown-module__arrow-icon___lvU4r {
color: inherit;
+ pointer-events: none;
+ width: calc(var(--qtm-base-font-size)*1.5);
}
-.c0 {
+.Dropdown-module__drop-container___SjYi- {
position: relative;
}
@@ -60,7 +51,7 @@ exports[`Dropdown component should match the snapshot 1`] = `
aria-expanded="false"
aria-haspopup="listbox"
aria-labelledby="downshift-0-label"
- class="c0"
+ class="Dropdown-module__drop-container___SjYi-"
role="combobox"
>