diff --git a/src/Input/DownshiftSelect/Select.stories.tsx b/src/Input/DownshiftSelect/Select.stories.tsx
index 9f9525c7b..5a6fe4145 100644
--- a/src/Input/DownshiftSelect/Select.stories.tsx
+++ b/src/Input/DownshiftSelect/Select.stories.tsx
@@ -379,3 +379,29 @@ ConfigurableWidth.parameters = {
},
},
};
+
+const SmallContainer = styled(Select.Components.Container)`
+ max-width: 200px;
+ font-size: 11px;
+`;
+
+export const Small = Template.bind({});
+Small.args = {
+ label: "I'm so small!",
+ placeholder: 'Try typing here :-P',
+ components: { Container: SmallContainer },
+ helperText: 'Why would you do this to me?',
+};
+Small.parameters = {
+ docs: {
+ description: {
+ story:
+ "
By default, the Select dictates a font-size of 16px that cascades through (almost) all sub-components. Appropriate spaces are defined using em
, so if you want to resize the Select, just change the container's font-size.
The exception to the 16px default is the helper text, which also just uses an em
relative value.
",
+ },
+ },
+};
+
+export const EmptyListText = Template.bind({});
+EmptyListText.args = {
+ emptyListText: '¯\\_(ツ)_/¯',
+};
diff --git a/src/Input/DownshiftSelect/Select.tsx b/src/Input/DownshiftSelect/Select.tsx
index 139642210..a72730ff8 100644
--- a/src/Input/DownshiftSelect/Select.tsx
+++ b/src/Input/DownshiftSelect/Select.tsx
@@ -13,6 +13,9 @@ export const defaultTransformFunction = (items: Item[], inputValue: string) =>
export const defaultItemToString = (item: Item) => item.label;
+export const defaultEmptyListText =
+ 'No results found. Try another keyword to search for.';
+
export interface Components {
Container: typeof internalComponents.Container;
Label: typeof internalComponents.Label;
@@ -24,6 +27,7 @@ export interface Components {
ToggleButton: typeof internalComponents.ToggleButton;
Menu: typeof internalComponents.Menu;
Item: typeof internalComponents.Item;
+ EmptyList: typeof internalComponents.EmptyList;
HelperText: typeof internalComponents.HelperText;
}
@@ -46,6 +50,7 @@ export type MenuProps = HTMLAttributes;
export interface ItemProps extends HTMLAttributes {
item: Item;
}
+export type EmptyListProps = HTMLAttributes;
export type HelperTextProps = HTMLAttributes;
export interface Props extends ComboboxProps {
@@ -95,6 +100,8 @@ export interface Props extends ComboboxProps {
// onInputValueChange?: (inputValue: string) => void;
onClear?: () => void;
+
+ emptyListText?: string;
}
export const Select: React.FC & { Components: Components } = ({
@@ -117,6 +124,9 @@ export const Select: React.FC & { Components: Components } = ({
// inputValue: inputValueExternal,
// onInputValueChange: onInputValueChangeExternal,
onClear,
+ onFocus: onFocusExternal,
+ onBlur: onBlurExternal,
+ emptyListText = defaultEmptyListText,
...props
}) => {
const mergedComponents = {
@@ -135,6 +145,7 @@ export const Select: React.FC & { Components: Components } = ({
ToggleButton,
Menu,
Item,
+ EmptyList,
HelperText,
} = mergedComponents;
@@ -149,6 +160,7 @@ export const Select: React.FC & { Components: Components } = ({
getMenuProps,
getItemProps,
reset,
+ openMenu,
} = useCombobox- ({
items: displayItems,
onInputValueChange: ({ inputValue }) => {
@@ -191,12 +203,31 @@ export const Select: React.FC
& { Components: Components } = ({
reset();
};
+ const [isFocused, setIsFocused] = useState(false);
+ const onFocusInternal = () => {
+ setIsFocused(true);
+ openMenu();
+ };
+ const onBlurInternal = () => setIsFocused(false);
+ const onFocus = () => {
+ if (isFunction(onFocusExternal)) {
+ onFocusExternal();
+ }
+ onFocusInternal();
+ };
+ const onBlur = () => {
+ if (isFunction(onBlurExternal)) {
+ onBlurExternal();
+ }
+ onBlurInternal();
+ };
+
return (
{label && (
@@ -206,11 +237,16 @@ export const Select: React.FC & { Components: Components } = ({
& { Components: Components } = ({
- {isOpen &&
+ {isOpen && displayItems.length > 0 ? (
displayItems.map((item, index) => (
- & { Components: Components } = ({
>
{defaultItemToString(item)}
- ))}
+ ))
+ ) : (
+ {emptyListText}
+ )}
{helperText && (
diff --git a/src/Input/DownshiftSelect/SelectStyle.ts b/src/Input/DownshiftSelect/SelectStyle.ts
index 38ae19446..b17a1e2ee 100644
--- a/src/Input/DownshiftSelect/SelectStyle.ts
+++ b/src/Input/DownshiftSelect/SelectStyle.ts
@@ -9,6 +9,7 @@ import {
IndicatorsContainerProps,
InputProps,
ItemProps,
+ EmptyListProps,
LabelProps,
LoadingIndicatorProps,
MenuProps,
@@ -17,13 +18,13 @@ import {
export const Container = styled.div`
position: relative;
+ font-size: 16px;
`;
export const Label = styled.label`
display: block;
margin-bottom: 8px;
color: ${Greyscale.devilsgrey};
- font-size: 16px;
font-weight: 500;
&[data-active='true'] {
@@ -42,17 +43,17 @@ export const Label = styled.label`
export const Combobox = styled.div`
display: grid;
grid-template-columns: 1fr auto;
- grid-column-gap: 12px;
- padding: 12px 16px 12px 16px;
- border-radius: 8px;
+ grid-column-gap: 0.75em;
+ padding: 0.75em 1em 0.75em 1em;
+ border-radius: 0.5em;
background-color: #ebf5fa;
- font-size: 16px;
:hover {
background-color: #d6eaf2;
}
- &[aria-expanded='true'] {
+ &[aria-expanded='true'],
+ &[data-active='true'] {
background-color: #c2e0ed;
}
@@ -68,9 +69,9 @@ export const Combobox = styled.div`
export const Input = styled.input`
border: none;
background-color: transparent;
- outline: none; // TODO
+ outline: none; // Okay, because the background-color changes on focus
color: ${Greyscale.devilsgrey};
- font-size: 16px;
+ font-size: inherit;
text-overflow: ellipsis;
&:not([value='']) {
@@ -86,9 +87,8 @@ export const IndicatorsContainer = styled.div`
display: flex;
flex-direction: row;
> :not(:last-child) {
- margin-right: 12px;
+ margin-right: 0.75em;
}
- font-size: 16px;
`;
export const _IndicatorButton = styled.button`
@@ -96,7 +96,7 @@ export const _IndicatorButton = styled.button`
border: none;
background: none;
color: ${Greyscale.devilsgrey};
- font-size: 16px;
+ font-size: inherit;
`;
export const ClearButton = styled(_IndicatorButton)``;
@@ -105,16 +105,16 @@ export const ToggleButton = styled(_IndicatorButton)``;
export const LoadingIndicator = styled(Loading)`
align-items: center;
- font-size: 9px;
+ font-size: 0.5625em;
`;
export const Menu = styled.ul`
margin-top: 4px;
position: absolute;
width: 100%;
- padding: 8px 0 8px 0;
+ padding: 0.5em 0 0.5em 0;
border: 1px solid #eeeeee;
- border-radius: 8px;
+ border-radius: 0.5em;
box-shadow: ${Shadow.down3};
background-color: white;
@@ -124,9 +124,8 @@ export const Menu = styled.ul`
`;
export const Item = styled.li`
- padding: 8px 16px;
+ padding: 0.5em 1em;
list-style-type: none;
- font-size: 16px;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
@@ -144,10 +143,20 @@ export const Item = styled.li`
}
`;
+export const EmptyList = styled.li`
+ padding: 0.5em 1em;
+ list-style-type: none;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ color: ${Greyscale.lightgrey};
+ cursor: not-allowed;
+`;
+
export const HelperText = styled.span`
margin-top: 4px;
color: ${Greyscale.devilsgrey};
- font-size: 14px;
+ font-size: 0.875em;
&[data-invalid='true'] {
color: ${PrimaryColor.glintsred};