From 1ad86a7b31e88a9b1c70bded8e57f3a6d2cbbddd Mon Sep 17 00:00:00 2001 From: desig9stein Date: Thu, 26 Jun 2025 10:28:06 +0300 Subject: [PATCH 01/15] refactor(input-group): update file upload style implementation --- .../input/_input-group-component.scss | 96 +++++ .../components/input/_input-group-theme.scss | 358 ++++++++++++++++-- .../input-group/input-group.component.html | 17 +- .../lib/input-group/input-group.component.ts | 5 - .../input-group-showcase.sample.html | 56 ++- 5 files changed, 482 insertions(+), 50 deletions(-) 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 9638b638ca7..54b2ebdcb2d 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 @@ -233,10 +233,35 @@ } @include m(file) { + @extend %form-group-display--file !optional; + @include e(label) { @extend %form-group-label--float !optional; } } + @include mx(file, focused) { + @extend %form-group-display--file-focused !optional; + } + + @include mx(file, border) { + @extend %form-group-display--file-border !optional; + } + + @include mx(file, border, focused) { + @extend %form-group-display--file-border-focused !optional; + } + + @include mx(file, border, valid) { + @extend %form-group-display--file-border-success !optional; + } + + @include mx(file, border, warning) { + @extend %form-group-display--file-border-warning !optional; + } + + @include mx(file, border, invalid) { + @extend %form-group-display--file-border-error !optional; + } @include m(required) { @include e(label) { @@ -561,6 +586,11 @@ @extend %form-group-bundle-search--disabled !optional; } } + + @include e(upload-button) { + @extend %upload-button !optional; + } + // BASE END // ============================== // @@ -902,6 +932,46 @@ } } + @include mx(bootstrap, file) { + @extend %form-group-display--bootstrap-file !optional; + + @include e(input) { + @extend %bootstrap-input-file !optional; + } + + @include e(bundle-end) { + @extend %bootstrap-bundle-end !optional; + } + } + + @include mx(bootstrap, file, focused) { + @extend %bootstrap-file-focused !optional; + } + + @include mx(bootstrap, file, valid) { + @extend %bootstrap-file-valid !optional; + } + + @include mx(bootstrap, file, warning) { + @extend %bootstrap-file-warning !optional; + } + + @include mx(bootstrap, file, invalid) { + @extend %bootstrap-file-invalid !optional; + } + + @include mx(bootstrap, file, valid, focused) { + @extend %bootstrap-file-valid-focused !optional; + } + + @include mx(bootstrap, file, warning, focused) { + @extend %bootstrap-file-warning-focused !optional; + } + + @include mx(bootstrap, file, invalid, focused) { + @extend %bootstrap-file-invalid-focused !optional; + } + @include mx(bootstrap, prefixed) { @extend %form-group-display--bootstrap-prefixed !optional; } @@ -970,6 +1040,32 @@ } } + @include mx(bootstrap, warning) { + @include e(input) { + @extend %bootstrap-input--warning !optional; + + &:hover { + @extend %bootstrap-input--warning !optional; + } + } + + @include e(file-input) { + @extend %bootstrap-input--warning !optional; + + &:hover { + @extend %bootstrap-input--warning !optional; + } + } + + @include e(textarea) { + @extend %bootstrap-input--warning !optional; + + &:hover { + @extend %bootstrap-input--warning !optional; + } + } + } + @include mx(bootstrap, invalid) { @include e(input) { @extend %bootstrap-input--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 f641fe6b10e..3c500439c12 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 @@ -702,10 +702,6 @@ font-family: inherit; } - input[type='file'] { - @include hide-default(); - } - textarea { overflow: auto; } @@ -760,7 +756,7 @@ } %form-group-placeholder { - &:has(input:placeholder-shown, textarea:placeholder-shown) { + &:has(input:placeholder-shown, textarea:placeholder-shown) { %form-group-label { transition: none !important; } @@ -884,7 +880,7 @@ } %form-group-bundle--hover { - cursor: pointer; + //cursor: pointer; &::after { border-block-end-width: rem(1px); @@ -946,6 +942,316 @@ max-width: inherit; } + @if $material-theme { + %form-group-display--file { + %form-group-file-input { + padding-inline: rem(4px); + } + } + + %form-group-display--file-border { + %form-group-input { + z-index: 2; + } + + // We need this otherwise we have to use !important + %form-group-bundle { + grid-template-columns: auto auto auto 1fr auto; + + %form-group-bundle-end { + grid-area: 1 / 5; + } + + &:hover { + %upload-button { + border-color: var-get($theme, 'hover-border-color'); + } + } + } + + %upload-button { + border-block: rem(1px) solid var-get($theme, 'border-color'); + } + } + + %form-group-display--file-border-focused { + %upload-button { + border-width: rem(2px); + border-color: var-get($theme, 'focused-border-color'); + } + + %form-group-bundle { + &:hover { + %upload-button { + border-color: var-get($theme, 'focused-border-color'); + } + } + } + } + + %form-group-display--file-border-success { + %upload-button { + border-color: var-get($theme, 'success-secondary-color'); + } + + %form-group-bundle { + &:hover { + %upload-button { + border-color: var-get($theme, 'success-secondary-color'); + } + } + } + } + + %form-group-display--file-border-warning { + %upload-button { + border-color: var-get($theme, 'warning-secondary-color'); + } + + %form-group-bundle { + &:hover { + %upload-button { + border-color: var-get($theme, 'warning-secondary-color'); + } + } + } + } + + %form-group-display--file-border-error { + %upload-button { + border-color: var-get($theme, 'error-secondary-color'); + } + + %form-group-bundle { + &:hover { + %upload-button { + border-color: var-get($theme, 'error-secondary-color'); + } + } + } + } + } + + @if $variant == 'fluent' { + %form-group-display--file-focused { + %form-group-input, + %form-group-file-input, + %upload-button { + margin-block-start: rem(-1px); + } + } + } + + %form-group-display--file { + .igx-button--flat { + --background: transparent; + --hover-background: transparent; + --focus-background: transparent; + --focus-visible-background: transparent; + --focus-hover-background: transparent; + --active-background: transparent; + --disabled-background: transparent; + --resting-elevation: none; + --hover-elevation: none; + --focus-elevation: none; + --active-elevation: none; + --shadow-color: none; + --border-color: transparent; + --hover-border-color: transparent; + --focus-border-color: transparent; + --focus-visible-border-color: transparent; + --active-border-color: transparent; + --disabled-border-color: transparent + } + + %form-group-bundle { + grid-template-columns: auto auto auto 1fr auto; + } + + %form-group-file-input { + grid-area: 1/3 / span 1 / span 2; + flex-grow: 1; + padding-inline: rem(4px); + cursor: pointer; + + @if $variant != 'material' { + display: flex; + align-items: center; + + span { + transform: revert; + inset: revert; + } + } + } + + %igx-input-group__notch { + grid-area: 1 / 3; + } + + %form-group-bundle-end { + grid-area: 1 / 5; + } + + %igx-input-group__filler { + grid-area: 1 / 4; + } + + %form-group-bundle-end { + grid-area: 1 / 5; + } + + %form-group-bundle-main { + display: contents; + } + + %form-group-input { + grid-column: 2 / -2; + grid-row: 1 / -1; + border: none; + inset: 0; + width: 100%; + height: 100%; + appearance: none; + opacity: 0; + z-index: 2; + cursor: pointer; + } + + ::file-selector-button { + cursor: pointer; + } + } + + %upload-button { + display: flex; + align-items: center; + grid-area: 1 / 2; + pointer-events: none; + height: var-get($theme, 'size'); + cursor: pointer; + } + + %form-group-display--bootstrap-file { + .igx-button--flat { + --foreground: #{var-get($theme, 'input-prefix-color')}; + --hover-foreground: #{var-get($theme, 'input-prefix-color')}; + --active-foreground: #{var-get($theme, 'input-prefix-color')}; + --focus-visible-foreground: #{var-get($theme, 'input-prefix-color')}; + --disabled-foreground: var-get($theme, 'disabled-text-color'); + } + + %upload-button { + background: var-get($theme, 'input-prefix-background'); + border: rem(1px) solid var-get($theme, 'border-color'); + border-inline-end-width: 0; + } + + %form-group-bundle-start, + %form-group-bundle-end { + [igxPrefix], + igx-prefix { + height: var-get($theme, 'size'); + } + } + } + + %bootstrap-file-focused, + %bootstrap-file-valid, + %bootstrap-file-warning, + %bootstrap-file-invalid, + { + %form-group-bundle { + border-radius: var-get($theme, 'box-border-radius'); + transition: box-shadow .15s ease-out, border .15s ease-out; + + &:hover { + %form-group-file-input { + box-shadow: none; + } + } + } + + %form-group-file-input { + box-shadow: none; + } + } + + %bootstrap-file-focused { + %form-group-bundle-start, + %form-group-bundle-end, + %upload-button { + border-color: var-get($theme, 'focused-border-color'); + } + + %form-group-bundle { + box-shadow: 0 0 0 rem(4px) var-get($theme, 'focused-secondary-color'); + } + } + + %bootstrap-file-valid { + %form-group-bundle-start, + %form-group-bundle-end, + %upload-button { + border-color: var-get($theme, 'success-secondary-color'); + } + } + + %bootstrap-file-warning { + %form-group-bundle-start, + %form-group-bundle-end, + %upload-button { + border-color: var-get($theme, 'warning-secondary-color'); + } + } + + %bootstrap-file-invalid { + %form-group-bundle-start, + %form-group-bundle-end, + %upload-button { + border-color: var-get($theme, 'error-secondary-color'); + } + } + + %bootstrap-file-valid-focused { + %form-group-bundle { + box-shadow: 0 0 0 rem(4px) var-get($theme, 'success-shadow-color'); + } + } + + %bootstrap-file-warning-focused { + %form-group-bundle { + box-shadow: 0 0 0 rem(4px) color($color: 'warn', $variant: '500', $opacity: .38); + } + } + + %bootstrap-file-invalid-focused { + %form-group-bundle { + box-shadow: 0 0 0 rem(4px) var-get($theme, 'error-shadow-color'); + } + } + + @if $variant == 'bootstrap' { + %form-group-display--file-focused { + %form-group-bundle-start, + %form-group-bundle-end, + %upload-button { + border-color: var-get($theme, 'focused-border-color'); + } + } + } + + .igx-input-group--bootstrap:not(.igx-input-group--prefixed) { + .igx-input-group__upload-button { + border-radius: var-get($theme, 'box-border-radius') 0 0 var-get($theme, 'box-border-radius'); + } + + .igx-input-group__file-input { + border-start-start-radius: 0; + border-end-start-radius: 0; + } + } + %form-group-bundle--box { // padding 0 is needed here because of the search variant padding: 0 !important; @@ -1943,13 +2249,6 @@ border-bottom-style: solid; } } - - %indigo-upload-button { - [igxButton] { - min-height: 0; - height: calc(100% - #{rem(8px)}); - } - } // INDIGO END // ============================================== @@ -2261,9 +2560,6 @@ } } - %fluent-upload-button { - padding: 0; - } // FLUENT END // ============================================== @@ -2405,7 +2701,9 @@ %bootstrap-input { height: auto; line-height: 1.5; + grid-area: 1 / 2; margin: 0; + z-index: 2; font-size: pad( map.get($bootstrap-font-size, 'compact'), map.get($bootstrap-font-size, 'cosy'), @@ -2445,15 +2743,24 @@ map.get($bootstrap-inline-padding, 'cosy'), map.get($bootstrap-inline-padding, 'comfortable') ); - grid-area: 1 / 2 / auto / auto; border-radius: var-get($theme, 'box-border-radius'); - z-index: 1; + } %bootstrap-file-input { height: inherit; } + %bootstrap-input-file { + grid-column: 2 / -2; + grid-row: 1 / -1; + height: var-get($theme, 'size'); + } + + %bootstrap-bundle-end { + grid-area: 1 / 5; + } + %bootstrap-input--focus { border: rem(1px) solid var-get($theme, 'focused-border-color'); box-shadow: 0 0 0 rem(4px) var-get($theme, 'focused-secondary-color'); @@ -2471,6 +2778,11 @@ } } + %bootstrap-input--warning { + border: rem(1px) solid var-get($theme, 'warning-secondary-color'); + box-shadow: 0 0 0 rem(4px) color($color: 'warn', $variant: '500', $opacity: .38); + } + %bootstrap-input--error { border: rem(1px) solid var-get($theme, 'error-secondary-color'); @@ -2511,16 +2823,6 @@ border-color: var-get($theme, 'disabled-border-color'); color: var-get($theme, 'disabled-text-color'); } - - // Upload button for file type input - %bootstrap-upload-button { - padding: 0; - - [igxButton] { - min-height: 0; - height: calc(100% - #{rem(8px)}); - } - } } /// Adds typography styles for the igx-input-group component. diff --git a/projects/igniteui-angular/src/lib/input-group/input-group.component.html b/projects/igniteui-angular/src/lib/input-group/input-group.component.html index 8b5a258edfa..ca1e3659b61 100644 --- a/projects/igniteui-angular/src/lib/input-group/input-group.component.html +++ b/projects/igniteui-angular/src/lib/input-group/input-group.component.html @@ -22,19 +22,22 @@ + + + @if (isFileType) { - +
- +
}
@@ -71,7 +74,6 @@
-
@@ -82,6 +84,7 @@
+
@@ -104,12 +107,12 @@
-
+
@@ -130,10 +133,10 @@
-
+
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 93b8a4579cf..2ffd4000654 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 @@ -335,11 +335,6 @@ export class IgxInputGroupComponent implements IgxInputGroupBase { return this.type === 'box' && this._theme === 'material'; } - /** @hidden @internal */ - public uploadButtonHandler() { - this.input.nativeElement.click(); - } - /** @hidden @internal */ public clearValueHandler() { this.input.clear(); diff --git a/src/app/input-group-showcase/input-group-showcase.sample.html b/src/app/input-group-showcase/input-group-showcase.sample.html index 646f3df2cba..ac90d84b97d 100644 --- a/src/app/input-group-showcase/input-group-showcase.sample.html +++ b/src/app/input-group-showcase/input-group-showcase.sample.html @@ -18,7 +18,11 @@

Angular

@if (getLabel()) { } - face + + @if (!hidePrefix()) { + face + } + Angular @if (getLabel()) { } - face + + @if (!hidePrefix()) { + face + } + - @if (!hideSuffix()) { + + @if (hideSuffix()) { face } - Hint text + @if (getHint()) { + {{getHint()}} + } @@ -77,17 +83,16 @@

Angular

} - @if (!hidePrefix()) { - favorite + @if (hidePrefix()) { + face + } + + @if (hideSuffix()) { + face } - - I am a Hint - - @if (!hideSuffix()) { - - favorite - + @if (getHint()) { + {{getHint()}} } Apple Orange @@ -102,20 +107,26 @@

Angular

[placeholder]="getPlaceholder()" [type]="getInputGroupType()" [style.--ig-size]="getSize()"> + @if (getLabel()) { } - @if (!hidePrefix()) { - favorite + @if (hidePrefix()) { + + face + } - @if (!hideSuffix()) { + @if (hideSuffix()) { favorite } - Select a unique falsy value + + @if (getHint()) { + {{getHint()}} + } @@ -123,27 +134,33 @@

Angular

#fieldFile [type]="getInputGroupType()" [style.--ig-size]="getSize()"> + @if (getLabel()) { - + } - @if (!hidePrefix()) { + @if (hidePrefix()) { face } - @if (!hideSuffix()) { + + @if (hideSuffix()) { face } - Type your web address + + @if (getHint()) { + {{getHint()}} + } @@ -182,21 +199,23 @@

Web components

[style.--ig-size]="getSize()" [label]="getLabel()" [required]="isRequired()" + [attr.placeholder]="getPlaceholder()" [disabled]="isDisabled()" [readOnly]="isReadonly()" [attr.value]="getValue()" - [attr.placeholder]="getPlaceholder()" [type]="getNativeInputType()" [outlined]="isOutlined()"> - @if (!hidePrefix()) { - + @if (hidePrefix()) { + } - @if (!hideSuffix()) { - + @if (hideSuffix()) { + + } + @if (getHint()) { + {{getHint()}} } - Type your web address Web components [disabled]="isDisabled()" [readOnly]="isReadonly()" [attr.value]="getValue()" - [attr.placeholder]="getPlaceholder()" + [placeholder]="getPlaceholder()" [outlined]="isOutlined()"> - @if (!hidePrefix()) { - + @if (hidePrefix()) { + + } + + @if (hideSuffix()) { + } - @if (!hideSuffix()) { - + @if (getHint()) { + {{getHint()}} } - Hint text + [required]="isRequired()" + [attr.placeholder]="getPlaceholder()" + [label]="getLabel()" + [disabled]="isDisabled()" + [outlined]="isOutlined()" + [style.--ig-size]="getSize()"> - @if (!hidePrefix()) { - + @if (hidePrefix()) { + } - @if (!hideSuffix()) { - + @if (getHint()) { + {{getHint()}} } - I am a Hint Apple Orange Grapes @@ -248,21 +269,31 @@

Web components

[outlined]="isOutlined()" [disabled]="isDisabled()" [style.--ig-size]="getSize()"> - I am a Hint - - @if (!hidePrefix()) { - - } - - @if (!hideSuffix()) { - + @if (getHint()) { + {{getHint()}} } -
- NO file type in web components -
+ + @if (hidePrefix()) { + + } + + @if (hideSuffix()) { + + } + @if (getHint()) { + {{getHint()}} + } +
diff --git a/src/app/input-group-showcase/input-group-showcase.sample.ts b/src/app/input-group-showcase/input-group-showcase.sample.ts index 314b188dc88..5dab7ef8366 100644 --- a/src/app/input-group-showcase/input-group-showcase.sample.ts +++ b/src/app/input-group-showcase/input-group-showcase.sample.ts @@ -1,5 +1,6 @@ import {Component, CUSTOM_ELEMENTS_SCHEMA, inject, signal, computed, viewChild, DestroyRef} from '@angular/core'; import {FormsModule, ReactiveFormsModule, UntypedFormBuilder, Validators} from '@angular/forms'; + import { defineComponents, IgcInputComponent, @@ -8,6 +9,7 @@ import { IgcSelectComponent, IgcSelectItemComponent, IgcSelectHeaderComponent, + IgcFileInputComponent, } from 'igniteui-webcomponents'; import { IGX_INPUT_GROUP_DIRECTIVES, @@ -27,7 +29,8 @@ defineComponents( IgcSelectGroupComponent, IgcSelectComponent, IgcSelectItemComponent, - IgcSelectHeaderComponent + IgcSelectHeaderComponent, + IgcFileInputComponent ); @Component({ @@ -64,11 +67,11 @@ export class InputGroupShowcaseSampleComponent { } }, inputType: { - label: 'Input Group Type', + label: 'Input Group Type (Only Material theme has border/box and line types)', control: { type: 'button-group', options: ['box', 'border', 'line', 'search'], - defaultValue: '' + defaultValue: 'box' } }, type: { @@ -82,7 +85,13 @@ export class InputGroupShowcaseSampleComponent { label: { control: { type: 'text', - defaultValue: 'Web address' + defaultValue: 'Label text' + } + }, + hint: { + control: { + type: 'text', + defaultValue: 'Hint text' } }, value: { @@ -117,7 +126,7 @@ export class InputGroupShowcaseSampleComponent { } }, hidePrefix: { - label: 'Hide Prefix', + label: 'Hide Prefix using (@if)', control: { type: 'boolean', defaultValue: false @@ -217,6 +226,12 @@ export class InputGroupShowcaseSampleComponent { public getSize = computed(() => `var(--ig-size-${this.properties()?.size || 'medium'})`); public getPlaceholder = computed(() => this.properties()?.placeholder || null); public getLabel = computed(() => this.properties()?.label || ''); + + public getHint = computed(() => { + const hint = this.properties()?.hint || ''; + return hint.trim() ? hint : null; + }); + public getNativeInputType = computed(() => this.properties()?.type || 'text'); public getInputGroupType = computed(() => this.properties()?.inputType || ''); @@ -224,7 +239,7 @@ export class InputGroupShowcaseSampleComponent { public isRequired = computed(() => !!this.properties()?.required); public isDisabled = computed(() => !!this.properties()?.disabled); public isReadonly = computed(() => !!this.properties()?.readonly); - public hidePrefix = computed(() => !!this.properties()?.hidePrefix); - public hideSuffix = computed(() => !!this.properties()?.hideSuffix); + public hidePrefix = computed(() => !this.properties()?.hidePrefix); + public hideSuffix = computed(() => !this.properties()?.hideSuffix); } From ded694ca34f88b64fa7300c9ffa48ea31ea4aa2c Mon Sep 17 00:00:00 2001 From: desig9stein Date: Mon, 7 Jul 2025 15:10:51 +0300 Subject: [PATCH 11/15] fix(input-group): fix bootstrap dabble border, and helper text min height in all themes --- .../components/input/_input-group-component.scss | 8 ++++---- .../components/input/_input-group-theme.scss | 16 ++++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) 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 8c3c5f36ebc..ffe88dd6262 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 @@ -933,10 +933,6 @@ @extend %bootstrap-input !optional; } - @include e(upload-button) { - @extend %bootstrap-upload-button !optional; - } - @include e(bundle-start) { @extend %form-group-bundle-start--bootstrap !optional; } @@ -956,6 +952,10 @@ @include e(bundle-end) { @extend %bootstrap-bundle-end !optional; } + + @include e(upload-button) { + @extend %bootstrap-upload-button !optional; + } } @include mx(bootstrap, file, disabled) { 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 f790849b693..bd7114ac04f 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 @@ -1119,11 +1119,6 @@ } %form-group-display--bootstrap-file { - %upload-button { - border: rem(1px) solid var-get($theme, 'border-color'); - border-inline-end-width: 0; - } - %form-group-bundle-start, %form-group-bundle-end { [igxPrefix], @@ -1133,6 +1128,15 @@ } } + %bootstrap-upload-button { + border: rem(1px) solid var-get($theme, 'border-color'); + border-inline-end: 0; + + igx-button { + border: 0; + } + } + %bootstrap-file-disabled-upload-button { border-color: var-get($theme, 'disabled-border-color'); } @@ -2086,7 +2090,7 @@ position: relative; display: grid; grid-auto-rows: minmax($hint-min-size, auto); - padding-block-start: $hint-spacing-block; + margin-block-start: $hint-spacing-block !important; padding-inline: $hint-spacing-inline; justify-content: space-between; From 6b86c3a2941108cc6eb1c946802ac28c64b15c34 Mon Sep 17 00:00:00 2001 From: desig9stein Date: Mon, 7 Jul 2025 15:33:25 +0300 Subject: [PATCH 12/15] fix(input-group): fix fluent theme upload button jump --- .../input/_input-group-component.scss | 41 +++++++++++-------- .../components/input/_input-group-theme.scss | 19 +++++---- 2 files changed, 34 insertions(+), 26 deletions(-) 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 ffe88dd6262..bff0ecc5788 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 @@ -631,24 +631,6 @@ @include e(label) { @extend %fluent-label !optional; } - - @include e(upload-button) { - @extend %fluent-upload-button !optional; - } - } - - @include mx(fluent, file) { - @include e(bundle) { - @extend %form-group-bundle-file--fluent !optional; - } - - @include e(bundle-start) { - @extend %form-group-bundle-start-file--fluent !optional; - } - - @include e(bundle-end) { - @extend %form-group-bundle-end-file--fluent !optional; - } } @include mx(fluent, placeholder) { @@ -704,11 +686,34 @@ } @include mx(fluent, file) { + @include e(file-input) { + @extend %fluent-file-input !optional; + } + + @include e(upload-button) { + @extend %fluent-upload-button !optional; + } + + @include e(bundle-end) { + @extend %form-group-bundle-end-file--fluent !optional; + } + @include e(label) { @extend %fluent-label-filled !optional; } } + @include mx(fluent, file, focused) { + @include e(file-input) { + @extend %fluent-focused-file-input !optional; + } + + @include e(upload-button) { + @extend %fluent-focused-upload-button !optional; + } + + } + @include mx(fluent, textarea-group) { @include e(bundle) { @extend %form-group-bundle-fluent--textarea !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 bd7114ac04f..b87575cb34e 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 @@ -1041,9 +1041,7 @@ @if $variant == 'fluent' { %form-group-display--file-focused { - %form-group-input, - %form-group-file-input, - %upload-button { + %form-group-input { margin-block-start: rem(-1px); } } @@ -1833,13 +1831,18 @@ } } - @if $variant == 'fluent' { - %form-group-file-input, - %upload-button { - max-height: calc(var-get($theme, 'size') - #{rem(2px)}); - } + + %fluent-file-input, + %fluent-upload-button { + max-height: calc(var-get($theme, 'size') - #{rem(2px)}); + } + + %fluent-focused-file-input, + %fluent-focused-upload-button { + max-height: calc(var-get($theme, 'size') - #{rem(4px)}); } + // This is a hack that removes the autofill background and it's essential, // otherwise the background is on top of the floating label in material theme. // The !important flag is because bootstrap theme(and potentially feature themes) is overriding the transition delay. From 807a52124bdf0ac0a1b3be7a69c77cb1cca7e662 Mon Sep 17 00:00:00 2001 From: desig9stein Date: Mon, 7 Jul 2025 15:57:50 +0300 Subject: [PATCH 13/15] fix(input-group): make sure that material type border has not border on focus --- .../lib/core/styles/components/input/_input-group-theme.scss | 4 ++++ 1 file changed, 4 insertions(+) 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 b87575cb34e..07f0cf65510 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 @@ -978,6 +978,10 @@ %upload-button { border-block: rem(1px) solid var-get($theme, 'border-color'); + + .igx-button { + border: none; + } } } From a8925ad06fe9b3fc16a858062f02d84983434650 Mon Sep 17 00:00:00 2001 From: desig9stein Date: Mon, 14 Jul 2025 10:41:28 +0300 Subject: [PATCH 14/15] fix(input-group): remove the inline border of the upload button --- .../src/lib/core/styles/components/input/_file-input-theme.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/projects/igniteui-angular/src/lib/core/styles/components/input/_file-input-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/input/_file-input-theme.scss index 016643841eb..e6de04e38e1 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/input/_file-input-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/input/_file-input-theme.scss @@ -122,6 +122,8 @@ } %upload-button { + border-inline: 0; + // That button can't have :focus, :active, :hover states, that's why we dont need to override them here. --foreground: #{var-get($theme, 'file-selector-button-foreground')}; --background: transparent; From 43ae2f36ad197be50476c8f5f9ef399c2ceef14d Mon Sep 17 00:00:00 2001 From: desig9stein Date: Fri, 18 Jul 2025 09:53:39 +0300 Subject: [PATCH 15/15] fix(input-group): fix fluent border, fix input look in grid filtering and cleanup the code --- .../src/lib/core/i18n/input-resources.ts | 2 +- .../styles/components/grid/_grid-theme.scss | 65 ++++++--- .../input/_input-group-component.scss | 107 +------------- .../components/input/_input-group-theme.scss | 137 ++++++------------ 4 files changed, 97 insertions(+), 214 deletions(-) diff --git a/projects/igniteui-angular/src/lib/core/i18n/input-resources.ts b/projects/igniteui-angular/src/lib/core/i18n/input-resources.ts index e8c5d49c23a..5b8c244506e 100644 --- a/projects/igniteui-angular/src/lib/core/i18n/input-resources.ts +++ b/projects/igniteui-angular/src/lib/core/i18n/input-resources.ts @@ -4,6 +4,6 @@ export interface IInputResourceStrings { } export const InputResourceStringsEN: IInputResourceStrings = { - igx_input_upload_button: 'Upload File', + igx_input_upload_button: 'Browse', igx_input_file_placeholder: 'No file chosen', }; diff --git a/projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-theme.scss b/projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-theme.scss index aff507895e6..97f1073e8f6 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-theme.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/grid/_grid-theme.scss @@ -880,7 +880,10 @@ width: 100%; max-width: rem(200px); min-width: rem(140px); - border: rem(1px) solid color($color: 'gray', $variant: 300); + + @if $variant != 'fluent' { + border: rem(1px) solid color($color: 'gray', $variant: 300); + } --size: calc(#{$filtering-row-height} - #{rem(8px)}); @@ -892,9 +895,8 @@ background: transparent; border-radius: 0; - &:hover, - &:focus, - &:focus-within { + /* stylelint-disable-next-line */ + &:hover { background: transparent; } } @@ -918,9 +920,8 @@ .igx-input-group__input { border: 0; - &:hover, - &:focus, - &:focus-within { + /* stylelint-disable-next-line */ + &:hover { border: 0; box-shadow: none; } @@ -930,31 +931,53 @@ display: none; } - .igx-input-group__bundle:focus, - .igx-input-group__bundle:focus-within { - .igx-input-group__bundle-main, - .igx-input-group__bundle-start, - .igx-input-group__bundle-end { - margin: 0 !important; - } - - border-width: rem(1px); - } - .igx-input-group__bundle-main { padding-inline-start: 0; } color: var-get($theme, 'filtering-row-text-color'); - &:hover, - &:focus, - &:focus-within { + &:hover{ color: var-get($theme, 'filtering-row-text-color'); border-color: color($color: 'primary', $variant: 500); } } + .igx-input-group--focused { + @if $variant != 'fluent' { + border-color: color($color: 'primary', $variant: 500); + border-width: rem(1px); + } + + color: var-get($theme, 'filtering-row-text-color'); + + .igx-input-group__bundle, + .igx-input-group__bundle-start, + .igx-input-group__bundle-end, + .igx-input-group__input { + border: 0 !important; + + @if $variant != 'fluent' { + box-shadow: none !important; + } + } + + .igx-input-group__bundle-main, + .igx-input-group__bundle-start, + .igx-input-group__bundle-end { + margin: 0 !important; + } + + .igx-input-group__bundle, + .igx-input-group__bundle-start, + .igx-input-group__bundle-end, + igx-prefix, + igx-suffix { + background: transparent !important; + border-radius: 0; + } + } + .igx-input-group__line { display: none; } 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 bff0ecc5788..00062ada101 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 @@ -52,7 +52,6 @@ @include e(input) { @extend %form-group-input !optional; @extend %autofill-background-fix !optional; - @extend %edge-clear-icon-fix !optional; &:hover { @extend %form-group-input--hover !optional; @@ -75,10 +74,6 @@ } } - @include e(clear-icon) { - @extend %form-group-clear-icon !optional; - } - @include e(hint) { @extend %form-group-helper !optional; } @@ -220,7 +215,6 @@ @include e(label) { @extend %form-group-label--float !optional; - @extend %form-group-label--fixed !optional; } } @@ -331,7 +325,6 @@ } @include e(label) { - @extend %form-group-label--fixed !optional; @extend %form-group-label--disabled !optional; } @@ -359,10 +352,6 @@ @extend %form-group-bundle--disabled !optional; } - @include e(label) { - @extend %form-group-label--fixed !optional; - } - @include e(input) { @extend %form-group-input--disabled !optional; } @@ -394,21 +383,9 @@ @extend %form-group-input--box !optional; } - @include e(bundle-start) { - @extend %form-group-bundle-start--box !optional; - } - - @include e(bundle-end) { - @extend %form-group-bundle-end--box !optional; - } - @include e(bundle-main) { @extend %form-group-bundle-main--box !optional; } - - @include e(notch) { - @extend %form-group-notch--box !optional; - } } @include mx(box, focused) { @@ -423,25 +400,10 @@ } } - @include mx(box, textarea-group, filled) { - @include e(notch) { - @extend %form-group-notch--box-textarea !optional; - } - } - @include mx(box, textarea-group, placeholder) { @extend %form-group-placeholder !optional; - - @include e(notch) { - @extend %form-group-notch--box-textarea !optional; - } } - @include mx(box, textarea-group, focused) { - @include e(notch) { - @extend %form-group-notch--box-textarea !optional; - } - } // Type box END // Type border START @@ -473,14 +435,6 @@ @extend %form-group-label--border !optional; } - @include e(bundle-start) { - @extend %form-group-bundle-start--border !optional; - } - - @include e(bundle-end) { - @extend %form-group-bundle-end--border !optional; - } - @include e(notch) { @extend %igx-input-group__notch--border !optional; } @@ -605,11 +559,6 @@ &:hover { @extend %form-group-bundle--fluent--hover !optional; } - - &:focus-within, - &:focus { - @extend %form-group-bundle--fluent--focus !optional; - } } @include e(bundle-main) { @@ -686,32 +635,13 @@ } @include mx(fluent, file) { - @include e(file-input) { - @extend %fluent-file-input !optional; - } - - @include e(upload-button) { - @extend %fluent-upload-button !optional; - } - - @include e(bundle-end) { - @extend %form-group-bundle-end-file--fluent !optional; - } - @include e(label) { @extend %fluent-label-filled !optional; } - } - @include mx(fluent, file, focused) { @include e(file-input) { - @extend %fluent-focused-file-input !optional; - } - - @include e(upload-button) { - @extend %fluent-focused-upload-button !optional; + @extend %fluent-file-input !optional; } - } @include mx(fluent, textarea-group) { @@ -721,16 +651,8 @@ } @include mx(fluent, focused) { - @include e(bundle-start) { - @extend %form-group-bundle-start--fluent--focused !optional; - } - - @include e(bundle-main) { - @extend %form-group-bundle-main--fluent--focused !optional; - } - - @include e(bundle-end) { - @extend %form-group-bundle-end--fluent--focused !optional; + @include e(bundle) { + @extend %form-group-bundle--fluent--focus !optional; } @include e(label) { @@ -738,12 +660,6 @@ } } - @include mx(fluent, focused, textarea-group) { - @include e(hint) { - @extend %form-group-helper--textarea--fluent--focused !optional; - } - } - @include mx(fluent, textarea-group) { @include e(bundle-start) { @extend %form-group-bundle-textarea-start--fluent !optional; @@ -757,11 +673,8 @@ } @include mx(fluent, required) { - @include e(bundle) { - @extend %form-group-bundle-required--fluent !optional; - } - @include e(label) { + @extend %form-group-bundle-required--fluent !optional; @extend %form-group-label-required--fluent !optional; } } @@ -857,10 +770,6 @@ @extend %form-group-bundle--indigo !optional; } - @include e(bundle-start) { - @extend %form-group-bundle--indigo-start !optional; - } - @include e(input) { @extend %form-group-input--indigo !optional; } @@ -876,10 +785,6 @@ @include e(textarea) { @extend %indigo-textarea !optional; } - - @include e(upload-button) { - @extend %indigo-upload-button !optional; - } } @include mx(indigo, focused) { @@ -1013,10 +918,6 @@ @extend %form-group-display--bootstrap-suffixed-valid !optional; } - @include mx(bootstrap, suffixed, warning) { - @extend %form-group-display--bootstrap-suffixed-warning !optional; - } - @include mx(bootstrap, suffixed, invalid) { @extend %form-group-display--bootstrap-suffixed-invalid !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 07f0cf65510..ae993f8177d 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 @@ -1043,14 +1043,6 @@ } } - @if $variant == 'fluent' { - %form-group-display--file-focused { - %form-group-input { - margin-block-start: rem(-1px); - } - } - } - %form-group-display--file { %form-group-bundle { grid-template-columns: auto auto auto 1fr auto; @@ -1835,18 +1827,6 @@ } } - - %fluent-file-input, - %fluent-upload-button { - max-height: calc(var-get($theme, 'size') - #{rem(2px)}); - } - - %fluent-focused-file-input, - %fluent-focused-upload-button { - max-height: calc(var-get($theme, 'size') - #{rem(4px)}); - } - - // This is a hack that removes the autofill background and it's essential, // otherwise the background is on top of the floating label in material theme. // The !important flag is because bootstrap theme(and potentially feature themes) is overriding the transition delay. @@ -2093,11 +2073,13 @@ } %form-group-helper { + --ig-caption-margin-top: #{$hint-spacing-block}; + --ig-caption-margin-bottom: 0; + color: var-get($theme, 'helper-text-color'); position: relative; display: grid; grid-auto-rows: minmax($hint-min-size, auto); - margin-block-start: $hint-spacing-block !important; padding-inline: $hint-spacing-inline; justify-content: space-between; @@ -2111,11 +2093,7 @@ } &:empty { - @if $variant == 'fluent' { - padding: 0; - } @else { - display: none; - } + display: none; } } @@ -2332,72 +2310,74 @@ %form-group-bundle--fluent { --min-width: #{sizable(rem(4px), rem(6px), rem(8px))}; + --_fluent-input-border-size: #{rem(1px)}; min-height: var-get($theme, 'size'); padding: 0; - border: rem(1px) solid var-get($theme, 'border-color'); background: var-get($theme, 'border-background'); align-items: stretch; - overflow: hidden; - - @if $variant == 'fluent' { - border-radius: var-get($theme, 'border-border-radius'); - } - - // Those focus styles are needed since when we focus the button inside - // the file type input the class .igx-input-group--focused is not added but the input is focused. - &:focus, - &:focus-within { - %form-group-bundle-start { - margin-block-start: rem(-1px); - margin-inline-start: rem(-1px); - } - - %form-group-bundle-end { - margin-block-start: rem(-1px); - margin-inline-end: rem(-1px); - } - - %form-group-bundle-start:empty + %form-group-bundle-main, - %form-group-bundle-end:empty + %form-group-bundle-main { - margin-inline-start: rem(-1px); - } + overflow: visible; + border-radius: var-get($theme, 'border-border-radius'); + position: relative; + border: rem(1px) solid transparent; - %form-group-bundle-main { - margin-block-start: rem(-1px); - } + &::before { + content: ''; + position: absolute; + width: calc(100% + var(--_fluent-input-border-size) * 2); + height: calc(100% + var(--_fluent-input-border-size) * 2); + pointer-events: none; + user-select: none; + inset: calc(var(--_fluent-input-border-size) * -1); + z-index: 1; + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'border-color'); + border-radius: inherit; } } %form-group-bundle--fluent--hover { - border-color: var-get($theme, 'hover-border-color'); + &::before { + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'hover-border-color'); + } } %form-group-bundle--fluent--focus { - border-color: var-get($theme, 'focused-border-color'); - border-width: rem(2px); + --_fluent-input-border-size: #{rem(2px)}; + + &::before { + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'focused-border-color'); + } &:hover { - border-color: var-get($theme, 'focused-border-color'); + &::before { + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'focused-border-color'); + } } } %form-group-bundle-error--fluent, %form-group-bundle-error--fluent--hover, %form-group-bundle-error--fluent--focus { - border-color: var-get($theme, 'error-secondary-color'); + &::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 { - border-color: var-get($theme, 'success-secondary-color'); + &::before { + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'success-secondary-color'); + } } %form-group-bundle--fluent--hover-disabled, %form-group-bundle--fluent-disabled { - border-color: var-get($theme, 'disabled-border-color'); background: var-get($theme, 'border-disabled-background'); + + &::before { + box-shadow: inset 0 0 0 var(--_fluent-input-border-size) var-get($theme, 'disabled-border-color'); + } } %form-group-bundle-main--fluent { @@ -2405,27 +2385,6 @@ cursor: default; } - @if $fluent-theme { - %form-group-bundle-start--fluent--focused { - margin-block-start: rem(-1px); - margin-inline-start: rem(-1px); - } - - %form-group-bundle-end--fluent--focused { - margin-block-start: rem(-1px); - margin-inline-end: rem(-1px); - } - - %form-group-bundle-start--fluent--focused:empty + %form-group-bundle-main--fluent--focused, - %form-group-bundle-end--fluent--focused:empty + %form-group-bundle-main--fluent--focused { - margin-inline-start: rem(-1px); - } - - %form-group-bundle-main--fluent--focused { - margin-block-start: rem(-1px); - } - } - %form-group-bundle-textarea-start--fluent, %form-group-bundle-textarea-end--fluent { &:empty { @@ -2442,6 +2401,10 @@ border: none; } + %fluent-file-input { + padding-inline: 0; + } + %indigo-textarea { padding-block: rem(6px); padding-inline: pad-inline(rem(2px), rem(4px), rem(6px)); @@ -2467,6 +2430,8 @@ color: var-get($theme, 'idle-secondary-color'); @if $variant == 'fluent' { + --ig-subtitle-2-line-height: rem(16px); + margin-block-end: rem(5px); } @else { margin-block-end: rem(4px); @@ -2503,10 +2468,6 @@ transform: translateY(0) scale(1); } - %form-group-helper--textarea--fluent--focused { - margin-block-start: rem(-1px); - } - %fluent-placeholder-label { transform: translateY(0) scale(1); } @@ -2872,9 +2833,7 @@ } %form-group-helper { - @include type-style($helper-text) { - margin: 0; - } + @include type-style($helper-text); } %form-group-prefix,