Skip to content
Open
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
2 changes: 1 addition & 1 deletion packages/ai/src/InputTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export default function InputTemplate(this: Input, hooks?: { preContent: Templat
style={this.styles.innerInput}
type={this.inputNativeType}
inner-input
inner-input-with-icon={!!this.icon.length}
inner-input-with-icon={this.iconsCount > 0}
disabled={this.disabled}
readonly={this._readonly || this.loading}
value={this.value}
Expand Down
2 changes: 1 addition & 1 deletion packages/main/src/InputTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export default function InputTemplate(this: Input, hooks?: { preContent: Templat
style={this.styles.innerInput}
type={this.inputNativeType}
inner-input
inner-input-with-icon={!!this.icon.length}
inner-input-with-icon={this.iconsCount > 0}
disabled={this.disabled}
readonly={this._readonly}
value={this.value}
Expand Down
1 change: 1 addition & 0 deletions packages/main/src/MultiComboBoxTemplate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export default function MultiComboBoxTemplate(this: MultiComboBox) {
id="ui5-multi-combobox-input"
value={this.value}
inner-input
inner-input-with-icon={this._effectiveShowClearIcon || !!this.icon || !this.readonly}
placeholder={this._getPlaceholder}
disabled={this.disabled}
readonly={this.readonly}
Expand Down
3 changes: 3 additions & 0 deletions packages/main/src/MultiInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,9 @@ class MultiInput extends Input implements IFormInputElement {

if (this.tokenizer) {
this.tokenizer.readonly = this.readonly;

// Set the CSS variable on the tokenizer element so it's available in the shadow DOM
this.tokenizer.style.setProperty("--_ui5-input-icons-count", `${this.iconsCount}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is not used as only tokens are rendered.

}
}

Expand Down
37 changes: 37 additions & 0 deletions packages/main/src/Tokenizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,7 @@ class Tokenizer extends UI5Element implements IFormInputElement {
_deletedDialogItems!: Token[];
_lastFocusedToken: Token | null = null;
_isFocusSetInternally: boolean = false;
_lastMarkedToken?: Token;
/**
* Scroll to end when tokenizer is expanded
* @private
Expand Down Expand Up @@ -423,6 +424,12 @@ class Tokenizer extends UI5Element implements IFormInputElement {
token.singleToken = (tokensLength === 1) || this.multiLine;
token.readonly = this.readonly;
});

// If expanding, immediately remove last-visible-token attribute to ensure proper spacing
if (this.expanded && this._lastMarkedToken) {
this._lastMarkedToken.removeAttribute("last-visible-token");
this._lastMarkedToken = undefined;
}
}

onEnterDOM() {
Expand Down Expand Up @@ -513,6 +520,36 @@ class Tokenizer extends UI5Element implements IFormInputElement {

this._scrollToEndIfNeeded();
this._tokenDeleting = false;
this._updateLastVisibleTokenAttribute();
}

/**
* Updates the last-visible-token attribute on tokens.
* When collapsed with overflow, marks the last visible token for proper spacing to the n-more indicator.
* @private
*/
_updateLastVisibleTokenAttribute() {
const tokensArray = this._tokens;
const hasOverflow = this._nMoreCount > 0;
const visibleTokens = tokensArray.filter(token => !token.overflows);
const lastVisibleToken = visibleTokens.length > 0 ? visibleTokens[visibleTokens.length - 1] : undefined;

// Only set attribute when NOT expanded AND overflow exists
const newMarkedToken = (!this.expanded && hasOverflow && lastVisibleToken) ? lastVisibleToken : undefined;
const previousToken = this._lastMarkedToken;

// Only update DOM if state changed (prevents render loop)
if (previousToken !== newMarkedToken) {
if (previousToken) {
previousToken.removeAttribute("last-visible-token");
}

if (newMarkedToken) {
newMarkedToken.setAttribute("last-visible-token", "");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we not just make private property in the token as "lastVisibleToken" and then manipulate it here, this is how the framework will attach itself last-visible-token as attribute in its natural reactive way in the template. Something like:

    const tokensArray = this._tokens;
    const hasOverflow = this._nMoreCount > 0;
    const shouldMark = !this.expanded && hasOverflow;

    tokensArray.forEach((token, index) => {
        const isVisible = !token.overflows;
        const visibleTokens = tokensArray.filter(t => !t.overflows);
        const isLastVisible = isVisible && token === visibleTokens[visibleTokens.length - 1];
        
        token.lastVisibleToken = shouldMark && isLastVisible;
    });

}

this._lastMarkedToken = newMarkedToken;
}
}

/**
Expand Down
4 changes: 4 additions & 0 deletions packages/main/src/themes/ComboBox.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@
width: 100%;
height: 100%;
border-radius: var(--_ui5_input_border_radius);
}

:host(:not([readonly])) [inner-input] {
padding: var(--_ui5_input_inner_padding_with_icon);
}
6 changes: 4 additions & 2 deletions packages/main/src/themes/MultiComboBox.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

.ui5-multi-combobox-tokenizer {
min-width: var(--_ui5_input_tokenizer_min_width);
max-width: calc(100% - 3rem - var(--_ui5-input-icons-count) * var(--_ui5_input_icon_min_width));
max-width: calc(100% - var(--_ui5_input_min_width_tokenizer_available) - var(--_ui5-input-icons-count) * var(--_ui5_input_icon_min_width));
border: none;
width: auto;
height: 100%;
Expand All @@ -48,7 +48,9 @@
}

:host([tokenizer-available]) [inner-input] {
padding-inline-start: var(--_ui5_input_inner_space_to_tokenizer);
padding-inline-start: 0;
padding-inline-end: var(--_ui5_input_inner_with_tokenizer_padding_inline_end);
min-width: var(--_ui5_input_min_width_tokenizer_available);
}

:host(:not([tokenizer-available])) .ui5-multi-combobox-tokenizer {
Expand Down
6 changes: 4 additions & 2 deletions packages/main/src/themes/MultiInput.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

.ui5-multi-input-tokenizer {
min-width: var(--_ui5_input_tokenizer_min_width);
max-width: calc(100% - 3rem - var(--_ui5-input-icons-count) * var(--_ui5_input_icon_min_width));
max-width: calc(100% - var(--_ui5_input_min_width_tokenizer_available) - var(--_ui5-input-icons-count) * var(--_ui5_input_icon_min_width));
border: none;
width: auto;
height: 100%;
Expand All @@ -29,7 +29,9 @@
}

:host([tokenizer-available]) [inner-input] {
padding-inline-start: var(--_ui5_input_inner_space_to_tokenizer);
padding-inline-start: 0;
padding-inline-end: var(--_ui5_input_inner_with_tokenizer_padding_inline_end);
min-width: var(--_ui5_input_min_width_tokenizer_available);
}

:host(:not([tokenizer-available])) .ui5-multi-input-tokenizer {
Expand Down
4 changes: 4 additions & 0 deletions packages/main/src/themes/Token.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
margin-inline-end: var(--_ui5_token_right_margin);
}

:host([last-visible-token]) {
margin-inline-end: 0;
}

:host([overflows]) {
display: none;
}
Expand Down
2 changes: 1 addition & 1 deletion packages/main/src/themes/Tokenizer.css
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@

.ui5-tokenizer-more-text {
display: inline-block;
margin-inline-start: .25rem;
margin-inline-start: var(--_ui5_token_right_margin);
cursor: pointer;
white-space: nowrap;
font-size: var(--sapFontSize);
Expand Down
13 changes: 9 additions & 4 deletions packages/main/src/themes/base/sizes-parameters.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
--_ui5_input_inner_padding: 0 0.625rem;
--_ui5_input_inner_padding_with_icon: 0 0.25rem 0 0.625rem;
--_ui5_input_inner_space_to_tokenizer: 0.125rem;
--_ui5_input_inner_space_to_n_more_text: 0.1875rem;
--_ui5_input_inner_space_to_n_more_text: 0.3125rem;
--_ui5_input_inner_with_tokenizer_padding_inline_end: 0.3125rem;
--_ui5_list_no_data_height: 3rem;
--_ui5_list_item_cb_margin_right: 0;
--_ui5_list_item_title_size: var(--sapFontLargeSize);
Expand Down Expand Up @@ -103,7 +104,7 @@
--_ui5_popup_default_header_height: 2.75rem;

--_ui5_year_picker_item_height: 3rem;
--_ui5_tokenizer_padding: 0.25rem;
--_ui5_tokenizer_padding: 0.3125rem;
--_ui5_token_height: 1.625rem;
--_ui5_token_icon_size: .75rem;
--_ui5_token_icon_padding: 0.25rem 0.5rem;
Expand Down Expand Up @@ -267,9 +268,10 @@
/* Input */
--_ui5_input_height: var(--sapElement_Compact_Height);
--_ui5_input_inner_padding: 0 0.5rem;
--_ui5_input_inner_padding_with_icon: 0 0.2rem 0 0.5rem;
--_ui5_input_inner_padding_with_icon: 0 0.25rem 0 0.5rem;
--_ui5_input_inner_space_to_tokenizer: 0.125rem;
--_ui5_input_inner_space_to_n_more_text: 0.125rem;
--_ui5_input_inner_space_to_n_more_text: 0.25rem;
--_ui5_input_inner_with_tokenizer_padding_inline_end: 0.25rem;
--_ui5_input_icon_min_width: var(--_ui5_input_compact_min_width);
--_ui5_input_min_width_tokenizer_available: 2rem;

Expand Down Expand Up @@ -351,6 +353,9 @@
--_ui5-tree-toggle-box-height: 1.5rem;
--_ui5-tree-toggle-icon-size: 0.8125rem;

/* Tokenizer */
--_ui5_tokenizer_padding: 0.25rem;

/* Toolbar */
--_ui5-toolbar-separator-height: 1.5rem;
--_ui5-toolbar-height: 2rem;
Expand Down
Loading