diff --git a/src/components/combo/themes/shared/combo.fluent.scss b/src/components/combo/themes/shared/combo.fluent.scss index ebe753dc1..c279f28d4 100644 --- a/src/components/combo/themes/shared/combo.fluent.scss +++ b/src/components/combo/themes/shared/combo.fluent.scss @@ -27,10 +27,27 @@ $dropdown-theme: dropdown-theme.$fluent; igc-input::part(container) { background: transparent; - border-inline-start: 0; - border-inline-end-color: transparent; - border-block-start: 0; border-radius: 0; + border-inline: 0; + border-block-start: 0; + + &::before { + inset-inline-start: 0; + width: calc(100% - var(--input-border-size)); + + // The shadow color is set by the color: prop set on the input-group [part=container]::before element + // Here we only change the shadow to look like border bottom + box-shadow: inset 0 calc(var(--input-border-size) * -1) 0 0; + border-radius: 0; + } + } + + igc-input:focus-within::part(container) { + &::before { + // The shadow color is set by the color: prop set on the input-group [part=container]::before element + // Here we only change the shadow to look like border bottom + box-shadow: inset 0 calc((var(--input-border-size) + #{rem(1px)}) * -1) 0 0; + } } igc-input::part(start) { @@ -80,23 +97,6 @@ $dropdown-theme: dropdown-theme.$fluent; } } -:host([invalid]:focus-within) { - igc-input::part(input) { - height: calc(var(--size) - #{rem(4px)}); - } - - igc-input::part(suffix) { - height: var(--size); - margin-inline-end: rem(-1px); - margin-block-start: rem(-2px); - } - - igc-input::part(prefix) { - margin-inline-start: rem(-1px); - margin-block-start: rem(-2px); - } -} - :host(:disabled), :host([disabled]) { ::slotted([slot='prefix']), diff --git a/src/components/date-range-picker/themes/shared/date-range-picker.fluent.scss b/src/components/date-range-picker/themes/shared/date-range-picker.fluent.scss index 26db16a76..1c51fa226 100644 --- a/src/components/date-range-picker/themes/shared/date-range-picker.fluent.scss +++ b/src/components/date-range-picker/themes/shared/date-range-picker.fluent.scss @@ -33,23 +33,11 @@ $theme: $fluent; } } -:host(:not([invalid])[readonly]:hover) { - igc-input::part(container), - igc-date-time-input::part(container) { - border-color: var-get($theme, 'border-color'); - } -} - -:host(:not([invalid])[readonly]:focus-within) { - igc-input::part(container) { - border-color: var-get($theme, 'focused-border-color'); - } -} - -:host(:not([invalid])[readonly]) { - igc-date-time-input:focus-within { - &::part(container) { - border-color: var-get($theme, 'focused-border-color'); +:host(:not([readonly], [invalid], [disabled])) { + igc-input[readonly]:not(:focus):hover::part(container) { + &::before { + // This represents the shadow color + color: var-get($theme, 'hover-border-color'); } } } diff --git a/src/components/input/themes/shared/input.fluent.scss b/src/components/input/themes/shared/input.fluent.scss index 7d503b65e..7c1fc255e 100644 --- a/src/components/input/themes/shared/input.fluent.scss +++ b/src/components/input/themes/shared/input.fluent.scss @@ -2,20 +2,18 @@ @use '../light/themes' as *; $theme: $fluent; -$resting-border-width: rem(1px); -$focused-border-width: rem(2px); -$resting-height: calc(var-get($theme, 'size') - #{($resting-border-width * 2)}); -$focused-height: calc(var-get($theme, 'size') - #{($focused-border-width * 2)}); :host { --component-size: var(--ig-size, #{var-get($theme, 'default-size')}); --input-size: var(--component-size); --helper-text-top-spacer: rem(5px); + --input-border-size: #{rem(1px)}; [part='prefix'], [part='suffix'] { font-size: rem(14px); cursor: default; + z-index: 0; ::slotted(*) { color: inherit; @@ -59,17 +57,35 @@ $focused-height: calc(var-get($theme, 'size') - #{($focused-border-width * 2)}); [part^='container'] { height: var-get($theme, 'size'); + background: var-get($theme, 'border-background'); + border: var(--input-border-size) solid transparent; border-radius: var-get($theme, 'border-border-radius'); - border: #{$resting-border-width} solid var-get($theme, 'border-color'); transition: none; cursor: text; grid-template-columns: auto 1fr auto; - overflow: hidden; + + &::before { + content: ''; + position: absolute; + inset: calc(var(--input-border-size) * -1); + width: calc(100% + (var(--input-border-size) * 2)); + height: calc(100% + (var(--input-border-size) * 2)); + + // The color: here is the actual box-shadow color. If we don't provide color-value to the shadow it + // defaults to the css color: prop the same way as border-color: do. + // We do this in order to have the shadow working correctly inside the Combo search + // We can't change the var-get($theme, 'border-color') in the combo search, but we can change the shadow + color: var-get($theme, 'border-color'); + box-shadow: inset 0 0 0 var(--input-border-size); + border-radius: var-get($theme, 'border-border-radius'); + user-select: none; + pointer-events: none; + z-index: 1; + } } [part~='input'] { color: var-get($theme, 'idle-text-color'); - height: $resting-height; background: initial; font-size: rem(14px); padding-inline: rem(8px); @@ -79,47 +95,58 @@ $focused-height: calc(var-get($theme, 'size') - #{($focused-border-width * 2)}); } } -:host(:not([aria-haspopup='dialog'],[role='combobox'])[readonly]) { - [part='prefix'], - [part='suffix'] { - background: transparent; +:host(:not([readonly], [invalid], :focus-within):hover) { + [part^='container'] { + &::before { + // The color: here is the actual box-shadow color. If we don't provide color-value to the shadow it + // defaults to the css color: prop the same way as border-color: do. + // We do this in order to have the shadow working correctly inside the Combo search + // We can't change the var-get($theme, 'hover-border-color') in the combo search, but we can change the shadow + color: var-get($theme, 'hover-border-color'); + box-shadow: inset 0 0 0 var(--input-border-size); + } } } -:host(:not([aria-haspopup='dialog'],[role='combobox'])[readonly]:hover) { +:host([aria-expanded][readonly]:not([invalid], :focus-within):hover) { [part^='container'] { - border-color: var-get($theme, 'border-color'); + &::before { + // The color: here is the actual box-shadow color. If we don't provide color-value to the shadow it + // defaults to the css color: prop the same way as border-color: do. + // We do this in order to have the shadow working correctly inside the Combo search + // We can't change the var-get($theme, 'hover-border-color') in the combo search, but we can change the shadow + color: var-get($theme, 'hover-border-color'); + box-shadow: inset 0 0 0 var(--input-border-size); + } } } -:host(:not([aria-haspopup='dialog'],[role='combobox'])[readonly]:focus-within) { +:host([aria-haspopup]:not([readonly], [invalid], :focus-within):hover) { [part^='container'] { - border-color: var-get($theme, 'focused-border-color'); + &::before { + color: var-get($theme, 'hover-border-color'); + box-shadow: inset 0 0 0 var(--input-border-size); + } } } -:host(:hover) { - [part^='container'] { - border-color: var-get($theme, 'hover-border-color'); +:host(:not([aria-haspopup],[aria-expanded])[readonly]) { + [part='prefix'], + [part='suffix'] { + background: transparent; } } :host(:focus-within) { [part^='container'] { - border-color: var-get($theme, 'focused-border-color'); - border-width: #{$focused-border-width}; - } - - [part~='input'] { - height: $focused-height; - } - - [part='prefix'] { - margin-inline-start: rem(-1px); - } - - [part='suffix'] { - margin-inline-end: rem(-1px); + &::before { + // The color: here is the actual box-shadow color. If we don't provide color-value to the shadow it + // defaults to the css color: prop the same way as border-color: do. + // We do this in order to have the shadow working correctly inside the Combo search + // We can't change the var-get($theme, 'focused-border-color') in the combo search, but we can change the shadow + color: var-get($theme, 'focused-border-color'); + box-shadow: inset 0 0 0 calc(var(--input-border-size) + #{rem(1px)}); + } } [name='prefix']::slotted(*), @@ -166,15 +193,32 @@ $focused-height: calc(var-get($theme, 'size') - #{($focused-border-width * 2)}); :host([invalid]:hover), :host([readonly][invalid]:hover), :host([readonly][invalid]:focus-within) { - [part^='container'] { - border-color: var-get($theme, 'error-secondary-color'); + ::part(helper-text) { + color: var-get($theme, 'error-secondary-color'); + } + + [part~='container'] { + &::before { + box-shadow: inset 0 0 0 var(--input-border-size) var-get($theme, 'error-secondary-color'); + } + } +} + +:host([invalid]:focus-within), +:host([readonly][invalid]:focus-within) { + [part~='container'] { + &::before { + box-shadow: inset 0 0 0 calc(var(--input-border-size) + #{rem(1px)}) var-get($theme, 'error-secondary-color'); + } } } :host(:disabled), :host([disabled]) { - [part^='container'] { - border-color: var-get($theme, 'disabled-border-color'); + [part~='container'] { + &::before { + box-shadow: inset 0 0 0 var(--input-border-size) var-get($theme, 'disabled-border-color'); + } } [part^='container'], diff --git a/src/components/select/themes/shared/select.fluent.scss b/src/components/select/themes/shared/select.fluent.scss index d6470f2c2..5fe19d48e 100644 --- a/src/components/select/themes/shared/select.fluent.scss +++ b/src/components/select/themes/shared/select.fluent.scss @@ -6,7 +6,6 @@ $theme: $fluent; $dropdown-theme: dropdown-theme.$fluent; $input-theme: input-theme.$fluent; -$focused-border-width: rem(2px); :host { --component-size: var(--ig-size, #{var-get($theme, 'default-size')}); @@ -40,23 +39,21 @@ $focused-border-width: rem(2px); background: var-get($theme, 'toggle-button-background-focus'); } - igc-input[readonly]:not([disabled])::part(container) { - border-width: #{$focused-border-width}; - } } :host(:not([invalid]):focus-within) { igc-input[readonly]:not([disabled])::part(container) { - border-color: var-get($input-theme, 'focused-border-color'); - border-width: #{$focused-border-width}; - } - - igc-input[readonly]:not([disabled])::part(prefix) { - margin-inline-start: rem(-1px); + &::before { + box-shadow: inset 0 0 0 calc((var(--input-border-size) + #{rem(1px)})) var-get($input-theme, 'focused-border-color'); + } } +} - igc-input[readonly]:not([disabled])::part(suffix) { - margin-inline-end: rem(-1px); +:host([invalid]:focus-within) { + igc-input[readonly]:not([disabled])::part(container) { + &::before { + box-shadow: inset 0 0 0 calc((var(--input-border-size) + #{rem(1px)})) var-get($input-theme, 'error-secondary-color'); + } } } @@ -82,3 +79,4 @@ $focused-border-width: rem(2px); } } } + diff --git a/src/components/textarea/themes/shared/textarea.fluent.scss b/src/components/textarea/themes/shared/textarea.fluent.scss index 7b0460ce1..e4e75b855 100644 --- a/src/components/textarea/themes/shared/textarea.fluent.scss +++ b/src/components/textarea/themes/shared/textarea.fluent.scss @@ -2,11 +2,13 @@ @use '../light/themes' as *; $theme: $fluent; +$border-size: rem(1px); :host { @include type-style('body-2'); --component-size: var(--ig-size, #{var-get($theme, 'default-size')}); + --textarea-border-size: #{rem(1px)}; ::part(helper-text) { @include type-style('caption'); @@ -17,44 +19,6 @@ $theme: $fluent; } } -:host(:hover) { - [part~='container'] { - border-color: var-get($theme, 'hover-border-color'); - } -} - -:host(:focus-within) { - [part~='container'] { - border-color: var-get($theme, 'focused-border-color'); - border-width: rem(2px); - } - - [part~='prefix']:not([hidden]) { - margin-inline-start: rem(-1px); - } - - [part~='suffix']:not([hidden]) { - margin-inline-end: rem(-1px); - } - - textarea { - margin-block: rem(-1px); - margin-inline-start: rem(-1px); - } - - [part~='prefix']:not([hidden]) ~ textarea { - margin-inline: initial; - } -} - -[part~='container'] { - border: rem(1px) solid var-get($theme, 'border-color'); - background: var-get($theme, 'border-background'); - align-items: stretch; - overflow: hidden; - border-radius: var-get($theme, 'border-border-radius'); -} - [part~='label'] { @include type-style('subtitle-2') { --ig-subtitle-2-line-height: #{rem(16px)}; @@ -67,8 +31,44 @@ $theme: $fluent; transform: translateY(0); transform-origin: top left; height: auto; +} +[part~='container'] { + position: relative; + background: var-get($theme, 'border-background'); + border: var(--textarea-border-size) solid transparent; + align-items: stretch; + border-radius: var-get($theme, 'border-border-radius'); + + &::before { + content: ''; + position: absolute; + inset: calc(var(--textarea-border-size) * -1); + width: calc(100% + (var(--textarea-border-size) * 2)); + height: calc(100% + (var(--textarea-border-size) * 2)); + box-shadow: inset 0 0 0 var(--textarea-border-size) var-get($theme, 'border-color'); + border-radius: var-get($theme, 'border-border-radius'); + user-select: none; + pointer-events: none; + z-index: 1; + } +} + + +:host(:not([readonly], [invalid], :focus-within):hover) { + [part~='container'] { + &::before { + box-shadow: inset 0 0 0 var(--textarea-border-size) var-get($theme, 'hover-border-color'); + } + } +} +:host(:focus-within) { + [part~='container'] { + &::before { + box-shadow: inset 0 0 0 calc(var(--textarea-border-size) + #{rem(1px)}) var-get($theme, 'focused-border-color'); + } + } } :host([invalid]) { @@ -99,14 +99,28 @@ textarea { } [part~='container'] { - border-color: var-get($theme, 'error-secondary-color'); + &::before { + box-shadow: inset 0 0 0 var(--textarea-border-size) var-get($theme, 'error-secondary-color') + } + } +} + +:host(:not(:disabled)[invalid]:focus-within), +:host(:not([disabled])[invalid]:focus-within) { + [part^='container'] { + &::before { + box-shadow: inset 0 0 0 calc(var(--textarea-border-size) + #{rem(1px)}) var-get($theme, 'error-secondary-color'); + } } } :host(:disabled), :host([disabled]) { [part~='container'] { - border-color: var-get($theme, 'disabled-border-color'); background: var-get($theme, 'border-disabled-background'); + + &::before { + box-shadow: inset 0 0 0 var(--textarea-border-size) var-get($theme, 'disabled-border-color'); + } } }