diff --git a/src/dev/pages/text-field/text-field.ejs b/src/dev/pages/text-field/text-field.ejs index d9886c6ce..35458fb14 100644 --- a/src/dev/pages/text-field/text-field.ejs +++ b/src/dev/pages/text-field/text-field.ejs @@ -23,6 +23,13 @@ + +
+

Label aware

+ + First name + +
diff --git a/src/lib/field-next/_core.slotted.scss b/src/lib/field-next/_core.slotted.scss index 65dfa1e75..bbb3f4089 100644 --- a/src/lib/field-next/_core.slotted.scss +++ b/src/lib/field-next/_core.slotted.scss @@ -38,6 +38,10 @@ text-overflow: ellipsis; } +@mixin slotted-forge-label { + font: inherit; +} + @mixin default-slot-disabled { cursor: not-allowed; } diff --git a/src/lib/field-next/base/base-field-adapter.ts b/src/lib/field-next/base/base-field-adapter.ts index 68346c358..9f47bbb56 100644 --- a/src/lib/field-next/base/base-field-adapter.ts +++ b/src/lib/field-next/base/base-field-adapter.ts @@ -1,4 +1,4 @@ -import { BaseAdapter, IBaseAdapter } from '@tylertech/forge/core'; +import { BaseAdapter, IBaseAdapter } from '../../core/base/base-adapter'; import { IFieldComponent } from '../field'; import { IBaseField } from './base-field'; diff --git a/src/lib/field-next/base/base-field.ts b/src/lib/field-next/base/base-field.ts index 59c261478..dfbb5feae 100644 --- a/src/lib/field-next/base/base-field.ts +++ b/src/lib/field-next/base/base-field.ts @@ -1,6 +1,6 @@ import { coerceBoolean, FoundationProperty } from '@tylertech/forge-core'; -import { BaseComponent } from '@tylertech/forge/core'; -import { IWithLabelAwareness, WithLabelAwareness } from '@tylertech/forge/core/mixins/label/with-label-aware'; +import { BaseComponent } from '../../core/base/base-component'; +import { IWithLabelAwareness, WithLabelAwareness } from '../../core/mixins/label/with-label-aware'; import { IBaseFieldAdapter } from './base-field-adapter'; import { BASE_FIELD_CONSTANTS, FieldDensity, FieldLabelAlignment, FieldLabelPosition, FieldShape, FieldSupportTextInset, FieldTheme, FieldVariant } from './base-field-constants'; import { BaseFieldFoundation } from './base-field-foundation'; diff --git a/src/lib/field-next/field.scss b/src/lib/field-next/field.scss index 3a177e131..db4a0052a 100644 --- a/src/lib/field-next/field.scss +++ b/src/lib/field-next/field.scss @@ -660,6 +660,12 @@ $variants: ( } } + .label { + ::slotted(forge-label) { + @include core.slotted-forge-label; + } + } + &--has-start { @include core.main-content-padding-inline(start, start); } diff --git a/src/lib/label/label-foundation.ts b/src/lib/label/label-foundation.ts index 0ae2c0143..f9cc1dcf1 100644 --- a/src/lib/label/label-foundation.ts +++ b/src/lib/label/label-foundation.ts @@ -17,6 +17,7 @@ export class LabelFoundation implements ILabelFoundation { // State private _for: string | null | undefined; private _forElement: HTMLElement | null | undefined; + private _clickTarget: HTMLElement | null | undefined; private _dynamic = false; private _nonInteractive = false; private _legend = false; @@ -74,7 +75,7 @@ export class LabelFoundation implements ILabelFoundation { private _handleClick(evt: PointerEvent): void { // Prevent duplicate clicks from a nested target element or if the event originates // from within the target element - const targetEl = this._adapter.getTargetElement(); + const targetEl = this._clickTarget ?? this._adapter.getTargetElement(); if (evt.target === targetEl || targetEl?.contains(evt.target as Node)) { return; } @@ -140,6 +141,15 @@ export class LabelFoundation implements ILabelFoundation { } } + public get clickTarget(): HTMLElement | null | undefined { + return this._clickTarget; + } + public set clickTarget(value: HTMLElement | null | undefined) { + if (this._clickTarget !== value) { + this._clickTarget = value; + } + } + public get dynamic(): boolean { return this._dynamic; } diff --git a/src/lib/label/label.ts b/src/lib/label/label.ts index 6d5773c21..2ca3549dd 100644 --- a/src/lib/label/label.ts +++ b/src/lib/label/label.ts @@ -30,6 +30,7 @@ declare global { * * @property {string | null | undefined} for - The id of the associated element. * @property {HTMLElement | null | undefined} forElement - The associated element. + * @property {HTMLElement | null | undefined} clickTarget - The element that a click should be simulated on. If not defined clicks act on the associated element. * @property {boolean} dynamic - Propagates changes in the label's text content to the associated element. * @property {boolean} nonInteractive - Removes click handling from the label. * @property {boolean} legend - Whether or not the label should be associated with an ancestor element. @@ -90,6 +91,9 @@ export class LabelComponent extends BaseComponent implements ILabelComponent { @FoundationProperty() public declare forElement: HTMLElement | null | undefined; + @FoundationProperty() + public declare clickTarget: HTMLElement | null | undefined; + @FoundationProperty() public declare dynamic: boolean; diff --git a/src/lib/text-field/text-field-adapter.ts b/src/lib/text-field/text-field-adapter.ts index 479dd017c..044ca8168 100644 --- a/src/lib/text-field/text-field-adapter.ts +++ b/src/lib/text-field/text-field-adapter.ts @@ -143,14 +143,15 @@ export class TextFieldAdapter extends BaseFieldAdapter implements ITextFieldAdap const elements = slot.assignedElements({ flatten: true }); // Attempt to find and connect a `` element - const forgeLabel = elements.find(el => el.tagName === TEXT_FIELD_CONSTANTS.selectors.FORGE_LABEL) as LabelComponent | undefined; + const forgeLabel = elements.find(el => el.matches(TEXT_FIELD_CONSTANTS.selectors.FORGE_LABEL)) as LabelComponent | undefined; if (forgeLabel) { - forgeLabel.forElement = inputElement; + forgeLabel.forElement = this._component; + forgeLabel.clickTarget = inputElement; return; } // Attempt to find and connect a `