Skip to content

Commit

Permalink
feat(ld-select): creatable mode
Browse files Browse the repository at this point in the history
  • Loading branch information
borisdiakur authored Jan 31, 2023
1 parent 63c9356 commit 7c8d7e7
Show file tree
Hide file tree
Showing 15 changed files with 805 additions and 81 deletions.
13 changes: 13 additions & 0 deletions screenshot/builds/master.json
Original file line number Diff line number Diff line change
Expand Up @@ -15188,6 +15188,19 @@
"isLandscape": false,
"isMobile": false
},
{
"id": "19948d3e",
"image": "be321548175c35b98fd373ca4cfdc518.png",
"userAgent": "default",
"desc": "ld-select filter with create button",
"testPath": "./src/liquid/components/ld-select/test/ld-select.e2e.ts",
"width": 600,
"height": 600,
"deviceScaleFactor": 1,
"hasTouch": false,
"isLandscape": false,
"isMobile": false
},
{
"id": "82fda3bf",
"image": "71f6a317d5d38f78087a9d107a54579e.png",
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions src/liquid/components/ld-button/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -668,13 +668,15 @@ Type: `Promise<void>`

- [ld-cookie-consent](../ld-cookie-consent)
- [ld-pagination](../ld-pagination)
- ld-select-popper
- [ld-table-header](../ld-table/ld-table-header)

### Graph
```mermaid
graph TD;
ld-cookie-consent --> ld-button
ld-pagination --> ld-button
ld-select-popper --> ld-button
ld-table-header --> ld-button
style ld-button fill:#f9f,stroke:#333,stroke-width:4px
```
Expand Down
2 changes: 2 additions & 0 deletions src/liquid/components/ld-icon/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ Left-click an icon below to download its SVG file. To download all icons at once
- [ld-input-message](../ld-input-message)
- [ld-notice](../ld-notice)
- [ld-pagination](../ld-pagination)
- ld-select-popper
- [ld-sidenav-header](../ld-sidenav/ld-sidenav-header)
- [ld-sidenav-navitem](../ld-sidenav/ld-sidenav-navitem)
- [ld-sidenav-toggle-outside](../ld-sidenav/ld-sidenav-toggle-outside)
Expand All @@ -383,6 +384,7 @@ graph TD;
ld-input-message --> ld-icon
ld-notice --> ld-icon
ld-pagination --> ld-icon
ld-select-popper --> ld-icon
ld-sidenav-header --> ld-icon
ld-sidenav-navitem --> ld-icon
ld-sidenav-toggle-outside --> ld-icon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@
padding-left: var(--ld-option-padding-left-lg);
}

&--filtered {
display: none;
}

*,
*::before,
*::after {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class LdOptionInternal {
@Prop() size?: 'sm' | 'lg'

/** Set to true on filtering via select input. */
@Prop({ reflect: true }) hidden = false
@Prop() filtered = false

/**
* Sets focus internally.
Expand Down Expand Up @@ -130,6 +130,7 @@ export class LdOptionInternal {
class={getClassNames([
'ld-option-internal',
this.size && `ld-option-internal--${this.size}`,
this.filtered && 'ld-option-internal--filtered',
])}
role="option"
ref={(el) => (this.optionRef = el as HTMLElement)}
Expand Down
7 changes: 5 additions & 2 deletions src/liquid/components/ld-select/ld-option/ld-option.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,11 @@ export class LdOption {
*/
@Prop() disabled: boolean

/** Set to true on filtering via select input. */
@Prop({ reflect: true }) hidden = false
/**
* @internal
* Set to true on filtering via select input.
*/
@Prop() filtered = false

componentWillLoad() {
// Setting selected via prop directly triggers the mutation observer to fire twice on attribute chage.
Expand Down
1 change: 0 additions & 1 deletion src/liquid/components/ld-select/ld-option/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ Please refer to the [`ld-select` documentation](components/ld-select) for usage
| Property | Attribute | Description | Type | Default |
| ---------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----------- |
| `disabled` | `disabled` | Disables the option. | `boolean` | `undefined` |
| `hidden` | `hidden` | Set to true on filtering via select input. | `boolean` | `false` |
| `key` | `key` | for tracking the node's identity when working with lists | `string \| number` | `undefined` |
| `ref` | `ref` | reference to component | `any` | `undefined` |
| `selected` | `selected` | If present, this boolean attribute indicates that the option is selected. | `boolean` | `undefined` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@
border-top: 0;
border-radius: var(--ld-br-m);
}

.ld-select-popper--all-filtered & {
border-top: 0;
}
}

.ld-select-popper__shadow {
Expand All @@ -57,14 +61,48 @@
}
}

.ld-select-popper__filter-input {
appearance: none;
.ld-select-popper__filter-container {
align-items: center;
background-color: var(--ld-col-wht);
border: 0;
border-top: solid var(--ld-col-neutral-100) var(--ld-sp-1);
box-sizing: border-box;
color: var(--ld-col-neutral-900);
display: grid;
font: var(--ld-typo-label-m);
grid-template-columns: 1fr auto;

.ld-select-popper--detached &,
.ld-select-popper--pinned & {
border-top: 0;
border-top-left-radius: var(--ld-br-m);
border-top-right-radius: var(--ld-br-m);
}

.ld-select-popper--all-filtered & {
border-bottom-left-radius: var(--ld-br-m);
border-bottom-right-radius: var(--ld-br-m);
}
}

.ld-select-popper__create-button {
font: var(--ld-typo-label-s);
line-height: var(--ld-select-trigger-line-height);
margin-right: var(--ld-sp-8);

&::part(button) {
--ld-button-padding-x-sm: var(--ld-sp-6);
--ld-button-padding-y-sm: var(--ld-sp-4);
min-height: 0px;
min-width: 0px;
}
}

.ld-select-popper__filter-input {
appearance: none;
background-color: transparent;
border: 0;
box-sizing: border-box;
color: inherit;
font: inherit;
height: 2.5rem;
line-height: var(--ld-select-trigger-line-height);
outline: none;
Expand Down
103 changes: 92 additions & 11 deletions src/liquid/components/ld-select/ld-select-popper/ld-select-popper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,24 @@ import { getClassNames } from '../../../utils/getClassNames'
export class LdSelectPopper {
@Element() el: HTMLElement

/** Indicates that all options are filtered (used in creatable mode) */
@Prop() allOptionsFiltered: boolean

/** A watcher is applied to the CSS class in order to be able to react to tether changes. */
@Prop({ reflect: true }) class: string

/**
* Creatable mode can be enabled when the filter prop is set to true.
* This mode allows the user to create new options using the filter input field.
*/
@Prop() creatable: boolean

/** The "create" input label (creatable mode). */
@Prop() createInputLabel: string

/** The "create" button label (creatable mode). */
@Prop() createButtonLabel: string

/** Popper is visually detached from the select trigger element (there's a gap between the two). */
@Prop() detached: boolean

Expand All @@ -33,6 +48,9 @@ export class LdSelectPopper {
/** Set this property to `true` in order to enable an input field for filtering options. */
@Prop() filter: boolean

/** The filter input value matches an option (do not allow to create the option). */
@Prop() filterMatchesOption: boolean

/** The filter input placeholder. */
@Prop() filterPlaceholder: string

Expand All @@ -47,17 +65,41 @@ export class LdSelectPopper {

@State() isPinned = false
@State() shadowHeight = '100%'
@State() filterInputValue = ''
@State() canCreate = false

/**
* @internal
* Emitted on filter change with the filter input value.
*/
@Event() ldselectfilterchange: EventEmitter<string>

/**
* @internal
* Emitted on create button click in filter input field.
*/
@Event() ldselectfiltercreate: EventEmitter<string>

private handleFilterInput = (ev) => {
this.filterInputValue = ev.target.value
this.ldselectfilterchange.emit(ev.target.value)
}

private handleCreate = (ev) => {
ev.preventDefault()
this.ldselectfiltercreate.emit(this.filterInputValue)
this.filterInputValue = ''
}

@Watch('creatable')
@Watch('filterMatchesOption')
@Watch('filterInputValue')
updateCanCreate() {
this.canCreate = Boolean(
this.creatable && !this.filterMatchesOption && this.filterInputValue
)
}

@Watch('class')
updatePinnedState() {
this.isPinned = this.el.classList.contains('ld-tether-pinned')
Expand All @@ -69,14 +111,25 @@ export class LdSelectPopper {
if (newValue) this.el.classList.add(`ld-theme-${newValue}`)
}

/**
* Focuses the tab
*/
@Watch('expanded')
updateFilter(newExpanded: boolean) {
if (!newExpanded) {
this.resetFilter()
}
}

/** Updates shadow height */
@Method()
async updateShadowHeight(height: string) {
this.shadowHeight = height
}

/** Focuses the tab */
@Method()
async resetFilter() {
this.filterInputValue = ''
}

componentWillLoad() {
this.popperClass && this.el.classList.add(this.popperClass)
}
Expand All @@ -95,20 +148,48 @@ export class LdSelectPopper {
this.detached && 'ld-select-popper--detached',
this.expanded && 'ld-select-popper--expanded',
this.filter && 'ld-select-popper--filter',
this.allOptionsFiltered && 'ld-select-popper--all-filtered',
this.isPinned && 'ld-select-popper--pinned',
this.size && `ld-select-popper--${this.size}`,
])}
part="popper"
>
{this.filter && (
<input
aria-haspopup="listbox"
type="text"
placeholder={this.filterPlaceholder}
class="ld-select-popper__filter-input"
part="filter-input focusable"
onInput={this.handleFilterInput}
/>
<div class="ld-select-popper__filter-container">
<input
aria-haspopup={this.allOptionsFiltered ? undefined : 'listbox'}
aria-label={this.canCreate ? this.createInputLabel : undefined}
type="text"
placeholder={this.filterPlaceholder}
class="ld-select-popper__filter-input"
part="filter-input focusable"
onInput={this.handleFilterInput}
/>
{this.canCreate && (
<ld-button
onClick={this.handleCreate}
size="sm"
class="ld-select-popper__create-button"
aria-label={this.createButtonLabel}
>
<ld-icon
class="ld-select-popper__create-icon"
role="presentation"
size="sm"
>
<svg viewBox="-1 -1 24 24" fill="none">
<path
d="M2.5 11h17M11 19.5v-17"
stroke="currentColor"
stroke-width="3"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</ld-icon>
</ld-button>
)}
</div>
)}
<div
class="ld-select-popper__scroll-container"
Expand Down
Loading

0 comments on commit 7c8d7e7

Please sign in to comment.