mirror of
https://github.com/DustinBrett/daedalOS.git
synced 2026-01-15 12:15:02 +00:00
Taskbar search pt5
This commit is contained in:
@@ -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
|
||||
|
||||
122
components/system/Taskbar/Search/StyledResults.ts
Normal file
122
components/system/Taskbar/Search/StyledResults.ts
Normal 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;
|
||||
20
components/system/Taskbar/Search/StyledResultsHeader.ts
Normal file
20
components/system/Taskbar/Search/StyledResultsHeader.ts
Normal 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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user