Skip to content

Commit

Permalink
feat(Select): add support for custom tag display on multiple variant (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
endv-bogdanb authored Jun 24, 2024
1 parent ae3d4d2 commit 989fc45
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 57 deletions.
124 changes: 79 additions & 45 deletions packages/beeq/src/components/select/_storybook/bq-select.stories.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { useArgs } from '@storybook/preview-api';
import type { Args, Meta, StoryObj } from '@storybook/web-components';
import { html, nothing } from 'lit-html';
import { ifDefined } from 'lit-html/directives/if-defined.js';
Expand Down Expand Up @@ -64,6 +65,7 @@ const meta: Meta = {
optionalLabel: { control: 'boolean', table: { disable: true } },
prefix: { control: 'boolean', table: { disable: true } },
suffix: { control: 'boolean', table: { disable: true } },
customTags: { control: 'boolean', table: { disable: true } },
options: { control: 'text', table: { disable: true } },
},
args: {
Expand All @@ -88,56 +90,38 @@ const meta: Meta = {
readonly: false,
required: false,
'validation-status': 'none',
customTags: false,
value: undefined,
// Not part of the public API, so we don't want to expose it in the docs
options: html`
<bq-option value="running">
<bq-icon slot="prefix" name="sneaker-move"></bq-icon>
Running
</bq-option>
<bq-option value="hiking">
<bq-icon slot="prefix" name="boot"></bq-icon>
Hiking
</bq-option>
<bq-option value="biking">
<bq-icon slot="prefix" name="person-simple-bike"></bq-icon>
Biking
</bq-option>
<bq-option value="swimming">
<bq-icon slot="prefix" name="swimming-pool"></bq-icon>
Swimming
</bq-option>
<bq-option value="pizza">
<bq-icon slot="prefix" name="pizza"></bq-icon>
Pizza
</bq-option>
<bq-option value="hamburger">
<bq-icon slot="prefix" name="hamburger"></bq-icon>
Hamburger
</bq-option>
<bq-option value="cookie">
<bq-icon slot="prefix" name="cookie"></bq-icon>
Cookie
</bq-option>
<bq-option value="ice-cream">
<bq-icon slot="prefix" name="ice-cream"></bq-icon>
Ice-cream
</bq-option>
`,
options: [
{ label: 'Running', value: 'running', icon: 'sneaker-move' },
{ label: 'Hiking', value: 'hiking', icon: 'boot' },
{ label: 'Biking', value: 'biking', icon: 'person-simple-bike' },
{ label: 'Swimming', value: 'swimming', icon: 'swimming-pool' },
{ label: 'Pizza', value: 'pizza', icon: 'pizza' },
{ label: 'Hamburger', value: 'hamburger', icon: 'hamburger' },
{ label: 'Cookie', value: 'cookie', icon: 'cookie' },
{ label: 'Ice-cream', value: 'ice-cream', icon: 'ice-cream' },
],
},
};
export default meta;

type Story = StoryObj;

const Template = (args: Args) => {
const [, updateArgs] = useArgs();

const onSelect = (event) => {
updateArgs({ value: event.detail.value });
args.bqSelect(event);
};

const onClear = (event) => {
updateArgs({ value: [] });
args.bqClear(event);
};

const tooltipTemplate = args.hasLabelTooltip
? html`
<bq-tooltip class="ms-xs">
Expand All @@ -146,11 +130,13 @@ const Template = (args: Args) => {
</bq-tooltip>
`
: nothing;

const labelTemplate = html`
<label class="flex flex-grow items-center" slot=${ifDefined(!args.optionalLabel ? 'label' : null)}>
Select label ${tooltipTemplate}
</label>
`;

const label = !args.optionalLabel
? labelTemplate
: html`
Expand All @@ -159,11 +145,12 @@ const Template = (args: Args) => {
<span class="text-text-secondary">Optional</span>
</div>
`;

const style = args.hasLabelTooltip
? html`
<style>
bq-select {
width: 75vw;
inline-size: 75vw;
}
</style>
`
Expand Down Expand Up @@ -195,10 +182,41 @@ const Template = (args: Args) => {
validation-status=${args['validation-status']}
value=${args.multiple ? ifDefined(JSON.stringify(args.value)) : args.value}
@bqBlur=${args.bqBlur}
@bqSelect=${args.bqSelect}
@bqClear=${args.bqClear}
@bqSelect=${args.customTags ? onSelect : args.bqSelect}
@bqClear=${args.customTags ? onClear : args.bqClear}
@bqFocus=${args.bqFocus}
>
${args.customTags
? html`${args.options
.filter((option) => args.value.includes(option.value))
.map((option, index) => {
if (index < args['max-tags-visible'] || args['max-tags-visible'] < 0) {
return html`<bq-tag
key=${option.value}
size="xsmall"
variant="filled"
slot="tags"
class="[&::part(text)]:text-nowrap [&::part(text)]:leading-small"
>
<bq-icon name=${option.icon} slot="prefix"></bq-icon>
${option.value}
</bq-tag>`;
} else if (index === args['max-tags-visible']) {
return html`
<bq-tag
key="more"
size="xsmall"
variant="filled"
slot="tags"
class="[&::part(text)]:text-nowrap [&::part(text)]:leading-small"
>
+${args.value.length - index}
</bq-tag>
`;
}
return nothing;
})}`
: nothing}
${!args.noLabel ? label : nothing}
${args.prefix ? html`<bq-icon name="user-circle" slot="prefix"></bq-icon>` : nothing}
${args.suffix ? html`<bq-icon name="arrow-down" slot="suffix"></bq-icon>` : nothing}
Expand All @@ -210,7 +228,13 @@ const Template = (args: Args) => {
</span>
`
: nothing}
${args.options}
${args.options.map(
(option) => html`
<bq-option value=${option.value}>
<bq-icon slot="prefix" name=${option.icon}></bq-icon> ${option.label}
</bq-option>
`,
)}
</bq-select>
`;
};
Expand Down Expand Up @@ -257,6 +281,16 @@ export const Multiple: Story = {
},
};

export const MultipleCustomRender: Story = {
render: Template,
args: {
'keep-open-on-select': true,
multiple: true,
customTags: true,
value: ['running', 'biking', 'pizza'],
},
};

export const Prefix: Story = {
render: Template,
args: {
Expand Down
9 changes: 3 additions & 6 deletions packages/beeq/src/components/select/bq-select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -513,17 +513,14 @@ export class BqSelect {
<div class="flex flex-1 overflow-x-auto" part="input-outline">
{/* Display selected values using BqTags for multiple selection */}
{this.multiple && (
<span
class="me-xs2 flex flex-1 gap-xs2 [&>bq-tag::part(text)]:text-nowrap [&>bq-tag::part(text)]:leading-small [&>bq-tag]:inline-flex"
part="tags"
>
{this.displayTags}
<span class="bq-select__tags" part="tags">
<slot name="tags">{this.displayTags}</slot>
</span>
)}
{/* HTML Input */}
<input
id={this.name || this.fallbackInputId}
class="bq-select__control--input w-full flex-grow"
class="bq-select__control--input flex-grow is-full"
autoComplete="off"
autoCapitalize="off"
autoFocus={this.autofocus}
Expand Down
25 changes: 19 additions & 6 deletions packages/beeq/src/components/select/scss/bq-select.scss
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
/* -------------------------------------------------------------------------- */

.bq-select__label {
@apply mb-[--bq-select--label-margin-bottom] flex items-center;
@apply flex items-center m-be-[--bq-select--label-margin-bottom];
@apply text-[length:--bq-select--label-text-size] text-[color:--bq-select--label-text-color];
}

.bq-select__helper-text {
@apply mt-[--bq-select--helper-margin-top] text-[length:--bq-select--helper-text-size] text-[color:--bq-select--helper-text-color];
@apply text-[length:--bq-select--helper-text-size] text-[color:--bq-select--helper-text-color] m-bs-[--bq-select--helper-margin-top];
}

.bq-select__helper-text.validation-error {
Expand Down Expand Up @@ -50,11 +50,11 @@
}

.bq-select__control {
@apply flex w-full items-center transition-[border-color,box-shadow];
@apply flex items-center transition-[border-color,box-shadow] is-full;
// Border
@apply rounded-[--bq-select--border-radius] border-[length:--bq-select--border-width] border-[color:--bq-select--border-color];
// Padding
@apply py-[--bq-select--paddingY] pe-[--bq-select--padding-end] ps-[--bq-select--padding-start];
@apply pe-[--bq-select--padding-end] ps-[--bq-select--padding-start] p-b-[var(--bq-select--paddingY)];
// Text
@apply select-none text-[length:--bq-select--text-size] text-[color:--bq-select--text-color] placeholder:text-[color:--bq-select--text-placeholder-color];
// Hover
Expand Down Expand Up @@ -113,7 +113,7 @@

.bq-select__control--input {
@apply flex-auto cursor-[inherit] select-none appearance-none bg-[inherit] font-[inherit] text-[length:inherit] text-[color:inherit];
@apply m-0 min-h-[--bq-select--icon-size] min-w-[0] border-none p-0 focus:outline-none focus-visible:outline-none;
@apply m-0 border-none p-0 min-bs-[var(--bq-select--icon-size)] min-is-0 focus:outline-none focus-visible:outline-none;

box-shadow: none;
font-weight: inherit;
Expand All @@ -130,7 +130,7 @@
--bq-ring-offset-width: initial;
--bq-ring-color-focus: initial;

@apply h-auto rounded-xs border-none p-0;
@apply rounded-xs border-none p-0 bs-auto;
}

/* -------------------------------------------------------------------------- */
Expand All @@ -150,6 +150,19 @@
@apply ms-[--bq-select--gap] transition-transform duration-300 ease-in-out;
}

.bq-select__tags {
@apply me-xs2 flex flex-1 gap-xs2;

bq-tag,
::slotted(bq-tag) {
@apply inline-flex;
}

bq-tag::part(text) {
@apply text-nowrap leading-small;
}
}

/* -------------------------------------------------------------------------- */
/* Slotted and internal icons */
/* -------------------------------------------------------------------------- */
Expand Down

0 comments on commit 989fc45

Please sign in to comment.