Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AutoComplete enable keypress navigation #774

Merged
merged 1 commit into from
Feb 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 30 additions & 9 deletions src/components/AutoComplete/AutoComplete.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,16 @@ const data: Items = Array.from({ length: 1000 }, (_, i) => {
};
});

interface FocusableItemProps extends React.HTMLAttributes<HTMLDivElement> {
focused?: boolean;
}

const FocusableItem: React.FC<FocusableItemProps> = ({ focused, children, style = {}, ...attr }) => (
<div style={{ backgroundColor: focused ? 'lightgrey' : 'transparent', ...style }} {...attr}>
{children}
</div>
);

export const Single: StoryFn<Props> = (args) => {
const [value, setValue] = useState('');
const [list, setList] = useState<Items>([]);
Expand All @@ -52,7 +62,16 @@ export const Single: StoryFn<Props> = (args) => {
items={list}
onChange={args.onChange}
keyGetter={(item) => item.id}
renderItem={(props) => <div onClick={props.onItemClick}>{`${props.item.id}: ${props.item.title}`}</div>}
renderItem={(props) => (
<FocusableItem
focused={Boolean(props.active)}
onClick={props.onItemClick}
onMouseLeave={props.onMouseLeave}
onMouseMove={props.onMouseMove}
>
{`${props.item.id}: ${props.item.title}`}
</FocusableItem>
)}
>
<AutoCompleteInput
type="text"
Expand Down Expand Up @@ -85,14 +104,14 @@ export const Multiple: StoryFn<Props> = (args) => {
onChange={args.onChange}
keyGetter={(item) => item.id}
renderItem={(props) => (
<div style={{ backgroundColor: props.active || props.hovered ? 'lightgrey' : 'transparent' }}>
<FocusableItem focused={props.active} onMouseLeave={props.onMouseLeave} onMouseMove={props.onMouseMove}>
<Checkbox onClick={props.onItemClick} name="item">
<CheckboxInput checked={props.checked} value={props.item.id} />
<CheckboxLabel>
{props.item.id}: {props.item.title}
</CheckboxLabel>
</Checkbox>
</div>
</FocusableItem>
)}
>
<AutoCompleteInput
Expand Down Expand Up @@ -137,11 +156,11 @@ export const WithRadio: StoryFn<Props> = (args) => {
onChange={args.onChange}
keyGetter={(item) => item.id}
renderItem={(props) => (
<div key={props.item.id}>
<FocusableItem focused={props.active} onMouseLeave={props.onMouseLeave} onMouseMove={props.onMouseMove}>
<label onClick={props.onItemClick}>
<span>{`${props.item.id}: ${props.item.title}`}</span>
</label>
</div>
</FocusableItem>
)}
>
<AutoCompleteInput
Expand Down Expand Up @@ -233,10 +252,12 @@ export const MultipleFiniteList: StoryFn<Props> = (args) => (
items={finiteList}
value={finiteList.slice(2, 4)}
renderItem={(props) => (
<Checkbox onClick={props.onItemClick} name="item">
<CheckboxInput checked={props.checked} value={props.item.id} />
<CheckboxLabel>{props.item.title}</CheckboxLabel>
</Checkbox>
<FocusableItem focused={props.active} onMouseLeave={props.onMouseLeave} onMouseMove={props.onMouseMove}>
<Checkbox onClick={props.onItemClick} name="item">
<CheckboxInput checked={props.checked} value={props.item.id} />
<CheckboxLabel>{props.item.title}</CheckboxLabel>
</Checkbox>
</FocusableItem>
)}
>
<AutoCompleteList />
Expand Down
4 changes: 2 additions & 2 deletions src/components/Checkbox/Checkbox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ export const Default: StoryFn<typeof Checkbox> = (args) => (
<>
<Checkbox {...args}>
<CheckboxLabel>Checkbox</CheckboxLabel>
<CheckboxInput value="value" checked={false} />
<CheckboxInput value="value" defaultChecked={false} />
</Checkbox>
<Checkbox {...args}>
<CheckboxInput value="value" checked={true} />
<CheckboxInput value="value" defaultChecked={true} />
<CheckboxLabel>Checkbox</CheckboxLabel>
</Checkbox>
</>
Expand Down
20 changes: 6 additions & 14 deletions src/components/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,28 +36,20 @@ export const CheckboxLabel: React.FC<React.PropsWithChildren<{ className?: strin

interface CheckboxInputProps extends React.HTMLAttributes<HTMLInputElement> {
value: string;
checked: boolean;
checked?: boolean;
defaultChecked?: boolean;
}

export const CheckboxInput = forwardRef<HTMLInputElement, CheckboxInputProps>(({ value, checked, ...attrs }, ref) => (
export const CheckboxInput = forwardRef<HTMLInputElement, CheckboxInputProps>(({ value, ...attrs }, ref) => (
<CheckboxContext.Consumer>
{({ id, onClick, name }) => (
<input
id={id}
type="checkbox"
name={name}
value={value}
defaultChecked={checked}
ref={ref}
onChange={onClick}
{...attrs}
/>
<input id={id} type="checkbox" name={name} value={value} ref={ref} onChange={onClick} {...attrs} />
)}
</CheckboxContext.Consumer>
));

export const Checkbox = forwardRef<HTMLDivElement, React.PropsWithChildren<CheckboxProps>>(
({ onClick, name, className, children }, ref) => {
({ onClick, name, className, children, ...attr }, ref) => {
const handleOnChange = useCallback<React.ChangeEventHandler<HTMLInputElement>>((event) => {
onClick(event.target.value);
}, []);
Expand All @@ -66,7 +58,7 @@ export const Checkbox = forwardRef<HTMLDivElement, React.PropsWithChildren<Check

return (
<CheckboxContext.Provider value={{ id: `${name}-${id}`, onClick: handleOnChange, name }}>
<StyledWrapper className={className} ref={ref}>
<StyledWrapper className={className} {...attr} ref={ref}>
{children}
</StyledWrapper>
</CheckboxContext.Provider>
Expand Down
2 changes: 1 addition & 1 deletion src/components/FilterCheckbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ interface FilterCheckboxProps extends CheckboxProps {

export const FilterCheckbox: React.FC<FilterCheckboxProps> = ({ name, onClick, checked, value, label, iconLeft }) => (
<StyledCheckbox name={name} onClick={onClick}>
<StyledChekboxInput checked={checked} value={value} />
<StyledChekboxInput defaultChecked={checked} value={value} />
<StyledCheckboxLabel>
{nullable(iconLeft, (icon) => icon)}
<Text weight="bold" size="s">
Expand Down
35 changes: 27 additions & 8 deletions src/harmony/AutoComplete/AutoComplete.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,16 @@ const data: Items = Array.from({ length: 1000 }, (_, i) => {
};
});

interface FocusableItemProps extends React.HTMLAttributes<HTMLDivElement> {
focused?: boolean;
}

const FocusableItem: React.FC<FocusableItemProps> = ({ focused, children, style = {}, ...attr }) => (
<div style={{ backgroundColor: focused ? 'lightgrey' : 'transparent', ...style }} {...attr}>
{children}
</div>
);

export const Single: StoryFn<Props> = (args) => {
const [value, setValue] = useState('');
const [list, setList] = useState<Items>([]);
Expand All @@ -51,7 +61,14 @@ export const Single: StoryFn<Props> = (args) => {
items={list}
onChange={args.onChange}
keyGetter={(item) => item.id}
renderItem={(props) => <div onClick={props.onItemClick}>{`${props.item.id}: ${props.item.title}`}</div>}
renderItem={(props) => (
<FocusableItem
focused={props.active}
onClick={props.onItemClick}
onMouseLeave={props.onMouseLeave}
onMouseMove={props.onMouseMove}
>{`${props.item.id}: ${props.item.title}`}</FocusableItem>
)}
>
<AutoCompleteInput
type="text"
Expand Down Expand Up @@ -84,12 +101,14 @@ export const Multiple: StoryFn<Props> = (args) => {
onChange={args.onChange}
keyGetter={(item) => item.id}
renderItem={(props) => (
<div
<FocusableItem
style={{
backgroundColor: props.active || props.hovered ? 'lightgrey' : 'transparent',
display: 'flex',
alignItems: 'center',
}}
focused={props.active}
onMouseLeave={props.onMouseLeave}
onMouseMove={props.onMouseMove}
>
<Checkbox
checked={props.checked}
Expand All @@ -98,7 +117,7 @@ export const Multiple: StoryFn<Props> = (args) => {
name="item"
label={`${props.item.id}: ${props.item.title}`}
/>
</div>
</FocusableItem>
)}
>
<AutoCompleteInput
Expand Down Expand Up @@ -143,11 +162,11 @@ export const WithRadio: StoryFn<Props> = (args) => {
onChange={args.onChange}
keyGetter={(item) => item.id}
renderItem={(props) => (
<div key={props.item.id}>
<FocusableItem focused={props.active} onMouseLeave={props.onMouseLeave} onMouseMove={props.onMouseMove}>
<label onClick={props.onItemClick}>
<span>{`${props.item.id}: ${props.item.title}`}</span>
</label>
</div>
</FocusableItem>
)}
>
<AutoCompleteInput
Expand Down Expand Up @@ -240,15 +259,15 @@ export const MultipleFiniteList: StoryFn<Props> = (args) => (
items={finiteList}
value={finiteList.slice(2, 4)}
renderItem={(props) => (
<div>
<FocusableItem focused={props.active} onMouseLeave={props.onMouseLeave} onMouseMove={props.onMouseMove}>
<Checkbox
onChange={props.onItemClick}
name="item"
checked={props.checked}
value={props.item.id}
label={props.item.title}
/>
</div>
</FocusableItem>
)}
>
<AutoCompleteList />
Expand Down
8 changes: 4 additions & 4 deletions src/harmony/Checkbox/Checkbox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,19 +16,19 @@ export default {

export const Default: StoryFn<typeof Checkbox> = (args) => (
<>
<Checkbox {...args} checked />
<Checkbox {...args} defaultChecked />
<Checkbox {...args} />
<Checkbox {...args} checked disabled />
<Checkbox {...args} defaultChecked disabled />
<Checkbox {...args} disabled />
</>
);

export const Labeled: StoryFn<typeof Checkbox> = (args) => {
return (
<div style={{ display: 'flex', flexDirection: 'column' }}>
<Checkbox {...args} label="Label 1" checked />
<Checkbox {...args} label="Label 1" defaultChecked />
<Checkbox {...args} label="Label 2" />
<Checkbox {...args} label="Label 3" checked disabled />
<Checkbox {...args} label="Label 3" defaultChecked disabled />
<Checkbox {...args} label="Label 4" disabled />
</div>
);
Expand Down
33 changes: 12 additions & 21 deletions src/harmony/Checkbox/Checkbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,15 @@ interface CheckboxProps extends React.InputHTMLAttributes<HTMLInputElement> {
label?: React.ReactNode;
}

export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(
({ checked, label, className, disabled, ...rest }, ref) => (
<label
className={cn(classes.Checkbox, className, {
[classes.CheckboxDisabled]: disabled,
})}
>
<input
className={cn(classes.CheckboxInput)}
type="checkbox"
ref={ref}
disabled={disabled}
{...rest}
defaultChecked={checked}
/>
{nullable(label, (labelComponent) => (
<span className={cn(classes.CheckboxLabel)}>{labelComponent}</span>
))}
</label>
),
);
export const Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(({ label, className, disabled, ...rest }, ref) => (
<label
className={cn(classes.Checkbox, className, {
[classes.CheckboxDisabled]: disabled,
})}
>
<input className={cn(classes.CheckboxInput)} type="checkbox" ref={ref} disabled={disabled} {...rest} />
{nullable(label, (labelComponent) => (
<span className={cn(classes.CheckboxLabel)}>{labelComponent}</span>
))}
</label>
));
Loading