Skip to content

Commit 5ca8bc4

Browse files
authored
Fix #1006 (#1131)
* placeholder * placeholder story * add more fruits * traverse shadowDOMs for scroll containers * ability to hide expand symbol * story that proves it works inside a shadow dom
1 parent 9d565b3 commit 5ca8bc4

File tree

5 files changed

+142
-25
lines changed

5 files changed

+142
-25
lines changed

packages/uui-combobox/lib/uui-combobox.element.ts

Lines changed: 48 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ export class UUIComboboxElement extends UUIFormControlMixin(LitElement, '') {
9191
* @attr
9292
* @default "Close"
9393
*/
94-
@property({ type: String })
94+
@property({ type: String, attribute: 'close-label' })
9595
public closeLabel = 'Close';
9696

9797
/**
@@ -103,6 +103,15 @@ export class UUIComboboxElement extends UUIFormControlMixin(LitElement, '') {
103103
@property({ type: Boolean, reflect: true })
104104
disabled = false;
105105

106+
/**
107+
* Removes the expand symbol.
108+
* @type {boolean}
109+
* @attr
110+
* @default false
111+
*/
112+
@property({ type: Boolean, reflect: false, attribute: 'hide-expand-symbol' })
113+
hideExpandSymbol = false;
114+
106115
/**
107116
* Sets the input to readonly mode, meaning value cannot be changed but still able to read and select its content.
108117
* @type {boolean}
@@ -112,6 +121,15 @@ export class UUIComboboxElement extends UUIFormControlMixin(LitElement, '') {
112121
@property({ type: Boolean, reflect: true })
113122
readonly = false;
114123

124+
/**
125+
* Defines the input placeholder.
126+
* @type {string}
127+
* @attr
128+
* @default ''
129+
*/
130+
@property()
131+
placeholder = '';
132+
115133
@query('#combobox-input')
116134
private _input!: HTMLInputElement;
117135

@@ -318,6 +336,7 @@ export class UUIComboboxElement extends UUIFormControlMixin(LitElement, '') {
318336
label="combobox-input"
319337
type="text"
320338
.value=${this._displayValue}
339+
.placeholder=${this.placeholder}
321340
autocomplete="off"
322341
.disabled=${this.disabled}
323342
.readonly=${this.readonly}
@@ -327,9 +346,11 @@ export class UUIComboboxElement extends UUIFormControlMixin(LitElement, '') {
327346
@keydown=${this.#onKeyDown}>
328347
<slot name="input-prepend" slot="prepend"></slot>
329348
${this.#renderClearButton()}
330-
<div id="expand-symbol-wrapper" slot="append">
331-
<uui-symbol-expand .open=${this._isOpen}></uui-symbol-expand>
332-
</div>
349+
${this.hideExpandSymbol
350+
? nothing
351+
: html`<div id="expand-symbol-wrapper" slot="append">
352+
<uui-symbol-expand .open=${this._isOpen}></uui-symbol-expand>
353+
</div>`}
333354
<slot name="input-append" slot="append"></slot>
334355
</uui-input>`;
335356
};
@@ -338,18 +359,18 @@ export class UUIComboboxElement extends UUIFormControlMixin(LitElement, '') {
338359
if (this.disabled) return nothing;
339360
if (this.readonly) return nothing;
340361

341-
return this.value || this.search
342-
? html`<uui-button
343-
id="clear-button"
344-
@click=${this.#onClear}
345-
@keydown=${this.#onClear}
346-
label="clear"
347-
slot="append"
348-
compact
349-
style="height: 100%;">
350-
<uui-icon name="remove" .fallback=${iconRemove.strings[0]}></uui-icon>
351-
</uui-button>`
352-
: '';
362+
return html`<uui-button
363+
id="clear-button"
364+
@click=${this.#onClear}
365+
@keydown=${this.#onClear}
366+
label="clear"
367+
slot="append"
368+
compact
369+
style="height: 100%;"
370+
tabindex=${this.value || this.search ? '' : '-1'}
371+
class=${this.value || this.search ? 'visible' : ''}>
372+
<uui-icon name="remove" .fallback=${iconRemove.strings[0]}></uui-icon>
373+
</uui-button>`;
353374
};
354375

355376
#renderDropdown = () => {
@@ -408,6 +429,17 @@ export class UUIComboboxElement extends UUIFormControlMixin(LitElement, '') {
408429
justify-content: center;
409430
}
410431
432+
#clear-button {
433+
opacity: 0;
434+
transition: opacity 80ms;
435+
}
436+
437+
:host(:not([disabled]):not([readonly]):focus-within)
438+
#clear-button.visible,
439+
:host(:not([disabled]):not([readonly]):hover) #clear-button.visible {
440+
opacity: 1;
441+
}
442+
411443
#dropdown {
412444
overflow: hidden;
413445
z-index: -1;

packages/uui-combobox/lib/uui-combobox.story.ts

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,18 +19,30 @@ import { until } from 'lit/directives/until.js';
1919

2020
const fruits = [
2121
'apple',
22-
'orange',
22+
'apricot',
23+
'avocado',
24+
'banana',
25+
'blackberry',
26+
'blueberry',
27+
'clementine',
28+
'coconut',
29+
'fig',
30+
'grape',
31+
'kiwi',
2332
'lemon',
33+
'mango',
2434
'melon',
25-
'banana',
35+
'orange',
36+
'papaya',
37+
'peach',
2638
'pear',
27-
'mango',
39+
'pineapple',
2840
'plum',
41+
'pomegranate',
2942
'raspberry',
30-
'kiwi',
31-
'avocado',
32-
'coconut',
33-
'grape',
43+
'strawberry',
44+
'tangerine',
45+
'watermelon',
3446
];
3547
/**
3648
* Combobox does not have built in filtering, so you need to provide a list of options and filter them before adding them to the list.
@@ -112,6 +124,12 @@ export const Default: Story = {
112124
},
113125
};
114126

127+
export const Placeholder: Story = {
128+
args: {
129+
placeholder: 'Placeholder',
130+
},
131+
};
132+
115133
export const Disabled: Story = {
116134
args: {
117135
disabled: true,
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { defineElement } from '@umbraco-ui/uui-base/lib/registration';
2+
import { html, LitElement } from 'lit';
3+
4+
/**
5+
* @element uui-popover-container
6+
*/
7+
@defineElement('uui-popover-container-shadowdomtester')
8+
export class UUIPopoverContainerShadowDomTesterElement extends LitElement {
9+
render() {
10+
return html`<div
11+
style="height: 500px; overflow: auto; outline: 1px solid black">
12+
<div
13+
style="width: 300px; height: 300px; outline: 1px solid black; overflow: auto;">
14+
<div style="height: 150px"></div>
15+
<uui-button
16+
id="popover-button"
17+
popovertarget="popover-container"
18+
look="primary"
19+
label="Open popover">
20+
Open popover
21+
</uui-button>
22+
<div style="height: 150px"></div>
23+
<div style="height: 150px"></div>
24+
</div>
25+
<div style="height: 400px"></div>
26+
</div>
27+
<uui-popover-container id="popover-container" popover>
28+
<div
29+
style="width: 100%; background-color: var(--uui-color-surface); max-width: 200px; box-shadow: var(--uui-shadow-depth-4); padding: var(--uui-size-space-4); border-radius: var(--uui-border-radius); font-size: 0.9rem;">
30+
<h3>Scroll!</h3>
31+
Scrolling in any of the 2 boxes should trigger an update
32+
</div>
33+
</uui-popover-container>`;
34+
}
35+
}

packages/uui-popover-container/lib/uui-popover-container.element.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,8 @@ export class UUIPopoverContainerElement extends LitElement {
332332
? /(auto|scroll|hidden)/
333333
: /(auto|scroll)/;
334334

335-
let el = this.#targetElement;
336-
while ((el = el.parentElement as HTMLElement)) {
335+
let el: HTMLElement | undefined | null = this.#targetElement;
336+
while (el) {
337337
style = getComputedStyle(el);
338338

339339
if (excludeStaticParent && style.position === 'static') {
@@ -347,6 +347,13 @@ export class UUIPopoverContainerElement extends LitElement {
347347
if (style.position === 'fixed') {
348348
return;
349349
}
350+
351+
if (el.parentElement) {
352+
el = el.parentElement;
353+
} else {
354+
// If we had no parentElement, then check for shadow roots:
355+
el = (el.getRootNode() as any)?.host;
356+
}
350357
}
351358
this.#scrollParents.push(document.body);
352359
}

packages/uui-popover-container/lib/uui-popover-container.story.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import readme from '../README.md?raw';
33
import { html } from 'lit';
44
import type { Meta, StoryObj } from '@storybook/web-components';
55
import { UUIPopoverContainerElement } from '.';
6+
import './uui-popover-container-shadowdomtester.element.js';
67

78
const meta: Meta<UUIPopoverContainerElement> = {
89
id: 'uui-popover-container',
@@ -215,3 +216,27 @@ export const InsideScrollContainer: Story = {
215216
</uui-popover-container>
216217
`,
217218
};
219+
220+
export const InsideShadowDOMScrollContainer: Story = {
221+
args: {
222+
placement: 'bottom-start',
223+
margin: 0,
224+
},
225+
argTypes: {
226+
open: {
227+
control: false,
228+
},
229+
},
230+
render: () => html`
231+
<div style="height: 500px; overflow: auto; outline: 1px solid black">
232+
<div
233+
style="width: 300px; height: 300px; outline: 1px solid black; overflow: auto;">
234+
<div style="height: 150px"></div>
235+
<uui-popover-container-shadowdomtester></uui-popover-container-shadowdomtester>
236+
<div style="height: 150px"></div>
237+
<div style="height: 150px"></div>
238+
</div>
239+
<div style="height: 400px"></div>
240+
</div>
241+
`,
242+
};

0 commit comments

Comments
 (0)