Skip to content

Commit

Permalink
feat: add compact picker (#238)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikeldking authored Oct 1, 2024
1 parent 1a3c502 commit eecfbd8
Show file tree
Hide file tree
Showing 8 changed files with 107 additions and 29 deletions.
2 changes: 1 addition & 1 deletion src/card/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const bodyCSS = css`
`;

export interface CardBaseProps {
title?: string;
title?: ReactNode;
subTitle?: string;
variant?: CardVariant;
children: ReactNode;
Expand Down
68 changes: 49 additions & 19 deletions src/dropdown/DropdownButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useButton } from '@react-aria/button';
import { useHover } from '@react-aria/interactions';
import { FocusRing } from '@react-aria/focus';
import { classNames } from '../utils/classNames';
import { FocusableRef, Validation } from '../types';
import { FocusableRef, SizingProps, Validation } from '../types';
import { useFocusableRef } from '../utils/useDOMRef';
import theme from '../theme';
import { AddonBefore } from '../field';
Expand All @@ -17,7 +17,10 @@ const appearKeyframes = keyframes`
0% { opacity: 0; }
100% { opacity: 1; }
`;
export interface DropdownButtonProps extends AddonableProps, Validation {
export interface DropdownButtonProps
extends AddonableProps,
Validation,
SizingProps {
/**
* Whether the button should be displayed with a quiet style.
* @default false
Expand Down Expand Up @@ -54,10 +57,7 @@ const buttonBaseCSS = css`
color: var(--ac-field-text-color-override, var(--ac-global-text-color-900));
}
.ac-dropdown-button__dropdown-icon {
margin: 10px 0 10px 10px;
flex: fixed;
width: 16px;
height: 16px;
font-size: 16px;
}
Expand Down Expand Up @@ -92,6 +92,37 @@ const buttonBaseCSS = css`
&.ac-dropdown-button--invalid > .ac-dropdown-button__text {
padding-right: 0;
}
// Sizing
&.ac-dropdown-button--default {
.ac-dropdown-button__text {
margin: var(--ac-global-dimension-static-size-100)
var(--ac-global-dimension-static-size-100)
var(--ac-global-dimension-static-size-100)
var(--ac-global-dimension-static-size-200);
}
.ac-dropdown-button__dropdown-icon {
margin: 10px 0 10px 10px;
flex: fixed;
width: 16px;
height: 16px;
}
}
&.ac-dropdown-button--compact {
.ac-dropdown-button__text {
margin: var(--ac-global-dimension-static-size-50)
var(--ac-global-dimension-static-size-50)
var(--ac-global-dimension-static-size-50)
var(--ac-global-dimension-static-size-100);
}
.ac-dropdown-button__dropdown-icon {
margin: var(--ac-global-dimension-size-50) 0
var(--ac-global-dimension-size-50) var(--ac-global-dimension-size-50);
flex: fixed;
width: 16px;
height: 16px;
}
}
`;

/**
Expand Down Expand Up @@ -155,12 +186,6 @@ const nonQuietButtonCSS = css`
cursor: default;
border: 1px solid ${theme.components.dropdown.borderColor};
}
.ac-dropdown-button__text {
margin: var(--ac-global-dimension-static-size-100)
var(--ac-global-dimension-static-size-100)
var(--ac-global-dimension-static-size-100)
var(--ac-global-dimension-static-size-200);
}
&.ac-dropdown-button--invalid {
border: 1px solid var(--ac-global-color-danger);
Expand Down Expand Up @@ -194,6 +219,7 @@ function DropdownButton(
style,
addonBefore,
validationState,
size = 'default',
// TODO: add support for autoFocus
// autoFocus,
...otherProps
Expand All @@ -214,14 +240,18 @@ function DropdownButton(
<button
{...mergeProps(buttonProps, hoverProps, otherProps)}
ref={domRef}
className={classNames('ac-dropdown-button', {
'ac-dropdown-button--quiet': isQuiet,
'is-active': isActive || isPressed,
'is-disabled': isDisabled,
'is-hovered': isHovered,
'ac-dropdown-button--invalid': isInvalid,
'ac-dropdown-button--valid': validationState === 'valid',
})}
className={classNames(
'ac-dropdown-button',
`ac-dropdown-button--${size}`,
{
'ac-dropdown-button--quiet': isQuiet,
'is-active': isActive || isPressed,
'is-disabled': isDisabled,
'is-hovered': isHovered,
'ac-dropdown-button--invalid': isInvalid,
'ac-dropdown-button--valid': validationState === 'valid',
}
)}
style={style}
css={css(
buttonBaseCSS,
Expand Down
2 changes: 2 additions & 0 deletions src/picker/Picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ function Picker<T extends object>(
addonBefore,
menuWidth,
validationState,
size = 'default',
} = props;

const state = useSelectState(props);
Expand Down Expand Up @@ -223,6 +224,7 @@ function Picker<T extends object>(
isActive={state.isOpen}
isDisabled={isDisabled}
autoFocus={autoFocus}
size={size}
className={classNames('ac-dropdown-trigger', {
'is-hovered': isHovered,
})}
Expand Down
9 changes: 2 additions & 7 deletions src/types/button.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ReactNode, SyntheticEvent } from 'react';
import { AriaLabelingProps, FocusableDOMProps } from '.';
import { AriaLabelingProps, FocusableDOMProps, SizingProps } from '.';

interface AriaBaseButtonProps extends FocusableDOMProps, AriaLabelingProps {
/**
Expand All @@ -14,7 +14,7 @@ export interface BaseButtonProps extends AriaBaseButtonProps {
children?: ReactNode;
}

export interface ButtonProps extends BaseButtonProps {
export interface ButtonProps extends BaseButtonProps, SizingProps {
children?: ReactNode | string;
variant: 'primary' | 'default' | 'danger' | 'quiet' | 'success';
disabled?: boolean;
Expand All @@ -26,9 +26,4 @@ export interface ButtonProps extends BaseButtonProps {
* The title of the button. Required if only showing an icon
*/
title?: string;
/**
* The size of the button
* @default 'normal'
*/
size?: 'normal' | 'compact';
}
1 change: 1 addition & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ export * from './style';
export * from './locale';
export * from './breadcrumb';
export * from './key';
export * from './sizing';
5 changes: 3 additions & 2 deletions src/types/select.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Validation, AriaValidationProps } from '../types';
import { Validation, AriaValidationProps, SizingProps } from '../types';
import { LabelableProps, Alignment, AddonableProps } from './labelable';
import { CollectionBase } from './collection';
import { HelpTextProps, InputBase, TextInputBase } from './input';
Expand Down Expand Up @@ -49,7 +49,8 @@ export interface PickerProps<T>
AddonableProps,
StyleProps,
Validation,
HelpTextProps {
HelpTextProps,
SizingProps {
/**
* Whether the picker should be displayed with a quiet style.
* @default false
Expand Down
7 changes: 7 additions & 0 deletions src/types/sizing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export type SizingProps = {
/**
* The size of the component
* @default 'default'
*/
size?: 'default' | 'compact';
};
42 changes: 42 additions & 0 deletions stories/Picker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
Button,
ContextualHelp,
Section,
Flex,
} from '../src';
import { ThemeToggleWrap } from './components/ThemeToggleWrap';

Expand Down Expand Up @@ -73,6 +74,47 @@ const Controlled: Story<PickerProps<string>> = args => {
);
};

export const Sizes: Story<PickerProps<string>> = args => {
const [frequency, setFrequency] = React.useState<string | undefined>(
'rarely'
);
return (
<ThemeToggleWrap>
<Flex direction="column" gap="size-200">
<Flex direction="row" gap="size-100">
<Picker
key="default"
{...args}
selectedKey={frequency}
onSelectionChange={selected => setFrequency(selected as string)}
>
<Item key="rarely">Rarely</Item>
<Item key="sometimes">Sometimes</Item>
<Item key="always">Always</Item>
</Picker>
<Button variant="default">Submit</Button>
</Flex>
<Flex direction="row" gap="size-100" alignItems="center">
<Picker
key="compact"
{...args}
size="compact"
selectedKey={frequency}
onSelectionChange={selected => setFrequency(selected as string)}
>
<Item key="rarely">Rarely</Item>
<Item key="sometimes">Sometimes</Item>
<Item key="always">Always</Item>
</Picker>
<Button variant="default" size="compact">
Submit
</Button>
</Flex>
</Flex>
</ThemeToggleWrap>
);
};

// By passing using the Args format for exported stories, you can control the props for a component for reuse in a test
// https://storybook.js.org/docs/react/workflows/unit-testing
export const controlled = Controlled.bind({});
Expand Down

0 comments on commit eecfbd8

Please sign in to comment.