Skip to content

Commit

Permalink
feat: InputTime dropdown menu has default max height of 10.5 rows (#252)
Browse files Browse the repository at this point in the history
* feat: InputTime dropdown menu has default max height of 10.5 rows
fixes #249

* docs: Add InputTime stories for disabled and sans-validation cases

* feat: InputTime has dropdownProps for customizing display of dropdown menu

* refactor: InputTime Dropdown CSS refactor with clear variable names.
  • Loading branch information
pixelbandito authored Aug 3, 2020
1 parent 6fcf6f3 commit 719ad61
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 13 deletions.
1 change: 1 addition & 0 deletions src/components/Dropdown/Menu/Menu.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
transition: opacity 200ms var(--rvr-easeInOutQuad);
opacity: 0;
display: block;
overflow-y: auto;
}

.entering {
Expand Down
28 changes: 27 additions & 1 deletion src/components/Dropdown/story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,15 @@ storiesOf('Star Systems/Dropdown', module)
'Overview',
() => (
<Dropdown
className={text('className', '')}
className={text('className', 'm-5')}
disabled={boolean('disabled', false)}
isOpen={boolean('isOpen', false)}
onToggle={action('onToggle')}
>
{text('children', 'Dropdown children')}
<Dropdown.Menu>
{text('Dropdown.Menu children', 'Dropdown menu children')}
</Dropdown.Menu>
</Dropdown>
),
{
Expand Down Expand Up @@ -104,6 +107,29 @@ storiesOf('Star Systems/Dropdown', module)
className="inline"
/>
</div>
<div className="m-5">
<OpenableDropdown
buttonProps={{
children: "With `menuProps.style.max-height: '100px'`",
}}
className="inline"
menuProps={{
// Too lazy to type out a story example
/* eslint-disable @typescript-eslint/no-explicit-any, react/no-array-index-key */
children: new Array(20)
.fill(null)
.map((props: any, i: number) => (
<div key={i} {...props}>
Item {i + 1}
</div>
)),
/* eslint-enable @typescript-eslint/no-explicit-any, react/no-array-index-key */
style: {
maxHeight: '100px',
},
}}
/>
</div>
<div className="m-5">
<OpenableDropdown
buttonProps={{
Expand Down
13 changes: 10 additions & 3 deletions src/components/InputTime/AsString.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import styles from './InputTime.module.css';

export interface AsStringProps
extends Omit<InputProps, 'value' | 'max' | 'min'> {
dropdownProps?: Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any
formatTime?: (date: Date) => string;
fuzzyInputProps?: InputProps;
max?: string;
Expand All @@ -41,6 +42,8 @@ export interface AsStringProps
const AsString: React.FC<AsStringProps> = ({
className = '',
disabled,
dropdownProps,
fauxDisabled,
formatTime,
forwardedRef,
fuzzyInputProps = {},
Expand Down Expand Up @@ -206,6 +209,7 @@ const AsString: React.FC<AsStringProps> = ({
<Input
className={styles.Input}
disabled={disabled}
fauxDisabled={fauxDisabled}
onBlur={handleBlurFuzzyValue}
onChange={handleChangeFuzzyValue}
ref={localRef}
Expand All @@ -214,7 +218,9 @@ const AsString: React.FC<AsStringProps> = ({
/>
<div className={styles.addons}>
<Icon
className={styles.icon}
className={classNames(styles.icon, {
[styles.disabledIcon]: disabled || fauxDisabled,
})}
fill="currentColor"
height={16}
name="clock"
Expand All @@ -223,8 +229,8 @@ const AsString: React.FC<AsStringProps> = ({
/>
{showDropdown && (
<Dropdown
className={styles.addons}
disabled={disabled}
className={styles.dropdown}
disabled={disabled || fauxDisabled}
formatTime={formatTime}
max={max}
min={min}
Expand All @@ -234,6 +240,7 @@ const AsString: React.FC<AsStringProps> = ({
stepFrom={stepFrom}
toggleAriaLabel={toggleAriaLabel}
value={value}
{...dropdownProps}
/>
)}
</div>
Expand Down
8 changes: 7 additions & 1 deletion src/components/InputTime/Dropdown/Dropdown.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,17 @@
margin-right: 0;
}

.dropdownToggle {
.toggle {
display: block;
padding: 3px;
}

.menu {
--item-height: calc(var(--rvr-space-lg) * 2);
--visible-items-before-scrolling: 5.5;
max-height: calc(var(--item-height) * var(--visible-items-before-scrolling));
}

.menuItem {
text-align: right;
white-space: nowrap;
Expand Down
29 changes: 21 additions & 8 deletions src/components/InputTime/Dropdown/Dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@ interface DropdownProps {
disabled?: boolean;
formatTime?: (date: Date) => string;
max?: string;
menuProps?: Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any
min?: string;
onSelectMenuItem: Function;
showDropdown?: 'click' | 'focus';
step?: number;
stepFrom?: string;
toggleAriaLabel?: string;
toggleProps?: Record<string, any>; // eslint-disable-line @typescript-eslint/no-explicit-any
value?: string;
[key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
}
Expand All @@ -39,12 +41,15 @@ const Dropdown: React.FC<DropdownProps> = ({
disabled,
formatTime,
max,
menuProps,
min,
onSelectMenuItem,
passedProps,
showDropdown,
step: customStep,
stepFrom,
toggleAriaLabel = 'Toggle time dropdown',
toggleProps,
value,
}) => {
const menuItems = useMemo(() => {
Expand Down Expand Up @@ -135,21 +140,29 @@ const Dropdown: React.FC<DropdownProps> = ({
return (
<EasyDropdown
className={classNames(className, styles.Dropdown)}
defaultIsOpen={false}
disabled={disabled}
isOpen={
undefined /* Suppresses typescript lint warning about missing prop */
/*
Explicit `undefined` suppresses typescript lint warning about missing prop.
We want to pass undefined to preserve controlled behavior
*/
undefined
}
onToggle={() => {}}
toggleProps={{
disabled,
}}
defaultIsOpen={false}
menuItems={menuItems}
menuProps={{ position: 'bottomLeft' }}
menuProps={{
className: styles.menu,
position: 'bottomLeft',
...menuProps,
}}
onToggle={() => {}}
toggleProps={toggleProps}
{...passedProps}
>
<Button
aria-label={toggleAriaLabel}
className={styles.dropdownToggle}
className={styles.toggle}
disabled={disabled}
level="text"
size="sm"
>
Expand Down
4 changes: 4 additions & 0 deletions src/components/InputTime/InputTime.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,7 @@
.icon:not(:last-child) {
margin-right: 0;
}

.disabledIcon {
color: var(--rvr-gray-40);
}
29 changes: 29 additions & 0 deletions src/components/InputTime/story.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,14 @@ storiesOf('Planets/InputTime', module)

return (
<>
<Wrap>
<Title>Required props only</Title>
<InteractiveInput
Component={InputTime}
onChange={action('onChange string')}
value={getShortTimeString(new Date().getHours(), 0)}
/>
</Wrap>
<Wrap>
<Title>With string times for max, min, and value</Title>
<InteractiveInput
Expand All @@ -180,6 +188,18 @@ storiesOf('Planets/InputTime', module)
value={getShortTimeString(new Date().getHours(), 0)}
/>
</Wrap>
<Wrap>
<Title>
Override menu max-height with
`dropdownProps.menuProps.style.maxHeight`
</Title>
<InteractiveInput
Component={InputTime}
dropdownProps={{ menuProps: { style: { maxHeight: '115px' } } }}
onChange={action('onChange string')}
value={getShortTimeString(new Date().getHours(), 0)}
/>
</Wrap>
<Wrap>
<Title>With Date times for max, min, and value</Title>
<InteractiveInput
Expand Down Expand Up @@ -222,6 +242,15 @@ storiesOf('Planets/InputTime', module)
value={getShortTimeString(new Date().getHours(), 0)}
/>
</Wrap>
<Wrap>
<Title>Disabled</Title>
<InteractiveInput
Component={InputTime}
disabled
onChange={action('onChange string')}
value={getShortTimeString(new Date().getHours(), 0)}
/>
</Wrap>
<Wrap>
<Title>Using a `ref` to control focus</Title>
<InputTime ref={ref} value={new Date().toISOString()} />{' '}
Expand Down

0 comments on commit 719ad61

Please sign in to comment.