Skip to content

feat(@clayui/core): adds new width API for the picker #5813

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

Merged
merged 8 commits into from
Apr 29, 2024
47 changes: 47 additions & 0 deletions packages/clay-core/docs/picker.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,52 @@ import Layout from '@clayui/layout';
import {useId} from '@clayui/shared';
import React from 'react';

const PickerWidthExample = () => {
const imports = `import {Option, Picker} from '@clayui/core';
import Form from '@clayui/form';
import React from 'react';`;

const code = `const CustomWidth = () => {
return (
<div style={{width: '240px'}}>
<Form.Group>
<label htmlFor="picker" id="picker-label">
Choose a fruit
</label>
<Picker
width="flexible"
aria-labelledby="picker-label"
id="picker"
items={[
'Apple',
'Banana',
'Mangos',
'Blueberry',
'Boysenberry',
'Cherry',
'Cranberry',
'Eggplant',
'Fig',
'Grape',
'Guava',
'Huckleberry',
]}
placeholder="Select a fruit"
>
{(item) => <Option key={item}>{item}</Option>}
</Picker>
</Form.Group>
</div>
);
};

render(<CustomWidth />)`;

return (
<Editor code={code} imports={imports} scope={{Form, Option, Picker}} />
);
};

const exampleImports = `import {Option, Picker} from '@clayui/core';
import Form from '@clayui/form';
import React from 'react';`;
Expand Down Expand Up @@ -262,6 +308,7 @@ const PickerGroupExample = () => {
);
};
export {
PickerWidthExample,
PickerExample,
PickerGroupExample,
PickerTriggerExample,
Expand Down
6 changes: 6 additions & 0 deletions packages/clay-core/docs/picker.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ storybookPath: 'design-system-components-picker'
---

import {
PickerWidthExample,
PickerExample,
PickerGroupExample,
PickerTriggerExample,
Expand All @@ -26,6 +27,7 @@ import {
- [Custom Trigger](#custom-trigger)
- [Custom Options](#custom-options)
- [Group](#group)
- [Flexibe width](#flexibe-width)
- [Hybrid component](#hybrid-component)

</div>
Expand Down Expand Up @@ -153,6 +155,10 @@ The composition allows you to customize the component or add new features. See s

<PickerGroupExample />

## Flexibe width

<PickerWidthExample />

## Hybrid component

Native select for mobile devices offers a better experience compared to Picker in some cases. The Picker offers the possibility to render using the native selector of the browser of the device when it is detected that it is on a mobile device, by default this property is disabled but it can be enabled by setting the `native` property to `true`.
Expand Down
15 changes: 15 additions & 0 deletions packages/clay-core/src/picker/Picker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ export type Props<T> = {
*/
selectedKey?: React.Key;

/**
* Flag to define the panel width behavior.
*/
width?: 'flexible' | 'fixed';

/**
* Sets the className for the React.Portal Menu element.
*/
Expand Down Expand Up @@ -163,6 +168,7 @@ export function Picker<T extends Record<string, any> | string | number>({
onSelectionChange,
placeholder = 'Select an option',
selectedKey: externalSelectedKey,
width = 'fixed',
...otherProps
}: Props<T>) {
const [active, setActive] = useControlledState({
Expand Down Expand Up @@ -529,6 +535,15 @@ export function Picker<T extends Record<string, any> | string | number>({
)}
ref={menuRef}
role="presentation"
style={
width === 'flexible' &&
(triggerRef.current?.clientWidth || 0) > 160
? {
maxWidth: 'none',
width: `${triggerRef.current?.clientWidth}px`,
}
: {}
}
>
{UNSAFE_behavior === 'secondary' &&
(isArrowVisible === 'top' ||
Expand Down
42 changes: 42 additions & 0 deletions packages/clay-core/stories/Picker.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,45 @@ export const CustomGroup = () => {
</div>
);
};

export const Width = ({width}: {width: 'fixed' | 'flexible'}) => {
const pickerId = useId();
const labelId = useId();

return (
<div style={{width: '250px'}}>
<Form.Group>
<label htmlFor={pickerId} id={labelId}>
Choose a fruit
</label>
<Picker aria-labelledby={labelId} id={pickerId} width={width}>
<Option key="apple">Apple</Option>
<Option disabled key="banana">
Banana
</Option>
<Option key="mangos">Mangos</Option>
<Option key="blueberry">Blueberry</Option>
<Option key="boysenberry">Boysenberry</Option>
<Option key="cherry">Cherry</Option>
<Option key="cranberry">Cranberry</Option>
<Option key="eggplant">Eggplant</Option>
<Option key="fig">Fig</Option>
<Option key="grape">Grape</Option>
<Option key="guava">Guava</Option>
<Option key="huckleberry">Huckleberry</Option>
</Picker>
</Form.Group>
</div>
);
};

Width.args = {
width: 'flexible',
};

Width.argTypes = {
width: {
control: {type: 'select'},
options: ['fixed', 'flexible'],
},
};
1 change: 1 addition & 0 deletions packages/clay-css/src/scss/variables/_dropdowns.scss
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,7 @@ $dropdown-menu-palette: () !default;
$dropdown-menu-palette: map-deep-merge(
(
'.dropdown-menu-select.dropdown-menu': (
min-width: 160px,
dropdown-header: (
padding-bottom: 0.375rem,
padding-left: 1.75rem,
Expand Down
Loading