445 lines
16 KiB
TypeScript
445 lines
16 KiB
TypeScript
import { RadioGroup, Listbox, Dialog, Transition } from "@headlessui/react";
|
|
import { Fragment, useState } from "react";
|
|
import { FiSettings, FiChevronsDown, FiCheck } from "react-icons/fi";
|
|
import styled, { css } from "styled-components";
|
|
|
|
const ModalContainer = styled.div`
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
background: rgba(0, 0, 0, 0.5);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
`;
|
|
|
|
const plans = [
|
|
{
|
|
name: 'Startup',
|
|
ram: '12GB',
|
|
cpus: '6 CPUs',
|
|
disk: '160 GB SSD disk',
|
|
},
|
|
{
|
|
name: 'Business',
|
|
ram: '16GB',
|
|
cpus: '8 CPUs',
|
|
disk: '512 GB SSD disk',
|
|
},
|
|
{
|
|
name: 'Enterprise',
|
|
ram: '32GB',
|
|
cpus: '12 CPUs',
|
|
disk: '1024 GB SSD disk',
|
|
},
|
|
]
|
|
|
|
|
|
|
|
export default function Settings() {
|
|
const [open, setOpen] = useState(false);
|
|
|
|
var classNameCondition = ""
|
|
if (open) {
|
|
classNameCondition = "fixed z-20 top-64 mt-4 right-4 md:top-68 md:right-8 bg-sky-400 w-14 h-14 rounded-full drop-shadow-lg flex justify-center items-center text-white text-2xl hover:bg-sky-500 hover:drop-shadow-2xl"
|
|
} else {
|
|
classNameCondition = "fixed z-20 top-64 mt-4 right-4 md:top-68 md:right-8 bg-slate-100 w-14 h-14 rounded-full drop-shadow-lg flex justify-center items-center text-sky-900 text-2xl hover:text-white hover:bg-sky-600 hover:drop-shadow-2xl"
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<button
|
|
title="Settings"
|
|
className={classNameCondition}
|
|
onClick={() => setOpen(true)}
|
|
>
|
|
<FiSettings />
|
|
</button>
|
|
|
|
<Transition appear show={open} as={Fragment}>
|
|
<Dialog
|
|
as="div"
|
|
className="fixed inset-0 z-10 overflow-y-auto"
|
|
onClose={() => setOpen(false)}
|
|
>
|
|
<div className="min-h-screen px-4 text-center">
|
|
<Transition.Child
|
|
as={Fragment}
|
|
enter="ease-out duration-300"
|
|
enterFrom="opacity-0"
|
|
enterTo="opacity-100"
|
|
leave="ease-in duration-200"
|
|
leaveFrom="opacity-100"
|
|
leaveTo="opacity-0"
|
|
>
|
|
<Dialog.Overlay className="fixed inset-0" />
|
|
</Transition.Child>
|
|
|
|
<span
|
|
className="inline-block h-screen align-middle"
|
|
aria-hidden="true"
|
|
>
|
|
​
|
|
</span>
|
|
<Transition.Child
|
|
as={Fragment}
|
|
enter="ease-out duration-300"
|
|
enterFrom="opacity-0 scale-95"
|
|
enterTo="opacity-100 scale-100"
|
|
leave="ease-in duration-200"
|
|
leaveFrom="opacity-100 scale-100"
|
|
leaveTo="opacity-0 scale-95"
|
|
>
|
|
<ModalContainer>
|
|
<div className="my-8 inline-block w-full max-w-md transform overflow-hidden rounded-2xl bg-white p-6 text-left align-middle shadow-xl transition-all">
|
|
<Dialog.Title
|
|
as="h1"
|
|
className="text-3xl font-medium leading-6 text-gray-900 pb-2"
|
|
>
|
|
Settings
|
|
</Dialog.Title>
|
|
<div className="mt-4">
|
|
<p className="text-sm text-gray-500">
|
|
{Denoising()}
|
|
{Drop()}
|
|
|
|
|
|
|
|
{/* choose options */}
|
|
{/* {Example()} */}
|
|
<br></br>
|
|
{/* {Radio()} */}
|
|
</p>
|
|
</div>
|
|
|
|
<div className="mt-6">
|
|
|
|
<button
|
|
className="relative inline-flex items-center justify-center p-0.5 mb-2 mr-2 overflow-hidden text-sm font-medium text-gray-900 rounded-lg group bg-sky-500 group-hover:from-sky-600 group-hover:to-sky-500 hover:text-white"
|
|
onClick={() => {
|
|
window.open("/about", "_blank");
|
|
setOpen(false);
|
|
}}
|
|
>
|
|
<span className="relative px-5 py-2 transition-all ease-in duration-75 bg-white rounded-md group-hover:bg-opacity-0">
|
|
Cancel
|
|
</span>
|
|
</button>
|
|
|
|
<button
|
|
type="button"
|
|
className="text-white bg-gradient-to-br from-purple-600 to-sky-500 hover:bg-gradient-to-bl font-medium rounded-lg text-sm px-5 py-2.5 text-center mr-2 mb-2"
|
|
onClick={() => setOpen(false)}
|
|
>
|
|
Let's Riff 🎸
|
|
</button>
|
|
|
|
</div>
|
|
</div>
|
|
</ModalContainer>
|
|
</Transition.Child>
|
|
</div>
|
|
</Dialog>
|
|
</Transition>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export function Denoising() {
|
|
return (
|
|
<div>
|
|
<label htmlFor="price" className="block text-sm font-medium text-gray-700">
|
|
Denoising
|
|
</label>
|
|
<div className="relative mt-1 rounded-md shadow-sm">
|
|
<input
|
|
type="text"
|
|
name="denoising"
|
|
className="block w-full rounded-md border-gray-300 pl-7 pr-12 focus:border-indigo-500 focus:ring-indigo-500 sm:text-sm"
|
|
placeholder="0.75"
|
|
/>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export function Example() {
|
|
const [selected, setSelected] = useState(people[0])
|
|
|
|
return (
|
|
<div className="fixed top-16 w-72">
|
|
<Listbox value={selected} onChange={setSelected}>
|
|
<div className="relative mt-1">
|
|
<Listbox.Button className="relative w-full cursor-default rounded-lg bg-white py-2 pl-3 pr-10 text-left shadow-md focus:outline-none focus-visible:border-indigo-500 focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 sm:text-sm">
|
|
<span className="block truncate">{selected.name}</span>
|
|
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
|
|
<FiChevronsDown
|
|
className="h-5 w-5 text-gray-400"
|
|
aria-hidden="true"
|
|
/>
|
|
</span>
|
|
</Listbox.Button>
|
|
<Transition
|
|
as={Fragment}
|
|
leave="transition ease-in duration-100"
|
|
leaveFrom="opacity-100"
|
|
leaveTo="opacity-0"
|
|
>
|
|
<Listbox.Options className="absolute mt-1 max-h-60 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
|
|
{people.map((person, personIdx) => (
|
|
<Listbox.Option
|
|
key={personIdx}
|
|
className={({ active }) =>
|
|
`relative cursor-default select-none py-2 pl-10 pr-4 ${active ? 'bg-amber-100 text-amber-900' : 'text-gray-900'
|
|
}`
|
|
}
|
|
value={person}
|
|
>
|
|
{({ selected }) => (
|
|
<>
|
|
<span
|
|
className={`block truncate ${selected ? 'font-medium' : 'font-normal'
|
|
}`}
|
|
>
|
|
{person.name}
|
|
</span>
|
|
{selected ? (
|
|
<span className="absolute inset-y-0 left-0 flex items-center pl-3 text-amber-600">
|
|
<FiCheck className="h-5 w-5" aria-hidden="true" />
|
|
</span>
|
|
) : null}
|
|
</>
|
|
)}
|
|
</Listbox.Option>
|
|
))}
|
|
</Listbox.Options>
|
|
</Transition>
|
|
</div>
|
|
</Listbox>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
|
|
|
|
export function Radio() {
|
|
const [selected, setSelected] = useState(plans[0])
|
|
|
|
return (
|
|
<div className="w-full px-4 py-16">
|
|
<div className="mx-auto w-full max-w-md">
|
|
<RadioGroup value={selected} onChange={setSelected}>
|
|
<RadioGroup.Label className="sr-only">Server size</RadioGroup.Label>
|
|
<div className="space-y-2">
|
|
{plans.map((plan) => (
|
|
<RadioGroup.Option
|
|
key={plan.name}
|
|
value={plan}
|
|
className={({ active, checked }) =>
|
|
`${active
|
|
? 'ring-2 ring-white ring-opacity-60 ring-offset-2 ring-offset-sky-300'
|
|
: ''
|
|
}
|
|
${checked ? 'bg-sky-900 bg-opacity-75 text-white' : 'bg-white'
|
|
}
|
|
relative flex cursor-pointer rounded-lg px-5 py-4 shadow-md focus:outline-none`
|
|
}
|
|
>
|
|
{({ active, checked }) => (
|
|
<>
|
|
<div className="flex w-full items-center justify-between">
|
|
<div className="flex items-center">
|
|
<div className="text-sm">
|
|
<RadioGroup.Label
|
|
as="p"
|
|
className={`font-medium ${checked ? 'text-white' : 'text-gray-900'
|
|
}`}
|
|
>
|
|
{plan.name}
|
|
</RadioGroup.Label>
|
|
<RadioGroup.Description
|
|
as="span"
|
|
className={`inline ${checked ? 'text-sky-100' : 'text-gray-500'
|
|
}`}
|
|
>
|
|
<span>
|
|
{plan.ram}/{plan.cpus}
|
|
</span>{' '}
|
|
<span aria-hidden="true">·</span>{' '}
|
|
<span>{plan.disk}</span>
|
|
</RadioGroup.Description>
|
|
</div>
|
|
</div>
|
|
{checked && (
|
|
<div className="shrink-0 text-white">
|
|
<CheckIcon className="h-6 w-6" />
|
|
</div>
|
|
)}
|
|
</div>
|
|
</>
|
|
)}
|
|
</RadioGroup.Option>
|
|
))}
|
|
</div>
|
|
</RadioGroup>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
function CheckIcon(props) {
|
|
return (
|
|
<svg viewBox="0 0 24 24" fill="none" {...props}>
|
|
<circle cx={12} cy={12} r={12} fill="#fff" opacity="0.2" />
|
|
<path
|
|
d="M7 13l3 3 7-7"
|
|
stroke="#fff"
|
|
strokeWidth={1.5}
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
/>
|
|
</svg>
|
|
)
|
|
}
|
|
|
|
|
|
const people = [
|
|
{
|
|
id: 1,
|
|
name: 'Wade Cooper',
|
|
avatar:
|
|
'https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
},
|
|
{
|
|
id: 2,
|
|
name: 'Arlene Mccoy',
|
|
avatar:
|
|
'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
},
|
|
{
|
|
id: 3,
|
|
name: 'Devon Webb',
|
|
avatar:
|
|
'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2.25&w=256&h=256&q=80',
|
|
},
|
|
{
|
|
id: 4,
|
|
name: 'Tom Cook',
|
|
avatar:
|
|
'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
},
|
|
{
|
|
id: 5,
|
|
name: 'Tanya Fox',
|
|
avatar:
|
|
'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
},
|
|
{
|
|
id: 6,
|
|
name: 'Hellen Schmidt',
|
|
avatar:
|
|
'https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
},
|
|
{
|
|
id: 7,
|
|
name: 'Caroline Schultz',
|
|
avatar:
|
|
'https://images.unsplash.com/photo-1568409938619-12e139227838?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
},
|
|
{
|
|
id: 8,
|
|
name: 'Mason Heaney',
|
|
avatar:
|
|
'https://images.unsplash.com/photo-1531427186611-ecfd6d936c79?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
},
|
|
{
|
|
id: 9,
|
|
name: 'Claudie Smitham',
|
|
avatar:
|
|
'https://images.unsplash.com/photo-1584486520270-19eca1efcce5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
},
|
|
{
|
|
id: 10,
|
|
name: 'Emil Schaefer',
|
|
avatar:
|
|
'https://images.unsplash.com/photo-1561505457-3bcad021f8ee?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
|
|
},
|
|
]
|
|
|
|
function classNames(...classes) {
|
|
return classes.filter(Boolean).join(' ')
|
|
}
|
|
|
|
export function Drop() {
|
|
const [selected, setSelected] = useState(people[3])
|
|
|
|
return (
|
|
<Listbox value={selected} onChange={setSelected}>
|
|
{({ open }) => (
|
|
<>
|
|
<Listbox.Label className="block text-sm font-medium text-gray-700">Assigned to</Listbox.Label>
|
|
<div className="relative mt-1">
|
|
<Listbox.Button className="relative w-full cursor-default rounded-md border border-gray-300 bg-white py-2 pl-3 pr-10 text-left shadow-sm focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500 sm:text-sm">
|
|
<span className="flex items-center">
|
|
<img src={selected.avatar} alt="" className="h-6 w-6 flex-shrink-0 rounded-full" />
|
|
<span className="ml-3 block truncate">{selected.name}</span>
|
|
</span>
|
|
<span className="pointer-events-none absolute inset-y-0 right-0 ml-3 flex items-center pr-2">
|
|
<FiChevronsDown className="h-5 w-5 text-gray-400" aria-hidden="true" />
|
|
</span>
|
|
</Listbox.Button>
|
|
|
|
<Transition
|
|
show={open}
|
|
as={Fragment}
|
|
leave="transition ease-in duration-100"
|
|
leaveFrom="opacity-100"
|
|
leaveTo="opacity-0"
|
|
>
|
|
<Listbox.Options className="absolute z-10 mt-1 max-h-56 w-full overflow-auto rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
|
|
{people.map((person) => (
|
|
<Listbox.Option
|
|
key={person.id}
|
|
className={({ active }) =>
|
|
classNames(
|
|
active ? 'text-white bg-indigo-600' : 'text-gray-900',
|
|
'relative cursor-default select-none py-2 pl-3 pr-9'
|
|
)
|
|
}
|
|
value={person}
|
|
>
|
|
{({ selected, active }) => (
|
|
<>
|
|
<div className="flex items-center">
|
|
<img src={person.avatar} alt="" className="h-6 w-6 flex-shrink-0 rounded-full" />
|
|
<span
|
|
className={classNames(selected ? 'font-semibold' : 'font-normal', 'ml-3 block truncate')}
|
|
>
|
|
{person.name}
|
|
</span>
|
|
</div>
|
|
|
|
{selected ? (
|
|
<span
|
|
className={classNames(
|
|
active ? 'text-white' : 'text-indigo-600',
|
|
'absolute inset-y-0 right-0 flex items-center pr-4'
|
|
)}
|
|
>
|
|
<CheckIcon className="h-5 w-5" aria-hidden="true" />
|
|
</span>
|
|
) : null}
|
|
</>
|
|
)}
|
|
</Listbox.Option>
|
|
))}
|
|
</Listbox.Options>
|
|
</Transition>
|
|
</div>
|
|
</>
|
|
)}
|
|
</Listbox>
|
|
)
|
|
} |