如何在MUI项目中实现类似GitLab搜索栏的带选择器的引导式搜索输入组件?
如何在MUI项目中实现类似GitLab搜索栏的带选择器的引导式搜索输入组件?
嗨,我来帮你搞定这个类似GitLab搜索栏的组件实现~其实你提到的MUI Autocomplete的GitHub Picker例子已经是很好的基础了,我们只需要基于它扩展一些特性,就能贴近GitLab的搜索栏效果。下面是具体的思路和实现步骤:
核心思路拆解
GitLab搜索栏的核心特点是:带分类筛选器、输入实时提示、分组展示结果、样式紧凑友好。我们可以用MUI的Autocomplete组件作为基础,通过自定义模板和逻辑来实现这些特性。
具体实现步骤
整合分类筛选器
GitLab的搜索栏左侧有分类按钮(比如项目、议题、代码),我们可以用MUI的ButtonGroup配合InputAdornment,把筛选器嵌入到输入框的前置位置,同时绑定状态来控制搜索范围。自定义搜索过滤逻辑
结合选中的筛选分类,在Autocomplete的filterOptions属性里自定义过滤规则,只返回符合当前分类的搜索结果;如果选择“全部”,则展示所有匹配项。分组展示下拉选项
利用Autocomplete的groupBy属性,把搜索结果按分类分组,再通过renderGroup自定义分组标题的样式,让下拉列表和GitLab一样清晰区分不同类型的内容。优化输入框与选项样式
自定义输入框的前后装饰(比如加搜索图标),同时给选项添加对应分类的图标,让视觉效果更贴近GitLab的风格;还可以通过sx属性调整圆角、间距等细节样式。
示例代码
import { useState } from 'react'; import { Autocomplete, TextField, ButtonGroup, Button, ListSubheader, ListItemText, Box } from '@mui/material'; import { Search, GitRepo, IssueOpened, Code } from '@mui/icons-material'; // 模拟搜索数据,包含分类、标题和对应图标 const searchOptions = [ { type: 'projects', label: '我的项目', icon: <GitRepo /> }, { type: 'issues', label: '修复登录bug', icon: <IssueOpened /> }, { type: 'code', label: 'userService.js', icon: <Code /> }, { type: 'projects', label: '文档站点', icon: <GitRepo /> }, { type: 'issues', label: '优化加载速度', icon: <IssueOpened /> }, ]; export default function GitLabStyleSearchBar() { const [selectedFilter, setSelectedFilter] = useState('all'); // 自定义过滤逻辑:结合输入关键词和选中的分类 const filterOptions = (options, { inputValue }) => { let filtered = options.filter(option => option.label.toLowerCase().includes(inputValue.toLowerCase()) ); // 如果选中了具体分类,进一步过滤 if (selectedFilter !== 'all') { filtered = filtered.filter(option => option.type === selectedFilter); } return filtered; }; // 分组逻辑:将英文分类名转为中文显示 const groupBy = (option) => { switch(option.type) { case 'projects': return '项目'; case 'issues': return '议题'; case 'code': return '代码'; default: return '全部'; } }; return ( <Box sx={{ width: 550, mx: 'auto' }}> <Autocomplete filterOptions={filterOptions} groupBy={groupBy} options={searchOptions} // 自定义输入框 renderInput={(params) => ( <TextField {...params} placeholder="搜索项目、代码、议题..." sx={{ '& .MuiOutlinedInput-root': { borderRadius: 2, // 调整圆角,贴近GitLab风格 '&:hover fieldset': { borderColor: '#e2e8f0' }, '&.Mui-focused fieldset': { borderColor: '#4f46e5' }, } }} InputProps={{ ...params.InputProps, startAdornment: ( <ButtonGroup size="small" sx={{ mr: 1, borderRight: '1px solid #e2e8f0' }}> <Button variant={selectedFilter === 'all' ? 'contained' : 'outlined'} onClick={() => setSelectedFilter('all')} sx={{ textTransform: 'none' }} > 全部 </Button> <Button variant={selectedFilter === 'projects' ? 'contained' : 'outlined'} onClick={() => setSelectedFilter('projects')} sx={{ textTransform: 'none' }} > 项目 </Button> <Button variant={selectedFilter === 'issues' ? 'contained' : 'outlined'} onClick={() => setSelectedFilter('issues')} sx={{ textTransform: 'none' }} > 议题 </Button> </ButtonGroup> ), endAdornment: ( <> <Search sx={{ mr: 1, color: '#94a3b8' }} /> {params.InputProps.endAdornment} </> ) }} /> )} // 自定义选项渲染,带图标 renderOption={(props, option) => ( <li {...props} sx={{ paddingY: 0.8 }}> <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}> {option.icon} <ListItemText primary={option.label} /> </Box> </li> )} // 自定义分组标题 renderGroup={(params) => ( <li> <ListSubheader sx={{ fontSize: '0.8rem', color: '#64748b', fontWeight: 500 }}> {params.group} </ListSubheader> <ul>{params.children}</ul> </li> )} /> </Box> ); }
额外优化建议
- 如果需要从后端获取实时搜索数据,可以用
Autocomplete的fetchOptions属性,配合useEffect调用接口,实现异步搜索; - 可以添加选中选项后的回调逻辑,比如跳转到对应页面;
- 调整按钮和输入框的颜色,匹配你的项目主题色,让组件更贴合整体风格。
备注:内容来源于stack exchange,提问作者til
相关产品推荐
相关产品推荐

