Build and styled search modal
This commit is contained in:
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user