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/_index.scss b/projects/igniteui-angular/src/lib/core/styles/components/_index.scss index f197f6628a9..5f0d6a09fc6 100644 --- a/projects/igniteui-angular/src/lib/core/styles/components/_index.scss +++ b/projects/igniteui-angular/src/lib/core/styles/components/_index.scss @@ -52,3 +52,4 @@ @forward 'tooltip/tooltip-theme'; @forward 'tree/tree-theme'; @forward 'watermark/watermark-theme'; +@forward 'input/file-input-theme'; 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/_file-input-component.scss b/projects/igniteui-angular/src/lib/core/styles/components/input/_file-input-component.scss new file mode 100644 index 00000000000..aebb911f782 --- /dev/null +++ b/projects/igniteui-angular/src/lib/core/styles/components/input/_file-input-component.scss @@ -0,0 +1,72 @@ +@use '../../base' as *; +@use 'sass:string'; + +/// @access private +@mixin component { + @include b(igx-file-input) { + $this: bem--selector-to-string(&); + + @include register-component( + $name: string.slice($this, 2, -1), + $deps: (igx-input-group) + ); + + @include e(file-names) { + @extend %file-names !optional; + } + + @include e(upload-button-wrapper) { + @extend %upload-button-wrapper !optional; + } + + @include e(upload-button) { + @extend %upload-button !optional; + } + + @include e(clear-icon) { + @extend %clear-icon !optional; + } + + @include m(filled) { + @include e(file-names) { + @extend %file-names--filled !optional; + } + + @include e(upload-button-wrapper) { + @extend %upload-button-wrapper--filled !optional; + } + + @include e(upload-button) { + @extend %upload-button--filled !optional; + } + } + + @include m(focused) { + @include e(file-names) { + @extend %file-names--focused !optional; + } + + @include e(upload-button-wrapper) { + @extend %upload-button-wrapper--focused !optional; + } + + @include e(upload-button) { + @extend %upload-button--focused !optional; + } + } + + @include m(disabled) { + @include e(file-names) { + @extend %file-names--disabled !optional; + } + + @include e(upload-button-wrapper) { + @extend %upload-button-wrapper--disabled !optional; + } + + @include e(upload-button) { + @extend %upload-button--disabled !optional; + } + } + } +} 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 new file mode 100644 index 00000000000..e6de04e38e1 --- /dev/null +++ b/projects/igniteui-angular/src/lib/core/styles/components/input/_file-input-theme.scss @@ -0,0 +1,203 @@ +@use 'sass:map'; +@use 'sass:meta'; +@use '../../base' as *; +@use '../../themes/schemas' as *; +@use 'igniteui-theming/sass/animations/easings' as *; + +//// +/// @group themes +/// @access public +//// + +/// @param {Map} $schema [$light-material-schema] - The schema used as basis for styling the component. +/// @param {Color} $file-names-background [null] - The file names container background color. +/// @param {Color} $file-names-background--focused [null] - The file names container background color when the file input is focused. +/// @param {Color} $file-names-background--filled [null] - The file names container background color when the file input is filled. +/// @param {Color} $file-names-background--disabled [null] - The file names container background color when the file input is disabled. +/// @param {Color} $file-names-foreground [null] - The file names color. +/// @param {Color} $file-names-foreground--focused [null] - The file names color when the file input is focused. +/// @param {Color} $file-names-foreground--filled [null] - The file names color when the file input is filled. +/// @param {Color} $file-names-foreground--disabled [null] - The file names color when the file input is disabled. +/// @param {Color} $file-selector-button-background [null] - The file input selector button background color. +/// @param {Color} $file-selector-button-background--focused [null] - The selector button background color when the file input is focused. +/// @param {Color} $file-selector-button-background--filled [null] - The selector button background color when the file input is filled. +/// @param {Color} $file-selector-button-background--disabled [null] - The selector button background color when the file input is disabled. +/// @param {Color} $file-selector-button-foreground [null] - The file input selector button foreground color. +/// @param {Color} $file-selector-button-foreground--focused [null] - The selector button foreground color when the file input is focused. +/// @param {Color} $file-selector-button-foreground--filled [null] - The selector button foreground color when the file input is filled. +/// @param {Color} $file-selector-button-foreground--disabled [null] - The selector button foreground color when the file input is disabled. +/// @example scss Change the focused border and label colors +/// $my-file-input-theme: file-input-theme($file-names-foreground: #09f); +/// // Pass the theme to the css-vars() mixin +/// @include css-vars($my-file-input-theme); +@function file-input-theme( + $schema: $light-material-schema, + $file-names-background: null, + $file-names-background--focused: null, + $file-names-background--filled: null, + $file-names-background--disabled: null, + $file-names-foreground: null, + $file-names-foreground--focused: null, + $file-names-foreground--filled: null, + $file-names-foreground--disabled: null, + + $file-selector-button-background: null, + $file-selector-button-background--focused: null, + $file-selector-button-background--filled: null, + $file-selector-button-background--disabled: null, + $file-selector-button-foreground: null, + $file-selector-button-foreground--focused: null, + $file-selector-button-foreground--filled: null, + $file-selector-button-foreground--disabled: null, +) { + $name: 'igx-file-input'; + + // the variable are scoped to the selector so no other input except the file type will have them. + $selector: '.igx-file-input'; + + $file-input-schema: (); + @if map.has-key($schema, 'file-input') { + $file-input-schema: map.get($schema, 'file-input'); + } @else { + $file-input-schema: $schema; + } + + $theme: digest-schema($file-input-schema); + + @return extend( + $theme, + ( + name: $name, + selector: $selector, + file-names-background: $file-names-background, + file-names-background--focused: $file-names-background--focused, + file-names-background--filled: $file-names-background--filled, + file-names-background--disabled: $file-names-background--disabled, + file-names-foreground: $file-names-foreground, + file-names-foreground--focused: $file-names-foreground--focused, + file-names-foreground--filled: $file-names-foreground--filled, + file-names-foreground--disabled: $file-names-foreground--disabled, + + file-selector-button-background: $file-selector-button-background, + file-selector-button-background--focused: $file-selector-button-background--focused, + file-selector-button-background--filled: $file-selector-button-background--filled, + file-selector-button-background--disabled: $file-selector-button-background--disabled, + file-selector-button-foreground: $file-selector-button-foreground, + file-selector-button-foreground--focused: $file-selector-button-foreground--focused, + file-selector-button-foreground--filled: $file-selector-button-foreground--filled, + file-selector-button-foreground--disabled: $file-selector-button-foreground--disabled, + ), + ); +} + +/// @deprecated Use the `css-vars` mixin instead. +/// @see {mixin} css-vars +/// @param {Map} $theme - The theme used to style the component. +@mixin file-input($theme) { + @include css-vars($theme); + $variant: map.get($theme, '_meta', 'theme'); + + %file-names { + color: var-get($theme, 'file-names-foreground'); + background-color: var-get($theme, 'file-names-background'); + } + + %file-names--filled { + color: var-get($theme, 'file-names-foreground--filled'); + background-color: var-get($theme, 'file-names-background--filled'); + } + + %file-names--focused { + color: var-get($theme, 'file-names-foreground--focused'); + background-color: var-get($theme, 'file-names-background--focused'); + } + + %file-names--disabled { + color: var-get($theme, 'file-names-foreground--disabled'); + background-color: var-get($theme, 'file-names-background--disabled'); + } + + %upload-button-wrapper { + background: #{var-get($theme, 'file-selector-button-background')} + } + + %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; + --resting-elevation: none; + --shadow-color: none; + --border-radius: 0; + } + + + %upload-button-wrapper--filled { + color: #{var-get($theme, 'file-selector-button-foreground--filled')}; + background: #{var-get($theme, 'file-selector-button-background--filled')}; + } + + %upload-button--filled { + --foreground: #{var-get($theme, 'file-selector-button-foreground--filled')}; + --background: transparent; + } + + %upload-button-wrapper--focused { + color: #{var-get($theme, 'file-selector-button-foreground--focused')}; + background: #{var-get($theme, 'file-selector-button-background--focused')}; + } + + %upload-button--focused { + --foreground: #{var-get($theme, 'file-selector-button-foreground--focused')}; + --background: transparent; + } + + %upload-button-wrapper--disabled { + color: #{var-get($theme, 'file-selector-button-foreground--disabled')}; + background: #{var-get($theme, 'file-selector-button-background--disabled')}; + } + + %upload-button--disabled { + --disabled-foreground: #{var-get($theme, 'file-selector-button-foreground--disabled')}; + --disabled-background: transparent; + } + + %clear-icon { + &:focus { + @if $variant == 'indigo' or $variant == 'fluent' { + background-color: color($color: 'primary', $variant: 500); + color: contrast-color($color: 'primary', $variant: 600); + } + + @if $variant == 'material' { + background-color: transparent; + color: color($color: 'secondary', $variant: 500); + } + + @if $variant == 'bootstrap' { + color: contrast-color($color: 'primary', $variant: 600); + background-color: color($color: 'primary', $variant: 500); + } + } + } +} + +/// Adds typography styles for the .igx-file-input. +/// Uses the 'subtitle-1', 'caption' +/// category from the typographic scale. +/// @group typography +/// @param {Map} $categories [(file-text: 'subtitle-1')] - The categories from the typographic scale used for type styles. +@mixin file-input-typography( + $categories: ( + file-text: 'subtitle-1' + ) +) { + $file-text: map.get($categories, 'file-text'); + + %file-names { + @include type-style($file-text) { + margin: 0; + } + } +} 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..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; } } @@ -233,10 +227,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) { @@ -306,7 +325,6 @@ } @include e(label) { - @extend %form-group-label--fixed !optional; @extend %form-group-label--disabled !optional; } @@ -319,7 +337,7 @@ } @include e(file-input) { - @extend %form-group-input--disabled !optional; + @extend %form-group-file-input--disabled !optional; } @include e(hint) { @@ -334,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; } @@ -369,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) { @@ -398,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 @@ -448,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; } @@ -561,6 +540,11 @@ @extend %form-group-bundle-search--disabled !optional; } } + + @include e(upload-button) { + @extend %upload-button !optional; + } + // BASE END // ============================== // @@ -575,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) { @@ -601,10 +580,6 @@ @include e(label) { @extend %fluent-label !optional; } - - @include e(upload-button) { - @extend %fluent-upload-button !optional; - } } @include mx(fluent, placeholder) { @@ -663,6 +638,10 @@ @include e(label) { @extend %fluent-label-filled !optional; } + + @include e(file-input) { + @extend %fluent-file-input !optional; + } } @include mx(fluent, textarea-group) { @@ -672,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) { @@ -689,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; @@ -708,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; } } @@ -808,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; } @@ -827,10 +785,6 @@ @include e(textarea) { @extend %indigo-textarea !optional; } - - @include e(upload-button) { - @extend %indigo-upload-button !optional; - } } @include mx(indigo, focused) { @@ -889,10 +843,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; } @@ -902,6 +852,56 @@ } } + @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 e(upload-button) { + @extend %bootstrap-upload-button !optional; + } + } + + @include mx(bootstrap, file, disabled) { + @include e(upload-button) { + @extend %bootstrap-file-disabled-upload-button !optional; + } + } + + @include mx(bootstrap, file, focused) { + @extend %bootstrap-file-focused !optional; + } + + @include mx(bootstrap, file, valid, focused) { + @extend %bootstrap-file-valid !optional; + } + + @include mx(bootstrap, file, warning, focused) { + @extend %bootstrap-file-warning !optional; + } + + @include mx(bootstrap, file, invalid, focused) { + @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; } @@ -910,6 +910,18 @@ @extend %form-group-display--bootstrap-suffixed !optional; } + @include mx(bootstrap, suffixed, focused) { + @extend %form-group-display--bootstrap-suffixed-focused !optional; + } + + @include mx(bootstrap, suffixed, valid) { + @extend %form-group-display--bootstrap-suffixed-valid !optional; + } + + @include mx(bootstrap, suffixed, invalid) { + @extend %form-group-display--bootstrap-suffixed-invalid !optional; + } + @include mx(bootstrap, search) { @include e(input) { @extend %bootstrap-input--search !optional; @@ -1001,34 +1013,34 @@ } @include mx(bootstrap, warning) { - @include e(input) { + @include e(input) { @extend %bootstrap-input--warning !optional; &:hover { @extend %bootstrap-input--warning !optional; } - } + } - @include e(file-input) { + @include e(file-input) { @extend %bootstrap-input--warning !optional; &:hover { @extend %bootstrap-input--warning !optional; } - } + } - @include e(label) { + @include e(label) { @extend %bootstrap-label !optional; - } + } - @include e(textarea) { + @include e(textarea) { @extend %bootstrap-input--warning !optional; &:hover { @extend %bootstrap-input--warning !optional; } - } - } + } + } @include mx(bootstrap, textarea-group) { @include e(bundle) { @@ -1046,41 +1058,13 @@ } @include e(file-input) { - @extend %bootstrap-input--disabled !optional; + @extend %bootstrap-file-input--disabled !optional; } @include e(textarea) { @extend %bootstrap-input--disabled !optional; } } - - @include mx(bootstrap, disabled, prefixed) { - @include e(input) { - @extend %bootstrap-input--disabled--prefixed !optional; - } - - @include e(file-input) { - @extend %bootstrap-input--disabled--prefixed !optional; - } - - @include e(textarea) { - @extend %bootstrap-input--disabled--prefixed !optional; - } - } - - @include mx(bootstrap, disabled, suffixed) { - @include e(input) { - @extend %bootstrap-input--disabled--suffixed !optional; - } - - @include e(file-input) { - @extend %bootstrap-input--disabled--suffixed !optional; - } - - @include e(textarea) { - @extend %bootstrap-input--disabled--suffixed !optional; - } - } // BOOTSTRAP END } } 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..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 @@ -602,6 +602,13 @@ 'indigo': 0, ), $variant); + $hint-min-size: map.get(( + 'material': rem(18px), + 'fluent': rem(18px), + 'bootstrap': rem(20px), + 'indigo': rem(15px), + ), $variant); + // Base Start %form-group-prefix--upload { padding: 0; @@ -702,10 +709,6 @@ font-family: inherit; } - input[type='file'] { - @include hide-default(); - } - textarea { overflow: auto; } @@ -760,7 +763,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 +887,7 @@ } %form-group-bundle--hover { - cursor: pointer; + //cursor: pointer; &::after { border-block-end-width: rem(1px); @@ -946,6 +949,288 @@ 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'); + + .igx-button { + border: none; + } + } + } + + %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'); + } + } + } + } + } + + %form-group-display--file { + %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%; + 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; + overflow: hidden; + } + + %form-group-display--bootstrap-file { + %form-group-bundle-start, + %form-group-bundle-end { + [igxPrefix], + igx-prefix { + height: var-get($theme, 'size'); + } + } + } + + %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'); + } + + %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; @@ -1521,11 +1806,13 @@ overflow: hidden; padding-block-start: $input-top-padding; padding-block-end: $input-bottom-padding; - height: calc(var-get($theme, 'size') - 2px); + height: var-get($theme, 'size'); + max-height: 100%; color: var-get($theme, 'filled-text-color'); span { @include ellipsis(); + position: relative; display: inline-block; width: inherit; @@ -1540,22 +1827,6 @@ } } - %form-group-clear-icon { - &:focus { - background-color: color($color: 'primary', $variant: 500); - color: contrast-color($color: 'primary', $variant: 600); - - @if $variant == 'material' { - background-color: transparent; - color: color($color: 'secondary', $variant: 500); - } - - @if $variant == 'bootstrap' { - color: contrast-color($color: 'primary', $variant: 600); - } - } - } - // 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. @@ -1573,12 +1844,6 @@ } } - %edge-clear-icon-fix { - &::-ms-clear { - display: none; - } - } - %form-group-file-input-indigo { padding-block: 0; } @@ -1611,6 +1876,14 @@ } } + %form-group-file-input--disabled { + cursor: default; + + &::placeholder { + color: var-get($theme, 'disabled-placeholder-color'); + } + } + %form-group-textarea { --textarea-size: #{sizable( rem(82px, map.get($base-scale-size, 'compact')), @@ -1800,10 +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: flex; - padding-block-start: $hint-spacing-block; + display: grid; + grid-auto-rows: minmax($hint-min-size, auto); padding-inline: $hint-spacing-inline; justify-content: space-between; @@ -1817,11 +2093,7 @@ } &:empty { - @if $variant == 'fluent' { - padding: 0; - } @else { - display: none; - } + display: none; } } @@ -1943,13 +2215,6 @@ border-bottom-style: solid; } } - - %indigo-upload-button { - [igxButton] { - min-height: 0; - height: calc(100% - #{rem(8px)}); - } - } // INDIGO END // ============================================== @@ -2045,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 { @@ -2118,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 { @@ -2155,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)); @@ -2180,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); @@ -2216,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); } @@ -2261,9 +2509,6 @@ } } - %fluent-upload-button { - padding: 0; - } // FLUENT END // ============================================== @@ -2296,6 +2541,39 @@ }; } } + + .igx-input-group__clear-icon + igx-suffix, + .igx-input-group__clear-icon + [igxPrefix] { + border-inline-start: rem(1px) solid var-get($theme, 'border-color'); + } + } + + %form-group-display--bootstrap-suffixed-focused { + .igx-input-group__clear-icon + igx-suffix, + .igx-input-group__clear-icon + [igxPrefix] { + border-color: var-get($theme, 'focused-border-color'); + } + } + + %form-group-display--bootstrap-suffixed-valid { + .igx-input-group__clear-icon + igx-suffix, + .igx-input-group__clear-icon + [igxPrefix] { + border-color: var-get($theme, 'success-secondary-color'); + } + } + + %form-group-display--bootstrap-suffixed-form-group-display--bootstrap-suffixed-warning { + .igx-input-group__clear-icon + igx-suffix, + .igx-input-group__clear-icon + [igxPrefix] { + border-color: var-get($theme, 'warning-secondary-color'); + } + } + + %form-group-display--bootstrap-suffixed-invalid { + .igx-input-group__clear-icon + igx-suffix, + .igx-input-group__clear-icon + [igxPrefix] { + border-color: var-get($theme, 'error-secondary-color'); + } } %form-group-display--disabled-bootstrap { @@ -2405,7 +2683,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 +2725,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 +2760,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'); @@ -2501,6 +2795,11 @@ box-shadow: none; } + %bootstrap-file-input--disabled { + border: rem(1px) solid var-get($theme, 'disabled-border-color'); + box-shadow: none; + } + %bootstrap-input--search { transform: translateY(0); } @@ -2511,16 +2810,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. @@ -2544,9 +2833,7 @@ } %form-group-helper { - @include type-style($helper-text) { - margin: 0; - } + @include type-style($helper-text); } %form-group-prefix, diff --git a/projects/igniteui-angular/src/lib/core/styles/themes/_core.scss b/projects/igniteui-angular/src/lib/core/styles/themes/_core.scss index 7f13940af1f..d2ad9978939 100644 --- a/projects/igniteui-angular/src/lib/core/styles/themes/_core.scss +++ b/projects/igniteui-angular/src/lib/core/styles/themes/_core.scss @@ -80,6 +80,7 @@ @use '../components/time-picker/time-picker-component' as time-picker; @use '../components/tree/tree-component' as tree; @use '../components/watermark/watermark-component' as watermark; +@use '../components/input/file-input-component' as file-input; @use '../print'; /// @param {boolean} $print-layout [true] - Activates the printing styles of the components. @@ -196,6 +197,7 @@ @include time-picker.component(); @include tree.component(); @include watermark.component(); + @include file-input.component(); // Build the component dependency-tree @include base.dependecy-tree(base.$components); diff --git a/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss b/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss index 072eeaf10e8..90ea11f5523 100644 --- a/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss +++ b/projects/igniteui-angular/src/lib/core/styles/themes/generators/_base.scss @@ -572,6 +572,17 @@ @include input-group($input-group-theme-map); } + @if is-used('igx-file-input', $exclude) { + $file-input-theme-map: file-input-theme( + $schema: $schema, + ); + $file-input-theme-map: meta.call( + $theme-handler, + $file-input-theme-map + ); + @include file-input($file-input-theme-map); + } + @if is-used('igx-list', $exclude) { $list-theme-map: list-theme( $schema: $schema, diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss index 97c8a89c9a4..2bb1b767151 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_bootstrap.scss @@ -33,6 +33,7 @@ @use '../components/tree/tree-theme' as *; @use '../components/label/label-theme' as *; @use '../components/query-builder/query-builder-theme' as *; +@use '../components/input/file-input-theme' as *; @mixin typography($type-scale) { @include badge-typography(); @@ -80,6 +81,9 @@ helper-text: 'body-2', input-text: 'body-1' )); + @include file-input-typography($categories: ( + file-text: 'body-1' + )); @include linear-bar-typography(); @include list-typography($categories: ( item: 'body-2', diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss index 03987eca9c2..2b8a6323070 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_fluent.scss @@ -32,6 +32,7 @@ @use '../components/tree/tree-theme' as *; @use '../components/label/label-theme' as *; @use '../components/query-builder/query-builder-theme' as *; +@use '../components/input/file-input-theme' as *; @mixin typography() { @include badge-typography(); @@ -83,6 +84,9 @@ helper-text: 'caption', input-text: 'body-2' )); + @include file-input-typography($categories: ( + file-text: 'body-2' + )); @include linear-bar-typography(); @include list-typography($categories: ( header: 'overline', @@ -100,6 +104,7 @@ @include radio-typography($categories: ( label: 'body-2' )); + @include slider-typography(); @include snackbar-typography($categories: ( text: 'caption' diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss index ee8596057e2..737346995c4 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_indigo.scss @@ -32,6 +32,7 @@ @use '../components/tree/tree-theme' as *; @use '../components/label/label-theme' as *; @use '../components/query-builder/query-builder-theme' as *; +@use '../components/input/file-input-theme' as *; @mixin typography($type-scale) { @include badge-typography($categories: ( @@ -78,6 +79,11 @@ helper-text: 'caption', input-text: 'body-2' )); + + @include file-input-typography($categories: ( + file-text: 'body-2' + )); + @include linear-bar-typography(); @include list-typography($categories: ( header: 'overline', diff --git a/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss b/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss index 8920a178e02..bc15191255c 100644 --- a/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss +++ b/projects/igniteui-angular/src/lib/core/styles/typography/_material.scss @@ -32,6 +32,7 @@ @use '../components/tree/tree-theme' as *; @use '../components/label/label-theme' as *; @use '../components/query-builder/query-builder-theme' as *; +@use '../components/input/file-input-theme' as *; @mixin typography() { @include badge-typography(); @@ -68,4 +69,5 @@ @include tree-typography(); @include label-typography(); @include query-builder-typography(); + @include file-input-typography(); } diff --git a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts index 8cccd6a2275..ea426fde4b9 100644 --- a/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts +++ b/projects/igniteui-angular/src/lib/date-range-picker/date-range-picker-inputs.common.ts @@ -126,7 +126,7 @@ export class IgxDateRangeInputsBaseComponent extends IgxInputGroupComponent { { provide: IgxInputGroupBase, useExisting: IgxDateRangeStartComponent }, { provide: IgxDateRangeInputsBaseComponent, useExisting: IgxDateRangeStartComponent } ], - imports: [NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, NgClass, IgxSuffixDirective, IgxIconComponent] + imports: [NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, IgxSuffixDirective, IgxIconComponent] }) export class IgxDateRangeStartComponent extends IgxDateRangeInputsBaseComponent { } @@ -161,7 +161,7 @@ export class IgxDateRangeStartComponent extends IgxDateRangeInputsBaseComponent { provide: IgxInputGroupBase, useExisting: IgxDateRangeEndComponent }, { provide: IgxDateRangeInputsBaseComponent, useExisting: IgxDateRangeEndComponent } ], - imports: [NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, NgClass, IgxSuffixDirective, IgxIconComponent] + imports: [NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, IgxSuffixDirective, IgxIconComponent] }) export class IgxDateRangeEndComponent extends IgxDateRangeInputsBaseComponent { } 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..488a6851f85 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,26 +22,29 @@ + + + @if (isFileType) { - +
- +
}
@if (isFileType) {
{{ fileNames }} @@ -52,7 +55,7 @@ @if (isFileType && isFilled) {
-
@@ -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..4e2140a5345 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 @@ -10,7 +10,8 @@ import { HostListener, Inject, Input, Optional, QueryList, booleanAttribute, inject, - DOCUMENT + DOCUMENT, + AfterContentChecked } from '@angular/core'; import { IInputResourceStrings, InputResourceStringsEN } from '../core/i18n/input-resources'; import { PlatformUtil, getComponentTheme } from '../core/utils'; @@ -33,9 +34,9 @@ import { IgxTheme, THEME_TOKEN, ThemeToken } from '../services/theme/theme.token selector: 'igx-input-group', templateUrl: 'input-group.component.html', providers: [{ provide: IgxInputGroupBase, useExisting: IgxInputGroupComponent }], - imports: [NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, NgClass, IgxSuffixDirective, IgxIconComponent] + imports: [NgTemplateOutlet, IgxPrefixDirective, IgxButtonDirective, IgxSuffixDirective, IgxIconComponent] }) -export class IgxInputGroupComponent implements IgxInputGroupBase { +export class IgxInputGroupComponent implements IgxInputGroupBase, AfterContentChecked { /** * Sets the resource strings. * By default it uses EN resources. @@ -270,7 +271,7 @@ export class IgxInputGroupComponent implements IgxInputGroupBase { /** @hidden @internal */ @HostBinding('class.igx-input-group--prefixed') public get hasPrefixes() { - return this._prefixes.length > 0 || this.isFileType; + return this._prefixes.length > 0; } /** @hidden @internal */ @@ -335,11 +336,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(); @@ -351,6 +347,30 @@ export class IgxInputGroupComponent implements IgxInputGroupBase { return this.input.type === 'file'; } + /** @hidden @internal */ + @HostBinding('class.igx-file-input') + public get isFileInput() { + return this.input.type === 'file'; + } + + /** @hidden @internal */ + @HostBinding('class.igx-file-input--filled') + public get isFileInputFilled() { + return this.isFileType && this.isFilled; + } + + /** @hidden @internal */ + @HostBinding('class.igx-file-input--focused') + public get isFileInputFocused() { + return this.isFileType && this.isFocused; + } + + /** @hidden @internal */ + @HostBinding('class.igx-file-input--disabled') + public get isFileInputDisabled() { + return this.isFileType && this.disabled; + } + /** @hidden @internal */ public get fileNames() { return this.input.fileNames || this._resourceStrings.igx_input_file_placeholder; 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..69264ed29cc 100644 --- a/src/app/input-group-showcase/input-group-showcase.sample.html +++ b/src/app/input-group-showcase/input-group-showcase.sample.html @@ -15,23 +15,32 @@

Angular

#field [type]="getInputGroupType()" [style.--ig-size]="getSize()"> + @if (getLabel()) { } - face + + @if (hidePrefix()) { + face + } + - @if (!hideSuffix()) { + + @if (hideSuffix()) { face } - Type your web address + + @if (getHint()) { + {{getHint()}} + } @@ -42,20 +51,25 @@

Angular

@if (getLabel()) { } - face + + @if (hidePrefix()) { + face + } - @if (!hideSuffix()) { + + @if (hideSuffix()) { face } - Hint text + @if (getHint()) { + {{getHint()}} + } @@ -68,14 +82,17 @@

Angular

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

Angular

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

Angular

#fieldFile [type]="getInputGroupType()" [style.--ig-size]="getSize()"> + @if (getLabel()) { - + } - face + + @if (hidePrefix()) { + face + } + - @if (!hideSuffix()) { + + @if (hideSuffix()) { face } - Type your web address + + @if (getHint()) { + {{getHint()}} + } @@ -162,17 +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 (!hideSuffix()) { - + + @if (hidePrefix()) { + + } + + @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 (!hideSuffix()) { - + + @if (hidePrefix()) { + + } + + @if (hideSuffix()) { + + } + + @if (getHint()) { + {{getHint()}} } - Hint text - - @if (!hideSuffix()) { - + [required]="isRequired()" + [attr.placeholder]="getPlaceholder()" + [label]="getLabel()" + [disabled]="isDisabled()" + [outlined]="isOutlined()" + [style.--ig-size]="getSize()"> + + @if (hidePrefix()) { + + } + + @if (getHint()) { + {{getHint()}} } - I am a Hint Apple Orange Grapes @@ -216,17 +269,31 @@

Web components

[outlined]="isOutlined()" [disabled]="isDisabled()" [style.--ig-size]="getSize()"> - I am a Hint - - @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); }