mirror of
https://github.com/sct/overseerr.git
synced 2025-09-17 17:24:35 +02:00
refactor(layout component + sub components): refactor layout - extract sidebar, search etc (#11)
Extract Sidebar, search, userDropdown, Notifications from Layout component
This commit is contained in:
26
src/components/Layout/Notifications/index.tsx
Normal file
26
src/components/Layout/Notifications/index.tsx
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const Notifications: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className="p-1 text-gray-400 rounded-full hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:shadow-outline focus:text-gray-500"
|
||||||
|
aria-label="Notifications"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="h-6 w-6"
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Notifications;
|
132
src/components/Layout/Sidebar/index.tsx
Normal file
132
src/components/Layout/Sidebar/index.tsx
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import Transition from '../../Transition';
|
||||||
|
|
||||||
|
interface SidebarProps {
|
||||||
|
open?: boolean;
|
||||||
|
setClosed: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sidebar: React.FC<SidebarProps> = ({ open, setClosed }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className="md:hidden">
|
||||||
|
<Transition show={open}>
|
||||||
|
<div className="fixed inset-0 flex z-40">
|
||||||
|
<Transition
|
||||||
|
enter="transition-opacity ease-linear duration-300"
|
||||||
|
enterFrom="opacity-0"
|
||||||
|
enterTo="opacity-100"
|
||||||
|
leave="transition-opacity ease-linear duration-300"
|
||||||
|
leaveFrom="opacity-100"
|
||||||
|
leaveTo="opacity-0"
|
||||||
|
>
|
||||||
|
<div className="fixed inset-0">
|
||||||
|
<div className="absolute inset-0 bg-gray-600 opacity-75"></div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
<Transition
|
||||||
|
enter="transition ease-in-out duration-300 transform"
|
||||||
|
enterFrom="-translate-x-full"
|
||||||
|
enterTo="translate-x-0"
|
||||||
|
leave="transition ease-in-out duration-300 transform"
|
||||||
|
leaveFrom="translate-x-0"
|
||||||
|
leaveTo="-translate-x-full"
|
||||||
|
>
|
||||||
|
<>
|
||||||
|
<div className="relative flex-1 flex flex-col max-w-xs w-full bg-gray-800">
|
||||||
|
<div className="absolute top-0 right-0 -mr-14 p-1">
|
||||||
|
<button
|
||||||
|
className="flex items-center justify-center h-12 w-12 rounded-full focus:outline-none focus:bg-gray-600"
|
||||||
|
aria-label="Close sidebar"
|
||||||
|
onClick={() => setClosed()}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="h-6 w-6 text-white"
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M6 18L18 6M6 6l12 12"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="flex-1 h-0 pt-5 pb-4 overflow-y-auto">
|
||||||
|
<div className="flex-shrink-0 flex items-center px-4">
|
||||||
|
<span className="text-xl text-cool-gray-50">
|
||||||
|
Overseerr
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<nav className="mt-5 px-2 space-y-1">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="group flex items-center px-2 py-2 text-base leading-6 font-medium rounded-md text-white bg-gray-900 focus:outline-none focus:bg-gray-700 transition ease-in-out duration-150"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="mr-4 h-6 w-6 text-gray-300 group-hover:text-gray-300 group-focus:text-gray-300 transition ease-in-out duration-150"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Dashboard
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="flex-shrink-0 w-14">
|
||||||
|
{/* <!-- Force sidebar to shrink to fit close icon --> */}
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="hidden md:flex md:flex-shrink-0">
|
||||||
|
<div className="flex flex-col w-64">
|
||||||
|
<div className="flex flex-col h-0 flex-1 bg-gray-800">
|
||||||
|
<div className="flex-1 flex flex-col pt-5 pb-4 overflow-y-auto">
|
||||||
|
<div className="flex items-center flex-shrink-0 px-4">
|
||||||
|
<span className="text-2xl text-cool-gray-50">Overseerr</span>
|
||||||
|
</div>
|
||||||
|
<nav className="mt-5 flex-1 px-2 bg-gray-800 space-y-1">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="group flex items-center px-2 py-2 text-sm leading-5 font-medium text-white rounded-md bg-gray-900 focus:outline-none focus:bg-gray-700 transition ease-in-out duration-150"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="mr-3 h-6 w-6 text-gray-300 group-hover:text-gray-300 group-focus:text-gray-300 transition ease-in-out duration-150"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke="currentColor"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
strokeWidth="2"
|
||||||
|
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
Dashboard
|
||||||
|
</a>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Sidebar;
|
68
src/components/Layout/UserDropdown/index.tsx
Normal file
68
src/components/Layout/UserDropdown/index.tsx
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
import React, { useState } from 'react';
|
||||||
|
import Transition from '../../Transition';
|
||||||
|
|
||||||
|
const UserDropdown: React.FC = () => {
|
||||||
|
const [isDropdownOpen, setDropdownOpen] = useState(false);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ml-3 relative">
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
className="max-w-xs flex items-center text-sm rounded-full focus:outline-none focus:shadow-outline"
|
||||||
|
id="user-menu"
|
||||||
|
aria-label="User menu"
|
||||||
|
aria-haspopup="true"
|
||||||
|
onClick={() => setDropdownOpen((state) => !state)}
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
className="h-8 w-8 rounded-full"
|
||||||
|
src="https://avatars1.githubusercontent.com/u/234213?s=460&u=7f30f76bd7bbdab45bab7544ebd80aa88ea11caf&v=4"
|
||||||
|
alt=""
|
||||||
|
/>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<Transition
|
||||||
|
show={isDropdownOpen}
|
||||||
|
enter="transition ease-out duration-100"
|
||||||
|
enterFrom="transform opacity-0 scale-95"
|
||||||
|
enterTo="transform opacity-100 scale-100"
|
||||||
|
leave="transition ease-in duration-75"
|
||||||
|
leaveFrom="transform opacity-100 scale-100"
|
||||||
|
leaveTo="transform opacity-0 scale-95"
|
||||||
|
>
|
||||||
|
<div className="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg">
|
||||||
|
<div
|
||||||
|
className="py-1 rounded-md bg-white shadow-xs"
|
||||||
|
role="menu"
|
||||||
|
aria-orientation="vertical"
|
||||||
|
aria-labelledby="user-menu"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition ease-in-out duration-150"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
Your Profile
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition ease-in-out duration-150"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
Settings
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition ease-in-out duration-150"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
Sign out
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Transition>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserDropdown;
|
@@ -1,128 +1,16 @@
|
|||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import Transition from '../Transition';
|
import Search from '../Search';
|
||||||
|
import UserDropdown from './UserDropdown';
|
||||||
|
import Sidebar from './Sidebar';
|
||||||
|
import Notifications from './Notifications';
|
||||||
|
|
||||||
const Layout: React.FC = ({ children }) => {
|
const Layout: React.FC = ({ children }) => {
|
||||||
const [isSidebarOpen, setSidebarOpen] = useState(false);
|
const [isSidebarOpen, setSidebarOpen] = useState(false);
|
||||||
const [isDropdownOpen, setDropdownOpen] = useState(false);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="h-screen flex overflow-hidden bg-gray-100">
|
<div className="h-screen flex overflow-hidden bg-gray-100">
|
||||||
<div className="md:hidden">
|
<Sidebar open={isSidebarOpen} setClosed={() => setSidebarOpen(false)} />
|
||||||
<Transition show={isSidebarOpen}>
|
|
||||||
<div className="fixed inset-0 flex z-40">
|
|
||||||
<Transition
|
|
||||||
enter="transition-opacity ease-linear duration-300"
|
|
||||||
enterFrom="opacity-0"
|
|
||||||
enterTo="opacity-100"
|
|
||||||
leave="transition-opacity ease-linear duration-300"
|
|
||||||
leaveFrom="opacity-100"
|
|
||||||
leaveTo="opacity-0"
|
|
||||||
>
|
|
||||||
<div className="fixed inset-0">
|
|
||||||
<div className="absolute inset-0 bg-gray-600 opacity-75"></div>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
<Transition
|
|
||||||
enter="transition ease-in-out duration-300 transform"
|
|
||||||
enterFrom="-translate-x-full"
|
|
||||||
enterTo="translate-x-0"
|
|
||||||
leave="transition ease-in-out duration-300 transform"
|
|
||||||
leaveFrom="translate-x-0"
|
|
||||||
leaveTo="-translate-x-full"
|
|
||||||
>
|
|
||||||
<>
|
|
||||||
<div className="relative flex-1 flex flex-col max-w-xs w-full bg-gray-800">
|
|
||||||
<div className="absolute top-0 right-0 -mr-14 p-1">
|
|
||||||
<button
|
|
||||||
className="flex items-center justify-center h-12 w-12 rounded-full focus:outline-none focus:bg-gray-600"
|
|
||||||
aria-label="Close sidebar"
|
|
||||||
onClick={() => setSidebarOpen(false)}
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
className="h-6 w-6 text-white"
|
|
||||||
stroke="currentColor"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="2"
|
|
||||||
d="M6 18L18 6M6 6l12 12"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div className="flex-1 h-0 pt-5 pb-4 overflow-y-auto">
|
|
||||||
<div className="flex-shrink-0 flex items-center px-4">
|
|
||||||
<span className="text-xl text-cool-gray-50">
|
|
||||||
Overseerr
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<nav className="mt-5 px-2 space-y-1">
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className="group flex items-center px-2 py-2 text-base leading-6 font-medium rounded-md text-white bg-gray-900 focus:outline-none focus:bg-gray-700 transition ease-in-out duration-150"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
className="mr-4 h-6 w-6 text-gray-300 group-hover:text-gray-300 group-focus:text-gray-300 transition ease-in-out duration-150"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="2"
|
|
||||||
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Dashboard
|
|
||||||
</a>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex-shrink-0 w-14">
|
|
||||||
{/* <!-- Force sidebar to shrink to fit close icon --> */}
|
|
||||||
</div>
|
|
||||||
</>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="hidden md:flex md:flex-shrink-0">
|
|
||||||
<div className="flex flex-col w-64">
|
|
||||||
<div className="flex flex-col h-0 flex-1 bg-gray-800">
|
|
||||||
<div className="flex-1 flex flex-col pt-5 pb-4 overflow-y-auto">
|
|
||||||
<div className="flex items-center flex-shrink-0 px-4">
|
|
||||||
<span className="text-2xl text-cool-gray-50">Overseerr</span>
|
|
||||||
</div>
|
|
||||||
<nav className="mt-5 flex-1 px-2 bg-gray-800 space-y-1">
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className="group flex items-center px-2 py-2 text-sm leading-5 font-medium text-white rounded-md bg-gray-900 focus:outline-none focus:bg-gray-700 transition ease-in-out duration-150"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
className="mr-3 h-6 w-6 text-gray-300 group-hover:text-gray-300 group-focus:text-gray-300 transition ease-in-out duration-150"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke="currentColor"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="2"
|
|
||||||
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
Dashboard
|
|
||||||
</a>
|
|
||||||
</nav>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div className="flex flex-col w-0 flex-1 overflow-hidden">
|
<div className="flex flex-col w-0 flex-1 overflow-hidden">
|
||||||
<div className="relative z-10 flex-shrink-0 flex h-16 bg-white shadow">
|
<div className="relative z-10 flex-shrink-0 flex h-16 bg-white shadow">
|
||||||
<button
|
<button
|
||||||
@@ -145,110 +33,10 @@ const Layout: React.FC = ({ children }) => {
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div className="flex-1 px-4 flex justify-between">
|
<div className="flex-1 px-4 flex justify-between">
|
||||||
<div className="flex-1 flex">
|
<Search />
|
||||||
<form className="w-full flex md:ml-0" action="#" method="GET">
|
|
||||||
<label htmlFor="search_field" className="sr-only">
|
|
||||||
Search
|
|
||||||
</label>
|
|
||||||
<div className="relative w-full text-gray-400 focus-within:text-gray-600">
|
|
||||||
<div className="absolute inset-y-0 left-0 flex items-center pointer-events-none">
|
|
||||||
<svg
|
|
||||||
className="h-5 w-5"
|
|
||||||
fill="currentColor"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
fillRule="evenodd"
|
|
||||||
clipRule="evenodd"
|
|
||||||
d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<input
|
|
||||||
id="search_field"
|
|
||||||
className="block w-full h-full pl-8 pr-3 py-2 rounded-md text-gray-900 placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 sm:text-sm"
|
|
||||||
placeholder="Search"
|
|
||||||
type="search"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
<div className="ml-4 flex items-center md:ml-6">
|
<div className="ml-4 flex items-center md:ml-6">
|
||||||
<button
|
<Notifications />
|
||||||
className="p-1 text-gray-400 rounded-full hover:bg-gray-100 hover:text-gray-500 focus:outline-none focus:shadow-outline focus:text-gray-500"
|
<UserDropdown />
|
||||||
aria-label="Notifications"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
className="h-6 w-6"
|
|
||||||
stroke="currentColor"
|
|
||||||
fill="none"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
strokeWidth="2"
|
|
||||||
d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
<div className="ml-3 relative">
|
|
||||||
<div>
|
|
||||||
<button
|
|
||||||
className="max-w-xs flex items-center text-sm rounded-full focus:outline-none focus:shadow-outline"
|
|
||||||
id="user-menu"
|
|
||||||
aria-label="User menu"
|
|
||||||
aria-haspopup="true"
|
|
||||||
onClick={() => setDropdownOpen((state) => !state)}
|
|
||||||
>
|
|
||||||
<img
|
|
||||||
className="h-8 w-8 rounded-full"
|
|
||||||
src="https://avatars1.githubusercontent.com/u/234213?s=460&u=7f30f76bd7bbdab45bab7544ebd80aa88ea11caf&v=4"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<Transition
|
|
||||||
show={isDropdownOpen}
|
|
||||||
enter="transition ease-out duration-100"
|
|
||||||
enterFrom="transform opacity-0 scale-95"
|
|
||||||
enterTo="transform opacity-100 scale-100"
|
|
||||||
leave="transition ease-in duration-75"
|
|
||||||
leaveFrom="transform opacity-100 scale-100"
|
|
||||||
leaveTo="transform opacity-0 scale-95"
|
|
||||||
>
|
|
||||||
<div className="origin-top-right absolute right-0 mt-2 w-48 rounded-md shadow-lg">
|
|
||||||
<div
|
|
||||||
className="py-1 rounded-md bg-white shadow-xs"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
aria-labelledby="user-menu"
|
|
||||||
>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition ease-in-out duration-150"
|
|
||||||
role="menuitem"
|
|
||||||
>
|
|
||||||
Your Profile
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition ease-in-out duration-150"
|
|
||||||
role="menuitem"
|
|
||||||
>
|
|
||||||
Settings
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="#"
|
|
||||||
className="block px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 transition ease-in-out duration-150"
|
|
||||||
role="menuitem"
|
|
||||||
>
|
|
||||||
Sign out
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Transition>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
32
src/components/Search/index.tsx
Normal file
32
src/components/Search/index.tsx
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const Search: React.FC = () => {
|
||||||
|
return (
|
||||||
|
<div className="flex-1 flex">
|
||||||
|
<form className="w-full flex md:ml-0" action="#" method="GET">
|
||||||
|
<label htmlFor="search_field" className="sr-only">
|
||||||
|
Search
|
||||||
|
</label>
|
||||||
|
<div className="relative w-full text-gray-400 focus-within:text-gray-600">
|
||||||
|
<div className="absolute inset-y-0 left-0 flex items-center pointer-events-none">
|
||||||
|
<svg className="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
id="search_field"
|
||||||
|
className="block w-full h-full pl-8 pr-3 py-2 rounded-md text-gray-900 placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 sm:text-sm"
|
||||||
|
placeholder="Search"
|
||||||
|
type="search"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Search;
|
Reference in New Issue
Block a user