Build and styled search modal

This commit is contained in:
James Ritchie
2022-03-25 15:28:22 +00:00
parent e368db81c8
commit 5655631f12
6 changed files with 180 additions and 17 deletions
@@ -0,0 +1,23 @@
export function ArrowKeysUpDownIcon(props: React.SVGProps<SVGSVGElement>) {
return (
<svg
className={props.className}
width="28"
height="14"
viewBox="0 0 30 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<rect width="14" height="14" rx="1.53846" fill="currentColor" />
<path
d="M6.60956 4.48804C6.80972 4.23784 7.19026 4.23784 7.39043 4.48804L10.3501 8.18765C10.612 8.51503 10.3789 9 9.95969 9H4.04031C3.62106 9 3.38797 8.51503 3.64988 8.18765L6.60956 4.48804Z"
fill="black"
/>
<rect x="16" width="14" height="14" rx="1.53846" fill="currentColor" />
<path
d="M23.3904 9.51196C23.1903 9.76216 22.8097 9.76216 22.6096 9.51196L19.6499 5.81235C19.388 5.48496 19.6211 5 20.0403 5L25.9597 5C26.3789 5 26.612 5.48497 26.3501 5.81235L23.3904 9.51196Z"
fill="black"
/>
</svg>
);
}
+27
View File
@@ -0,0 +1,27 @@
export function LoadingIcon(props: React.SVGProps<SVGSVGElement>) {
return (
<svg
className={props.className}
xmlns="http://www.w3.org/2000/svg"
width="26"
height="26"
viewBox="0 0 26 26"
fill="none"
>
<circle
cx="13"
cy="13"
r="10"
stroke="black"
strokeOpacity="0.3"
strokeWidth="4"
/>
<path
d="M13 23C7.47715 23 3 18.5228 3 13"
stroke="#4338CA"
strokeWidth="4"
strokeLinecap="round"
/>
</svg>
);
}
+76 -12
View File
@@ -1,24 +1,27 @@
import { SearchIcon } from "@heroicons/react/outline";
import { ExclamationIcon, SearchIcon } from "@heroicons/react/outline";
import { ShortcutIcon } from "./Icons/ShortcutIcon";
import { Body } from "./Primitives/Body";
import { Dialog, DialogTrigger, DialogContent } from "./UI/Dialog";
import { EscapeKeyIcon } from "./Icons/EscapeKeyIcon";
import { ArrowKeysUpDownIcon } from "./Icons/ArrowKeysUpDownIcon";
import { LoadingIcon } from "./Icons/LoadingIcon";
import { SearchItem } from "./SearchItem";
import classnames from "~/utilities/classnames";
export type SearchBarProps = {
className?: string;
};
import classnames from "~/utilities/classnames";
export function SearchBar({ className }: SearchBarProps) {
return (
<Dialog>
<DialogTrigger>
<div className="flex justify-between items-center group w-44 rounded-sm bg-slate-300 transition hover:bg-slate-400 hover:bg-opacity-50 dark:bg-slate-800 dark:text-slate-400 hover:cursor-pointer hover:dark:bg-slate-700 hover:dark:bg-opacity-70">
<div className="flex items-center pl-2">
<div className="flex items-center pl-1">
<SearchIcon className="w-4 h-4 mr-1" />
<Body>Search</Body>
</div>
<div className="flex items-center gap-1 pr-2">
<div className="flex items-center gap-1 pr-1">
<ShortcutIcon className="w-4 h-4 text-sm bg-slate-200 transition group-hover:bg-slate-100 dark:bg-slate-700 dark:group-hover:bg-slate-600">
</ShortcutIcon>
@@ -31,18 +34,79 @@ export function SearchBar({ className }: SearchBarProps) {
<DialogContent
className={classnames(
"fixed z-50",
"w-[95vw] max-w-md rounded-lg p-4 md:w-full",
"top-[30%] left-[50%] -translate-x-[50%] -translate-y-[50%]",
"bg-white dark:bg-gray-800",
"focus:outline-none focus-visible:ring focus-visible:ring-purple-500 focus-visible:ring-opacity-75"
"w-[95vw] max-w-xl rounded-lg",
"top-0 left-[50%] -translate-x-[50%]",
"mt-[60px]",
"bg-white border-[1px] dark:border-slate-700 dark:bg-slate-800"
)}
>
<SearchCommandPalette />
<JamesCommandPalette />
</DialogContent>
</Dialog>
);
}
export default function SearchCommandPalette() {
return <div className="text-center">Search Command Palette</div>;
function JamesCommandPalette() {
return (
<>
<div className="search-container max-h-[60vh] px-4 pt-4 overflow-hidden">
<label className="relative text-gray-400 focus-within:text-gray-600 block">
<SearchIcon className="absolute w-7 h-7 top-1/2 transform -translate-y-1/2 left-3 text-white pointer-events-none" />
<input
type="text"
placeholder="Search the JSON…"
className="search-field w-full pl-12 pr-4 py-4 rounded-sm text-white text-2xl caret-indigo-700 bg-slate-900 border-indigo-700 focus:outline-none focus:ring focus:ring-indigo-700"
/>
</label>
<div className="search-content flex flex-col mt-4 mb-2">
<div className="results flex">
<div className="results-loading flex">
<LoadingIcon className="animate-spin h-5 w-5 mr-1"></LoadingIcon>
<Body className="text-slate-400">Loading</Body>
</div>
<div className="results-returned">
<Body className="text-slate-400">35 results</Body>
</div>
<div className="results-none flex">
<ExclamationIcon className="h-5 w-5 mr-1 text-white"></ExclamationIcon>
<Body className="text-slate-400">
No results for "sdgiuhnkjdfg"
</Body>
</div>
</div>
</div>
<ul className="search-items w-full max-h-[inherit] pb-24 overflow-y-auto">
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
<SearchItem></SearchItem>
</ul>
</div>
<div className="footer flex items-center w-full gap-4 px-3 py-2 border-t-[1px] border-slate-700 rounded-br-lg rounded-bl-lg bg-slate-900">
<div className="flex items-center gap-1">
<ShortcutIcon className="w-4 h-4 text-sm text-slate-900 bg-slate-300 transition duration-75 group-hover:bg-slate-100 dark:bg-slate-500 dark:group-hover:bg-slate-600">
</ShortcutIcon>
<Body className="text-slate-500">to select</Body>
</div>
<div className="flex items-center gap-1">
<ArrowKeysUpDownIcon className="transition text-slate-300 dark:text-slate-500" />
<Body className="text-slate-500">to navigate</Body>
</div>
<div className="flex items-center gap-1">
<EscapeKeyIcon className="transition text-slate-300 dark:text-slate-500" />
<Body className="text-slate-500">to close</Body>
</div>
</div>
</>
);
}
+49
View File
@@ -0,0 +1,49 @@
import { ChevronRightIcon } from "@heroicons/react/outline";
import { ArrayIcon } from "./Icons/ArrayIcon";
import { Body } from "./Primitives/Body";
import { Mono } from "./Primitives/Mono";
export type SearchItemProps = {
className?: string;
};
export function SearchItem(className: SearchItemProps) {
return (
<li className="w-full rounded-sm mb-2 last:mb-10 group dark:bg-slate-900 transition hover:cursor-pointer hover:dark:bg-indigo-700">
<div className="main-container flex items-center w-full p-2 pl-4 pr-3">
<ArrayIcon className="h-6 w-6 text-slate-400 transition group-hover:text-white"></ArrayIcon>
<div className="flex flex-col w-full ml-3">
<div className="path flex items-center gap-1 mb-1 text-white">
<Body className="text-xl">item</Body>
<ChevronRightIcon className="w-4 h-4"></ChevronRightIcon>
<Body className="text-xl">includes</Body>
<ChevronRightIcon className="w-4 h-4"></ChevronRightIcon>
<Body className="text-xl">tweets</Body>
<ChevronRightIcon className="w-4 h-4"></ChevronRightIcon>
<Body className="text-xl"></Body>
<ChevronRightIcon className="w-4 h-4"></ChevronRightIcon>
<Body className="text-xl">0</Body>
<ChevronRightIcon className="w-4 h-4"></ChevronRightIcon>
<Body className="text-xl">size</Body>
<ChevronRightIcon className="w-4 h-4"></ChevronRightIcon>
<Body className="text-xl">date</Body>
</div>
<div className="key-value flex justify-between">
<Mono className="text-slate-500 transition group-hover:text-white">
<span className="text-indigo-500 transition group-hover:text-white group-hover:underline group-hover:underline-offset-1">
2019
</span>
-12-31T19:26:16.000Z
</Mono>
<Mono className="text-slate-500 transition group-hover:text-white">
Tue, Dec 31,
<span className="text-indigo-500 transition group-hover:text-white group-hover:underline group-hover:underline-offset-1">
2019
</span>
, 7:26:16 PM GMT
</Mono>
</div>
</div>
</div>
</li>
);
}
+1 -1
View File
@@ -8,7 +8,7 @@ export const DialogContent = React.forwardRef<
<DialogPrimitive.Portal>
<DialogPrimitive.Overlay
forceMount
className="fixed inset-0 z-20 bg-black/50"
className="fixed inset-0 z-20 bg-black/60"
/>
<DialogPrimitive.Content forceMount {...props} ref={forwardedRef}>
{children}
+4 -4
View File
@@ -6,10 +6,10 @@ module.exports = {
tiny: ".5rem", // 8px
xs: ".625rem", // 10px
sm: ".75rem", // 12px (SmallBody)
base: ".875rem", // 14px (Body) <p>
lg: "1rem", // 16px (SmallTitle) <h3>
xl: "1.125rem", // 18px (Title) <h2>
"2xl": "1.375rem", // 22px (LargeTitle) <h1>
base: ".875rem", // 14px (Body) <p>
lg: "1rem", // 16px (SmallTitle) <h3>
xl: "1.125rem", // 18px (Title) <h2>
"2xl": "1.375rem", // 22px (LargeTitle) <h1>
"3xl": "1.5rem", // 24px
"4xl": "1.875rem", // 30px
"5xl": "2rem", // 32px