refactor(search): improve TextInput clear button styling and add component unit tests (#7578)

# Description of Changes

FIxes minor stylistic problem about the search bar. Mainly the X and the
spacing on the result's icons vs text.


### New
<img width="1594" height="600" alt="image"
src="https://github.com/user-attachments/assets/f3710cad-f1a6-4aa1-9c2a-f3f474fd2dd6"
/>


### Old
<img width="1584" height="618" alt="image"
src="https://github.com/user-attachments/assets/2d9c26a8-2d68-4d86-9d51-b12f90b17fe0"
/>


<!--
Please provide a summary of the changes, including:

- What was changed
- Why the change was made
- Any challenges encountered

Closes #(issue_number)
-->

---

## Checklist

### General

- [X] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [X] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [X] I have performed a self-review of my own code
- [X] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [X] I have run `task check` to verify linters, typechecks, and tests
pass
- [X] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.
This commit is contained in:
brios
2026-08-20 21:21:50 +00:00
committed by GitHub
parent b3acdc4aab
commit 4e5b1102b6
4 changed files with 124 additions and 15 deletions
@@ -0,0 +1,79 @@
import { render, screen, fireEvent } from "@testing-library/react";
import { describe, it, expect, vi } from "vitest";
import { TextInput } from "@app/components/shared/TextInput";
import { MantineProvider } from "@mantine/core";
function renderWithMantine(ui: React.ReactElement) {
return render(<MantineProvider>{ui}</MantineProvider>);
}
describe("TextInput", () => {
it("renders input with value and placeholder", () => {
renderWithMantine(
<TextInput
id="test-input"
name="test-input"
value="hello"
onChange={vi.fn()}
placeholder="Type here..."
/>,
);
const input = screen.getByPlaceholderText("Type here...");
expect(input).toBeInTheDocument();
expect(input).toHaveValue("hello");
});
it("shows clear button when there is a value and triggers clear on click", () => {
const onChange = vi.fn();
renderWithMantine(
<TextInput
id="test-input"
name="test-input"
value="search text"
onChange={onChange}
showClearButton={true}
/>,
);
const clearButton = screen.getByRole("button", {
name: /(?:clear|textInput\.clear)/i,
});
expect(clearButton).toBeInTheDocument();
fireEvent.click(clearButton);
expect(onChange).toHaveBeenCalledWith("");
});
it("does not show clear button when value is empty", () => {
renderWithMantine(
<TextInput
id="test-input"
name="test-input"
value=""
onChange={vi.fn()}
showClearButton={true}
/>,
);
expect(
screen.queryByRole("button", { name: /clear input/i }),
).not.toBeInTheDocument();
});
it("does not show clear button when showClearButton is false", () => {
renderWithMantine(
<TextInput
id="test-input"
name="test-input"
value="some text"
onChange={vi.fn()}
showClearButton={false}
/>,
);
expect(
screen.queryByRole("button", { name: /clear input/i }),
).not.toBeInTheDocument();
});
});
@@ -119,12 +119,25 @@ export const TextInput = forwardRef<HTMLInputElement, TextInputProps>(
/>
{shouldShowClearButton && (
<ActionIcon
variant="tertiary"
variant="quiet"
accent="neutral"
shape="circle"
className={styles.clearButton}
style={
{
"--ai-size": "1.25rem",
width: "1.25rem",
height: "1.25rem",
} as React.CSSProperties
}
onClick={handleClear}
aria-label={t("textInput.clear", "Clear input")}
>
<LocalIcon icon="close-rounded" width="1.25rem" height="1.25rem" />
<LocalIcon
icon="close-rounded"
width="0.875rem"
height="0.875rem"
/>
</ActionIcon>
)}
</div>
@@ -209,9 +209,6 @@
}
.super-search-item {
display: flex;
align-items: center;
gap: 0.5rem;
width: 100%;
padding: 0.45rem 0.5rem;
border: none;
@@ -227,6 +224,18 @@
background: var(--c-hover);
}
.super-search-item .mantine-Button-inner {
width: 100%;
}
.super-search-item .mantine-Button-label {
display: flex;
align-items: center;
gap: 0.75rem;
width: 100%;
overflow: visible;
}
.super-search-item-icon {
display: flex;
align-items: center;
@@ -241,6 +250,7 @@
display: flex;
flex-direction: column;
min-width: 0;
flex: 1 1 auto;
}
.super-search-item-title {
@@ -52,22 +52,29 @@
.clearButton {
position: absolute;
right: 8px;
right: 6px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
padding: 4px;
border-radius: 4px;
display: flex;
--ai-size: 1.35rem !important;
width: 1.35rem !important;
height: 1.35rem !important;
min-width: 1.35rem !important;
min-height: 1.35rem !important;
padding: 0 !important;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 16px;
transition: background-color 0.2s ease;
border-radius: var(--radius-full, 9999px);
background: transparent;
border: none;
cursor: pointer;
color: var(--c-text-subtle);
transition:
background-color 0.15s ease,
color 0.15s ease;
}
.clearButton:hover {
background-color: var(--c-hover);
color: var(--c-text);
background-color: var(--c-hover) !important;
}