Skip to content

Commit

Permalink
feat(components/lookup): country field displays hint text within the …
Browse files Browse the repository at this point in the history
  • Loading branch information
Blackbaud-TrevorBurch authored Mar 3, 2025
1 parent 65dcaeb commit 9283bbf
Show file tree
Hide file tree
Showing 24 changed files with 373 additions and 427 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,6 @@ import { E2eVariations } from '@skyux-sdk/e2e-schematics';
describe('lookup-storybook', () => {
E2eVariations.forEachTheme((theme) => {
describe(`in ${theme} theme`, () => {
describe(`in country field with phone info`, () => {
it(`should render the input dropdown`, () => {
cy.visit(
`/iframe.html?globals=theme:${theme}&id=countryfieldcomponent-countryfield--phone-info-country-field`,
)
.get('#ready')
.should('exist')
.end();
cy.get('app-country-field').should('exist').should('be.visible');
cy.get('textarea').should('exist').should('be.visible').type('ba');

cy.get('app-country-field').screenshot(
`countryfieldcomponent-countryfield--country-field-dropdown-with-phone-info-${theme}`,
);
cy.get('app-country-field').percySnapshot(
`countryfieldcomponent-countryfield--country-field-dropdown-with-phone-info-${theme}`,
{
widths: E2eVariations.DISPLAY_WIDTHS,
},
);
});
});
['empty', 'disabled', 'prepopulated', 'disabled-prepopulated'].forEach(
(mode) => {
describe(`in ${mode} country field`, () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
<form [formGroup]="countryForm">
<sky-input-box labelText="Country field input" [disabled]="disabledFlag">
<sky-country-field
formControlName="countryControl"
[includePhoneInfo]="phoneInfoFlag"
/>
<sky-country-field formControlName="countryControl" />
</sky-input-box>
</form>
<span *ngIf="ready$ | async" id="ready"></span>
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,6 @@ type Story = StoryObj<CountryFieldComponent>;
export const EmptyCountryField: Story = {};
EmptyCountryField.args = {};

export const PhoneInfoCountryField: Story = {};
PhoneInfoCountryField.args = {
phoneInfoFlag: true,
};

export const DisabledCountryField: Story = {};
DisabledCountryField.args = {
disabledFlag: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ import { FontLoadingService } from '@skyux/storybook/font-loading';
standalone: false,
})
export class CountryFieldComponent {
@Input()
public phoneInfoFlag = false;

@Input()
public set prePopulatedFlag(value: boolean) {
if (value) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ <h2 class="sky-section-heading">Input box</h2>
<form>
<sky-input-box
hintText="Here's some hint text."
labelText="Country"
[disabled]="disableFields"
>
<label class="sky-control-label"> Country </label>
<sky-country-field
name="countryField"
required
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
"_description": "Menu item text to display the user has searched and there are more items to view",
"message": "Show matches ({0})"
},
"skyux_country_field_dropdown_hint_text": {
"_description": "Hint text within the country field dropdown",
"message": "Type to search for a country"
},
"skyux_country_field_search_placeholder": {
"_description": "Placeholder for country search autocomplete",
"message": "Search for a country"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,13 +61,20 @@ export class SkyAutocompleteAdapterService {
dropdownRef: ElementRef,
isInputBox: boolean,
): void {
const parentElement = isInputBox
? elementRef.nativeElement.closest('.sky-input-box')
: elementRef.nativeElement;
if (parentElement) {
const width = parentElement.getBoundingClientRect().width;
this.#renderer.setStyle(dropdownRef.nativeElement, 'width', `${width}px`);
}
// `setTimeout` ensures that the input box size is correct when grabbing the width. When the input is initially focused a parent's `overflow-y: auto` value can cause the width to be incorrect during initial rendering.
setTimeout(() => {
const parentElement = isInputBox
? elementRef.nativeElement.closest('.sky-input-box')
: elementRef.nativeElement;
if (parentElement) {
const width = parentElement.getBoundingClientRect().width;
this.#renderer.setStyle(
dropdownRef.nativeElement,
'width',
`${width}px`,
);
}
});
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
class="sky-autocomplete"
role="combobox"
[attr.aria-expanded]="
isOpen && (showActionsArea || (isResultsVisible | async))
isOpen &&
(showActionsArea || dropdownHintText || (isResultsVisible | async))
"
[attr.aria-labelledby]="ariaLabelledBy"
[attr.aria-controls]="
isOpen && (showActionsArea || (isResultsVisible | async))
isOpen &&
(showActionsArea || dropdownHintText || (isResultsVisible | async))
? resultsListId
: null
"
Expand Down Expand Up @@ -76,6 +78,10 @@
</div>
}
</div>
} @else if (dropdownHintText) {
<div class="sky-autocomplete-dropdown-hint-text sky-font-deemphasized">
{{ dropdownHintText }}
</div>
}
@if (showActionsArea) {
<div class="sky-autocomplete-actions">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
--sky-override-autocomplete-actions-no-results-padding: 7px 13px;
--sky-override-autocomplete-actions-top-border: 1px solid
#{$sky-border-color-neutral-medium};
--sky-override-autocomplete-dropdown-hint-text-line-height: normal;
--sky-override-autocomplete-dropdown-hint-text-padding: 7px 13px;
--sky-override-autocomplete-no-results-font-size: 15px;
--sky-override-autocomplete-no-results-padding: #{$sky-padding-squish-default};
--sky-override-autocomplete-result-background-color: transparent;
Expand All @@ -33,6 +35,8 @@
--sky-override-autocomplete-actions-no-results-padding: 7px 13px;
--sky-override-autocomplete-actions-top-border: 1px solid
#{$sky-border-color-neutral-medium};
--sky-override-autocomplete-dropdown-hint-text-line-height: normal;
--sky-override-autocomplete-dropdown-hint-text-padding: 7px 13px;
--sky-override-autocomplete-no-results-font-size: 15px;
--sky-override-autocomplete-no-results-padding: #{$sky-padding-squish-default};
--sky-override-autocomplete-result-margin-bottom: 0;
Expand Down Expand Up @@ -144,6 +148,20 @@
}
}

.sky-autocomplete-dropdown-hint-text {
display: inline-block;
padding: var(
--sky-override-autocomplete-dropdown-hint-text-padding,
var(--sky-space-inset-pillarbox-1_2-top-m) 0
var(--sky-space-inset-pillarbox-1_2-bottom-m)
var(--sky-space-inset-pillarbox-1_2-left-m)
);
line-height: var(
--sky-override-autocomplete-dropdown-hint-text-line-height,
var(--sky-font-line_height-body-m)
);
}

.sky-autocomplete-action-add {
float: right;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ describe('Autocomplete component', () => {
return document.querySelector('sky-autocomplete') as HTMLElement;
}

function getDisplayedHintText(): string {
return (
document
.querySelector('.sky-autocomplete-dropdown-hint-text')
?.textContent.trim() || ''
);
}

function getInputElement(async = false): HTMLInputElement {
if (async) {
return document.getElementById(
Expand Down Expand Up @@ -452,6 +460,83 @@ describe('Autocomplete component', () => {
expect(actionsContainer).toBeNull();
}));

it('should show a dropdown hint message', fakeAsync(() => {
const expectedMessage = 'Type to search for a person';
component.dropdownHintText = expectedMessage;
fixture.detectChanges();

const inputElement = getInputElement();

SkyAppTestUtility.fireDomEvent(inputElement, 'focus');
fixture.detectChanges();
tick();
fixture.detectChanges();

const hintText = getDisplayedHintText();
expect(hintText).toBe(expectedMessage);

const actionsContainer = getActionsContainer();
expect(actionsContainer).toBeNull();
}));

it('should not show a dropdown hint message when no results are found', fakeAsync(() => {
const expectedMessage = 'Type to search for a person';
component.dropdownHintText = expectedMessage;
fixture.detectChanges();

const inputElement = getInputElement();

SkyAppTestUtility.fireDomEvent(inputElement, 'focus');
fixture.detectChanges();
tick();
fixture.detectChanges();

let hintText = getDisplayedHintText();
expect(hintText).toBe(expectedMessage);

let actionsContainer = getActionsContainer();
expect(actionsContainer).toBeNull();

enterSearch('abcdefgh', fixture);

const container = getSearchResultsSection();
expect(container?.textContent?.trim()).toBe('No matches found');

actionsContainer = getActionsContainer();
expect(actionsContainer).toBeNull();

hintText = getDisplayedHintText();
expect(hintText).toBe('');
}));

it('should not show a dropdown hint message when results are found', fakeAsync(() => {
const expectedMessage = 'Type to search for a person';
component.dropdownHintText = expectedMessage;
fixture.detectChanges();

const inputElement = getInputElement();

SkyAppTestUtility.fireDomEvent(inputElement, 'focus');
fixture.detectChanges();
tick();
fixture.detectChanges();

let hintText = getDisplayedHintText();
expect(hintText).toBe(expectedMessage);

const actionsContainer = getActionsContainer();
expect(actionsContainer).toBeNull();

const spy = spyOn(autocomplete, 'searchOrDefault').and.callThrough();

enterSearch('r', fixture);

expect(spy.calls.argsFor(0)[0]).toEqual('r');

hintText = getDisplayedHintText();
expect(hintText).toBe('');
}));

it('should show a no results found message in the actions area if the add button is shown', fakeAsync(() => {
component.showAddButton = true;
// NOTE: The "New" is from the "New" button
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,13 @@ export class SkyAutocompleteComponent implements OnDestroy, AfterViewInit {
return this.#_descriptorProperty;
}

/**
* Hint text to show in the dropdown
* @internal
*/
@Input()
public dropdownHintText: string | undefined;

/**
* @internal
* Whether to display a button in the dropdown that opens a picker where users can view all options.
Expand Down Expand Up @@ -415,7 +422,7 @@ export class SkyAutocompleteComponent implements OnDestroy, AfterViewInit {
.pipe(takeUntil(this.#inputDirectiveUnsubscribe))
.subscribe(() => {
this.#hasFocus = true;
if (this.showActionsArea) {
if (this.showActionsArea || this.dropdownHintText) {
this.#openDropdown();
}
});
Expand Down Expand Up @@ -598,7 +605,7 @@ export class SkyAutocompleteComponent implements OnDestroy, AfterViewInit {
if (targetIsSearchResult) {
this.#selectSearchResultById(activeElementId);

if (!this.showActionsArea) {
if (!this.showActionsArea && !this.dropdownHintText) {
this.#closeDropdown();
} else {
this.#resetSearch();
Expand Down Expand Up @@ -701,7 +708,7 @@ export class SkyAutocompleteComponent implements OnDestroy, AfterViewInit {
public onResultClick(id: string, event: MouseEvent): void {
this.#selectSearchResultById(id);

if (!this.showActionsArea) {
if (!this.showActionsArea && !this.dropdownHintText) {
this.#closeDropdown();
} else {
this.#resetSearch();
Expand Down Expand Up @@ -740,7 +747,7 @@ export class SkyAutocompleteComponent implements OnDestroy, AfterViewInit {
});
}

if (!this.showActionsArea) {
if (!this.showActionsArea && !this.dropdownHintText) {
this.#closeDropdown();
} else {
this.#resetSearch();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
[data]="data"
[debounceTime]="debounceTime"
[descriptorProperty]="descriptorProperty"
[dropdownHintText]="dropdownHintText"
[enableShowMore]="enableShowMore"
[messageStream]="messageStream"
[propertiesToSearch]="propertiesToSearch"
Expand Down Expand Up @@ -49,6 +50,7 @@
[data]="data"
[debounceTime]="debounceTime"
[descriptorProperty]="descriptorProperty"
[dropdownHintText]="dropdownHintText"
[enableShowMore]="enableShowMore"
[messageStream]="messageStream"
[propertiesToSearch]="propertiesToSearch"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ export class SkyAutocompleteFixtureComponent {
public debounceTime: number | undefined;
public descriptorProperty: string | undefined;
public disabled: boolean | undefined = false;
public dropdownHintText: string | undefined;
public enableShowMore: boolean | undefined = false;
public hideInput = false;
public propertiesToSearch: string[] | undefined;
Expand Down
Loading

0 comments on commit 9283bbf

Please sign in to comment.