From c8f32dbefea93f3151dbf96e0862261b3a30ffa4 Mon Sep 17 00:00:00 2001 From: James Brooks <52410024+jabrks@users.noreply.github.com> Date: Wed, 7 May 2025 18:35:37 +0100 Subject: [PATCH] Canon - Styling fixes for field clear button (#29878) I spotted a couple of problems with the new clear button added to the TextField in #29820. Firstly, it did not use the correct colour token and therefore was not visible in dark mode. Secondly, for fields without a fixed width, the field would grow/shrink in size as the button was shown or hidden. Both of these issues have been rectified here --- .changeset/chatty-months-grow.md | 5 +++++ packages/canon/css/components.css | 10 +++++++++- packages/canon/css/styles.css | 10 +++++++++- packages/canon/css/textfield.css | 10 +++++++++- .../src/components/TextField/TextField.stories.tsx | 2 +- .../src/components/TextField/TextField.styles.css | 10 +++++++++- 6 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 .changeset/chatty-months-grow.md diff --git a/.changeset/chatty-months-grow.md b/.changeset/chatty-months-grow.md new file mode 100644 index 0000000000..1495e7732e --- /dev/null +++ b/.changeset/chatty-months-grow.md @@ -0,0 +1,5 @@ +--- +'@backstage/canon': patch +--- + +Use correct colour token for TextField clear button icon, prevent layout shift whenever it is hidden or shown and properly size focus area around it. Also stop leading icon shrinking when used together with clear button. diff --git a/packages/canon/css/components.css b/packages/canon/css/components.css index c122251b5b..6aae715633 100644 --- a/packages/canon/css/components.css +++ b/packages/canon/css/components.css @@ -581,6 +581,7 @@ width: 1.5rem; height: 1.5rem; color: var(--canon-fg-primary); + flex-shrink: 0; display: block; } @@ -594,18 +595,25 @@ cursor: inherit; background: none; border: none; + padding: 0; transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; } +.canon-TextFieldInput:not([data-filled]):has( + .canon-TextFieldClearButton) { + padding-right: 1.25rem; +} + .canon-TextFieldInput[type="search"]::-webkit-search-cancel-button, .canon-TextFieldInput[type="search"]::-webkit-search-decoration { appearance: none; } .canon-TextFieldClearButton { - padding: 0 0 0 var(--canon-space-1); + margin-left: var(--canon-space-1); vertical-align: middle; + color: var(--canon-fg-primary); background: none; border: none; + padding: 0; display: none; } diff --git a/packages/canon/css/styles.css b/packages/canon/css/styles.css index d1f3ba045d..5fb6a934cb 100644 --- a/packages/canon/css/styles.css +++ b/packages/canon/css/styles.css @@ -9805,6 +9805,7 @@ width: 1.5rem; height: 1.5rem; color: var(--canon-fg-primary); + flex-shrink: 0; display: block; } @@ -9818,18 +9819,25 @@ cursor: inherit; background: none; border: none; + padding: 0; transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; } +.canon-TextFieldInput:not([data-filled]):has( + .canon-TextFieldClearButton) { + padding-right: 1.25rem; +} + .canon-TextFieldInput[type="search"]::-webkit-search-cancel-button, .canon-TextFieldInput[type="search"]::-webkit-search-decoration { appearance: none; } .canon-TextFieldClearButton { - padding: 0 0 0 var(--canon-space-1); + margin-left: var(--canon-space-1); vertical-align: middle; + color: var(--canon-fg-primary); background: none; border: none; + padding: 0; display: none; } diff --git a/packages/canon/css/textfield.css b/packages/canon/css/textfield.css index d55b5b6f2c..a2980d6beb 100644 --- a/packages/canon/css/textfield.css +++ b/packages/canon/css/textfield.css @@ -48,6 +48,7 @@ width: 1.5rem; height: 1.5rem; color: var(--canon-fg-primary); + flex-shrink: 0; display: block; } @@ -61,18 +62,25 @@ cursor: inherit; background: none; border: none; + padding: 0; transition: border-color .2s ease-in-out, outline-color .2s ease-in-out; } +.canon-TextFieldInput:not([data-filled]):has( + .canon-TextFieldClearButton) { + padding-right: 1.25rem; +} + .canon-TextFieldInput[type="search"]::-webkit-search-cancel-button, .canon-TextFieldInput[type="search"]::-webkit-search-decoration { appearance: none; } .canon-TextFieldClearButton { - padding: 0 0 0 var(--canon-space-1); + margin-left: var(--canon-space-1); vertical-align: middle; + color: var(--canon-fg-primary); background: none; border: none; + padding: 0; display: none; } diff --git a/packages/canon/src/components/TextField/TextField.stories.tsx b/packages/canon/src/components/TextField/TextField.stories.tsx index df2eb63be3..0615a157a1 100644 --- a/packages/canon/src/components/TextField/TextField.stories.tsx +++ b/packages/canon/src/components/TextField/TextField.stories.tsx @@ -130,7 +130,7 @@ export const WithOnClear: Story = { ...WithLabel.args, placeholder: 'Search...', type: 'search', - onClear: () => null, + onClear: () => console.log('Cleared!'), }, }; diff --git a/packages/canon/src/components/TextField/TextField.styles.css b/packages/canon/src/components/TextField/TextField.styles.css index ae901c5cc1..ad3ccc931b 100644 --- a/packages/canon/src/components/TextField/TextField.styles.css +++ b/packages/canon/src/components/TextField/TextField.styles.css @@ -65,6 +65,7 @@ width: 1.5rem; height: 1.5rem; color: var(--canon-fg-primary); + flex-shrink: 0; } .canon-TextFieldInput { @@ -78,6 +79,11 @@ width: 100%; height: 100%; cursor: inherit; + padding: 0; +} + +.canon-TextFieldInput:not([data-filled]):has(+ .canon-TextFieldClearButton) { + padding-right: 1.25rem; } .canon-TextFieldInput[type='search']::-webkit-search-cancel-button, @@ -87,10 +93,12 @@ .canon-TextFieldClearButton { display: none; - padding: 0 0 0 var(--canon-space-1); + padding: 0; + margin-left: var(--canon-space-1); background: none; border: none; vertical-align: middle; + color: var(--canon-fg-primary); } .canon-TextFieldInput[data-filled] + .canon-TextFieldClearButton {