feat: add search functionality to sidebar tabs; update styles for search input and empty state

This commit is contained in:
alexsparkes
2026-02-01 14:44:11 +00:00
parent cbedaf627c
commit d937f8a82e
3 changed files with 58 additions and 8 deletions

View File

@@ -6,6 +6,7 @@ import ReminderInfo from '../components/ReminderInfo';
import SidebarToggle from '../components/SidebarToggle';
import ErrorBoundary from '../../../../features/misc/modals/ErrorBoundary';
import { TAB_TYPES } from '../constants/tabConfig';
import { SearchInput } from 'components/Form/Settings';
const Tabs = ({
children,
@@ -41,8 +42,9 @@ const Tabs = ({
const [currentName, setCurrentName] = useState(initial.name);
const [showReminder, setShowReminder] = useState(localStorage.getItem('showReminder') === 'true');
const [isSidebarCollapsed, setIsSidebarCollapsed] = useState(
localStorage.getItem('sidebarCollapsed') === 'true'
localStorage.getItem('sidebarCollapsed') === 'true',
);
const [searchQuery, setSearchQuery] = useState('');
const contentRef = useRef(null);
const handleTabClick = (tab, name) => {
@@ -127,6 +129,12 @@ const Tabs = ({
// Show sidebar for Settings and Discover tabs
const showSidebar = activeTab === TAB_TYPES.SETTINGS || activeTab === TAB_TYPES.DISCOVER;
// Filter tabs based on search query
const filteredChildren = children.filter((tab) => {
if (!searchQuery.trim()) return true;
return tab.props.label.toLowerCase().includes(searchQuery.toLowerCase());
});
// Keyboard shortcut for sidebar toggle (Ctrl/Cmd + B)
useEffect(() => {
const handleKeyPress = (e) => {
@@ -147,9 +155,17 @@ const Tabs = ({
{showSidebar ? (
<div className={`modalSidebar ${isSidebarCollapsed ? 'collapsed' : 'expanded'}`}>
<div className="sidebarHeader">
{!isSidebarCollapsed && activeTab === TAB_TYPES.SETTINGS && (
<SearchInput
value={searchQuery}
onChange={(e) => setSearchQuery(e.target.value)}
placeholder={t('widgets.search')}
fullWidth
/>
)}
<SidebarToggle isCollapsed={isSidebarCollapsed} onToggle={handleToggleSidebar} />
</div>
{children.map((tab, index) => (
{filteredChildren.map((tab, index) => (
<Tab
key={index}
currentTab={currentTab}
@@ -159,6 +175,9 @@ const Tabs = ({
isCollapsed={isSidebarCollapsed}
/>
))}
{searchQuery.trim() && filteredChildren.length === 0 && (
<div className="sidebarEmptyState">{t('widgets.weather.not_found')}</div>
)}
{!isSidebarCollapsed && (
<ReminderInfo isVisible={showReminder} onHide={handleHideReminder} />
)}

View File

@@ -1,4 +1,4 @@
import { FiSidebar } from "react-icons/fi";
import { FiSidebar } from 'react-icons/fi';
import { Tooltip } from 'components/Elements';
import { useT } from 'contexts/TranslationContext';

View File

@@ -14,13 +14,34 @@
flex-shrink: 0;
transition: min-width 0.4s cubic-bezier(0.4, 0, 0.2, 1);
// Container for toggle button positioning
// Container for search bar and toggle button
.sidebarHeader {
display: flex;
justify-content: flex-end;
margin-bottom: 0.5rem;
height: 32px;
justify-content: space-between;
align-items: center;
gap: 0.5rem;
margin-bottom: 0.5rem;
.search-input-container {
flex: 1;
width: auto;
.search-input-field {
height: 38px;
font-size: 14px;
padding: 0 14px 0 42px;
border-radius: 10px;
&::placeholder {
opacity: 0.6;
}
}
.search-input-icon {
left: 16px;
font-size: 18px;
}
}
}
svg {
@@ -52,7 +73,9 @@
gap: 12px;
margin: 0.15rem 0.25rem;
padding: 0.65rem 0.75rem;
transition: background 0.2s ease, transform 0.1s ease;
transition:
background 0.2s ease,
transform 0.1s ease;
outline: none;
border: none;
background: none;
@@ -88,6 +111,14 @@
}
}
.sidebarEmptyState {
padding: 2rem 1rem;
text-align: center;
font-size: 14px;
color: t($color);
opacity: 0.6;
}
.tab-list-active {
background: t($modal-sidebarActive);
position: relative;