Skip to content

Commit

Permalink
feat: fluid state for dropdown (#3008)
Browse files Browse the repository at this point in the history
Signed-off-by: Akshat Patel <[email protected]>
Co-authored-by: Akshat Patel <[email protected]>
  • Loading branch information
eduardmarcinco and Akshat55 authored Nov 22, 2024
1 parent 3bda789 commit 3108b90
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 27 deletions.
83 changes: 57 additions & 26 deletions src/dropdown/dropdown.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ import { hasScrollableParents } from "carbon-components-angular/utils";
<div
class="cds--list-box"
[ngClass]="{
'cds--dropdown': type !== 'multi',
'cds--dropdown': type !== 'multi' && !(skeleton && fluid),
'cds--multiselect': type === 'multi',
'cds--multi-select--selected': type === 'multi' && getSelectedCount() > 0,
'cds--dropdown--light': theme === 'light',
Expand All @@ -83,8 +83,11 @@ import { hasScrollableParents } from "carbon-components-angular/utils";
'cds--dropdown--sm cds--list-box--sm': size === 'sm',
'cds--dropdown--md cds--list-box--md': size === 'md',
'cds--dropdown--lg cds--list-box--lg': size === 'lg',
'cds--list-box--expanded': !menuIsClosed
}">
'cds--list-box--expanded': !menuIsClosed,
'cds--list-box--invalid': invalid
}"
[attr.data-invalid]="invalid ? true : null">
<div *ngIf="skeleton && fluid" class="cds--list-box__label"></div>
<button
#dropdownButton
[id]="id"
Expand All @@ -96,7 +99,8 @@ import { hasScrollableParents } from "carbon-components-angular/utils";
[attr.aria-readonly]="readonly"
aria-haspopup="listbox"
(click)="disabled || readonly ? $event.stopPropagation() : toggleMenu()"
(blur)="onBlur()"
(focus)="fluid ? handleFocus($event) : null"
(blur)="fluid ? handleFocus($event) : onBlur()"
[attr.disabled]="disabled ? true : null">
<div
(click)="clearSelected()"
Expand Down Expand Up @@ -125,18 +129,6 @@ import { hasScrollableParents } from "carbon-components-angular/utils";
[ngTemplateOutletContext]="getRenderTemplateContext()"
[ngTemplateOutlet]="displayValue">
</ng-template>
<svg
*ngIf="invalid"
class="cds--dropdown__invalid-icon"
cdsIcon="warning--filled"
size="16">
</svg>
<svg
*ngIf="!invalid && warn"
cdsIcon="warning--alt--filled"
size="16"
class="cds--list-box__invalid-icon cds--list-box__invalid-icon--warning">
</svg>
<span class="cds--list-box__menu-icon">
<svg
*ngIf="!skeleton"
Expand All @@ -147,6 +139,18 @@ import { hasScrollableParents } from "carbon-components-angular/utils";
</svg>
</span>
</button>
<svg
*ngIf="invalid"
class="cds--list-box__invalid-icon"
cdsIcon="warning--filled"
size="16">
</svg>
<svg
*ngIf="!invalid && warn"
cdsIcon="warning--alt--filled"
size="16"
class="cds--list-box__invalid-icon cds--list-box__invalid-icon--warning">
</svg>
<div
#dropdownMenu
[ngClass]="{
Expand All @@ -155,8 +159,9 @@ import { hasScrollableParents } from "carbon-components-angular/utils";
<ng-content *ngIf="!menuIsClosed"></ng-content>
</div>
</div>
<hr *ngIf="fluid" class="cds--list-box__divider" />
<div
*ngIf="helperText && !invalid && !warn && !skeleton"
*ngIf="helperText && !invalid && !warn && !skeleton && !fluid"
class="cds--form__helper-text"
[ngClass]="{
'cds--form__helper-text--disabled': disabled
Expand All @@ -183,6 +188,25 @@ import { hasScrollableParents } from "carbon-components-angular/utils";
})
export class Dropdown implements OnInit, AfterContentInit, AfterViewInit, OnDestroy, ControlValueAccessor {
static dropdownCount = 0;
@HostBinding("class.cds--list-box__wrapper--fluid--invalid") get fluidInvalidClass() {
return this.invalid && this.fluid;
}

@HostBinding("class.cds--list-box__wrapper--fluid--focus") get fluidFocusClass() {
return this.fluid && this._isFocused && this.menuIsClosed;
}

protected get writtenValue() {
return this._writtenValue;
}

protected set writtenValue(val: any[]) {
if (val && val.length === 0) {
this.clearSelected();
}
this._writtenValue = val;
}

@Input() id = `dropdown-${Dropdown.dropdownCount++}`;
/**
* Label for the dropdown.
Expand Down Expand Up @@ -319,6 +343,13 @@ export class Dropdown implements OnInit, AfterContentInit, AfterViewInit, OnDest
@ViewChild("dropdownMenu", { static: true }) dropdownMenu;

@HostBinding("class.cds--dropdown__wrapper") hostClass = true;

@HostBinding("class.cds--list-box__wrapper") hostWrapperClass = true;
/**
* Experimental: enable fluid state
*/
@HostBinding("class.cds--list-box__wrapper--fluid") @Input() fluid = false;

/**
* Set to `true` if the dropdown is closed (not expanded).
*/
Expand All @@ -340,17 +371,10 @@ export class Dropdown implements OnInit, AfterContentInit, AfterViewInit, OnDest

protected onTouchedCallback: () => void = this._noop;

protected _isFocused = false;

// primarily used to capture and propagate input to `writeValue` before the content is available
private _writtenValue: any = [];
protected get writtenValue() {
return this._writtenValue;
}
protected set writtenValue(val: any[]) {
if (val && val.length === 0) {
this.clearSelected();
}
this._writtenValue = val;
}

/**
* Creates an instance of Dropdown.
Expand Down Expand Up @@ -801,6 +825,13 @@ export class Dropdown implements OnInit, AfterContentInit, AfterViewInit, OnDest
return value instanceof TemplateRef;
}

handleFocus(event: FocusEvent) {
this._isFocused = event.type === "focus";
if (event.type === "blur") {
this.onBlur();
}
}

/**
* Controls when it's needed to apply the selection feedback
*/
Expand Down
10 changes: 9 additions & 1 deletion src/dropdown/dropdown.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ export default {
appendInline: false,
dropUp: false,
size: "md",
theme: "dark"
theme: "dark",
fluid: false
},
argTypes: {
type: {
Expand Down Expand Up @@ -103,6 +104,7 @@ const Template = (args) => ({
placeholder="Select"
[disabled]="disabled"
[readonly]="readonly"
[fluid]="fluid"
(selected)="selected($event)"
(onClose)="onClose($event)">
<cds-dropdown-list [items]="items"></cds-dropdown-list>
Expand All @@ -111,6 +113,11 @@ const Template = (args) => ({
});
export const Basic = Template.bind({});

export const Fluid = Template.bind({});
Fluid.args = {
fluid: true
};

const MultiTemplate = (args) => ({
props: args,
template: `
Expand All @@ -131,6 +138,7 @@ const MultiTemplate = (args) => ({
placeholder="Select"
[disabled]="disabled"
[readonly]="readonly"
[fluid]="fluid"
(selected)="selected($event)"
(onClose)="onClose($event)">
<cds-dropdown-list [items]="items"></cds-dropdown-list>
Expand Down

0 comments on commit 3108b90

Please sign in to comment.