Ah?
This commit is contained in:
parent
d5e5fe995b
commit
0364c20240
@ -10,7 +10,9 @@ import React from "react";
|
|||||||
* @return {JSX.Element}
|
* @return {JSX.Element}
|
||||||
*/
|
*/
|
||||||
function App() {
|
function App() {
|
||||||
return <div>Hello world!</div>;
|
return <Scrollbar style={{ width: 250, height: 250 }}>
|
||||||
|
<p>Hello world!</p>
|
||||||
|
</Scrollbar>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
7
src/assets/svg/background.svg
Normal file
7
src/assets/svg/background.svg
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<svg width="1187" height="1234" viewBox="0 0 1187 1234" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M408.998 745.256C206.829 467.159 -0.745132 678.488 53.4493 872.858C189.728 1182.79 541.828 1319.16 839.898 1177.41C942.643 1128.57 1029.84 1050.24 1091.25 951.643C934.96 1103.83 651.196 1078.4 408.998 745.208V745.256Z" fill="#F0F0F0"/>
|
||||||
|
<path d="M589.732 553.768C311.677 115.242 0.000483082 348.859 0.000483082 616.83C-0.108684 705.549 18.2856 793.237 53.9153 873.85C16.9159 692.296 217.547 552.363 404.339 812.896C675.684 1191.27 941.763 1124.69 1090.72 952.538C1138.53 876.188 1169.42 789.736 1181.14 699.443V700.63C1117.18 906.92 834.959 940.474 589.732 553.768Z" fill="#F5F5F5"/>
|
||||||
|
<path d="M780.298 357.556C573.819 3.33809 311.98 35.3415 134.904 225.06C47.4877 335.363 -0.21692 473.901 0.000741558 616.829C18.6403 357.604 320.112 177.116 593.041 616.829C835.635 1008.16 1137.87 906.216 1180.86 701.744V699.781C1184.64 671.939 1186.24 643.826 1185.66 615.715V587.685C1080.6 665.864 942.439 635.678 780.252 357.532L780.298 357.556Z" fill="#FAFAFA"/>
|
||||||
|
<path d="M781.72 420.618C970.818 736.727 1133.84 655.859 1186.06 588.242C1183.96 540.989 1176.61 494.146 1164.16 448.648C1076.01 450.611 1055.46 435.275 968.721 297.983C836.17 86.7264 669.183 -55.8716 377.451 42.2463C282.888 80.7758 199.359 143.787 134.788 225.303C335.256 33.4762 581.228 85.5393 781.72 420.618Z" fill="white"/>
|
||||||
|
<path d="M955.787 325.116C1042.25 462.675 1094.88 469.676 1164.15 448.672C1074.33 120.595 745.743 -69.6327 430.245 23.761C412.352 29.0424 394.753 35.204 377.449 42.2459C638.053 -43.2499 822.887 113.86 955.787 325.116Z" fill="white"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
3
src/assets/svg/selectIcon.svg
Normal file
3
src/assets/svg/selectIcon.svg
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M13.1315 4.6875H2.86897C2.56116 4.6875 2.38929 5.0125 2.57991 5.23438L7.71116 11.1844C7.85804 11.3547 8.14085 11.3547 8.28929 11.1844L13.4205 5.23438C13.6112 5.0125 13.4393 4.6875 13.1315 4.6875Z" fill="#262626"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 326 B |
111
src/components/MainSection.tsx
Normal file
111
src/components/MainSection.tsx
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
import classNames from "classnames";
|
||||||
|
import React from "react";
|
||||||
|
import Inputgroup from "./Inputgroup";
|
||||||
|
import Select from "./Select";
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Button } from "./Button/Button";
|
||||||
|
import { SVGSearch } from "../components/icons";
|
||||||
|
import TextInputBox from "components/TextInputBox";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
className?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const options = [
|
||||||
|
{ name: "All" },
|
||||||
|
{ name: "Wade Cooper" },
|
||||||
|
{ name: "Arlene Mccoy" },
|
||||||
|
{ name: "Devon Webb" },
|
||||||
|
{ name: "Tom Cook" },
|
||||||
|
{ name: "Tanya Fox" },
|
||||||
|
{ name: "Hellen Schmidt" },
|
||||||
|
];
|
||||||
|
const Items = [
|
||||||
|
{ name: "test" },
|
||||||
|
{ name: "Wade Cooper" },
|
||||||
|
{ name: "Arlene Mccoy" },
|
||||||
|
{ name: "Devon Webb" },
|
||||||
|
{ name: "Tom Cook" },
|
||||||
|
{ name: "Tanya Fox" },
|
||||||
|
{ name: "Hellen Schmidt" },
|
||||||
|
];
|
||||||
|
export default function MainSection({
|
||||||
|
className,
|
||||||
|
...props
|
||||||
|
}: Props): JSX.Element {
|
||||||
|
const [value, setValue] = useState(options[0]);
|
||||||
|
const [selectedPerson, setSelectedPerson] = useState<any>(Items);
|
||||||
|
const [query, setQuery] = useState("");
|
||||||
|
|
||||||
|
let filteredItems =
|
||||||
|
query === ""
|
||||||
|
? Items
|
||||||
|
: Items.filter((item) =>
|
||||||
|
item.name
|
||||||
|
.toLowerCase()
|
||||||
|
.replace(/\s+/g, "")
|
||||||
|
.includes(query.toLowerCase().replace(/\s+/g, ""))
|
||||||
|
);
|
||||||
|
|
||||||
|
const removeOption = (e: React.SyntheticEvent) => {
|
||||||
|
const newSelect = filteredItems.filter(
|
||||||
|
(element: any) => element.name !== e
|
||||||
|
);
|
||||||
|
setSelectedPerson(newSelect);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="bg-main bg-center bg-cover bg-origin-border bg-no-repeat h-full py-32 px-2 sm:px-6 md:px-6 lg:px-0">
|
||||||
|
<div className="m-auto text-center font-semibold text-4xl ">
|
||||||
|
Scientific Library with Free Access
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-row items-center justify-center space-x-3 pt-2">
|
||||||
|
<div className=" text-2xl text-gray-400">Search</div>
|
||||||
|
<div className=" text-3xl text-blue-500">320 455</div>
|
||||||
|
<div className=" text-2xl text-gray-400">Items</div>
|
||||||
|
</div>
|
||||||
|
<div className="max-w-xl m-auto pt-16">
|
||||||
|
<Inputgroup className="m-0 p-0">
|
||||||
|
<div className="flex items-center w-full divide-x-2 divide-solid divide-gray-200">
|
||||||
|
<div className="flex w-1/3">
|
||||||
|
<Select
|
||||||
|
inGroup={true}
|
||||||
|
className="w-full top-0"
|
||||||
|
options={options}
|
||||||
|
value={value}
|
||||||
|
onChange={setValue}
|
||||||
|
displayValueResolver={(value) => value.name}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="w-full">
|
||||||
|
<TextInputBox
|
||||||
|
query={query}
|
||||||
|
setQuery={setQuery}
|
||||||
|
onChange={setSelectedPerson}
|
||||||
|
value={selectedPerson}
|
||||||
|
queryItems={filteredItems}
|
||||||
|
displayValueResolver={(value) => value.name}
|
||||||
|
inGroup={true}
|
||||||
|
removeOption={removeOption}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="pr-0.5">
|
||||||
|
<Button
|
||||||
|
onClick={() => {
|
||||||
|
const Query = { option: value.name, item: selectedPerson.name };
|
||||||
|
console.log(Query);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Button.Icon>
|
||||||
|
<SVGSearch className="fill-white stroke-white w-4 "></SVGSearch>
|
||||||
|
</Button.Icon>
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Inputgroup>
|
||||||
|
<div className="mt-7 pr-1 text-right font-semibold text-sm">
|
||||||
|
Advanced Search
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
155
src/components/TextInputBox.tsx
Normal file
155
src/components/TextInputBox.tsx
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
import classNames from "classnames";
|
||||||
|
import React from "react";
|
||||||
|
import "../index.css";
|
||||||
|
import { Combobox, Transition } from "@headlessui/react";
|
||||||
|
import { Fragment } from "react";
|
||||||
|
|
||||||
|
type Props<T> = {
|
||||||
|
removeOption: Function;
|
||||||
|
inGroup?: boolean;
|
||||||
|
queryItems?: T[];
|
||||||
|
query: string;
|
||||||
|
setQuery: (element: any) => void;
|
||||||
|
disabled?: boolean;
|
||||||
|
className?: string;
|
||||||
|
value?: T;
|
||||||
|
displayValueResolver?: (element: T) => any;
|
||||||
|
onChange: (element: T) => void;
|
||||||
|
} & Omit<
|
||||||
|
React.ComponentPropsWithRef<"select">,
|
||||||
|
"value" | "onChange" | "queryItems"
|
||||||
|
>;
|
||||||
|
|
||||||
|
const inputStyle = `
|
||||||
|
w-full
|
||||||
|
cursor-default
|
||||||
|
rounded
|
||||||
|
overflow-hidden
|
||||||
|
border
|
||||||
|
border-solid
|
||||||
|
shadow-none
|
||||||
|
border-gray-100
|
||||||
|
focus:outline-none
|
||||||
|
focus:border-gray-200
|
||||||
|
hover:border-gray-200
|
||||||
|
py-2 pl-3
|
||||||
|
text-sm
|
||||||
|
text-gray-900
|
||||||
|
`;
|
||||||
|
|
||||||
|
const inputList = `
|
||||||
|
absolute z-10 mt-1 w-full max-h-56
|
||||||
|
bg-white shadow-lg
|
||||||
|
rounded py-1
|
||||||
|
overflow-hidden
|
||||||
|
focus:outline-none
|
||||||
|
text-base
|
||||||
|
sm:text-sm`;
|
||||||
|
|
||||||
|
const inputInGroup = [
|
||||||
|
`border-none
|
||||||
|
hover:none
|
||||||
|
active:none
|
||||||
|
focus:none
|
||||||
|
`,
|
||||||
|
];
|
||||||
|
|
||||||
|
function TextInputBox<T>({
|
||||||
|
removeOption,
|
||||||
|
inGroup = false, // We should use this flag to choose how we will style our component
|
||||||
|
query,
|
||||||
|
setQuery,
|
||||||
|
className,
|
||||||
|
queryItems = [],
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
displayValueResolver,
|
||||||
|
disabled,
|
||||||
|
...props
|
||||||
|
}: Props<T>): JSX.Element {
|
||||||
|
return (
|
||||||
|
<div className={classNames("", className)}>
|
||||||
|
<Combobox value={value} onChange={onChange}>
|
||||||
|
<div className="relative">
|
||||||
|
<div className="relative w-full bg-white text-left focus:outline-none sm:text-sm">
|
||||||
|
<Combobox.Input
|
||||||
|
className={classNames([
|
||||||
|
[`${inputStyle}`],
|
||||||
|
{ [`${inputInGroup}`]: inGroup },
|
||||||
|
className,
|
||||||
|
])}
|
||||||
|
onChange={(event) => setQuery(event.target.value)}
|
||||||
|
placeholder={"Search..."}
|
||||||
|
displayValue={(value: T) =>
|
||||||
|
displayValueResolver ? displayValueResolver(value) : value
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
{query.length > 0 && (
|
||||||
|
<div className={`${inputList}`}>
|
||||||
|
<Transition
|
||||||
|
as={Fragment}
|
||||||
|
leave="transition ease-in duration-100"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
afterLeave={() => setQuery("")}
|
||||||
|
>
|
||||||
|
<Combobox.Options>
|
||||||
|
{queryItems.length === 0 && query !== "" ? (
|
||||||
|
<p >Nothing found.</p>
|
||||||
|
) : null}
|
||||||
|
{query.length > 0 && (
|
||||||
|
<Combobox.Option value={{ id: null, name: query }} className="cursor-default">
|
||||||
|
query: "{query}"
|
||||||
|
</Combobox.Option>
|
||||||
|
)}
|
||||||
|
{queryItems.map((item: any, id: number) => (
|
||||||
|
<Combobox.Option
|
||||||
|
key={id}
|
||||||
|
className={({ active, selected }) =>
|
||||||
|
classNames(
|
||||||
|
active
|
||||||
|
? "text-gray-900 bg-blue-50"
|
||||||
|
: "font-normal ",
|
||||||
|
"cursor-default select-none relative py-2 pl-3 pr-9",
|
||||||
|
selected
|
||||||
|
? "text-gray-900 bg-blue-100"
|
||||||
|
: "font-normal "
|
||||||
|
)
|
||||||
|
}
|
||||||
|
value={item}
|
||||||
|
>
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
{`${
|
||||||
|
displayValueResolver
|
||||||
|
? displayValueResolver(item)
|
||||||
|
: item
|
||||||
|
}`}
|
||||||
|
<span className=" block relative left-0 right-0 text-gray-200">
|
||||||
|
<button
|
||||||
|
onClick={() =>
|
||||||
|
removeOption(
|
||||||
|
displayValueResolver
|
||||||
|
? displayValueResolver(item)
|
||||||
|
: item
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
x
|
||||||
|
</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</Combobox.Option>
|
||||||
|
))}
|
||||||
|
</Combobox.Options>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Combobox>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default TextInputBox;
|
Loading…
x
Reference in New Issue
Block a user