最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Material UI with React: How to style <Autocomplete> with rounded corners - Stack Overflow

programmeradmin0浏览0评论

I've always been a fan of Google's search bar, with nice rounded corners and ample padding around the text.

I'm trying to replicate this style using Material UI's <Autoplete/> ponent, but I can't seem to do it. I'm using Next.js. What I have so far is:

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


const LiveSearch = (props) => {

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

  useEffect(() => {
    fetch(``)
      .then(res => res.json())
      .then(json => setJsonResults(json));
  }, []);

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

      </Stack>

  )
}

export default LiveSearch;

The above code should run as-is – there's an axios call in there to populate the autoplete results too.

I've tried various way to get the <SearchIcon /> icon prefix inside the input with no success, but really I'd just be happy if I could figure out how to pad it. You can see in the google screenshot how the autoplete lines up really well with the box, but in my version, the border-radius just rounds the element, and so it no longer lines up with the dropdown.

I'm new to Material UI, so I'm still not quite sure how to do these styles, but I think the issue is that the border is being drawn by some internal element, and although I can set the borderRadius on the ponent itself global CSS:

.MuiOutlinedInput-root {
  border-radius: 30px;
}

I can't seem to set the padding or borders anywhere. I've also tried setting style with sx but it does nothing.

I've always been a fan of Google's search bar, with nice rounded corners and ample padding around the text.

I'm trying to replicate this style using Material UI's <Autoplete/> ponent, but I can't seem to do it. I'm using Next.js. What I have so far is:

import React, { useState, useEffect } from 'react';
import TextField from '@mui/material/TextField';
import Stack from '@mui/material/Stack';
import Autoplete from '@mui/material/Autoplete';
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./users`)
      .then(res => res.json())
      .then(json => setJsonResults(json));
  }, []);

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

      </Stack>

  )
}

export default LiveSearch;

The above code should run as-is – there's an axios call in there to populate the autoplete results too.

I've tried various way to get the <SearchIcon /> icon prefix inside the input with no success, but really I'd just be happy if I could figure out how to pad it. You can see in the google screenshot how the autoplete lines up really well with the box, but in my version, the border-radius just rounds the element, and so it no longer lines up with the dropdown.

I'm new to Material UI, so I'm still not quite sure how to do these styles, but I think the issue is that the border is being drawn by some internal element, and although I can set the borderRadius on the ponent itself global CSS:

.MuiOutlinedInput-root {
  border-radius: 30px;
}

I can't seem to set the padding or borders anywhere. I've also tried setting style with sx but it does nothing.

Share Improve this question edited Jul 23, 2022 at 16:45 John Kealy asked Jul 23, 2022 at 16:12 John KealyJohn Kealy 1,8932 gold badges20 silver badges41 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

You simply add border radius to fieldset:

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

Codesandbox

You have to look at the autoplete css classes and override them in your ponent or use them in your theme, if you use one.

<Autoplete
    ponentsProps={{
      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 ponent="li" {...props} key={jsonResults.id}>
        {jsonResults.name} - Ahhh
      </Box>
    )}
    renderInput={(params) => (
      <TextField
        {...params}
        label="Search users..."
        sx={{
          "& .MuiOutlinedInput-root": {
            borderRadius: "50px",

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

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

I'm trying to figure out how to line up the edges (figured it out, see update), but this is how I was able to insert the Search icon, via renderInput and I got rid of the expand and collapse arrows at the end of the bar by setting freeSolo={true} (but this allows user input to not be bound to provided options).

import { Search } from '@mui/icons-material';
import { Autoplete, AutopleteRenderInputParams, InputAdornment } from '@mui/material';

...
<Autoplete
            freeSolo={true}
            renderInput={(renderInputParams: AutopleteRenderInputParams) => (
                <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 >
            )}
            ...
/>

Ignore the colors and other styling, but this is what it looks like:

Update

I was able to line up the edges by controlling the border-radius via css and setting the bottom left and right to 0 and top ones to 20px.

Here's a demo:

Here are the changes I had to make in css. I also left the bottom border so there is a division between the search and the results, but you can style if however you like. (Also I'm using scss so I declared colors as variables at the top).

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

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

div.MuiAutoplete-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;
}

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

div.MuiAutoplete-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;
}
发布评论

评论列表(0)

  1. 暂无评论