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 libs/cdk/forms/cva/cva.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export class CvaDirective<T = any>
}

/**
* readOnly Value to Mark component read only
* readOnly value to mark component read only
*/
@Input()
readonly: boolean;
Expand Down
1 change: 1 addition & 0 deletions libs/core/input-group/input-group.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,7 @@ fd-input-group {
pointer-events: none;
opacity: var(--sapContent_DisabledOpacity);
}

.fd-input-group[aria-disabled='true']::-webkit-input-placeholder,
.fd-input-group.is-disabled::-webkit-input-placeholder,
.fd-input-group:disabled::-webkit-input-placeholder {
Expand Down
11 changes: 11 additions & 0 deletions libs/core/multi-input/multi-input.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,17 @@
[ngTemplateOutlet]="control"
[ngTemplateOutletContext]="{ displayAddonButton: displayAddonButton }"
></ng-template>
} @else if (display()) {
<fd-tokenizer
[display]="display()"
[tokenizerFocusable]="false"
[ariaLabelledBy]="ariaLabelledBy"
class="fd-multi-input-tokenizer-custom"
>
@for (token of viewModel.selectedOptions; track token; let last = $last) {
<fd-token [display]="display()" [isLast]="last">{{ token.label }}</fd-token>
}
</fd-tokenizer>
} @else {
<fd-popover
additionalBodyClass="fd-popover-custom-list"
Expand Down
2 changes: 2 additions & 0 deletions libs/core/multi-input/multi-input.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ $block: fd-multi-input;

&-custom {
display: block;
flex-grow: 1;
flex-basis: 0;
}

&-item {
Expand Down
13 changes: 13 additions & 0 deletions libs/core/multi-input/multi-input.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -295,4 +295,17 @@ describe('MultiInputComponent', () => {
expect(element.style.pointerEvents).toBe('auto');
expect(element.tabIndex).toBe(0);
});

describe('when in display mode', () => {
beforeEach(() => {
fixture.componentRef.setInput('display', true);
fixture.detectChanges();
});

it('should render a tokenizer in display mode', () => {
const tokenizerElement = fixture.nativeElement.querySelector('fd-tokenizer');
expect(tokenizerElement).toBeTruthy();
expect(component.tokenizer.display()).toBe(true);
});
});
});
4 changes: 4 additions & 0 deletions libs/core/multi-input/multi-input.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
forwardRef,
HostListener,
Injector,
input,
Input,
isDevMode,
OnChanges,
Expand Down Expand Up @@ -418,6 +419,9 @@ export class MultiInputComponent<ItemType = any, ValueType = any>
@ViewChild(TokenizerComponent)
tokenizer: TokenizerComponent;

/** Whether the input is display-only */
display = input(false);

/** @hidden */
get _optionItems(): _OptionItem<ItemType, ValueType>[] {
return this.optionItems$.value;
Expand Down
4 changes: 3 additions & 1 deletion libs/core/token/token.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,16 @@
[attr.aria-setsize]="_totalCount"
[attr.aria-posinset]="_itemPosition"
[class.fd-token__disabled]="disabled"
[class.fd-token--display]="display"
[class.fd-token--isLast]="isLast"
[class.fd-token--selected]="selected"
[class.fd-token--readonly]="readOnly"
[attr.aria-selected]="selected"
>
<span class="fd-token__text no-text-select">
<ng-container #viewContainer></ng-container>
</span>
@if (!readOnly) {
@if (!readOnly && !display) {
<span
(click)="closeClickHandler($event)"
role="button"
Expand Down
13 changes: 13 additions & 0 deletions libs/core/token/token.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,16 @@ fd-token {
-ms-user-select: none;
user-select: none;
}

// remove this when latest fundamental styles are adopted
.fd-token--display {
--fdToken_Text_Color: var(--sapTextColor);
--fdToken_Border: none;
--fdToken_Background_Color: transparent;
--fdToken_Min_Width: fit-content;

margin-inline: 0;
padding-inline: 0;
text-align: start;
pointer-events: none;
}
11 changes: 11 additions & 0 deletions libs/core/token/token.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,17 @@ describe('TokenComponent', () => {
expect(fixture.nativeElement.querySelector('.fd-token__close')).toBeFalsy();
});

it('should not render close icon when in display-only mode', async () => {
component.display = false;
fixture.detectChanges();
await fixture.whenStable();
expect(fixture.nativeElement.querySelector('.fd-token__close')).toBeTruthy();
component.display = true;
fixture.detectChanges();
await fixture.whenStable();
expect(fixture.nativeElement.querySelector('.fd-token__close')).toBeFalsy();
});

it('should fire onCloseClick when clicking x', () => {
jest.spyOn(component.onCloseClick, 'emit');
const content = fixture.nativeElement.querySelector('.fd-token__close');
Expand Down
7 changes: 7 additions & 0 deletions libs/core/token/token.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ export class TokenComponent implements AfterViewInit, OnDestroy {
@Input()
disabled = false;

/** Whether the token is display-only */
@Input()
display = false;

@Input()
isLast = false;

/** @hidden */
@ViewChild('tokenWrapperElement')
tokenWrapperElement: ElementRef;
Expand Down
55 changes: 44 additions & 11 deletions libs/core/token/tokenizer.component.html
Original file line number Diff line number Diff line change
@@ -1,25 +1,41 @@
<div class="fd-tokenizer fd-tokenizer--scrollable" [class.is-focus]="_tokenizerHasFocus">
<div
class="fd-tokenizer fd-tokenizer--scrollable"
[class.is-focus]="_tokenizerHasFocus"
[class.fd-tokenizer--display]="display()"
>
<div class="fd-tokenizer__inner" #tokenizerInner>
<div
[attr.aria-hidden]="tokenList.length === 0"
role="listbox"
[attr.aria-label]="'coreTokenizer.tokenizerLabel' | fdTranslate"
[style.width]="_tokensContainerWidth"
[class.fd-tokenizer__inner-show-dot]="display()"
>
<ng-content select="fd-token"></ng-content>
</div>
@if (showOverflowPopover && (_contentDensityObserver.isCompactSignal() || compactCollapse)) {
@if (
showOverflowPopover &&
_hiddenTokens.length > 0 &&
(_contentDensityObserver.isCompactSignal() || compactCollapse || display())
) {
<ng-template [ngTemplateOutlet]="tokensOverflow"></ng-template>
} @else {
@if (_showMoreElement && _hiddenTokens.length > 0) {
<span (click)="moreClicked()" #moreElementSpan class="fd-tokenizer-more" role="button" tabindex="-1">
@if (_contentDensityObserver.isCompactSignal() || compactCollapse) {
<span
(click)="moreClicked()"
#moreElementSpan
class="fd-tokenizer-more"
[class.fd-tokenizer-allow-pointer]="display()"
role="button"
tabindex="-1"
>
@if (_contentDensityObserver.isCompactSignal() || compactCollapse || display()) {
{{
'coreTokenizer.moreLabel'
| fdTranslate: { count: moreTokensLeft.length + moreTokensRight.length }
}}
}
@if (!_contentDensityObserver.isCompactSignal() && !compactCollapse) {
@if (!_contentDensityObserver.isCompactSignal() && !compactCollapse && !display()) {
{{ 'coreTokenizer.moreLabel' | fdTranslate: { count: hiddenCozyTokenCount } }}
}
</span>
Expand All @@ -41,16 +57,26 @@
}
</div>
<ng-template #tokensOverflow>
<fd-popover placement="bottom-start" title="" [noArrow]="false" [focusTrapped]="true" [focusAutoCapture]="true">
<fd-popover
placement="bottom-start"
title=""
[noArrow]="false"
[focusTrapped]="true"
[focusAutoCapture]="display() ? false : true"
>
<fd-popover-control>
<ng-template [ngTemplateOutlet]="moreElement"></ng-template>
</fd-popover-control>
<fd-popover-body>
<ul fd-list class="fd-tokenizer__overflow-list">
@for (token of _hiddenTokens; track token) {
<li fd-list-item class="fd-tokenizer__overflow-list-item">
<li
fd-list-item
class="fd-tokenizer__overflow-list-item"
[class.fd-tokenizer__overflow-list-item-display]="display()"
>
<ng-container #viewContainer></ng-container>
@if (!token.readOnly) {
@if (!token.readOnly && !token.display) {
<span
class="fd-token__close"
role="button"
Expand All @@ -66,11 +92,18 @@
</ng-template>
<ng-template #moreElement>
@if (_showMoreElement && _hiddenTokens.length > 0) {
<span (click)="moreClicked()" #moreElementSpan class="fd-tokenizer-more" role="button" tabindex="-1">
@if (_contentDensityObserver.isCompactSignal() || compactCollapse) {
<span
(click)="moreClicked()"
#moreElementSpan
class="fd-tokenizer-more"
[class.fd-tokenizer-allow-pointer]="display()"
role="button"
tabindex="-1"
>
@if (_contentDensityObserver.isCompactSignal() || compactCollapse || display()) {
{{ 'coreTokenizer.moreLabel' | fdTranslate: { count: moreTokensLeft.length + moreTokensRight.length } }}
}
@if (!_contentDensityObserver.isCompactSignal() && !compactCollapse) {
@if (!_contentDensityObserver.isCompactSignal() && !compactCollapse && !display()) {
{{ 'coreTokenizer.moreLabel' | fdTranslate: { count: hiddenCozyTokenCount } }}
}
</span>
Expand Down
65 changes: 65 additions & 0 deletions libs/core/token/tokenizer.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,69 @@ input {
.fd-tokenizer__overflow-list-item {
display: flex;
justify-content: space-between;

&-display {
pointer-events: none;
border: none;
}
}

.fd-tokenizer {
&--display {
border: none;
box-shadow: none;
overflow: visible;
pointer-events: none;
background: transparent;

.fd-tokenizer__inner {
justify-content: flex-start;
overflow: visible;
}

.fd-tokenizer__inner-show-dot:has(+ fd-popover),
.fd-tokenizer__inner-show-dot:has(+ .fd-tokenizer-more) {
&::after {
content: '\00B7';
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 1rem;
}
}

.fd-token {
margin-inline-end: 0;

&--display {
&::after {
content: '\00B7';
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 1rem;
}
}

&--isLast {
&::after {
content: '';
min-width: 0;
}
}
}

.fd-tokenizer__input {
display: none;
}
}
}

.fd-tokenizer.fd-tokenizer--display.is-hover,
.fd-tokenizer.fd-tokenizer--display:hover {
background: transparent;
}

.fd-tokenizer-allow-pointer {
pointer-events: all;
}
Loading