Styling the <Autocomplete/> component in Material UI with React to achieve rounded corners

Google's search bar has always been a favorite of mine, with its rounded corners and generous text padding.

https://i.stack.imgur.com/UbKrr.png

I'm attempting to replicate this aesthetic using Material UI's <Autocomplete/> component in my Next.js project, but I'm facing some challenges. Here is what I have so far:

import React, { useState, useEffect } from 'react';
import TextField from '@mui/material/TextField';
import Stack from '@mui/material/Stack';
import Autocomplete from '@mui/material/Autocomplete';
import { borderRadius, Box } from '@mui/system';
import SearchIcon from '@material-ui/icons/Search';


const LiveSearch = (props) => {

  const [jsonResults, setJsonResults] = useState([]);

  useEffect(() => {
    fetch(`https://jsonplaceholder.typicode.com/users`)
      .then(res => res.json())
      .then(json => setJsonResults(json));
  }, []);

  return (
      <Stack sx={{ width: 400, margin: "auto" }}>
        <Autocomplete
          id="Hello"
          getOptionLabel={(jsonResults) => jsonResults.name}
          options={jsonResults}
          noOptionsText="No results"
          isOptionEqualToValue={(option, value) => {
            option.name === value.name
          }}
          renderOption={(props, jsonResults) => (
            <Box component="li" {...props} key={jsonResults.id}>
              {jsonResults.name} - Ahhh
            </Box>
          )}
          renderInput={(params) => <TextField {...params} label="Search users..." />}
        />
                  

      </Stack>

  )
}

export default LiveSearch;

The code above should work flawlessly – it includes an axios call to populate the autocomplete results as well.

https://i.stack.imgur.com/cHZMS.png

I have been experimenting with different methods to add the <SearchIcon /> icon prefix inside the input field without success. My main goal, however, is to figure out how to apply padding. In the Google example, the autocomplete aligns perfectly with the box, but in my implementation, the border-radius rounds the element separately, causing misalignment with the dropdown.

Being new to Material UI, I am still learning how to customize styles effectively. It seems that the border is defined by an internal element, making it challenging to adjust padding or borders directly. Despite trying to set styles using sx, I have not been able to achieve the desired result.

Answer №1

If you want to customize the appearance of the autocomplete feature, you can check out the autocomplete css classes and modify them in your component or apply them in your theme.

<Autocomplete
    componentsProps={{
      paper: {
        sx: {
          width: 350,
          margin: "auto"
        }
      }
    }}
    id="Hello"
    notched
    getOptionLabel={(jsonResults) => jsonResults.name}
    options={jsonResults}
    noOptionsText="No results"
    isOptionEqualToValue={(option, value) => {
      option.name === value.name;
    }}
    renderOption={(props, jsonResults) => (
      <Box component="li" {...props} key={jsonResults.id}>
        {jsonResults.name} - Ahhh
      </Box>
    )}
    renderInput={(params) => (
      <TextField
        {...params}
        label="Search users..."
        sx={{
          "& .MuiOutlinedInput-root": {
            borderRadius: "50px",

            legend: {
              marginLeft: "30px"
            }
          },
          "& .MuiAutocomplete-inputRoot": {
            paddingLeft: "20px !important",
            borderRadius: "50px"
          },
          "& .MuiInputLabel-outlined": {
            paddingLeft: "20px"
          },
          "& .MuiInputLabel-shrink": {
            marginLeft: "20px",
            paddingLeft: "10px",
            paddingRight: 0,
            background: "white"
          }
        }}
      />
    )}
  />

Try it out: https://codesandbox.io/s/infallible-field-qsstrs?file=/src/Search.js

Answer №2

After some trial and error, I managed to align the edges (problem solved, check out the updates). Here's how I added the Search icon using renderInput and removed the expand and collapse arrows at the end of the bar by setting freeSolo={true} (although this allows user input not bound to provided options).

import { Search } from '@mui/icons-material';
import { Autocomplete, AutocompleteRenderInputParams, InputAdornment } from '@mui/material';

...
<Autocomplete
            freeSolo={true}
            renderInput={(renderInputParams: AutocompleteRenderInputParams) => (
                <div ref={renderInputParams.InputProps.ref}
                    style={{
                        alignItems: 'center',
                        width: '100%',
                        display: 'flex',
                        flexDirection: 'row'
                    }}>
                    <TextField style={{ flex: 1 }} InputProps={{
                        ...renderInputParams.InputProps, startAdornment: (<InputAdornment position='start'> <Search /> </InputAdornment>),
                    }}
                        placeholder='Search'
                        inputProps={{
                            ...renderInputParams.inputProps
                        }}
                        InputLabelProps={{ style: { display: 'none' } }}
                    />
                </div >
            )}
            ...
/>

Let's ignore the colors and styling for now, here's a visual representation:

https://i.stack.imgur.com/umzRx.png

Updates

I achieved edge alignment by adjusting the border-radius with CSS, setting the bottom left and right corners to 0, and the top ones to 20px.

Watch this demo:

https://i.stack.imgur.com/3IC7w.gif

Below are the CSS modifications made. The bottom border was intentionally kept for differentiation between search and results - feel free to customize it as desired. (Note: SCSS was utilized with color variables declared at the beginning).

div.MuiAutocomplete-root div.MuiOutlinedInput-root { /* Search bar when not in focus */
  border-radius: 40px;
  background-color: $dark-color;
}

div.MuiAutocomplete-root div.MuiOutlinedInput-root.Mui-focused { /* Search bar when focused */
  border-radius: 20px 20px 0px 0px !important;
}

div.MuiAutocomplete-root div.Mui-focused fieldset { /* fieldset element is what controls the border color. Leaving only the bottom border when dropdown is visible */
  border-width: 1px !important;
  border-color: transparent transparent $light-gray-color transparent !important;
}

.MuiAutocomplete-listbox { /* To control the background color of the listbox, which is the dropdown */
  background-color: $dark-color;
}

div.MuiAutocomplete-popper div { /* To get rid of the rounding applied by Mui-paper on the dropdown */
  border-top-right-radius: 0px;
  border-top-left-radius: 0px;
}

Answer №3

To create rounded corners in your fieldset, simply apply a border radius:

<Autocomplete
  sx={{ '& fieldset': { borderRadius: 33 }}}
/>

View Example on Codesandbox

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the process for setting %20 to represent a space in URL parameters?

I am currently working on developing an android application that involves sending data to the server side using GPRS and SMS (via an SMS gateway). The challenge I am facing is with formatting the data before sending it to the SMS gateway. The format provid ...

What is the best approach for designing the architecture of a server-side node.js application?

Can you recommend a suitable architecture or pattern for building server-side applications using node.js? For the front-end, I plan on implementing a backbone.js MVC framework and utilizing websockets for communication. If you could provide some examples ...

Tips for sending information to a JavaScript variable through AJAX requests

Hello there, I'm currently working on a project that involves posting data stored in a JavaScript variable using AJAX. Can anyone assist me with the correct syntax for this process? <div class="container-fluid"> <div class="card shadow m ...

Transforming a Fixed Bootstrap Site into a Mobile-Friendly Design

I am facing an issue with my bootstrap website as it is not responsive to different view sizes. I would like to make it responsive but I am unsure of how to do so. Additionally, I am using LESS to modify the twitter bootstrap css. Currently, my site is str ...

Leverage the object imported from the global <script> tag within a React component

I am currently attempting to incorporate a PayPal button into my React project. As per the instructions provided in PayPal's developer documentation, I have to include <script src="https://www.paypal.com/sdk/js?client-id=YOUR_CLIENT_ID"& ...

Passing variable values from .post response to PHP: A guide

I'm currently working on integrating Geocode from the Google Maps API into my WordPress plugin within the wp-admin. I have created a custom post type that includes an input field for the address of a place, and I also have jQuery code set up to watch ...

Setting the default value in setState in React Native allows you to initialize state

const fetchData = async (key) => { try { const jsonData = await AsyncStorage.getItem(key) return jsonData != null ? JSON.parse(jsonData) : false; } catch(error) { console.log(error); } } useEffect ...

Exploring the architecture of Redux-thunk and validating the impact of side effects

I've been using redux-thunk and I'm not entirely sure if my side effects (specifically the showAlertError function) are structured properly. While my jest test setup seems to be fine at first glance, I encountered an error: jest.fn() value mus ...

What is the method for initializing fancybox with the precise image index?

My current usage of fancybox involves the following code snippet: $("a[rel=Fancy" + UserId + "].Items").fancybox({ 'autoscale': 'false', 'cyclic': true, 'transitionIn': 'elastic', & ...

Having difficulty saving data in database using Ajax request from a Chrome extension

I am currently working on an extension that captures the page URL and saves it in a database once the user clicks the submit button. However, I have encountered a roadblock and believe there might be a missing piece in the extension setup that I cannot pi ...

Tips for transitioning from mui v4 to mui v5 styling

I'm struggling to figure out how to future-proof my styling migration from Material-UI v4 to v5. It appears that MUI has transitioned to using Emotion for its styling in v5, which means the old styling methods used in v4 are no longer supported. It se ...

The function $(this).addClass() seems to be malfunctioning

While trying to follow a tutorial, I noticed that the style sheet isn't being applied to the clicked element in the list. What could be causing this issue? In the example provided, when a string is added to the text box and the button is clicked, a n ...

serving static content on subdomains with Express JS

I created an API using Node.js Express JS and utilized apidocjs.com to generate the static content. The issue I am currently facing is that I want the documentation file to be located under a subdomain such as docs.example.com or api.example.com/docs. What ...

Error encountered within eot file using file-loader and webpack

I am facing an issue while trying to integrate React Rainbow Components with Next.js (TypeScript). I encountered a problem with importing fonts, which led me to use webpack along with the url-loader. However, despite my efforts, I keep encountering the er ...

Transforming the timezone of a date from the Backend to the timezone selected by the user in the User

I have an API that provides dates in the format: 12/23/2023 at 03:31 a.m. CST My goal is to convert this to a date with the user-selected timezone in the following format: 12/23/2023 at 7:31 p.m. The timezone part is not required for display in the UI. c ...

AWS Lambda, where the billing time exceeds the actual processing time

While working on my Lambda function in Node.js, I noticed a significant difference in the time measured from the start to the end of the function compared to the billed duration provided by Lambda. The function itself takes around 1400 milliseconds to exec ...

Do we really need to implement ajax in this code snippet?

In my scenario, I have two JSP files named test1.jsp and test2.jsp. The flow of my program goes like this: I need to retrieve data from a textbox in test1.jsp, but the Ajax call is initiated from a different page. My objective is to receive the controller ...

Using jQuery to dynamically add or remove table rows based on user inputs

Apologies if this is too elementary. I am attempting to insert rows into a table if the current number of rows is less than what the user requires. Simultaneously, I need to remove any excess rows if the current number exceeds the user's specificati ...

Stop GIFs from playing automatically

Looking for a solution to disable autoplay for animated gifs on my chat-site (php-based). Tried script below but out of ideas: <script> myVid=document.getElementsByTagName('img'); function disableAutoplay() { myVid.autoplay=false; m ...

Is there a way to conceal JavaScript code?

I am trying to keep my AJAX code hidden from users who view the source of my PHP page. How can I achieve this? Below is the AJAX code that I currently have: <script type="text/javascript"> function Ajax(){ var xmlHttp; try{ xmlHttp=n ...