From 67a3795ba8aca38196bf6561b03f4346daedf3e2 Mon Sep 17 00:00:00 2001 From: Bartosz-Do Date: Mon, 21 Sep 2026 15:24:35 +0200 Subject: [PATCH] Fix validation colors on `.input-group-text` in `.input-group-flat` (#3111) --- .changeset/fix-input-group-flat-validation.md | 5 ++++ core/scss/tests/input-group-flat.test.mjs | 23 +++++++++++++++++++ core/scss/ui/_forms.scss | 22 ++++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 .changeset/fix-input-group-flat-validation.md create mode 100644 core/scss/tests/input-group-flat.test.mjs diff --git a/.changeset/fix-input-group-flat-validation.md b/.changeset/fix-input-group-flat-validation.md new file mode 100644 index 000000000..e2c679889 --- /dev/null +++ b/.changeset/fix-input-group-flat-validation.md @@ -0,0 +1,5 @@ +--- +"@tabler/core": patch +--- + +Fixed `.input-group-flat` so `.input-group-text` follows the `.is-valid` and `.is-invalid` border and focus colors. diff --git a/core/scss/tests/input-group-flat.test.mjs b/core/scss/tests/input-group-flat.test.mjs new file mode 100644 index 000000000..24b432efb --- /dev/null +++ b/core/scss/tests/input-group-flat.test.mjs @@ -0,0 +1,23 @@ +import { describe, expect, it } from 'vitest' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import { compile as compileSass } from 'sass' + +const scssDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..') +const { css } = compileSass(path.join(scssDir, 'ui', '_forms.scss'), { loadPaths: ['node_modules'], style: 'expanded' }) +const flat = css.replace(/\s+/g, ' ') + +describe('input-group-flat validation', () => { + it.each(['valid', 'invalid'])('carries the %s border color over to the input-group-text', (state) => { + expect(flat).toContain(`.input-group-flat:has(.form-control.is-${state}) .input-group-text`) + }) + + it.each(['valid', 'invalid'])('follows .was-validated for the :%s pseudo-class', (state) => { + expect(flat).toContain(`.was-validated .input-group-flat:has(.form-control:${state}) .input-group-text`) + }) + + it.each(['valid', 'invalid'])('keeps the %s color while the group has focus', (state) => { + expect(flat).toMatch(new RegExp(`\\.input-group-flat:has\\(\\.form-control\\.is-${state}\\):focus-within[^{]*\\{ outline-color: [^;]+; \\}`)) + expect(flat).toMatch(new RegExp(`\\.input-group-flat:has\\(\\.form-control\\.is-${state}\\):focus-within \\.form-control,[^{]*\\.input-group-text \\{ border-color: [^;]+ !important; \\}`)) + }) +}) diff --git a/core/scss/ui/_forms.scss b/core/scss/ui/_forms.scss index 626977e30..c53b8ae53 100644 --- a/core/scss/ui/_forms.scss +++ b/core/scss/ui/_forms.scss @@ -1,3 +1,4 @@ +@use 'sass:map'; @use '../config' as *; textarea { @@ -211,6 +212,27 @@ Input group border-inline-start: 0; } } + + @each $state, $data in $form-validation-states { + $border-color: map.get($data, 'border-color'); + $focus-ring-color: map.get($data, 'focus-ring-color'); + + &:has(.form-control.is-#{$state}), + .was-validated &:has(.form-control:#{$state}) { + .input-group-text { + border-color: $border-color; + } + + &:focus-within { + outline-color: $focus-ring-color; + + .form-control, + .input-group-text { + border-color: $border-color !important; + } + } + } + } } /**