From 36f3aee254edb44717541070309e542292704591 Mon Sep 17 00:00:00 2001 From: sivanova Date: Mon, 18 Aug 2025 10:00:33 +0300 Subject: [PATCH 1/7] feat(input-group): add read-only styles --- .../components/input/_input-group-theme.scss | 217 +++++++++++++----- 1 file changed, 160 insertions(+), 57 deletions(-) diff --git a/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss index 1b036517f8e..21ab1184568 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss @@ -202,6 +202,28 @@ -webkit-appearance: none; } + &:has(input:read-only:not(:disabled, [role="combobox"], [type="file"])), + &:has(textarea:read-only:not(:disabled)) { + igx-prefix, + [igxPrefix], + igx-suffix, + [igxSuffix] { + color: var-get($theme, 'disabled-text-color'); + } + + %form-group-label { + color: var-get($theme, 'idle-secondary-color'); + } + + %form-group-line { + background: var-get($theme, 'focused-secondary-color'); + } + + %form-group-helper { + color: var-get($theme, 'helper-text-color'); + } + } + igx-icon, igx-icon[igxPrefix], igx-icon[igxSuffix] { @@ -363,9 +385,14 @@ %form-group-bundle--hover { //cursor: pointer; - &::after { - border-block-end-width: rem(1px); - border-block-end-color: var-get($theme, 'hover-bottom-line-color'); + &:has(input:not([readonly])), + &:has(textarea:not([readonly])), + &:has(input[readonly][role="combobox"]), + &:has(input[readonly][type="file"]) { + &::after { + border-block-end-width: rem(1px); + border-block-end-color: var-get($theme, 'hover-bottom-line-color'); + } } } @@ -397,10 +424,16 @@ } %form-group-bundle--error { - &::after { - border-block-end-color: var-get($theme, 'error-secondary-color'); + &:has(input:not([readonly])), + &:has(textarea:not([readonly])), + &:has(input[readonly][role="combobox"]), + &:has(input[readonly][type="file"]) { + &::after { + border-block-end-color: var-get($theme, 'error-secondary-color'); + } + + caret-color: initial; } - caret-color: initial; } %form-group-bundle--disabled { @@ -612,8 +645,7 @@ %bootstrap-file-focused, %bootstrap-file-valid, %bootstrap-file-warning, - %bootstrap-file-invalid, - { + %bootstrap-file-invalid { %form-group-bundle { border-radius: var-get($theme, 'box-border-radius'); transition: box-shadow .15s ease-out, border .15s ease-out; @@ -714,6 +746,11 @@ &:hover { background: var-get($theme, 'box-background-hover'); } + + &:has(input:read-only:not(:disabled, [role="combobox"], [type="file"])), + &:has(textarea:read-only:not(:disabled)) { + background: var-get($theme, 'box-background-focus'); + } } %form-group-bundle--box-focus { @@ -873,22 +910,27 @@ display: none; } - &:hover { - %form-group-bundle-start { - border-color: var-get($theme, 'hover-border-color'); - } + &:has(input:not([readonly])), + &:has(textarea:not([readonly])), + &:has(input[readonly][role="combobox"]), + &:has(input[readonly][type="file"]) { + &:hover { + %form-group-bundle-start { + border-color: var-get($theme, 'hover-border-color'); + } - %igx-input-group__filler { - border-color: var-get($theme, 'hover-border-color'); - } + %igx-input-group__filler { + border-color: var-get($theme, 'hover-border-color'); + } - %igx-input-group__notch { - border-block-start-color: var-get($theme, 'hover-border-color'); - border-block-end-color: var-get($theme, 'hover-border-color'); - } + %igx-input-group__notch { + border-block-start-color: var-get($theme, 'hover-border-color'); + border-block-end-color: var-get($theme, 'hover-border-color'); + } - %form-group-bundle-end { - border-color: var-get($theme, 'hover-border-color'); + %form-group-bundle-end { + border-color: var-get($theme, 'hover-border-color'); + } } } } @@ -948,8 +990,10 @@ } %form-group-bundle-search--hover { - box-shadow: var-get($theme, 'search-hover-shadow'); - border-color: var-get($theme, 'hover-border-color'); + &:has(input:not([readonly])) { + box-shadow: var-get($theme, 'search-hover-shadow'); + border-color: var-get($theme, 'hover-border-color'); + } } %form-group-bundle-search--focus { @@ -1323,11 +1367,14 @@ } %form-group-input--hover { - cursor: pointer; - color: var-get($theme, 'filled-text-hover-color'); + &:not([readonly]), + &[role="combobox"] { + cursor: pointer; + color: var-get($theme, 'filled-text-hover-color'); - &::placeholder { - color: var-get($theme, 'hover-placeholder-color'); + &::placeholder { + color: var-get($theme, 'hover-placeholder-color'); + } } } @@ -1490,29 +1537,34 @@ } %form-group-border--error { - %form-group-bundle-start { - border-inline-start-color: var-get($theme, 'error-secondary-color'); - border-block-start-color: var-get($theme, 'error-secondary-color'); - border-block-end-color: var-get($theme, 'error-secondary-color'); - } + &:has(input:not([readonly])), + &:has(textarea:not([readonly])), + &:has(input[readonly][role="combobox"]), + &:has(input[readonly][type="file"]) { + %form-group-bundle-start { + border-inline-start-color: var-get($theme, 'error-secondary-color'); + border-block-start-color: var-get($theme, 'error-secondary-color'); + border-block-end-color: var-get($theme, 'error-secondary-color'); + } - %form-group-bundle-end { - border-inline-end-color: var-get($theme, 'error-secondary-color'); - border-block-start-color: var-get($theme, 'error-secondary-color'); - border-block-end-color: var-get($theme, 'error-secondary-color'); - } + %form-group-bundle-end { + border-inline-end-color: var-get($theme, 'error-secondary-color'); + border-block-start-color: var-get($theme, 'error-secondary-color'); + border-block-end-color: var-get($theme, 'error-secondary-color'); + } - %igx-input-group__notch, - %igx-input-group__filler { - border-block-color: var-get($theme, 'error-secondary-color'); - } + %igx-input-group__notch, + %igx-input-group__filler { + border-block-color: var-get($theme, 'error-secondary-color'); + } - %form-group-bundle--border:hover { - %form-group-bundle-start, - %form-group-bundle-end, - %igx-input-group__filler, - %igx-input-group__notch { - border-color: var-get($theme, 'error-secondary-color'); + %form-group-bundle--border:hover { + %form-group-bundle-start, + %form-group-bundle-end, + %igx-input-group__filler, + %igx-input-group__notch { + border-color: var-get($theme, 'error-secondary-color'); + } } } } @@ -1656,6 +1708,19 @@ &:focus { background: var-get($theme, 'box-background-hover'); } + + &:has(input:read-only:not(:disabled, [role="combobox"], [type="file"])), + &:has(textarea:read-only:not(:disabled)) { + &:not(:focus-within) { + &::after { + border-block-end: rem(1px) solid var-get($theme, 'disabled-text-color'); + } + + &:hover { + background: unset; + } + } + } } %indigo-label--focused { @@ -1807,11 +1872,26 @@ box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'border-color'); border-radius: inherit; } + + &:has(input:read-only:not(:disabled, [role="combobox"], [type="file"])), + &:has(textarea:read-only:not(:disabled)) { + igx-prefix, + [igxPrefix], + igx-suffix, + [igxSuffix] { + background: transparent; + } + } } - %form-group-bundle--fluent--hover { - &::before { - box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'hover-border-color'); + %form-group-bundle--fluent--hover:not(:focus-within) { + &:has(input:not([readonly])), + &:has(textarea:not([readonly])), + &:has(input[readonly][role="combobox"]), + &:has(input[readonly][type="file"]) { + &::before { + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'hover-border-color'); + } } } @@ -1832,8 +1912,14 @@ %form-group-bundle-error--fluent, %form-group-bundle-error--fluent--hover, %form-group-bundle-error--fluent--focus { - &::before { - box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'error-secondary-color'); + // should be fixed + &:has(input:not([readonly])), + &:has(textarea:not([readonly])), + &:has(input[readonly][role="combobox"]), + &:has(input[readonly][type="file"]) { + &::before { + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'error-secondary-color'); + } } } @@ -2184,6 +2270,20 @@ transition: box-shadow .15s ease-out, border .15s ease-out; } } + + &:has(input:read-only:not(:disabled, [role="combobox"], [type="file"])), + &:has(textarea:read-only:not(:disabled)) { + %bootstrap-input { + background: var-get($theme, 'border-disabled-background'); + } + + igx-prefix, + [igxPrefix], + igx-suffix, + [igxSuffix] { + background: var-get($theme, 'border-disabled-background'); + } + } } %bootstrap-input, @@ -2240,13 +2340,16 @@ } %bootstrap-input--error { - border: rem(1px) solid var-get($theme, 'error-secondary-color'); + &:not([readonly]), + &[role="combobox"] { + border: rem(1px) solid var-get($theme, 'error-secondary-color'); - &:focus { - box-shadow: 0 0 0 rem(4px) var-get($theme, 'error-shadow-color'); - - + %bootstrap-file-input { + &:focus { box-shadow: 0 0 0 rem(4px) var-get($theme, 'error-shadow-color'); + + + %bootstrap-file-input { + box-shadow: 0 0 0 rem(4px) var-get($theme, 'error-shadow-color'); + } } } } From 23640e88c3be91897d1f69e25a6d84e82d71ea74 Mon Sep 17 00:00:00 2001 From: sivanova Date: Thu, 28 Aug 2025 10:38:17 +0300 Subject: [PATCH 2/7] feat(date-picker/time-picker): readonly styles --- .../date-picker/_date-picker-component.scss | 4 + .../date-picker/_date-picker-theme.scss | 91 +++++++++++++++++++ .../components/input/_input-group-theme.scss | 38 ++++---- .../time-picker/_time-picker-component.scss | 4 + .../time-picker/_time-picker-theme.scss | 91 +++++++++++++++++++ .../lib/date-picker/date-picker.component.ts | 5 +- .../lib/time-picker/time-picker.component.ts | 5 +- src/app/date-picker/date-picker.sample.html | 3 +- src/app/date-picker/date-picker.sample.ts | 13 +++ 9 files changed, 228 insertions(+), 26 deletions(-) diff --git a/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-component.scss b/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-component.scss index 6a0e62ba5de..268119fbe36 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-component.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-component.scss @@ -30,5 +30,9 @@ @include m(dropdown) { @extend %date-picker--dropdown !optional; } + + @include m(readonly) { + @extend %date-picker--readonly !optional; + } } } diff --git a/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-theme.scss index 36151648bae..625b4f8c646 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-theme.scss @@ -91,4 +91,95 @@ --component-size: var(--ig-size, #{var-get($theme, 'default-size')}) !important; } } + + %date-picker--readonly igx-input-group { + igx-prefix, + [igxPrefix], + igx-suffix, + [igxSuffix] { + color: var(--disabled-text-color); + + @if $variant == 'fluent' { + background: transparent; + } + + @if $variant == 'bootstrap' { + background: var(--border-disabled-background); + } + } + + @if $variant == 'bootstrap' { + %form-group-input { + background: var(--border-disabled-background); + } + } + + &%form-group-display--box:not(%form-group-display--disabled) { + %form-group-bundle { + background: var(--box-background-focus); + + &:hover { + &:has(input[readonly][role="combobox"])::after { + border-block-end-color: var(--idle-bottom-line-color); + } + } + } + } + + &%form-group-display--border:not(%form-group-display--disabled) { + %form-group-bundle:hover { + %form-group-bundle-start, + %igx-input-group__filler, + %form-group-bundle-end { + border-color: var(--border-color); + } + + %igx-input-group__notch { + border-block-start-color: var(--border-color); + border-block-end-color: var(--border-color); + } + } + } + + &:not(%form-group-display--disabled) { + %form-group-bundle:not(:focus-within) { + @if $variant == 'indigo' { + &::after { + border-block-end-color: var(--disabled-text-color); + } + + &:hover { + background: unset; + } + } + + &:hover:has(input[readonly][role="combobox"]) { + &::before { + @if $variant == 'fluent' { + box-shadow: inset 0 0 0 rem(1px) var(--border-color); + } + } + + &::after { + @if $variant == 'material' { + border-block-end-color: var(--border-color); + } @else if $variant == 'indigo' { + border-block-end-color: var(--disabled-text-color); + } + } + } + } + } + + &:hover { + %form-group-input--hover { + cursor: default; + color: va(--filled-text-color); + + &::placeholder { + color: var(--placeholder-color); + } + } + } + } } diff --git a/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss index 21ab1184568..1e01b124dd1 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss @@ -383,8 +383,6 @@ } %form-group-bundle--hover { - //cursor: pointer; - &:has(input:not([readonly])), &:has(textarea:not([readonly])), &:has(input[readonly][role="combobox"]), @@ -397,16 +395,21 @@ } %form-group-bundle--focus { - &::after { - @if $variant != 'indigo' { - border-block-end-width: rem(2px); + &:has(input:not([readonly])), + &:has(textarea:not([readonly])), + &:has(input[readonly][role="combobox"]), + &:has(input[readonly][type="file"]) { + &::after { + @if $variant != 'indigo' { + border-block-end-width: rem(2px); + } + border-block-end-color: var-get($theme, 'focused-bottom-line-color'); } - border-block-end-color: var-get($theme, 'focused-bottom-line-color'); - } - @if $variant == 'indigo' { - caret-color: var-get($theme, 'focused-bottom-line-color'); - } + @if $variant == 'indigo' { + caret-color: var-get($theme, 'focused-bottom-line-color'); + } + } } %form-group-bundle--success { @@ -915,11 +918,9 @@ &:has(input[readonly][role="combobox"]), &:has(input[readonly][type="file"]) { &:hover { - %form-group-bundle-start { - border-color: var-get($theme, 'hover-border-color'); - } - - %igx-input-group__filler { + %form-group-bundle-start, + %igx-input-group__filler, + %form-group-bundle-end { border-color: var-get($theme, 'hover-border-color'); } @@ -927,10 +928,6 @@ border-block-start-color: var-get($theme, 'hover-border-color'); border-block-end-color: var-get($theme, 'hover-border-color'); } - - %form-group-bundle-end { - border-color: var-get($theme, 'hover-border-color'); - } } } } @@ -1909,10 +1906,9 @@ } } - %form-group-bundle-error--fluent, + %form-group-bundle-error--fluent:not(:focus-within), %form-group-bundle-error--fluent--hover, %form-group-bundle-error--fluent--focus { - // should be fixed &:has(input:not([readonly])), &:has(textarea:not([readonly])), &:has(input[readonly][role="combobox"]), diff --git a/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-component.scss b/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-component.scss index 7c574c4ce59..fb3b6bace46 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-component.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-component.scss @@ -104,5 +104,9 @@ @extend %time-picker__buttons--vertical !optional; } } + + @include m(readonly) { + @extend %time-picker-display--readonly !optional; + } } } diff --git a/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-theme.scss index 9a661698792..3deebc470c6 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-theme.scss @@ -244,6 +244,97 @@ %time-picker__buttons--vertical { align-items: flex-end; } + + %time-picker-display--readonly igx-input-group { + igx-prefix, + [igxPrefix], + igx-suffix, + [igxSuffix] { + color: var(--disabled-text-color); + + @if $variant == 'fluent' { + background: transparent; + } + + @if $variant == 'bootstrap' { + background: var(--border-disabled-background); + } + } + + @if $variant == 'bootstrap' { + %form-group-input { + background: var(--border-disabled-background); + } + } + + &%form-group-display--box:not(%form-group-display--disabled) { + %form-group-bundle { + background: var(--box-background-focus); + + &:hover { + &:has(input[readonly][role="combobox"])::after { + border-block-end-color: var(--idle-bottom-line-color); + } + } + } + } + + &%form-group-display--border:not(%form-group-display--disabled) { + %form-group-bundle:hover { + %form-group-bundle-start, + %igx-input-group__filler, + %form-group-bundle-end { + border-color: var(--border-color); + } + + %igx-input-group__notch { + border-block-start-color: var(--border-color); + border-block-end-color: var(--border-color); + } + } + } + + &:not(%form-group-display--disabled) { + %form-group-bundle:not(:focus-within) { + @if $variant == 'indigo' { + &::after { + border-block-end-color: var(--disabled-text-color); + } + + &:hover { + background: unset; + } + } + + &:hover:has(input[readonly][role="combobox"]) { + &::before { + @if $variant == 'fluent' { + box-shadow: inset 0 0 0 rem(1px) var(--border-color); + } + } + + &::after { + @if $variant == 'material' { + border-block-end-color: var(--border-color); + } @else if $variant == 'indigo' { + border-block-end-color: var(--disabled-text-color); + } + } + } + } + } + + &:hover { + %form-group-input--hover { + cursor: default; + color: va(--filled-text-color); + + &::placeholder { + color: var(--placeholder-color); + } + } + } + } } /// Adds typography styles for the igx-calendar component. diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts index a3a6935af7d..4431335c782 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts @@ -372,6 +372,7 @@ export class IgxDatePickerComponent extends PickerBaseDirective implements Contr public resourceStrings: IDatePickerResourceStrings; /** @hidden @internal */ + @HostBinding('class.igx-date-picker--readonly') @Input({ transform: booleanAttribute }) public readOnly = false; @@ -571,7 +572,7 @@ export class IgxDatePickerComponent extends PickerBaseDirective implements Contr * ``` */ public open(settings?: OverlaySettings): void { - if (!this.collapsed || this.disabled) { + if (!this.collapsed || this.disabled || this.readOnly) { return; } @@ -669,7 +670,7 @@ export class IgxDatePickerComponent extends PickerBaseDirective implements Contr * ``` */ public clear(): void { - if (!this.disabled) { + if (!this.disabled || !this.readOnly) { this._calendar?.deselectDate(); this.dateTimeEditor.clear(); } diff --git a/projects/igniteui-angular/src/lib/time-picker/time-picker.component.ts b/projects/igniteui-angular/src/lib/time-picker/time-picker.component.ts index c5174302fec..eb875fec39c 100644 --- a/projects/igniteui-angular/src/lib/time-picker/time-picker.component.ts +++ b/projects/igniteui-angular/src/lib/time-picker/time-picker.component.ts @@ -253,6 +253,7 @@ export class IgxTimePickerComponent extends PickerBaseDirective public headerOrientation: PickerHeaderOrientation = PickerHeaderOrientation.Horizontal; /** @hidden @internal */ + @HostBinding('class.igx-time-picker--readonly') @Input({ transform: booleanAttribute }) public readOnly = false; @@ -780,7 +781,7 @@ export class IgxTimePickerComponent extends PickerBaseDirective * ``` */ public open(settings?: OverlaySettings): void { - if (this.disabled || !this.toggleRef.collapsed) { + if (this.disabled || !this.toggleRef.collapsed || this.readOnly) { return; } @@ -824,7 +825,7 @@ export class IgxTimePickerComponent extends PickerBaseDirective * ``` */ public clear(): void { - if (this.disabled) { + if (this.disabled || this.readOnly) { return; } diff --git a/src/app/date-picker/date-picker.sample.html b/src/app/date-picker/date-picker.sample.html index 2e52f629db1..ded04c6a749 100644 --- a/src/app/date-picker/date-picker.sample.html +++ b/src/app/date-picker/date-picker.sample.html @@ -3,11 +3,12 @@
Angular Date Picker
Date: Thu, 28 Aug 2025 14:44:58 +0300 Subject: [PATCH 3/7] refactor(input-group): add input read only directive Adds the ability to apply and override the read-only state of an input group via a CSS class. --- .../date-picker/date-picker.component.html | 4 ++- .../lib/date-picker/date-picker.component.ts | 2 ++ .../input/readOnlyInput.directive.ts | 26 +++++++++++++++++++ .../lib/input-group/input-group.component.ts | 12 +++++++++ 4 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 projects/igniteui-angular/src/lib/directives/input/readOnlyInput.directive.ts diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html index 81159a032bd..551816ddb1c 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.html @@ -14,7 +14,9 @@ } - (false); + + private _inputGroup: IgxInputGroupComponent | null = inject( + IgxInputGroupComponent, + { + optional: true + } + ); + + constructor() { + effect(() => { + if (this._inputGroup) { + this._inputGroup.readOnly = this.igxReadOnlyInput(); + } + }); + } +} diff --git a/projects/igniteui-angular/src/lib/input-group/input-group.component.ts b/projects/igniteui-angular/src/lib/input-group/input-group.component.ts index 4e2140a5345..86a739ffa42 100644 --- a/projects/igniteui-angular/src/lib/input-group/input-group.component.ts +++ b/projects/igniteui-angular/src/lib/input-group/input-group.component.ts @@ -126,6 +126,18 @@ export class IgxInputGroupComponent implements IgxInputGroupBase, AfterContentCh private _filled = false; private _theme: IgxTheme; private _resourceStrings = getCurrentResourceStrings(InputResourceStringsEN); + private _readOnly: undefined | boolean; + + /** @hidden @internal */ + @HostBinding('class.igx-input-group--readonly') + public get readOnly(): boolean { + return this._readOnly ?? (this.input?.nativeElement.readOnly || false); + } + + /** @hidden @internal */ + public set readOnly(value: boolean) { + this._readOnly = value; + } /** @hidden */ @HostBinding('class.igx-input-group--valid') From b33b1e15a8dbab73810f609cee6695f98a972061 Mon Sep 17 00:00:00 2001 From: sivanova Date: Fri, 29 Aug 2025 10:21:25 +0300 Subject: [PATCH 4/7] refactor(input-group): read-only styles using new directive --- .../date-picker/_date-picker-component.scss | 4 - .../date-picker/_date-picker-theme.scss | 91 ----- .../input/_input-group-component.scss | 16 +- .../components/input/_input-group-theme.scss | 365 +++++++++--------- .../time-picker/_time-picker-component.scss | 4 - .../time-picker/_time-picker-theme.scss | 91 ----- .../lib/date-picker/date-picker.component.ts | 1 - .../date-range-picker.component.html | 2 +- .../date-range-picker.component.ts | 8 +- .../time-picker/time-picker.component.html | 2 +- .../lib/time-picker/time-picker.component.ts | 4 +- 11 files changed, 202 insertions(+), 386 deletions(-) diff --git a/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-component.scss b/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-component.scss index 268119fbe36..6a0e62ba5de 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-component.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-component.scss @@ -30,9 +30,5 @@ @include m(dropdown) { @extend %date-picker--dropdown !optional; } - - @include m(readonly) { - @extend %date-picker--readonly !optional; - } } } diff --git a/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-theme.scss index 625b4f8c646..36151648bae 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/date-picker/_date-picker-theme.scss @@ -91,95 +91,4 @@ --component-size: var(--ig-size, #{var-get($theme, 'default-size')}) !important; } } - - %date-picker--readonly igx-input-group { - igx-prefix, - [igxPrefix], - igx-suffix, - [igxSuffix] { - color: var(--disabled-text-color); - - @if $variant == 'fluent' { - background: transparent; - } - - @if $variant == 'bootstrap' { - background: var(--border-disabled-background); - } - } - - @if $variant == 'bootstrap' { - %form-group-input { - background: var(--border-disabled-background); - } - } - - &%form-group-display--box:not(%form-group-display--disabled) { - %form-group-bundle { - background: var(--box-background-focus); - - &:hover { - &:has(input[readonly][role="combobox"])::after { - border-block-end-color: var(--idle-bottom-line-color); - } - } - } - } - - &%form-group-display--border:not(%form-group-display--disabled) { - %form-group-bundle:hover { - %form-group-bundle-start, - %igx-input-group__filler, - %form-group-bundle-end { - border-color: var(--border-color); - } - - %igx-input-group__notch { - border-block-start-color: var(--border-color); - border-block-end-color: var(--border-color); - } - } - } - - &:not(%form-group-display--disabled) { - %form-group-bundle:not(:focus-within) { - @if $variant == 'indigo' { - &::after { - border-block-end-color: var(--disabled-text-color); - } - - &:hover { - background: unset; - } - } - - &:hover:has(input[readonly][role="combobox"]) { - &::before { - @if $variant == 'fluent' { - box-shadow: inset 0 0 0 rem(1px) var(--border-color); - } - } - - &::after { - @if $variant == 'material' { - border-block-end-color: var(--border-color); - } @else if $variant == 'indigo' { - border-block-end-color: var(--disabled-text-color); - } - } - } - } - } - - &:hover { - %form-group-input--hover { - cursor: default; - color: va(--filled-text-color); - - &::placeholder { - color: var(--placeholder-color); - } - } - } - } } diff --git a/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-component.scss b/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-component.scss index 00062ada101..bf077148fc2 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-component.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-component.scss @@ -42,11 +42,11 @@ } @include e(notch) { - @extend %igx-input-group__notch !optional; + @extend %igx-input-group__notch !optional; } @include e(filler) { - @extend %igx-input-group__filler !optional; + @extend %igx-input-group__filler !optional; } @include e(input) { @@ -111,20 +111,24 @@ @extend %suffixed !optional; } + @include m(readonly) { + @extend %form-group-display--readonly !optional; + } + // Textarea modifier @include m(textarea-group) { @extend %textarea-group !optional; @include e(bundle-main) { - @extend %form-group-textarea-group-bundle-main !optional; + @extend %form-group-textarea-group-bundle-main !optional; } @include e(bundle) { - @extend %form-group-textarea-group-bundle !optional; + @extend %form-group-textarea-group-bundle !optional; } @include e(label) { - @extend %form-group-textarea-label !optional; + @extend %form-group-textarea-label !optional; } } @@ -282,6 +286,8 @@ } @include m(invalid) { + @extend %form-group-display--invalid !optional; + @include e(label) { @extend %form-group-label--error !optional; } diff --git a/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss index 853c7802a7a..05b21fa297c 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/input/_input-group-theme.scss @@ -202,28 +202,6 @@ -webkit-appearance: none; } - &:has(input:read-only:not(:disabled, [role="combobox"], [type="file"])), - &:has(textarea:read-only:not(:disabled)) { - igx-prefix, - [igxPrefix], - igx-suffix, - [igxSuffix] { - color: var-get($theme, 'disabled-text-color'); - } - - %form-group-label { - color: var-get($theme, 'idle-secondary-color'); - } - - %form-group-line { - background: var-get($theme, 'focused-secondary-color'); - } - - %form-group-helper { - color: var-get($theme, 'helper-text-color'); - } - } - igx-icon, igx-icon[igxPrefix], igx-icon[igxSuffix] { @@ -308,6 +286,91 @@ } } + %form-group-display--readonly:not(%form-group-display--file) { + igx-prefix, + [igxPrefix], + igx-suffix, + [igxSuffix] { + color: var-get($theme, 'disabled-text-color'); + + @if $variant == 'fluent' { + background: transparent; + } + + @if $variant == 'bootstrap' { + background: var-get($theme, 'border-disabled-background'); + } + } + + @if $variant == 'bootstrap' { + %form-group-input { + background: var-get($theme, 'border-disabled-background'); + } + } + + %form-group-bundle--hover::after { + @if $variant == 'material' { + border-block-end-color: var-get($theme, 'idle-bottom-line-color'); + } + } + + @if $variant == 'indigo' { + %form-group-bundle--hover:not(:focus-within) { + background: unset; + + &::after { + border-block-end-color: var-get($theme, 'disabled-text-color'); + } + } + } + + &%igx-input-group-fluent:not(:focus-within) { + %form-group-bundle--hover::before { + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'border-color'); + } + } + + &%form-group-display--box:not(%form-group-display--disabled) { + %form-group-bundle { + background: var-get($theme, 'box-background-focus'); + } + } + + &%form-group-display--border:not(%form-group-display--disabled) { + %form-group-bundle:hover:not(:focus-within) { + %form-group-bundle-start, + %igx-input-group__filler, + %form-group-bundle-end { + border-color: var-get($theme, 'border-color'); + } + + %igx-input-group__notch { + border-block-start-color: var-get($theme, 'border-color'); + border-block-end-color: var-get($theme, 'border-color'); + } + } + } + + &%form-group-display--search { + %form-group-bundle-search--hover:not(:focus-within) { + box-shadow: var-get($theme, 'search-resting-shadow'); + } + } + + &:hover { + %form-group-input--hover { + cursor: default; + color: var-get($theme, 'filled-text-color'); + + &:not(:focus-within) { + &::placeholder { + color: var-get($theme, 'placeholder-color'); + } + } + } + } + } + %form-group-display--disabled { pointer-events: none; user-select: none; @@ -383,33 +446,23 @@ } %form-group-bundle--hover { - &:has(input:not([readonly])), - &:has(textarea:not([readonly])), - &:has(input[readonly][role="combobox"]), - &:has(input[readonly][type="file"]) { - &::after { - border-block-end-width: rem(1px); - border-block-end-color: var-get($theme, 'hover-bottom-line-color'); - } + &::after { + border-block-end-width: rem(1px); + border-block-end-color: var-get($theme, 'hover-bottom-line-color'); } } %form-group-bundle--focus { - &:has(input:not([readonly])), - &:has(textarea:not([readonly])), - &:has(input[readonly][role="combobox"]), - &:has(input[readonly][type="file"]) { - &::after { - @if $variant != 'indigo' { - border-block-end-width: rem(2px); - } - border-block-end-color: var-get($theme, 'focused-bottom-line-color'); + &::after { + @if $variant != 'indigo' { + border-block-end-width: rem(2px); } + border-block-end-color: var-get($theme, 'focused-bottom-line-color'); + } - @if $variant == 'indigo' { - caret-color: var-get($theme, 'focused-bottom-line-color'); - } - } + @if $variant == 'indigo' { + caret-color: var-get($theme, 'focused-bottom-line-color'); + } } %form-group-bundle--success { @@ -426,19 +479,6 @@ caret-color: initial; } - %form-group-bundle--error { - &:has(input:not([readonly])), - &:has(textarea:not([readonly])), - &:has(input[readonly][role="combobox"]), - &:has(input[readonly][type="file"]) { - &::after { - border-block-end-color: var-get($theme, 'error-secondary-color'); - } - - caret-color: initial; - } - } - %form-group-bundle--disabled { cursor: default; @@ -781,11 +821,6 @@ &:hover { background: var-get($theme, 'box-background-hover'); } - - &:has(input:read-only:not(:disabled, [role="combobox"], [type="file"])), - &:has(textarea:read-only:not(:disabled)) { - background: var-get($theme, 'box-background-focus'); - } } %form-group-bundle--box-focus { @@ -945,21 +980,16 @@ display: none; } - &:has(input:not([readonly])), - &:has(textarea:not([readonly])), - &:has(input[readonly][role="combobox"]), - &:has(input[readonly][type="file"]) { - &:hover { - %form-group-bundle-start, - %igx-input-group__filler, - %form-group-bundle-end { - border-color: var-get($theme, 'hover-border-color'); - } + &:hover { + %form-group-bundle-start, + %igx-input-group__filler, + %form-group-bundle-end { + border-color: var-get($theme, 'hover-border-color'); + } - %igx-input-group__notch { - border-block-start-color: var-get($theme, 'hover-border-color'); - border-block-end-color: var-get($theme, 'hover-border-color'); - } + %igx-input-group__notch { + border-block-start-color: var-get($theme, 'hover-border-color'); + border-block-end-color: var-get($theme, 'hover-border-color'); } } } @@ -1019,10 +1049,8 @@ } %form-group-bundle-search--hover { - &:has(input:not([readonly])) { - box-shadow: var-get($theme, 'search-hover-shadow'); - border-color: var-get($theme, 'hover-border-color'); - } + box-shadow: var-get($theme, 'search-hover-shadow'); + border-color: var-get($theme, 'hover-border-color'); } %form-group-bundle-search--focus { @@ -1283,10 +1311,6 @@ color: var-get($theme, 'success-secondary-color'); } - %form-group-label--error { - color: var-get($theme, 'error-secondary-color'); - } - %form-group-label--required { &::after { content: '#{$required-symbol}'; @@ -1396,14 +1420,11 @@ } %form-group-input--hover { - &:not([readonly]), - &[role="combobox"] { - cursor: pointer; - color: var-get($theme, 'filled-text-hover-color'); + cursor: pointer; + color: var-get($theme, 'filled-text-hover-color'); - &::placeholder { - color: var-get($theme, 'hover-placeholder-color'); - } + &::placeholder { + color: var-get($theme, 'hover-placeholder-color'); } } @@ -1561,39 +1582,31 @@ } } - %form-group-line--error { - background: var-get($theme, 'error-secondary-color'); - } - - %form-group-border--error { - &:has(input:not([readonly])), - &:has(textarea:not([readonly])), - &:has(input[readonly][role="combobox"]), - &:has(input[readonly][type="file"]) { - %form-group-bundle-start { - border-inline-start-color: var-get($theme, 'error-secondary-color'); - border-block-start-color: var-get($theme, 'error-secondary-color'); - border-block-end-color: var-get($theme, 'error-secondary-color'); - } + %form-group-border--error:not(%form-group-display--readonly), + %form-group-border--error%form-group-display--file { + %form-group-bundle-start { + border-inline-start-color: var-get($theme, 'error-secondary-color'); + border-block-start-color: var-get($theme, 'error-secondary-color'); + border-block-end-color: var-get($theme, 'error-secondary-color'); + } - %form-group-bundle-end { - border-inline-end-color: var-get($theme, 'error-secondary-color'); - border-block-start-color: var-get($theme, 'error-secondary-color'); - border-block-end-color: var-get($theme, 'error-secondary-color'); - } + %form-group-bundle-end { + border-inline-end-color: var-get($theme, 'error-secondary-color'); + border-block-start-color: var-get($theme, 'error-secondary-color'); + border-block-end-color: var-get($theme, 'error-secondary-color'); + } - %igx-input-group__notch, - %igx-input-group__filler { - border-block-color: var-get($theme, 'error-secondary-color'); - } + %igx-input-group__notch, + %igx-input-group__filler { + border-block-color: var-get($theme, 'error-secondary-color'); + } - %form-group-bundle--border:hover { - %form-group-bundle-start, - %form-group-bundle-end, - %igx-input-group__filler, - %igx-input-group__notch { - border-color: var-get($theme, 'error-secondary-color'); - } + %form-group-bundle--border:hover { + %form-group-bundle-start, + %form-group-bundle-end, + %igx-input-group__filler, + %igx-input-group__notch { + border-color: var-get($theme, 'error-secondary-color'); } } } @@ -1660,10 +1673,6 @@ %form-group-helper--warning { color: var-get($theme, 'warning-secondary-color'); } - - %form-group-helper--error { - color: var-get($theme, 'error-secondary-color'); - } } %form-group-helper-item { @@ -1737,19 +1746,6 @@ &:focus { background: var-get($theme, 'box-background-hover'); } - - &:has(input:read-only:not(:disabled, [role="combobox"], [type="file"])), - &:has(textarea:read-only:not(:disabled)) { - &:not(:focus-within) { - &::after { - border-block-end: rem(1px) solid var-get($theme, 'disabled-text-color'); - } - - &:hover { - background: unset; - } - } - } } %indigo-label--focused { @@ -1901,26 +1897,11 @@ box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'border-color'); border-radius: inherit; } - - &:has(input:read-only:not(:disabled, [role="combobox"], [type="file"])), - &:has(textarea:read-only:not(:disabled)) { - igx-prefix, - [igxPrefix], - igx-suffix, - [igxSuffix] { - background: transparent; - } - } } - %form-group-bundle--fluent--hover:not(:focus-within) { - &:has(input:not([readonly])), - &:has(textarea:not([readonly])), - &:has(input[readonly][role="combobox"]), - &:has(input[readonly][type="file"]) { - &::before { - box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'hover-border-color'); - } + %form-group-bundle--fluent--hover { + &::before { + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'hover-border-color'); } } @@ -1938,19 +1919,6 @@ } } - %form-group-bundle-error--fluent:not(:focus-within), - %form-group-bundle-error--fluent--hover, - %form-group-bundle-error--fluent--focus { - &:has(input:not([readonly])), - &:has(textarea:not([readonly])), - &:has(input[readonly][role="combobox"]), - &:has(input[readonly][type="file"]) { - &::before { - box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'error-secondary-color'); - } - } - } - %form-group-bundle-success--fluent, %form-group-bundle-success--fluent--hover, %form-group-bundle-success--fluent--focus { @@ -1980,6 +1948,48 @@ } } + %form-group-display--invalid:not(%form-group-display--readonly), + %form-group-display--invalid%form-group-display--file { + @if $variant != 'indigo' { + %form-group-label--error, + %form-group-helper--error { + color: var-get($theme, 'error-secondary-color'); + } + } + + %form-group-line--error { + background: var-get($theme, 'error-secondary-color'); + } + + %form-group-bundle--error { + &::after { + border-block-end-color: var-get($theme, 'error-secondary-color'); + } + + caret-color: initial; + } + + &%form-group-display--bootstrap { + %bootstrap-input--error { + border: rem(1px) solid var-get($theme, 'error-secondary-color'); + + &:focus { + box-shadow: 0 0 0 rem(4px) var-get($theme, 'error-shadow-color'); + } + } + } + + &%igx-input-group-fluent { + %form-group-bundle-error--fluent, + %form-group-bundle-error--fluent--hover, + %form-group-bundle-error--fluent--focus { + &::before { + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'error-secondary-color'); + } + } + } + } + // Native input %fluent-input { font-size: rem(14px); @@ -2293,20 +2303,6 @@ transition: box-shadow .15s ease-out, border .15s ease-out; } } - - &:has(input:read-only:not(:disabled, [role="combobox"], [type="file"])), - &:has(textarea:read-only:not(:disabled)) { - %bootstrap-input { - background: var-get($theme, 'border-disabled-background'); - } - - igx-prefix, - [igxPrefix], - igx-suffix, - [igxSuffix] { - background: var-get($theme, 'border-disabled-background'); - } - } } %bootstrap-input, @@ -2362,9 +2358,8 @@ box-shadow: 0 0 0 rem(4px) color($color: 'warn', $variant: '500', $opacity: .38); } - %bootstrap-input--error { - &:not([readonly]), - &[role="combobox"] { + %form-group-display:not(%form-group-display--file) { + %bootstrap-input--error { border: rem(1px) solid var-get($theme, 'error-secondary-color'); &:focus { diff --git a/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-component.scss b/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-component.scss index fb3b6bace46..7c574c4ce59 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-component.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-component.scss @@ -104,9 +104,5 @@ @extend %time-picker__buttons--vertical !optional; } } - - @include m(readonly) { - @extend %time-picker-display--readonly !optional; - } } } diff --git a/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-theme.scss index 3deebc470c6..9a661698792 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/time-picker/_time-picker-theme.scss @@ -244,97 +244,6 @@ %time-picker__buttons--vertical { align-items: flex-end; } - - %time-picker-display--readonly igx-input-group { - igx-prefix, - [igxPrefix], - igx-suffix, - [igxSuffix] { - color: var(--disabled-text-color); - - @if $variant == 'fluent' { - background: transparent; - } - - @if $variant == 'bootstrap' { - background: var(--border-disabled-background); - } - } - - @if $variant == 'bootstrap' { - %form-group-input { - background: var(--border-disabled-background); - } - } - - &%form-group-display--box:not(%form-group-display--disabled) { - %form-group-bundle { - background: var(--box-background-focus); - - &:hover { - &:has(input[readonly][role="combobox"])::after { - border-block-end-color: var(--idle-bottom-line-color); - } - } - } - } - - &%form-group-display--border:not(%form-group-display--disabled) { - %form-group-bundle:hover { - %form-group-bundle-start, - %igx-input-group__filler, - %form-group-bundle-end { - border-color: var(--border-color); - } - - %igx-input-group__notch { - border-block-start-color: var(--border-color); - border-block-end-color: var(--border-color); - } - } - } - - &:not(%form-group-display--disabled) { - %form-group-bundle:not(:focus-within) { - @if $variant == 'indigo' { - &::after { - border-block-end-color: var(--disabled-text-color); - } - - &:hover { - background: unset; - } - } - - &:hover:has(input[readonly][role="combobox"]) { - &::before { - @if $variant == 'fluent' { - box-shadow: inset 0 0 0 rem(1px) var(--border-color); - } - } - - &::after { - @if $variant == 'material' { - border-block-end-color: var(--border-color); - } @else if $variant == 'indigo' { - border-block-end-color: var(--disabled-text-color); - } - } - } - } - } - - &:hover { - %form-group-input--hover { - cursor: default; - color: va(--filled-text-color); - - &::placeholder { - color: var(--placeholder-color); - } - } - } - } } /// Adds typography styles for the igx-calendar component. diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts index 29f900862e9..6c0834299db 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts @@ -388,7 +388,6 @@ export class IgxDatePickerComponent extends PickerBaseDirective implements Contr public resourceStrings: IDatePickerResourceStrings; /** @hidden @internal */ - @HostBinding('class.igx-date-picker--readonly') @Input({ transform: booleanAttribute }) public readOnly = false; diff --git a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.html b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.html index ef9c89352b7..e661900d62d 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.html +++ b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.html @@ -24,7 +24,7 @@ - diff --git a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts index 896da542e17..8285ffbf184 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts +++ b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts @@ -37,6 +37,7 @@ import { getCurrentResourceStrings } from '../core/i18n/resources'; import { fadeIn, fadeOut } from 'igniteui-angular/animations'; import { PickerCalendarOrientation } from '../date-common/types'; import { calendarRange, isDateInRanges } from '../calendar/common/helpers'; +import { IgxReadOnlyInputDirective } from '../directives/input/readOnlyInput.directive'; const SingleInputDatesConcatenationString = ' - '; @@ -75,6 +76,7 @@ const SingleInputDatesConcatenationString = ' - '; IgxInputGroupComponent, IgxInputDirective, IgxPrefixDirective, + IgxReadOnlyInputDirective, DateRangePickerFormatPipe ] }) @@ -350,6 +352,10 @@ export class IgxDateRangePickerComponent extends PickerBaseDirective @Input({ transform: booleanAttribute }) public showWeekNumbers = false; + /** @hidden @internal */ + @Input({ transform: booleanAttribute }) + public readOnly = false; + /** * Emitted when the picker's value changes. Used for two-way binding. * @@ -642,7 +648,7 @@ export class IgxDateRangePickerComponent extends PickerBaseDirective * ``` */ public open(overlaySettings?: OverlaySettings): void { - if (!this.collapsed || this.disabled) { + if (!this.collapsed || this.disabled || this.readOnly) { return; } diff --git a/projects/igniteui-angular/src/lib/time-picker/time-picker.component.html b/projects/igniteui-angular/src/lib/time-picker/time-picker.component.html index c0358f97a63..1c1cc42d568 100644 --- a/projects/igniteui-angular/src/lib/time-picker/time-picker.component.html +++ b/projects/igniteui-angular/src/lib/time-picker/time-picker.component.html @@ -1,5 +1,5 @@ - string; /** @hidden @internal */ - @HostBinding('class.igx-time-picker--readonly') @Input({ transform: booleanAttribute }) public readOnly = false; From c95f4bab40c162812d7f016a230f5330a7c5b655 Mon Sep 17 00:00:00 2001 From: sivanova Date: Fri, 29 Aug 2025 10:53:07 +0300 Subject: [PATCH 5/7] refactor(input-group): update directive name --- projects/igniteui-angular/src/lib/combo/combo.component.html | 2 +- projects/igniteui-angular/src/lib/combo/combo.component.ts | 2 ++ .../src/lib/date-picker/date-picker.component.ts | 2 +- .../src/lib/date-range-picker/date-range-picker.component.ts | 2 +- ...readOnlyInput.directive.ts => read-only-input.directive.ts} | 0 projects/igniteui-angular/src/lib/select/select.component.html | 1 + projects/igniteui-angular/src/lib/select/select.component.ts | 3 ++- .../src/lib/time-picker/time-picker.component.ts | 2 +- 8 files changed, 9 insertions(+), 5 deletions(-) rename projects/igniteui-angular/src/lib/directives/input/{readOnlyInput.directive.ts => read-only-input.directive.ts} (100%) diff --git a/projects/igniteui-angular/src/lib/combo/combo.component.html b/projects/igniteui-angular/src/lib/combo/combo.component.html index 9e795a6f3d3..9fa321d2514 100644 --- a/projects/igniteui-angular/src/lib/combo/combo.component.html +++ b/projects/igniteui-angular/src/lib/combo/combo.component.html @@ -9,7 +9,7 @@ , set2: Set): any[] => { IgxComboAddItemComponent, IgxButtonDirective, IgxRippleDirective, + IgxReadOnlyInputDirective, IgxComboFilteringPipe, IgxComboGroupingPipe ] diff --git a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts index a8a13e2bdc5..76636ab7e5d 100644 --- a/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts +++ b/projects/igniteui-angular/src/lib/date-picker/date-picker.component.ts @@ -66,7 +66,7 @@ import { IgxTextSelectionDirective } from '../directives/text-selection/text-sel import { getCurrentResourceStrings } from '../core/i18n/resources'; import { fadeIn, fadeOut } from 'igniteui-angular/animations'; import { PickerCalendarOrientation } from '../date-common/types'; -import { IgxReadOnlyInputDirective } from '../directives/input/readOnlyInput.directive'; +import { IgxReadOnlyInputDirective } from '../directives/input/read-only-input.directive'; let NEXT_ID = 0; diff --git a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts index 833bfa515a3..46347ae67c4 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts +++ b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker.component.ts @@ -37,7 +37,7 @@ import { getCurrentResourceStrings } from '../core/i18n/resources'; import { fadeIn, fadeOut } from 'igniteui-angular/animations'; import { PickerCalendarOrientation } from '../date-common/types'; import { calendarRange, isDateInRanges } from '../calendar/common/helpers'; -import { IgxReadOnlyInputDirective } from '../directives/input/readOnlyInput.directive'; +import { IgxReadOnlyInputDirective } from '../directives/input/read-only-input.directive'; const SingleInputDatesConcatenationString = ' - '; diff --git a/projects/igniteui-angular/src/lib/directives/input/readOnlyInput.directive.ts b/projects/igniteui-angular/src/lib/directives/input/read-only-input.directive.ts similarity index 100% rename from projects/igniteui-angular/src/lib/directives/input/readOnlyInput.directive.ts rename to projects/igniteui-angular/src/lib/directives/input/read-only-input.directive.ts diff --git a/projects/igniteui-angular/src/lib/select/select.component.html b/projects/igniteui-angular/src/lib/select/select.component.html index b450ccf0bfe..46a8a63c0b5 100644 --- a/projects/igniteui-angular/src/lib/select/select.component.html +++ b/projects/igniteui-angular/src/lib/select/select.component.html @@ -8,6 +8,7 @@ Date: Tue, 2 Sep 2025 09:57:54 +0300 Subject: [PATCH 6/7] test(input-group): covering the newly added readonly directive --- .../input/read-only-input.directive.spec.ts | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 projects/igniteui-angular/src/lib/directives/input/read-only-input.directive.spec.ts diff --git a/projects/igniteui-angular/src/lib/directives/input/read-only-input.directive.spec.ts b/projects/igniteui-angular/src/lib/directives/input/read-only-input.directive.spec.ts new file mode 100644 index 00000000000..43f7b4edfc0 --- /dev/null +++ b/projects/igniteui-angular/src/lib/directives/input/read-only-input.directive.spec.ts @@ -0,0 +1,61 @@ +import { Component, ViewChild } from '@angular/core'; +import { TestBed, waitForAsync } from '@angular/core/testing'; +import { NoopAnimationsModule } from '@angular/platform-browser/animations'; +import { IgxReadOnlyInputDirective } from './read-only-input.directive'; +import { IgxDatePickerComponent, IgxInputGroupComponent } from 'igniteui-angular'; +import { By } from '@angular/platform-browser'; + +describe('IgxReadOnlyInputDirective', () => { + beforeEach(waitForAsync(() => { + TestBed.configureTestingModule({ + imports: [ + NoopAnimationsModule, + TestComponent + ] + }) + .compileComponents(); + })); + + it('should update readOnly property and `igx-input-group--readonly` class correctly', () => { + const fixture = TestBed.createComponent(TestComponent); + fixture.detectChanges(); + + const inputGroupDebug = fixture.debugElement.query(By.directive(IgxInputGroupComponent)); + const inputGroupEl = inputGroupDebug.nativeElement as HTMLElement; + expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBeFalse(); + + const inputDebug = fixture.debugElement.query(By.css('input')); + const inputEl = inputDebug.nativeElement as HTMLInputElement; + expect(inputEl.readOnly).toBeFalse(); + + fixture.componentInstance.datePicker.readOnly = true; + fixture.detectChanges(); + expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBeTrue(); + expect(inputEl.readOnly).toBeTrue(); + + fixture.componentInstance.datePicker.readOnly = false; + fixture.detectChanges(); + expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBeFalse(); + expect(inputEl.readOnly).toBeFalse(); + + // When the date-picker component is in dialog mode, the native input is always readonly + fixture.componentInstance.datePicker.mode = 'dialog'; + fixture.detectChanges(); + expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBeFalse(); + expect(inputEl.readOnly).toBeTrue(); + + fixture.componentInstance.datePicker.readOnly = true; + fixture.detectChanges(); + expect(inputGroupEl.classList.contains('igx-input-group--readonly')).toBeTrue(); + expect(inputEl.readOnly).toBeTrue(); + }); +}); + +@Component({ + template: ``, + imports: [IgxDatePickerComponent, IgxReadOnlyInputDirective] +}) +class TestComponent { + @ViewChild(IgxDatePickerComponent, { static: true }) + public datePicker!: IgxDatePickerComponent; +} From 3936cf43cff12e856dbef2b72f8773d31ab5325c Mon Sep 17 00:00:00 2001 From: sivanova Date: Wed, 3 Sep 2025 10:47:03 +0300 Subject: [PATCH 7/7] fix(date-picker/time-picker): remove default readonly state --- .../lib/grids/filtering/base/grid-filtering-row.component.html | 2 -- .../excel-style/excel-style-date-expression.component.html | 2 -- .../src/lib/query-builder/query-builder-tree.component.html | 2 -- 3 files changed, 6 deletions(-) diff --git a/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.html b/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.html index 48bf1c5c0a1..ce397fa1313 100644 --- a/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.html +++ b/projects/igniteui-angular/src/lib/grids/filtering/base/grid-filtering-row.component.html @@ -60,7 +60,6 @@