Skip to content
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
5 changes: 5 additions & 0 deletions .changeset/mighty-bats-fix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cube-dev/ui-kit": minor
---

Add sections support for Select.
5 changes: 5 additions & 0 deletions .changeset/old-comics-sneeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@cube-dev/ui-kit": minor
---

Remove divider support in Menu but add dividers between sections.
72 changes: 71 additions & 1 deletion src/components/fields/ComboBox/ComboBox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import { ComboBox, CubeComboBoxProps } from './ComboBox';
export default {
title: 'Pickers/ComboBox',
component: ComboBox,
subcomponents: { Item: ComboBox.Item },
subcomponents: { Item: ComboBox.Item, Section: ComboBox.Section },
args: { id: 'name', width: '200px', label: 'Choose your favourite color' },
parameters: { controls: { exclude: baseProps } },
argTypes: { ...SELECTED_KEY_ARG },
Expand Down Expand Up @@ -367,3 +367,73 @@ ItemsWithDescriptions.play = async ({ canvasElement }) => {

await userEvent.click(trigger);
};

// ---------------------------------
// Section stories for ComboBox
// ---------------------------------

export const SectionsStatic: StoryFn<CubeComboBoxProps<any>> = (args) => (
<ComboBox {...args} width="280px" placeholder="Select a color">
<ComboBox.Section title="Warm colors">
<ComboBox.Item key="red">Red</ComboBox.Item>
<ComboBox.Item key="orange">Orange</ComboBox.Item>
<ComboBox.Item key="yellow">Yellow</ComboBox.Item>
</ComboBox.Section>
<ComboBox.Section>
<ComboBox.Item key="teal">Teal</ComboBox.Item>
<ComboBox.Item key="cyan">Cyan</ComboBox.Item>
</ComboBox.Section>
<ComboBox.Section title="Cool colors">
<ComboBox.Item key="blue">Blue</ComboBox.Item>
<ComboBox.Item key="purple">Purple</ComboBox.Item>
</ComboBox.Section>
</ComboBox>
);

SectionsStatic.storyName = 'Sections – static items';
SectionsStatic.play = ItemsWithDescriptions.play;

export const SectionsDynamic: StoryFn<CubeComboBoxProps<any>> = (args) => {
const groups = [
{
name: 'Fruits',
children: [
{ id: 'apple', label: 'Apple' },
{ id: 'orange', label: 'Orange' },
{ id: 'banana', label: 'Banana' },
],
},
{
name: 'Vegetables',
children: [
{ id: 'carrot', label: 'Carrot' },
{ id: 'peas', label: 'Peas' },
{ id: 'broccoli', label: 'Broccoli' },
],
},
];

return (
<ComboBox
{...args}
defaultItems={groups}
width="280px"
placeholder="Select an item"
>
{(group: any) => (
<ComboBox.Section
key={group.name}
title={group.name}
items={group.children}
>
{(item: any) => (
<ComboBox.Item key={item.id}>{item.label}</ComboBox.Item>
)}
</ComboBox.Section>
)}
</ComboBox>
);
};

SectionsDynamic.storyName = 'Sections – dynamic collection';
SectionsDynamic.play = ItemsWithDescriptions.play;
21 changes: 15 additions & 6 deletions src/components/fields/ComboBox/ComboBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
useHover,
useOverlayPosition,
} from 'react-aria';
import { Item, useComboBoxState } from 'react-stately';
import { Section as BaseSection, Item, useComboBoxState } from 'react-stately';

import { useEvent } from '../../../_internal/index';
import { DownIcon, LoadingIcon } from '../../../icons';
Expand Down Expand Up @@ -207,13 +207,15 @@ export const ComboBox = forwardRef(function ComboBox<T extends object>(
let isAsync = loadingState != null;
let { contains } = useFilter({ sensitivity: 'base' });

let state = useComboBoxState({
let comboBoxStateProps: any = {
...props,
defaultFilter: filter || contains,
filter: undefined,
allowsEmptyCollection: isAsync,
menuTrigger,
});
};

let state = useComboBoxState(comboBoxStateProps);

styles = extractStyles(otherProps, PROP_STYLES, styles);

Expand Down Expand Up @@ -242,7 +244,7 @@ export const ComboBox = forwardRef(function ComboBox<T extends object>(
buttonProps: triggerProps,
} = useComboBox(
{
...props,
...comboBoxStateProps,
inputRef,
buttonRef: triggerRef,
listBoxRef,
Expand Down Expand Up @@ -471,14 +473,21 @@ export const ComboBox = forwardRef(function ComboBox<T extends object>(
);
}) as unknown as (<T>(
props: CubeComboBoxProps<T> & { ref?: ForwardedRef<HTMLDivElement> },
) => ReactElement) & { Item: typeof Item };
) => ReactElement) & { Item: typeof Item; Section: typeof BaseSection };

type SectionComponentCB = typeof BaseSection;

const ComboBoxSectionComponent = Object.assign(BaseSection, {
displayName: 'Section',
}) as SectionComponentCB;

// Extend typing on Item to accept optional `description` prop like Select does.
ComboBox.Item = Item as unknown as (props: {
description?: ReactNode;
[key: string]: any;
}) => ReactElement;

ComboBox.Section = ComboBoxSectionComponent;

Object.defineProperty(ComboBox, 'cubeInputType', {
value: 'ComboBox',
enumerable: false,
Expand Down
65 changes: 64 additions & 1 deletion src/components/fields/Select/Select.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default {
title: 'Pickers/Select',
component: Select,
args: { width: '200px' },
subcomponents: { Item: Select.Item },
subcomponents: { Item: Select.Item, Section: Select.Section },
parameters: { controls: { exclude: baseProps } },
argTypes: {
...SELECTED_KEY_ARG,
Expand Down Expand Up @@ -137,3 +137,66 @@ export const WithDescription: StoryFn<CubeSelectProps<any>> = (args) => (
);
WithDescription.args = {};
WithDescription.play = WithDisabledOption.play;

// ------------------------------
// Section stories
// ------------------------------

export const SectionsStatic: StoryFn<CubeSelectProps<any>> = (args) => (
<Select {...args} placeholder="Pick something" width="260px">
<Select.Section title="Warm colors">
<Select.Item key="red">Red</Select.Item>
<Select.Item key="orange">Orange</Select.Item>
<Select.Item key="yellow">Yellow</Select.Item>
</Select.Section>
<Select.Section>
<Select.Item key="cyan">Cyan</Select.Item>
<Select.Item key="teal">Teal</Select.Item>
</Select.Section>
<Select.Section title="Cool colors">
<Select.Item key="blue">Blue</Select.Item>
<Select.Item key="purple">Purple</Select.Item>
</Select.Section>
</Select>
);

SectionsStatic.storyName = 'Sections – static items';
SectionsStatic.play = WithDisabledOption.play;

export const SectionsDynamic: StoryFn<CubeSelectProps<any>> = (args) => {
const groups = [
{
name: 'Fruits',
children: [
{ id: 'apple', label: 'Apple' },
{ id: 'orange', label: 'Orange' },
{ id: 'banana', label: 'Banana' },
],
},
{
name: 'Vegetables',
children: [
{ id: 'carrot', label: 'Carrot' },
{ id: 'peas', label: 'Peas' },
{ id: 'broccoli', label: 'Broccoli' },
],
},
];

return (
<Select {...args} items={groups} width="260px" placeholder="Choose an item">
{(group: any) => (
<Select.Section
key={group.name}
title={group.name}
items={group.children}
>
{(item: any) => <Select.Item key={item.id}>{item.label}</Select.Item>}
</Select.Section>
)}
</Select>
);
};

SectionsDynamic.storyName = 'Sections – dynamic collection';
SectionsDynamic.play = WithDisabledOption.play;
Loading
Loading