Jeremy Threlfall
This project implements an interactive search widget using JavaScript that toggles visibility when a button is clicked or the Enter key is pressed while typing. It manages focus and accessibility by moving keyboard focus to the input when opened and blurring it on close. The input value clears on close to provide a fresh start. It also updates ARIA attributes to communicate state changes to assistive technologies, ensuring an inclusive user experience.
The HTML is simple and clean. There’s a main container with the class search that holds just two things: an input box for typing your search, and a button with a search icon. The input has a placeholder that tells users what to do, and the button is there to toggle the search on and off.
This straightforward setup makes it easy to style and control with JavaScript. Because the input and button live together inside the same container, it’s intuitive for both users and the code. Plus, it keeps things accessible so people can use the keyboard or mouse to interact smoothly.
<div class="search">
	<input type="text" class="input" placeholder="Search..." />
	<button class="btn">
		<div class="fas fa-search"></div>
	</button>
</div>The styling centers around the .search container and its child elements .input and .btn. Initially, the input is narrow with a fixed width of 50px and white background, blending seamlessly into the button next to it. When the .search container toggles the .active class, the input smoothly expands its width to 200px, creating space for typing.
Meanwhile, the button uses absolute positioning inside .search, sized to 50px square, and shifts horizontally with a transition when .active is added. This sliding effect makes the search input visually extend while the button slides right, maintaining a clean, compact look.
All transitions are set to ease over 0.3s, providing a polished and fluid user experience that complements the simple JavaScript toggling logic.
/* Basic CSS Reset */
...
.search {
	position: relative;
	height: 50px;
}
.search .input {
	background-color: #fff;
	border: 0;
	font-size: 18px;
	padding: 15px;
	height: 50px;
	width: 50px;
	transition: width 0.3s ease;
}
.btn {
	background-color: #fff;
	border: 0;
	cursor: pointer;
	font-size: 24px;
	position: absolute;
	top: 0;
	left: 0;
	height: 50px;
	width: 50px;
	transition: transform 0.3s ease;
}
.search .input:focus,
.btn:focus {
	outline: none;
}
.search.active .input {
	width: 200px;
}
.search.active .btn {
	transform: translateX(198px);
}The core of this project lies in the simple yet effective toggleSearch function, which toggles the active class on the .search container to show or hide the search input. When toggled open, it sets the ARIA attribute aria-expanded to true, signaling assistive technologies that the search is expanded, improving accessibility.
The function optionally resets the input’s value to an empty string to clear previous searches, ensuring a fresh start whenever the search is reopened. It also manages keyboard focus by shifting focus to the input after the toggle, but only if it isn’t already focused, providing a smooth user experience.
Keyboard interaction is handled thoughtfully as well. Pressing Enter while focused inside the input triggers the toggle logic, which clears the input, toggles the visibility, and then blurs the input to remove focus. This prevents accidental repeated submissions and aligns with common accessibility patterns.
const search = document.querySelector('.search');
const btn = document.querySelector('.btn');
const input = document.querySelector('.input');
// change this value based on css transition speed
const FOCUS_DELAY = 300;
// toggle search active class, and optionally reset input
const toggleSearch = (resetInput) => {
	const isActive = search.classList.toggle('active');
	search.setAttribute('aria-expanded', isActive);
	if (resetInput) input.value = '';
	// focus on input if not already focused
	if (document.activeElement !== input) {
		setTimeout(() => input.focus(), FOCUS_DELAY);
	}
};
btn.addEventListener('click', () => toggleSearch(false));
// handle enter key when input is focused, this will also clear input, toggle active class, and unfocus/blur input
input.addEventListener('keydown', (e) => {
	if (document.activeElement === input) {
		if (e.key === 'Enter') {
			e.preventDefault();
			toggleSearch(true);
			input.blur();
		}
	}
});This project demonstrates how a small amount of deliberate JavaScript, combined with clean CSS and HTML, can create a smooth and accessible interactive search experience. The toggleSearch function handles UI state, user input, and accessibility attributes in a clear and maintainable way. Keyboard interactions, focus management, and ARIA attributes ensure the component is intuitive for all users. Overall, the code remains minimal, readable, and inclusive, showing that even simple projects can follow best practices for usability and accessibility.
Jeremy is a Fullstack Developer. Originally from the United States, he currently resides in Taiwan, and works freelance remotely.
Portfolio