Taskbar search pt5

This commit is contained in:
Dustin Brett
2023-11-06 00:22:28 -08:00
parent a9cdfdd88d
commit bd7a152ef4
6 changed files with 193 additions and 151 deletions

View File

@@ -1,25 +1,40 @@
import type { TabName } from "components/system/Taskbar/Search";
import ResultEntry from "components/system/Taskbar/Search/ResultEntry";
import StyledResultsHeader from "./StyledResultsHeader";
type ResultsSectionProps = {
activeItem: string;
activeTab: TabName;
changeTab?: (tab: TabName) => void;
details?: boolean;
results: lunr.Index.Result[];
searchTerm: string;
setActiveItem: React.Dispatch<React.SetStateAction<string>>;
title: string;
title: TabName;
};
const ResultSection: FC<ResultsSectionProps> = ({
activeTab,
activeItem,
details,
results,
searchTerm,
setActiveItem,
changeTab,
title,
}) =>
results.length > 0 ? (
<figure>
<figcaption>{title}</figcaption>
<StyledResultsHeader
className={
activeTab === title || (title as string) === "Best match"
? "disabled"
: undefined
}
onClick={() => changeTab?.(title)}
>
{title}
</StyledResultsHeader>
<ol>
{results.map(({ ref }) => (
<ResultEntry

View File

@@ -0,0 +1,122 @@
import styled from "styled-components";
import ScrollBars from "styles/common/ScrollBars";
const StyledResults = styled.div`
color: #fff;
display: flex;
height: calc(100% - 52px);
width: 100%;
.list {
${ScrollBars()}
background-color: rgba(40, 40, 40, 95%);
overflow-y: auto;
width: 100%;
li {
&.active-item {
background-color: rgba(30, 80, 115, 75%);
}
position: relative;
figure {
display: flex;
padding: 12px;
padding-right: 32px;
picture,
img {
height: 32px;
width: 32px;
}
figcaption {
font-size: 8px;
margin-top: -2px;
max-width: calc(100% - 26px);
padding-left: 8px;
h1 {
font-size: 14.5px;
font-weight: 400;
overflow: hidden;
padding-right: 12px;
text-overflow: ellipsis;
span {
font-weight: 600;
}
}
h2 {
font-size: 13px;
font-weight: 300;
padding-top: 6px;
}
}
&.simple {
padding: 10px;
picture,
img {
height: 16px;
width: 16px;
}
figcaption {
h1 {
font-size: 13px;
font-weight: 300;
white-space: nowrap;
}
}
}
}
div.select {
border-left: 1px solid transparent;
display: flex;
height: 100%;
place-content: center;
place-items: center;
position: absolute;
right: 0;
top: 0;
width: 26px;
svg {
fill: #fff;
height: 16px;
width: 16px;
}
}
&:hover {
background-color: rgba(100, 100, 100, 95%);
div.select {
background-color: rgba(60, 60, 60, 95%);
border-left: 1px solid rgba(40, 40, 40, 95%);
}
figure {
&:not(:hover) {
background-color: rgba(60, 60, 60, 95%);
}
}
&.active-item {
background-color: rgba(16, 88, 145, 95%);
}
}
div.select:hover {
background-color: rgba(100, 100, 100, 95%);
}
}
}
`;
export default StyledResults;

View File

@@ -0,0 +1,20 @@
import styled from "styled-components";
const StyledResultsHeader = styled.figcaption`
font-size: 13px;
font-weight: 600;
padding-bottom: 8px;
padding-left: 12px;
padding-top: 7px;
&.disabled {
pointer-events: none;
user-select: none;
}
&:hover {
background-color: rgba(60, 60, 60, 95%);
}
`;
export default StyledResultsHeader;

View File

@@ -1,7 +1,6 @@
import TaskbarPanel from "components/system/Taskbar/TaskbarPanel";
import { m as motion } from "framer-motion";
import styled from "styled-components";
import ScrollBars from "styles/common/ScrollBars";
const StyledSearch = styled(motion.nav)`
${({ theme }) =>
@@ -113,132 +112,6 @@ const StyledSearch = styled(motion.nav)`
height: 100%;
width: 100%;
}
.results {
color: #fff;
display: flex;
height: calc(100% - 52px);
width: 100%;
.list {
${ScrollBars()}
background-color: rgba(40, 40, 40, 95%);
overflow-y: auto;
width: 100%;
> figure > figcaption {
font-size: 13px;
font-weight: 600;
padding-bottom: 8px;
padding-left: 12px;
padding-top: 7px;
}
li {
&.active-item {
background-color: rgba(30, 80, 115, 75%);
}
position: relative;
figure {
display: flex;
padding: 12px;
padding-right: 32px;
picture,
img {
height: 32px;
width: 32px;
}
figcaption {
font-size: 8px;
margin-top: -2px;
max-width: calc(100% - 26px);
padding-left: 8px;
h1 {
font-size: 14.5px;
font-weight: 400;
overflow: hidden;
padding-right: 12px;
text-overflow: ellipsis;
span {
font-weight: 600;
}
}
h2 {
font-size: 13px;
font-weight: 300;
padding-top: 6px;
}
}
&.simple {
padding: 10px;
picture,
img {
height: 16px;
width: 16px;
}
figcaption {
h1 {
font-size: 13px;
font-weight: 300;
white-space: nowrap;
}
}
}
}
div.select {
border-left: 1px solid transparent;
display: flex;
height: 100%;
place-content: center;
place-items: center;
position: absolute;
right: 0;
top: 0;
width: 26px;
svg {
fill: #fff;
height: 16px;
width: 16px;
}
}
&:hover {
background-color: rgba(100, 100, 100, 95%);
div.select {
background-color: rgba(60, 60, 60, 95%);
border-left: 1px solid rgba(40, 40, 40, 95%);
}
figure {
&:not(:hover) {
background-color: rgba(60, 60, 60, 95%);
}
}
&.active-item {
background-color: rgba(16, 88, 145, 95%);
}
}
div.select:hover {
background-color: rgba(100, 100, 100, 95%);
}
}
}
}
`;
export default StyledSearch;

View File

@@ -7,6 +7,7 @@ import {
} from "components/system/StartMenu/Sidebar/SidebarIcons";
import Details from "components/system/Taskbar/Search/Details";
import ResultSection from "components/system/Taskbar/Search/ResultSection";
import StyledResults from "components/system/Taskbar/Search/StyledResults";
import StyledSearch from "components/system/Taskbar/Search/StyledSearch";
import StyledSections from "components/system/Taskbar/Search/StyledSections";
import StyledTabs from "components/system/Taskbar/Search/StyledTabs";
@@ -41,7 +42,7 @@ type StyleVariant = Variant & {
const TABS = ["All", "Documents", "Photos", "Videos"] as const;
type TabName = (typeof TABS)[number];
export type TabName = (typeof TABS)[number];
type TabData = {
icon: React.JSX.Element;
@@ -140,6 +141,20 @@ const Search: FC<SearchProps> = ({ toggleSearch }) => {
[activeTab, results, subResults]
);
const [singleLineView, setSingleLineView] = useState(false);
const changeTab = useCallback(
(tab: TabName) => {
if (inputRef.current) {
inputRef.current.value = (
tab === "All"
? inputRef.current.value
: `${tab}: ${inputRef.current.value}`
).replace(`${activeTab}: `, "");
}
setActiveTab(tab);
},
[activeTab]
);
useEffect(() => {
if (firstResult?.ref && (!bestMatch || bestMatch !== firstResult?.ref)) {
@@ -182,18 +197,7 @@ const Search: FC<SearchProps> = ({ toggleSearch }) => {
<li
key={tab}
className={tab === activeTab ? "active" : undefined}
onClick={() => {
if (inputRef.current) {
const tabText = `${activeTab}: `;
inputRef.current.value = (
tab === "All"
? inputRef.current.value
: `${tab}: ${inputRef.current.value}`
).replace(tabText, "");
}
setActiveTab(tab);
}}
onClick={() => changeTab(tab)}
{...label(
tab === "All"
? "Find the most relevant results on this PC"
@@ -270,16 +274,17 @@ const Search: FC<SearchProps> = ({ toggleSearch }) => {
)}
{searchTerm &&
(firstResult ? (
<div className="results">
<StyledResults>
{(!singleLineView || !activeItem) && (
<div className="list">
{firstResult && (
<ResultSection
activeItem={activeItem}
activeTab={activeTab}
results={[firstResult]}
searchTerm={searchTerm}
setActiveItem={setActiveItem}
title="Best match"
title={"Best match" as TabName}
details
/>
)}
@@ -289,12 +294,14 @@ const Search: FC<SearchProps> = ({ toggleSearch }) => {
<ResultSection
key={title}
activeItem={activeItem}
activeTab={activeTab}
changeTab={changeTab}
results={subResult.filter(
(result) => firstResult !== result
)}
searchTerm={searchTerm}
setActiveItem={setActiveItem}
title={title}
title={title as TabName}
/>
)
)}
@@ -306,7 +313,7 @@ const Search: FC<SearchProps> = ({ toggleSearch }) => {
url={activeItem || firstResult?.ref}
/>
)}
</div>
</StyledResults>
) : (
// TODO: Debounce showing this at first
<div className="no-results">NO RESULTS</div>

View File

@@ -1,3 +1,7 @@
import {
SEARCH_BUTTON_LABEL,
START_BUTTON_LABEL,
} from "components/system/Taskbar/functions";
import { useProcesses } from "contexts/process";
import { useSession } from "contexts/session";
import { useViewport } from "contexts/viewport";
@@ -16,10 +20,10 @@ declare global {
}
}
const openStartMenu = (): void =>
const openByTitle = (title: string): void =>
(
document.querySelector(
"main>nav>button[title='Start']"
`main>nav>button[title='${title}']`
) as HTMLButtonElement
)?.click();
@@ -40,7 +44,7 @@ const haltAndDebounceBinding = (event: KeyboardEvent): boolean => {
return false;
};
const metaCombos = new Set(["ARROWDOWN", "ARROWUP", "D", "E", "R"]);
const metaCombos = new Set(["ARROWDOWN", "ARROWUP", "D", "E", "R", "S"]);
const updateKeyStates = (event: KeyboardEvent): void => {
const { altKey, ctrlKey, shiftKey, metaKey } = event;
@@ -56,11 +60,12 @@ const useGlobalKeyboardShortcuts = (): void => {
const altBindingsRef = useRef<Record<string, () => void>>({});
const shiftBindingsRef = useRef<Record<string, () => void>>({
E: () => open("FileExplorer"),
ESCAPE: openStartMenu,
ESCAPE: () => openByTitle(START_BUTTON_LABEL),
F10: () => open("Terminal"),
F12: () => open("DevTools"),
F5: () => window.location.reload(),
R: () => open("Run"),
S: () => openByTitle(SEARCH_BUTTON_LABEL),
});
useEffect(() => {
@@ -123,7 +128,7 @@ const useGlobalKeyboardShortcuts = (): void => {
) {
metaDown = false;
if (metaComboUsed) metaComboUsed = false;
else openStartMenu();
else openByTitle(START_BUTTON_LABEL);
}
};