@headlessui/react#Transition TypeScript Examples
The following examples show how to use
@headlessui/react#Transition.
You can vote up the ones you like or vote down the ones you don't like,
and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: index.tsx From interbtc-ui with Apache License 2.0 | 6 votes |
CloseButton = React.forwardRef<Ref, InterlayButtonBaseProps>(
({ onClick }, ref): JSX.Element => {
return (
<Transition.Child
as={React.Fragment}
enter={clsx('ease-in-out', 'duration-300')}
enterFrom='opacity-0'
enterTo='opacity-100'
leave={clsx('ease-in-out', 'duration-300')}
leaveFrom='opacity-100'
leaveTo='opacity-0'
>
<div className={clsx('absolute', 'top-0', 'right-0', '-mr-12', 'pt-2')}>
<InterlayButtonBase
ref={ref}
className={clsx(
'ml-1',
'justify-center',
'h-10',
'w-10',
'rounded-full',
'focus:outline-none',
'focus:ring-2',
'focus:ring-inset',
'focus:ring-white'
)}
onClick={onClick}
>
<span className='sr-only'>Close sidebar</span>
<XIcon className={clsx('h-6', 'w-6', 'text-white')} aria-hidden='true' />
</InterlayButtonBase>
</div>
</Transition.Child>
);
}
)
Example #2
Source File: ContentSwitch.tsx From yet-another-generic-startpage with MIT License | 6 votes |
SwitchTransition = styled(Transition)`
position: absolute;
width: 100%;
&.transition {
transition: transform 0.7s ease-in-out;
}
&.display {
transform: translateX(0);
}
&.hideLeft {
transform: translateX(-150vw);
}
&.hideRight {
transform: translateX(150vw);
}
`
Example #3
Source File: stake-actions.tsx From arkadiko with GNU General Public License v3.0 | 6 votes |
StakeActions: React.FC<StakeActionsProps> = ({ children }) => {
return (
<Menu as="div" className="relative flex items-center justify-end">
{({ open }) => (
<>
<Menu.Button className="inline-flex items-center justify-center w-8 h-8 text-gray-400 bg-white rounded-full hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
<span className="sr-only">Open options</span>
<StyledIcon as="DotsVerticalIcon" size={5} />
</Menu.Button>
<Transition
show={open}
as={Fragment}
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"
>
<Menu.Items
static
className="absolute top-0 z-10 w-48 mx-3 mt-1 origin-top-right bg-white divide-y divide-gray-200 rounded-md shadow-lg dark:bg-zinc-800 dark:divide-zinc-600 right-7 ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div className="px-1 py-1">{children}</div>
</Menu.Items>
</Transition>
</>
)}
</Menu>
);
}
Example #4
Source File: Modal.tsx From pali-wallet with MIT License | 5 votes |
Modal = ({
children,
className = '',
onClose,
show = true,
}: IModal) => (
<Transition appear show={show} as={Fragment}>
<Dialog
as="div"
className={`fixed z-10 inset-0 overflow-y-auto ${className}`}
onClose={onClose ?? (() => {})}
>
<div
onClick={() => console.log('inside onClick')}
className="fixed z-0 -inset-0 w-full bg-brand-black bg-opacity-50 transition-all duration-300 ease-in-out"
/>
<div className="px-4 min-h-screen 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 align-middle h-screen" 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"
>
{children}
</Transition.Child>
</div>
</Dialog>
</Transition>
)
Example #5
Source File: index.tsx From interbtc-ui with Apache License 2.0 | 5 votes |
Sidebar = ({ className, children }: Props): JSX.Element => {
const [sidebarOpen, setSidebarOpen] = React.useState(false);
const handleClose = () => {
setSidebarOpen(false);
};
const handleOpen = () => {
setSidebarOpen(true);
};
return (
<div className={clsx('h-screen', 'flex', 'overflow-hidden', className)}>
<Transition.Root show={sidebarOpen} as={React.Fragment}>
<Dialog
as='div'
static
className={clsx('fixed', 'inset-0', 'flex', 'z-40', ON_SMALL_SCREEN_CLASS_NAME)}
open={sidebarOpen}
onClose={setSidebarOpen}
>
<Transition.Child
as={React.Fragment}
enter={clsx('transition-opacity', 'ease-linear', 'duration-300')}
enterFrom='opacity-0'
enterTo='opacity-100'
leave={clsx('transition-opacity', 'ease-linear', 'duration-300')}
leaveFrom='opacity-100'
leaveTo='opacity-0'
>
<Dialog.Overlay className={clsx('fixed', 'inset-0', 'bg-interlayHaiti-400', 'bg-opacity-75')} />
</Transition.Child>
<Transition.Child
as={React.Fragment}
enter={clsx('transition', 'ease-in-out', 'duration-300', 'transform')}
enterFrom='-translate-x-full'
enterTo='translate-x-0'
leave={clsx('transition', 'ease-in-out', 'duration-300', 'transform')}
leaveFrom='translate-x-0'
leaveTo='-translate-x-full'
>
<SidebarContent onSmallScreen onClose={handleClose} />
</Transition.Child>
<div className={clsx('flex-shrink-0', 'w-14')} />
</Dialog>
</Transition.Root>
<div className={clsx('hidden', 'md:flex', 'md:flex-shrink-0')}>
<div className={clsx('flex', 'flex-col', 'w-64')}>
<SidebarContent onClose={handleClose} />
</div>
</div>
<div className={clsx('flex', 'flex-col', 'w-0', 'flex-1', 'overflow-hidden')}>
<div className={clsx(ON_SMALL_SCREEN_CLASS_NAME, 'pl-1', 'pt-1', 'sm:pl-3', 'sm:pt-3')}>
<OpenButton onClick={handleOpen} />
</div>
<main className={clsx('flex-1', 'relative', 'z-0', 'overflow-y-auto', 'focus:outline-none')}>{children}</main>
</div>
</div>
);
}
Example #6
Source File: VariantSelectButton.tsx From Meshtastic with GNU General Public License v3.0 | 5 votes |
VariantSelectButton = ({
options,
}: VariantSelectButtonProps): JSX.Element => {
const [selected, setSelected] = useState(options[options.length - 1]);
return (
<Listbox value={selected} onChange={setSelected}>
{({ open }) => (
<>
<div className="relative select-none">
<Listbox.Button as={Fragment}>
<motion.button
whileHover={{ backgroundColor: 'var(--tertiary)' }}
whileTap={{ scale: 0.99 }}
className="relative -mt-5 ml-2 flex w-fit gap-1 rounded-lg bg-secondary p-2 py-2 pl-3 pr-10 text-lg font-medium leading-6 shadow-md md:mt-2"
>
<span className="block truncate">{selected.name}</span>
<span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
<HiSelector
className="h-5 w-5 text-gray-400"
aria-hidden="true"
/>
</span>
</motion.button>
</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-60 w-full overflow-auto rounded-md bg-primary py-1 shadow-md ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{options.map((variant, index) => (
<Listbox.Option
key={index}
className={({ active }) =>
`relative cursor-default select-none py-2 pl-3 pr-9 ${
active ? 'bg-secondary' : ''
}`
}
value={variant}
>
{({ selected, active }) => (
<>
<span
className={`block truncate ${
selected ? 'font-semibold' : 'font-normal'
}`}
>
{variant.name}
</span>
{selected ? (
<span
className={`absolute inset-y-0 right-0 flex items-center pr-4 ${
active ? '' : 'text-primaryInv'
}`}
>
<FiCheck className="h-5 w-5" aria-hidden="true" />
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</>
)}
</Listbox>
);
}
Example #7
Source File: ModalBase.tsx From contracts-ui with GNU General Public License v3.0 | 5 votes |
ModalBase = ({ isOpen, setIsOpen, title, children }: ModalProps) => {
function closeModal() {
setIsOpen(false);
}
return (
<>
<Transition appear show={isOpen} as={Fragment}>
<Dialog as="div" className="fixed inset-0 z-99 overflow-y-auto " onClose={closeModal}>
<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 bg-black dark:opacity-70 opacity-10" />
</Transition.Child>
{/* This element is to trick the browser into centering the modal contents. */}
<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"
>
<div className="inline-block w-full max-w-lg my-8 overflow-hidden text-left align-middle transition-all transform opacity-100 dark:bg-gray-900 bg-white shadow-xl rounded-xl">
<div className="flex justify-between border-b dark:border-gray-800 border-gray-200">
<Dialog.Title
as="h3"
className="text-lg font-bold leading-6 p-6 dark:text-gray-300 text-gray-600"
>
{title}
</Dialog.Title>
<XIcon
className="w-4 h-4 mx-6 mt-7 text-gray-500 cursor-pointer"
aria-hidden="true"
onClick={closeModal}
/>
</div>
<div className="px-6">{children}</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition>
</>
);
}
Example #8
Source File: Nav.tsx From supabase-ui-web with Apache License 2.0 | 5 votes |
function Nav({ contents, show, setShow }: any) {
return (
<>
<Transition
show={show}
enter="transition-opacity duration-75"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity duration-150"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<div
onClick={setShow}
className="z-30 fixed inset-0 bg-gray-600 bg-opacity-75"
aria-hidden="true"
></div>
</Transition>
<Transition
show={show}
enter="transform transition ease-in-out duration-500 sm:duration-700"
enterFrom="-translate-x-full"
enterTo="translate-x-0"
leave="transform transition ease-in-out duration-500 sm:duration-700"
leaveFrom="translate-x-0"
leaveTo="-translate-x-full"
>
<div className="fixed inset-0 flex z-40 md:hidden" role="dialog" aria-modal="true">
{/* // capture close clicks */}
<div className="absolute h-full w-full" onClick={setShow}></div>
{/* content of mobile menu */}
<div className="relative flex-1 flex flex-col max-w-xs w-full bg-white dark:bg-gray-800">
{contents}
</div>
<div className="flex-shrink-0 w-14">
{/* <!-- Force sidebar to shrink to fit close icon --> */}
</div>
</div>
</Transition>
</>
)
}
Example #9
Source File: Accordion.tsx From ui with MIT License | 5 votes |
export function Item({ children, className, label, id }: ItemProps) {
const { defaultActiveId, icon, iconPosition, onChange } =
useContext(AccordionContext)
let panelClasses = [AccordionStyles['sbui-accordion-item__panel']]
let buttonClasses = [AccordionStyles['sbui-accordion-item__button']]
if (className) {
buttonClasses.push(className)
}
const isDefaultActive = id ? defaultActiveId?.includes(id) : false
const handleOnChange = useCallback(
(open: boolean) => () => {
if (onChange) {
onChange({ id, label, open })
}
},
[onChange, id, label]
)
return (
<Disclosure defaultOpen={isDefaultActive}>
{({ open }) => (
<>
<Disclosure.Button
className={
open
? `${buttonClasses.join(' ')} sbui-accordion-item__button--open`
: buttonClasses.join(' ')
}
>
{iconPosition === 'left' && icon}
<Typography.Text>{label}</Typography.Text>
{iconPosition === 'right' && icon}
</Disclosure.Button>
<Transition
show={open}
enter={AccordionStyles[`sbui-accordion-item__panel--enter`]}
enterFrom={AccordionStyles[`sbui-accordion-item__panel--enterFrom`]}
enterTo={AccordionStyles[`sbui-accordion-item__panel--enterTo`]}
leave={AccordionStyles[`sbui-accordion-item__panel--leave`]}
leaveFrom={AccordionStyles[`sbui-accordion-item__panel--leaveFrom`]}
leaveTo={AccordionStyles[`sbui-accordion-item__panel--leaveTo`]}
afterEnter={handleOnChange(open)}
afterLeave={handleOnChange(open)}
>
<Disclosure.Panel className={panelClasses.join(' ')} static>
{children}
</Disclosure.Panel>
</Transition>
</>
)}
</Disclosure>
)
}
Example #10
Source File: DropdownMenu.tsx From sdk with ISC License | 5 votes |
export default function DropdownMenu({title, selectedItem, setSelectedItem, items}: DropdownMenuProps) {
return(
<div className={"flex items-center justify-center"}>
<div className={"w-60 max-w-xs"}>
<Listbox value={selectedItem} onChange={setSelectedItem} as={"div"} className={"space-y-1"}>
{({open}) => (
<>
<Listbox.Label className={"block text-sm font-medium"}>{title}</Listbox.Label>
<div className={"relative"}>
<span className={"inline-block w-full rounded-md"}>
<Listbox.Button
className={classNames(
"cursor-default relative w-full",
"py-2 pl-3 pr-10 text-center",
"rounded-md shadow-md",
"sm:text-sm",
"focus:outline-none focus-visible:ring-2",
"focus-visible:ring-opacity-75 focus-visible:ring-white",
"focus-visible:ring-offset-2 focus-visible:border-indigo-500"
)}
>
<span className={"block truncate text-lg"}>{selectedItem?.label || ""}</span>
<span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
<SelectorIcon className="w-5 h-5 text-gray-400" aria-hidden="true"/>
</span>
</Listbox.Button>
</span>
<Transition
// as={Fragment}
show={open}
unmount={false}
enter="transition duration-100 ease-in"
enterFrom="transform opacity-0"
enterTo="transform opacity-100"
leave="transition duration-75 ease-out"
leaveFrom="transform opacity-100"
leaveTo="transform opacity-0"
className={"absolute mt-1 w-full rounded-md dark:bg-gray-600"}
>
<Listbox.Options static className={"z-10 overflow-auto max-h-60 sm:text-sm"}>
{items.map((item) => {
const selected = item.key === selectedItem.key;
return(<Listbox.Option
key={item.key}
value={item}
disabled={item.disabled || selected}
>
{({ active }) => (
<div className={classNames(
"cursor-default select-none relative",
active ? "bg-blue-500" : ""
)}>
<span
className={classNames(
selected ? "font-semibold" : "font-normal",
"block truncate"
)}
>
{item.label}
</span>
</div>
)}
</Listbox.Option>
)})}
</Listbox.Options>
</Transition>
</div>
</>
)}
</Listbox>
</div>
</div>
)
}
Example #11
Source File: ProfileDropDown.tsx From platform with MIT License | 5 votes |
export default function ProfileDropDown(props) {
const { signOut, avatarUrl } = props;
return (
<Menu as="div" className="relative inline-block text-left">
{({ open }) => (
<>
<div>
<Menu.Button className="inline-flex justify-center w-full rounded-lg border-2 border-teal-500 shadow-sm bg-white text-sm font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-offset-gray-100 focus:ring-teal-500">
{avatarUrl ? (
<img
className="rounded-md h-8 w-8"
src={avatarUrl}
alt="Avatar"
/>
) : (
<span className="inline-block relative h-8 w-8 rounded-lg">
<svg
className="h-full w-full text-gray-300 rounded-lg"
fill="currentColor"
viewBox="0 0 24 24"
>
<path d="M24 20.993V24H0v-2.996A14.977 14.977 0 0112.004 15c4.904 0 9.26 2.354 11.996 5.993zM16.002 8.999a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
</span>
)}
</Menu.Button>
</div>
<Transition
show={open}
as={Fragment}
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"
>
<Menu.Items
static
className="origin-top-right absolute right-0 mt-2 w-32 sm:w-44 rounded-md shadow-lg bg-white border border-teal-500 ring-black ring-opacity-100 divide-y divide-gray-100 focus:outline-none"
>
<div className="py-1">
<Menu.Item>
{({ active }) => (
<Link
to="/app/profile"
className={classNames(
active ? "bg-gray-100 text-gray-900" : "text-gray-700",
"block px-4 py-1 sm:py-2 text-xs sm:text-sm"
)}
>
Profile
</Link>
)}
</Menu.Item>
</div>
<div className="py-1">
<Menu.Item>
{({ active }) => (
<div
onClick={signOut}
className={classNames(
active ? "bg-gray-100 text-gray-900" : "text-gray-700",
"block px-4 py-1 sm:py-2 text-xs sm:text-sm cursor-pointer"
)}
>
Logout
</div>
)}
</Menu.Item>
</div>
</Menu.Items>
</Transition>
</>
)}
</Menu>
);
}
Example #12
Source File: Modal.tsx From projectboard with MIT License | 5 votes |
function Modal({ title, isOpen, center, size, className, onDismiss, children, modalStyles }: Props) {
const ref = useRef<HTMLDivElement>(null) as RefObject<HTMLDivElement>;
const outerRef = useRef(null);
const wrapperClasses = classnames(
'fixed flex flex-col items-center inset-0 z-50',
{
'justify-center': center,
}
);
const modalClasses = classnames(
'flex flex-col items-center transform bg-white modal shadow-large-modal rounded-xl overflow-hidden',
{
'mt-20 mb-2 ': !center,
},
sizeClasses[size],
className
);
const handleClick = useCallback((e) => {
if (!onDismiss) return;
const markdownDropdown = document.getElementById('block-menu-container');
const insideMarkdown = markdownDropdown?.contains(e.target);
if (ref.current && !ref.current.contains(e.target) && !insideMarkdown) {
onDismiss();
}
}, [onDismiss]);
useLockBodyScroll();
let modal = (
<div ref={outerRef}
onClick={handleClick}
>
<Transition
show={isOpen}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition easy-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
className={wrapperClasses}
>
<div ref={ref}
className={modalClasses}
style={modalStyles}
>
{title && <div className='flex items-center justify-between w-full pl-8 pr-4 border-b border-gray-200'>
<div className='text-sm font-semibold text-gray-700'>{title}</div>
<div className='p-4'
onClick={onDismiss}
><CloseIcon className='w-4 text-gray-500 hover:text-gray-700' /></div>
</div>}
{children}
</div>
</Transition>
</div>
);
return ReactDOM.createPortal(
modal,
document.getElementById('root-modal') as Element
);
}
Example #13
Source File: modal.tsx From website with Apache License 2.0 | 5 votes |
export function Modal({isOpen, ...props}: Props) {
const close = () => {
props.setIsOpen(false);
};
return (
<Transition appear as={Fragment} show={isOpen}>
<Dialog
as="div"
className="overflow-y-auto fixed inset-0 z-10"
initialFocus={props.focusRef}
onClose={close}
>
<div className="px-4 min-h-screen 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 bg-black/30 dark:bg-black/80 backdrop-blur-md" />
</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"
>
<div className="inline-block overflow-hidden relative z-10 p-6 my-8 w-full max-w-xl text-left align-middle bg-white dark:bg-gray-800 rounded-2xl shadow-xl transition-all">
<div className="relative">
<Dialog.Title as="h3" className="text-lg font-medium leading-6">
{props.title}
</Dialog.Title>
<div className="absolute top-0 right-0 text-xl">
<button
type="button"
className="leading-none"
onClick={close}
>
×
</button>
</div>
</div>
{props.description && (
<div className="mt-2">
<p className="text-sm text-gray-100">{props.description}</p>
</div>
)}
<div className="mt-4">{props.children}</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition>
);
}
Example #14
Source File: BlogNav.tsx From vignette-web with MIT License | 5 votes |
// en: `ENG`,
// ja: `日本`,
// ko: `한국`,
// 'zh-CN': `中国`,
// 'zh-TW': `中国`,
// fil: `FIL`,
// fr: `FR`,
// id: `IDN`,
// de: `DE`,
// it: `IT`,
// nl: `NL`,
function MyListbox({ router }: { router: NextRouter }) {
const [selectedLocale, setSelectedLocale] = useState(router.locale)
return (
<div>
<Listbox
value={selectedLocale}
onChange={(selected) => {
setSelectedLocale(selected)
setCookies(`NEXT_LOCALE`, selected)
router.push(router.asPath, undefined, {
locale: selected,
})
}}
>
<Listbox.Button className="relative flex w-full cursor-default items-center rounded-lg bg-transparent pl-1 text-left text-sm font-semibold outline-none sm:font-normal">
<ReactCountryFlag
countryCode={locales[selectedLocale as string].flag}
svg
/>
<span className="mx-1">
{locales[selectedLocale as string].shortName}
</span>
<BiChevronDown />
</Listbox.Button>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="w-18 absolute z-100 mt-1 max-h-96 overflow-auto rounded-md border bg-white text-black shadow-lg focus:outline-none dark:border-neutral-700 dark:bg-[#181a1b] dark:text-white">
{Object.keys(locales).map((key) => (
/* Use the `active` state to conditionally style the active option. */
/* Use the `selected` state to conditionally style the selected option. */
<Listbox.Option key={key} value={key} as={Fragment}>
{({ active, selected }) => (
<li
className={`flex cursor-default items-center px-2 py-1 sm:px-1 lg:py-0 ${
active
? `bg-gray-100 dark:bg-neutral-700 `
: `bg-white dark:bg-[#181a1b]`
}`}
>
<ReactCountryFlag countryCode={locales[key].flag} svg />
<span className="mx-1 text-sm text-black dark:text-white">
{locales[key].name}
</span>
{selected && (
<AiOutlineCheck className="fill-black dark:fill-white" />
)}
</li>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</Listbox>
</div>
)
}
Example #15
Source File: select.tsx From website with Apache License 2.0 | 5 votes |
export function Select<T>(props: {
items: Array<Value<T>>;
selected: Value<T>;
setSelected: (value: Value<T>) => unknown;
}) {
const {selected, setSelected} = props;
return (
<div className="w-24">
<Listbox value={selected} onChange={setSelected}>
<div className="relative mt-1">
<Listbox.Button className="relative py-2 pr-10 pl-3 w-full text-left bg-black hover:bg-gray-800 rounded-lg focus-visible:border-indigo-500 focus:outline-none focus-visible:ring-2 focus-visible:ring-white/75 focus-visible:ring-offset-2 focus-visible:ring-offset-orange-300 shadow-md cursor-default sm:text-sm">
<span className="block truncate">{selected.name}</span>
<span className="flex absolute inset-y-0 right-0 items-center pr-2 pointer-events-none">
<HiChevronDown
className="w-4 h-4 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="overflow-auto absolute py-1 mt-1 w-full max-h-60 text-base bg-white rounded-md focus:outline-none ring-1 ring-black/5 shadow-lg sm:text-sm">
{props.items.map(item => (
<Listbox.Option
key={item.name}
className={({active}) =>
`${active ? 'text-amber-900 bg-amber-100' : 'text-gray-900'}
cursor-default select-none relative py-2 pl-10 pr-4`
}
value={item}
>
{({selected, active}) => (
<>
<span
className={`${
selected ? 'font-medium' : 'font-normal'
} block truncate`}
>
{item.name}
</span>
{selected && (
<span
className={`${
active ? 'text-amber-600' : 'text-amber-600'
}
absolute inset-y-0 left-0 flex items-center pl-3`}
>
<HiCheck className="w-5 h-5" aria-hidden="true" />
</span>
)}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</Listbox>
</div>
);
}
Example #16
Source File: Nav.tsx From vignette-web with MIT License | 5 votes |
// en: `ENG`,
// ja: `日本`,
// ko: `한국`,
// 'zh-CN': `中国`,
// 'zh-TW': `中国`,
// fil: `FIL`,
// fr: `FR`,
// id: `IDN`,
// de: `DE`,
// it: `IT`,
// nl: `NL`,
function MyListbox({ router }: { router: NextRouter }) {
const [selectedLocale, setSelectedLocale] = useState(router.locale)
return (
<div>
<Listbox
value={selectedLocale}
onChange={(selected) => {
setSelectedLocale(selected)
setCookies(`NEXT_LOCALE`, selected)
router.push(router.asPath, undefined, {
locale: selected,
})
}}
>
<Listbox.Button className="relative flex w-full cursor-default items-center rounded-lg bg-transparent pl-1 text-left text-sm font-semibold outline-none sm:font-normal">
<ReactCountryFlag
countryCode={locales[selectedLocale as string].flag}
svg
/>
<span className="mx-1">
{locales[selectedLocale as string].shortName}
</span>
<BiChevronDown />
</Listbox.Button>
<Transition
as={Fragment}
leave="transition ease-in duration-100"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Listbox.Options className="w-18 absolute z-100 mt-1 max-h-96 overflow-auto rounded-md border bg-white text-black shadow-lg focus:outline-none dark:border-neutral-700 dark:bg-[#181a1b] dark:text-white">
{Object.keys(locales).map((key) => (
/* Use the `active` state to conditionally style the active option. */
/* Use the `selected` state to conditionally style the selected option. */
<Listbox.Option key={key} value={key} as={Fragment}>
{({ active, selected }) => (
<li
className={`flex cursor-default items-center px-2 py-1 sm:px-1 lg:py-0 ${
active
? `bg-gray-100 dark:bg-neutral-700 `
: `bg-white dark:bg-[#181a1b]`
}`}
>
<ReactCountryFlag countryCode={locales[key].flag} svg />
<span className="mx-1 text-sm text-black dark:text-white">
{locales[key].name}
</span>
{selected && (
<AiOutlineCheck className="fill-black dark:fill-white" />
)}
</li>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</Listbox>
</div>
)
}
Example #17
Source File: token-price-select.tsx From arkadiko with GNU General Public License v3.0 | 5 votes |
export function TokenPriceSelect({ tokenPrices, selected, setSelected }: Props) {
return (
<Listbox value={selected} onChange={setSelected}>
{({ open }) => (
<>
<Listbox.Label className="block text-sm font-medium text-gray-700 sr-only">Token price</Listbox.Label>
<div className="relative mt-1">
<Listbox.Button className="relative w-full py-2 pl-3 pr-10 text-left bg-white border border-gray-300 rounded-md shadow-sm cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm">
<span className="block truncate">{selected.name}</span>
<span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
<SelectorIcon className="w-5 h-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 w-full py-1 mt-1 overflow-auto text-base bg-white rounded-md shadow-lg max-h-60 ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm">
{tokenPrices.map((token:any) => (
<Listbox.Option
key={token.id}
className={({ active }) =>
classNames(
active ? 'text-white bg-indigo-600' : 'text-gray-900',
'cursor-default select-none relative py-2 pl-3 pr-9'
)
}
value={token}
>
{({ selected, active }) => (
<>
<span className={classNames(selected ? 'font-semibold' : 'font-normal', 'block truncate')}>
{token.name}
</span>
{selected ? (
<span
className={classNames(
active ? 'text-white' : 'text-indigo-600',
'absolute inset-y-0 right-0 flex items-center pr-4'
)}
>
<CheckIcon className="w-5 h-5" aria-hidden="true" />
</span>
) : null}
</>
)}
</Listbox.Option>
))}
</Listbox.Options>
</Transition>
</div>
</>
)}
</Listbox>
)
}
Example #18
Source File: Modal.tsx From ui with MIT License | 4 votes |
Modal = ({
children,
customFooter = undefined,
closable,
description,
hideFooter = false,
alignFooter = 'left',
layout = 'horizontal',
loading = false,
cancelText = 'Cancel',
onConfirm = () => {},
onCancel = () => {},
confirmText = 'Confirm',
showIcon = false,
title,
footerBackground,
icon,
variant = 'success',
visible = false,
size = 'large',
style,
overlayStyle,
contentStyle,
className = '',
overlayClassName,
triggerElement,
}: Props) => {
const [open, setOpen] = React.useState(visible ? visible : false)
useEffect(() => {
setOpen(visible)
}, [visible])
function stopPropagation(e: React.MouseEvent) {
e.stopPropagation()
}
let footerClasses = [ModalStyles['sbui-modal-footer']]
if (footerBackground) {
footerClasses.push(ModalStyles['sbui-modal-footer--with-bg'])
}
let modalClasses = [
ModalStyles[`sbui-modal`],
ModalStyles[`sbui-modal--${size}`],
]
if (className) modalClasses.push(className)
let overlayClasses = [ModalStyles['sbui-modal-overlay']]
if (overlayClassName) overlayClasses.push(overlayClassName)
const footerContent = customFooter ? (
customFooter
) : (
<Space
style={{
width: '100%',
justifyContent:
layout === 'vertical'
? 'center'
: alignFooter === 'right'
? 'flex-end'
: 'flex-start',
}}
>
<Button type="outline" onClick={onCancel} disabled={loading}>
{cancelText}
</Button>
<Button
onClick={onConfirm}
loading={loading}
danger={variant === 'danger'}
>
{confirmText}
</Button>
</Space>
)
function handleOpenChange(open: boolean) {
if (visible !== undefined && !open) {
// controlled component behaviour
onCancel()
} else {
// un-controlled component behaviour
setOpen(open)
}
}
return (
<Dialog.Root open={open} onOpenChange={handleOpenChange}>
{triggerElement && (
<Dialog.Trigger className={ModalStyles[`sbui-modal__trigger`]}>
{triggerElement}
</Dialog.Trigger>
)}
<Transition show={open}>
<Dialog.Overlay>
<Transition.Child
enter={ModalStyles[`sbui-modal-overlay--enter`]}
enterFrom={ModalStyles[`sbui-modal-overlay--enterFrom`]}
enterTo={ModalStyles[`sbui-modal-overlay--enterTo`]}
leave={ModalStyles[`sbui-modal-overlay--leave`]}
leaveFrom={ModalStyles[`sbui-modal-overlay--leaveFrom`]}
leaveTo={ModalStyles[`sbui-modal-overlay--leaveTo`]}
>
<div className={ModalStyles['sbui-modal-overlay-container']}>
<div
className={overlayClasses.join(' ')}
style={overlayStyle}
></div>
</div>
</Transition.Child>
</Dialog.Overlay>
<Dialog.Content forceMount style={{ width: '100vw' }}>
<div
className={ModalStyles['sbui-modal-container'] + ' ' + className}
onClick={() => (onCancel ? onCancel() : null)}
>
<div className={ModalStyles['sbui-modal-flex-container']}>
<Transition.Child
enter={ModalStyles[`sbui-modal--enter`]}
enterFrom={ModalStyles[`sbui-modal--enterFrom`]}
enterTo={ModalStyles[`sbui-modal--enterTo`]}
leave={ModalStyles[`sbui-modal--leave`]}
leaveFrom={ModalStyles[`sbui-modal--leaveFrom`]}
leaveTo={ModalStyles[`sbui-modal--leaveTo`]}
className="fixed inset-0 overflow-y-auto"
>
<div
className={modalClasses.join(' ')}
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline"
onClick={stopPropagation}
style={style}
>
<div
className={ModalStyles['sbui-modal-content']}
style={contentStyle}
>
<Space
size={5}
style={{
alignItems:
layout === 'vertical' ? 'center' : 'flex-start',
}}
direction={layout}
>
{icon ? icon : null}
<Space
size={4}
direction="vertical"
style={{
alignItems: 'flex-start',
textAlign: layout === 'vertical' ? 'center' : null,
width: '100%',
}}
>
<span style={{ width: 'inherit' }}>
{title && (
<Typography.Title
style={{
marginBottom: '.1rem',
marginTop: '0',
}}
level={4}
>
{title}
</Typography.Title>
)}
{description && (
<Typography.Text>{description}</Typography.Text>
)}
</span>
{children}
{!footerBackground && !hideFooter && footerContent}
</Space>
</Space>
</div>
{!hideFooter && footerBackground && (
<div className={footerClasses.join(' ')}>
{footerContent}
</div>
)}
{closable && (
<div className={ModalStyles['sbui-modal-close-container']}>
<Button
onClick={onCancel}
type="text"
shadow={false}
icon={<IconX size="medium" />}
/>
</div>
)}
</div>
</Transition.Child>
</div>
</div>
</Dialog.Content>
</Transition>
</Dialog.Root>
)
}
Example #19
Source File: ProfileMenu.tsx From projectboard with MIT License | 4 votes |
ProfileMenu = ({ isOpen, className, onDismiss }: Props) => {
let classes = classnames(
'select-none w-53 shadow-modal z-50 flex flex-col py-1 bg-white font-normal rounded text-gray-800',
className
);
const ref = useRef(null);
let ready = false;
const { projectData } = useSelector((state: RootState) => state.currentProject);
const { logout } = useAuth0();
useClickOutside(ref, () => {
if (ready && isOpen && onDismiss) {
onDismiss();
}
});
useEffect(() => {
// eslint-disable-next-line react-hooks/exhaustive-deps
setTimeout(() => (ready = true), 300);
});
return (
<div ref={ref}>
<Transition
show={isOpen}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition easy-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
className={classes}
style={{ left: '-140px' }}
>
<Link to="/projects" className="flex items-center h-8 px-3 hover:bg-gray-100 cursor-pointer">
All Projects
</Link>
<div className="w-full px-3 my-1 border-b border-gray-200"></div>
<Link
to="/edit-profile"
className="flex items-center h-8 px-3 hover:bg-gray-100 cursor-pointer"
>
Edit Profile
</Link>
<Link
to="/edit-project"
className="flex items-center h-8 px-3 hover:bg-gray-100 cursor-pointer"
>
Edit Project
</Link>
{projectData.access === 'admin' && (
<>
<div className="w-full px-3 my-1 border-b border-gray-200"></div>
<Link
to={`/projects/${projectData.project._id}/members`}
className="flex items-center h-8 px-3 hover:bg-gray-100 "
>
Manage Members
</Link>
</>
)}
<div className="w-full px-3 my-1 border-b border-gray-200"></div>
<a
rel="noreferrer"
href="https://hashnode.com/@vishwajeetraj11"
target="_blank"
className="flex items-center h-8 px-3 hover:bg-gray-100 "
>
Join me on Hashnode
</a>
<a
rel="noreferrer"
href="https://vishwajeetraj11.hashnode.dev/introducing-product-board-a-project-management-platform"
target="_blank"
className="flex items-center h-8 px-3 hover:bg-gray-100 "
>
Introducing Project Board
</a>
<a
rel="noreferrer"
href="https://github.com/vishwajeetraj11/productboard"
target="_blank"
className="flex items-center h-8 px-3 hover:bg-gray-100 "
>
Github
</a>
<a
rel="noreferrer"
href="https://www.buymeacoffee.com/vishwajeetraj11"
target="_blank"
className="flex items-center h-8 px-3 hover:bg-gray-100 "
>
Buy Me a Coffee
</a>
<div className="w-full px-3 my-1 border-b border-gray-200"></div>
<div
className="flex items-center h-8 px-3 hover:bg-gray-100 cursor-pointer"
onClick={() =>
logout({
returnTo: window.location.origin
})
}
>
Logout
</div>
</Transition>
</div>
);
}
Example #20
Source File: about.tsx From vignette-web with MIT License | 4 votes |
OpenSource: NextPage<pageProps> = ({
contributors,
commits,
netReceived,
pullRequests,
openIssues,
totalPaid,
balance,
}) => {
const { t } = useTranslation(`about`)
const [isOpen, setIsOpen] = useState(false)
return (
<>
<SEO title={t(`page-title`)} />
<Nav />
<Container className="pt-8 lg:pt-16" id="content">
<div className="z-20 mx-auto px-2 pb-8 lg:max-w-7xl ">
<h1 className="lg:text-0xl bg-gradient-to-br from-[#005BEA] to-[#00C6FB] bg-clip-text text-4xl font-bold text-transparent xxs:text-5xl lg:text-9xl">
{t(`title1`)} <br />
{t(`title2`)}
</h1>
<p className="my-4 mb-8 mt-8 text-lg sm:px-2 sm:text-xl lg:mb-20 lg:text-2xl">
{t(`hero-p`)}
</p>
<Container offset={10} noMargin fadeIn>
<div className="mx-auto flex flex-wrap gap-8 pb-16 text-center">
<div className="mx-auto text-xl">
<div className="mb-1 text-6xl font-bold">{commits}</div>
{t(`commits`)}
<BiGitPullRequest
className="mx-auto mt-2 fill-pinkRed"
size={40}
/>
</div>
<div className="mx-auto text-xl">
<div className="mb-1 text-6xl font-bold">{pullRequests}</div>
{t(`pull-requests`)}
<BiGitPullRequest
className="mx-auto mt-2 fill-pinkRed"
size={40}
/>
</div>
<div className="mx-auto text-xl">
<div className="mb-1 text-6xl font-bold">{openIssues}</div>
{t(`open-issues`)}
<BiGitPullRequest
className="mx-auto mt-2 fill-pinkRed"
size={40}
/>
</div>
</div>
<div className="w-full text-center">
<a
href="https://github.com/vignetteapp"
className="button mx-auto "
>
{t(`visit-github-button`)}
</a>
</div>
</Container>
</div>
<Container fadeIn noMargin className="mt-32 text-center ">
<Image src={repoIcon} alt="" quality={100} width={72} height={72} />
<h2 className="mt-8 text-2xl font-bold lg:text-3xl">
{t(`section1-title`)}
</h2>
<div className=" mx-auto mt-6 flex max-w-6xl flex-wrap justify-center gap-4 px-0 lg:p-8 ">
{contributors.map((user) => (
<Link
passHref
key={user.login}
href={`https://github.com/${user.login}`}
>
<a className="p-4">
<div className="mx-auto">
<Image
width={64}
height={64}
className="rounded-full"
src={user.profile}
alt=""
/>
</div>
</a>
</Link>
))}
</div>
<p className="mx-auto mt-8 text-xs leading-snug text-gray-700 dark:text-gray-300 sm:max-w-md sm:text-sm">
{t(`section1-p`)}
</p>
<p className="mt-4 text-xs text-gray-800 dark:text-gray-200 ">
{t(`updates-daily-text`)}
</p>
</Container>
<Container>
<div className="mt-14 text-center lg:mt-28">
<div className="inline-flex overflow-hidden rounded-2xl drop-shadow-xl">
<Image
alt=""
src={VignettePadding}
width={64}
height={64}
quality={100}
/>
</div>
<h2 className="mt-3 text-2xl font-semibold">
{t(`section2-title`)}
</h2>
<p className="mx-auto mt-2 max-w-md">{t(`section2-p`)}</p>
</div>
<div className="mx-auto mt-10 flex flex-wrap justify-center gap-4 lg:max-w-5xl ">
{teamMembers.map((m: Member) => (
<a
href={m.url}
key={m.name}
className=" my-2 mx-2 text-center lg:mx-8"
>
<div className="inline-flex overflow-hidden rounded-full ">
<Image
alt=""
className=""
src={m.avatar}
width={64}
height={64}
/>
</div>
<h4 className=" my-1 font-medium capitalize">{m.name}</h4>
<p className="max-w-[9em] text-xs">{m.role}</p>
</a>
))}
</div>
</Container>
<Container className="mt-12 text-center">
<Image src={donationImage} width={400} height={400} alt="" />
<h1 className="text-3xl font-bold"> {t(`section3-title`)}</h1>
<p className="mx-auto mt-2 mb-2 max-w-[34em]">{t(`section3-p`)}</p>
<button
onClick={() => setIsOpen(true)}
className="font-semibold text-pinkRed hover:underline"
>
{t(`gives-back-button`)}
</button>
<Transition appear show={isOpen} as={Fragment}>
<Dialog
as="div"
className="fixed inset-0 z-10 overflow-y-auto"
onClose={() => setIsOpen(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>
<Dialog.Overlay className="fixed inset-0 bg-black/20 backdrop-blur-sm dark:bg-neutral-900/80 " />
{/* This element is to trick the browser into centering the modal contents. */}
<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"
>
<div className="prose-md prose my-8 inline-block w-full max-w-2xl transform overflow-hidden rounded-2xl bg-white px-6 py-4 text-left align-middle shadow-xl transition-all dark:prose-invert dark:bg-black">
<Dialog.Title
as="h3"
className="text-lg font-medium leading-6 "
>
{t(`gives-back-button`)}
</Dialog.Title>
<div className="mt-2">
<ReactMarkdown>{t(`gives-back-p`)}</ReactMarkdown>
</div>
<div className="mt-6">
<button
type="button"
className="button-small inline-flex justify-center border border-transparent bg-pinkRed px-4 py-2 text-sm font-medium text-white hover:bg-[#ff2277] focus:outline-none focus-visible:ring-2 focus-visible:ring-blue-500 focus-visible:ring-offset-2 dark:bg-pinkRed"
onClick={() => setIsOpen(false)}
>
{t(`got-it-button`)}
</button>
</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition>
<div className="mx-auto my-10 flex w-full max-w-5xl flex-wrap justify-center gap-6 text-lg lg:gap-20 lg:text-xl ">
<div className="w-40 md:w-52">
<h3 className="mb-1 text-3xl font-bold lg:text-5xl">
${netReceived}
</h3>
{t(`earned`)}
</div>
<div className="w-40 md:w-52">
<h3 className="mb-1 text-3xl font-bold lg:text-5xl">
${balance}
</h3>
{t(`balance`)}
</div>
<div className="w-52">
<h3 className="mb-1 text-3xl font-bold lg:text-5xl">
${totalPaid}
</h3>
{t(`paid`)}
</div>
</div>
<a className="button">{t(`support-us-button`)}</a>
</Container>
</Container>
<Footer />
</>
)
}
Example #21
Source File: index.tsx From ledokku with MIT License | 4 votes |
Database = () => {
const { id: databaseId } = useParams<{ id: string }>();
const toast = useToast();
const [isUnlinkModalOpen, setIsUnlinkModalOpen] = useState(false);
const [isLinkModalOpen, setIsLinkModalOpen] = useState(false);
const [arrayOfUnlinkLogs, setArrayOfUnlinkLogs] = useState<RealTimeLog[]>([]);
const [arrayOfLinkLogs, setArrayOfLinkLogs] = useState<RealTimeLog[]>([]);
const [appAboutToUnlink, setAppAboutToUnlink] = useState<string>();
const [isTerminalVisible, setIsTerminalVisible] = useState(false);
const [processStatus, setProcessStatus] = useState<
'running' | 'notStarted' | 'finished'
>('notStarted');
const [unlinkLoading, setUnlinkLoading] = useState(false);
const [linkLoading, setLinkLoading] = useState(false);
const [selectedApp, setSelectedApp] = useState({
value: { name: '', id: '' },
label: 'Please select an app',
});
const [
linkDatabaseMutation,
{
data: databaseLinkData,
loading: databaseLinkLoading,
error: databaseLinkError,
},
] = useLinkDatabaseMutation();
const { data: appsData } = useAppsQuery();
const { data, loading, refetch /* error */ } = useDatabaseByIdQuery({
variables: {
databaseId,
},
ssr: false,
skip: !databaseId,
});
const [unlinkDatabaseMutation] = useUnlinkDatabaseMutation();
useUnlinkDatabaseLogsSubscription({
onSubscriptionData: (data) => {
const logsExist = data.subscriptionData.data?.unlinkDatabaseLogs;
if (logsExist) {
setArrayOfUnlinkLogs((currentLogs) => {
return [...currentLogs, logsExist];
});
if (
logsExist.type === 'end:success' ||
logsExist.type === 'end:failure'
) {
setProcessStatus('finished');
}
}
},
});
useLinkDatabaseLogsSubscription({
onSubscriptionData: (data) => {
const logsExist = data.subscriptionData.data?.linkDatabaseLogs;
if (logsExist) {
setArrayOfLinkLogs((currentLogs) => {
return [...currentLogs, logsExist];
});
if (
logsExist.type === 'end:success' ||
logsExist.type === 'end:failure'
) {
setProcessStatus('finished');
}
}
},
});
if (!data || !appsData) {
return null;
}
// // TODO display error
if (loading) {
// TODO nice loading
return <p>Loading...</p>;
}
const { database } = data;
const { apps } = appsData;
const handleUnlink = async (databaseId: string, appId: string) => {
try {
await unlinkDatabaseMutation({
variables: {
input: {
databaseId,
appId,
},
},
});
setIsTerminalVisible(true);
setUnlinkLoading(true);
} catch (e) {
toast.error(e.message);
}
};
if (!database) {
// TODO nice 404
return <p>Database not found.</p>;
}
const linkedApps = database.apps;
const linkedIds = linkedApps?.map((db) => db.id);
const notLinkedApps = apps.filter((db) => {
return linkedIds?.indexOf(db.id) === -1;
});
const appOptions = notLinkedApps.map((app) => {
return {
value: { name: app.name, id: app.id },
label: app.name,
};
});
const handleConnect = async (databaseId: string, appId: string) => {
try {
await linkDatabaseMutation({
variables: {
input: {
databaseId,
appId,
},
},
});
setSelectedApp({
value: { name: '', id: '' },
label: 'Please select an app',
});
setIsTerminalVisible(true);
setLinkLoading(true);
} catch (e) {
toast.error(e.message);
}
};
return (
<div>
<HeaderContainer>
<Header />
<DatabaseHeaderInfo database={database} />
<DatabaseHeaderTabNav database={database} />
</HeaderContainer>
<Container maxW="5xl" mt={10}>
<div className="grid sm:grid-cols-1 md:grid-cols-2 lg:grid-cols-2 xl:grid-cols-2 gap-4 mt-10">
<div>
<Heading as="h2" size="md" py={5}>
Database info
</Heading>
<div className="bg-gray-100 shadow overflow-hidden rounded-lg border-b border-gray-200">
<Table mt="4" mb="4" variant="simple">
<Tbody mt="10">
<Tr py="4">
<Td className="font-semibold" py="3" px="4">
Database name
</Td>
<Td py="3" px="4">
{database.name}
</Td>
</Tr>
<Tr>
<Td className="font-semibold" py="7" px="4">
id
</Td>
<Td w="1/3" py="3" px="4">
{database.id}
</Td>
</Tr>
<Tr>
<Td className="font-semibold" py="3" px="4">
Type
</Td>
<Td py="3" px="4">
{database.type}
</Td>
</Tr>
</Tbody>
</Table>
</div>
</div>
<div className="w-full">
<h1 className="font-bold text-lg font-bold py-5">Apps</h1>
{apps.length === 0 ? (
<>
<div className="mt-3 mb-4">
<h2 className="text-gray-400">
Currently you haven't created apps, to do so proceed with
the app creation flow
</h2>
</div>
<Link to="/create-app">
<Button width="large" color={'grey'}>
Create app
</Button>
</Link>
</>
) : (
<>
{notLinkedApps.length !== 0 ? (
<div>
<Listbox
as="div"
value={selectedApp}
//@ts-ignore
onChange={setSelectedApp}
>
{({ open }) => (
<div className="relative w-80">
<Listbox.Button className="cursor-default relative w-full rounded-md border border-gray-300 bg-white pl-3 pr-10 py-2 text-left focus:outline-none focus:shadow-outline-blue focus:border-blue-300 transition ease-in-out duration-150 sm:text-sm sm:leading-5">
<span className="block truncate">
{selectedApp.label}
</span>
<span className="absolute inset-y-0 right-0 flex items-center pr-2 pointer-events-none">
<svg
className="h-5 w-5 text-gray-400"
viewBox="0 0 20 20"
fill="none"
stroke="currentColor"
>
<path
d="M7 7l3-3 3 3m0 6l-3 3-3-3"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</span>
</Listbox.Button>
{open && (
<Transition
show={open}
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"
className="absolute mt-1 w-full rounded-md bg-white shadow-lg z-10"
>
<Listbox.Options
static
className="max-h-60 rounded-md py-1 text-base leading-6 shadow-ring-1 ring-black ring-opacity-5 overflow-auto focus:outline-none sm:text-sm sm:leading-5"
>
{appOptions.map(
(app) =>
app.value.id !== selectedApp.value.id && (
<Listbox.Option
key={appOptions.indexOf(app)}
value={app as any}
>
{({ active }) => (
<div
className={cx(
'cursor-default select-none relative py-2 px-4',
{
'bg-gray-200': active,
'bg-white text-black': !active,
}
)}
>
{app.label}
</div>
)}
</Listbox.Option>
)
)}
</Listbox.Options>
</Transition>
)}
</div>
)}
</Listbox>
{databaseLinkError && (
<p className="text-red-500 text-sm font-semibold">
{databaseLinkError.graphQLErrors[0].message}
</p>
)}
<Button
color="grey"
width="large"
className="mt-2"
isLoading={
databaseLinkLoading &&
!databaseLinkData &&
!databaseLinkError
}
disabled={!selectedApp.value.id}
onClick={() => setIsLinkModalOpen(true)}
>
Link app
</Button>
{isLinkModalOpen && (
<Modal>
<ModalTitle>Link app</ModalTitle>
<ModalDescription>
{isTerminalVisible ? (
<>
<p className="mb-2 ">
Linking <b>{selectedApp.value.name}</b> with{' '}
<b>{database.name}</b>!
</p>
<p className="text-gray-500 mb-2">
Linking process usually takes a couple of
minutes. Breathe in, breathe out, logs are about
to appear below:
</p>
<Terminal className={'w-6/6'}>
{arrayOfLinkLogs.map((log) => (
<p
key={arrayOfLinkLogs.indexOf(log)}
className="text-s leading-5"
>
{log.message}
</p>
))}
</Terminal>
</>
) : (
<p>
Are you sure, you want to link{' '}
<b>{selectedApp.value.name}</b> to{' '}
<b>{database.name}</b>?
</p>
)}
</ModalDescription>
<ModalButton
ctaFn={() => {
setProcessStatus('running');
handleConnect(databaseId, selectedApp.value.id);
}}
ctaText={'Link'}
otherButtonText={'Cancel'}
isCtaLoading={isTerminalVisible ? false : linkLoading}
isCtaDisabled={isTerminalVisible}
isOtherButtonDisabled={processStatus === 'running'}
closeModal={() => {
setIsLinkModalOpen(false);
refetch({ databaseId });
setLinkLoading(false);
setIsTerminalVisible(false);
setProcessStatus('notStarted');
}}
/>
</Modal>
)}
</div>
) : (
<>
<p className="mt-3 mb-3 mr-8 text-cool-gray-400">
All your apps are already linked to this database! If you
want to create more apps proceed with create app flow.
</p>
<div className="ml-80">
<Link to="/create-app">
<Button
color={'grey'}
variant="outline"
className="text-sm mr-3"
>
Create app
</Button>
</Link>
</div>
</>
)}
{!loading && database && database.apps && (
<>
<h2 className="mb-1 mt-3 font-semibold">
{database.apps.length > 0 && 'Linked apps'}
</h2>
{database.apps.map((app) => (
<div
key={database.apps?.indexOf(app)}
className="flex flex-row justify-start"
>
<Link to={`/app/${app.id}`} className="py-2 block">
<div className="w-64 flex items-center py-3 px-2 shadow hover:shadow-md transition-shadow duration-100 ease-in-out rounded bg-white">
{app.name}
</div>
</Link>
<Button
width="normal"
className="mt-4 ml-2 h-10"
color="red"
onClick={() => {
setIsUnlinkModalOpen(true);
setAppAboutToUnlink(app.name);
}}
>
Unlink
</Button>
{isUnlinkModalOpen && (
<Modal>
<ModalTitle>Unlink app</ModalTitle>
<ModalDescription>
{isTerminalVisible ? (
<>
<p className="mb-2 ">
Unlinking <b>{database.name}</b> from{' '}
<b>{appAboutToUnlink}</b>!
</p>
<p className="text-gray-500 mb-2">
Unlinking process usually takes a couple of
minutes. Breathe in, breathe out, logs are
about to appear below:
</p>
<Terminal className={'w-6/6'}>
{arrayOfUnlinkLogs.map((log) => (
<p
key={arrayOfUnlinkLogs.indexOf(log)}
className="text-s leading-5"
>
{log.message}
</p>
))}
</Terminal>
</>
) : (
<p>
Are you sure, you want to unlink{' '}
<b>{database.name}</b> from{' '}
<b>{appAboutToUnlink}</b>?
</p>
)}
</ModalDescription>
<ModalButton
ctaFn={() => {
setProcessStatus('running');
handleUnlink(database.id, app.id);
}}
ctaText={'Unlink'}
otherButtonText={'Cancel'}
isCtaLoading={
isTerminalVisible ? false : unlinkLoading
}
isOtherButtonDisabled={
processStatus === 'running'
}
isCtaDisabled={isTerminalVisible}
closeModal={() => {
setIsUnlinkModalOpen(false);
refetch({ databaseId });
setUnlinkLoading(false);
setIsTerminalVisible(false);
setAppAboutToUnlink('');
setProcessStatus('notStarted');
}}
/>
</Modal>
)}
</div>
))}
</>
)}
</>
)}
</div>
</div>
</Container>
</div>
);
}
Example #22
Source File: Listbox.tsx From ui with MIT License | 4 votes |
function Listbox({
children,
className,
descriptionText,
error,
icon,
id,
label,
labelOptional,
layout,
onChange,
value,
style,
size = 'medium',
defaultValue,
borderless = false,
}: Props) {
const [selected, setSelected] = useState(defaultValue || undefined)
const [selectedNode, setSelectedNode] = useState<any>({})
useEffect(() => {
if (value) {
setSelected(value)
}
}, [value])
useEffect(() => {
const data: any = children
const content: any = flatten(data)
function findNode(value: any) {
return content.find((node: any) => node.props.value == value)
}
/*
* value prop overrides everything
*/
if (value) {
setSelected(value)
const node: any = findNode(value)
setSelectedNode(node?.props ? node.props : undefined)
return
}
/*
* if no value prop, then use selected state
*/
if (selected) {
const node: any = findNode(selected)
setSelectedNode(node?.props ? node.props : undefined)
} else {
/*
* if no selected value (including a `defaultvalue`), then use first child
*/
setSelectedNode(content[0].props)
}
}, [children, selected, value])
function handleOnChange(e: any) {
if (onChange) onChange(e)
setSelected(e)
}
let selectClasses = [SelectStyles['sbui-listbox']]
if (error) selectClasses.push(SelectStyles['sbui-listbox--error'])
if (icon) selectClasses.push(SelectStyles['sbui-listbox--with-icon'])
if (size) selectClasses.push(SelectStyles[`sbui-listbox--${size}`])
if (borderless) selectClasses.push(SelectStyles['sbui-listbox--borderless'])
return (
<FormLayout
label={label}
labelOptional={labelOptional}
layout={layout}
id={id}
error={error}
descriptionText={descriptionText}
className={className}
style={style}
size={size}
>
<div className={SelectStyles['sbui-listbox-container']}>
<HeadlessListbox value={selected} onChange={handleOnChange}>
{({ open }) => {
return (
<div className="relative">
<HeadlessListbox.Button className={selectClasses.join(' ')}>
{icon && <InputIconContainer icon={icon} />}
<span className={SelectStyles['sbui-listbox-addonbefore']}>
{selectedNode?.addOnBefore && <selectedNode.addOnBefore />}
<span className={SelectStyles['sbui-listbox-label']}>
{selectedNode?.label}
</span>
</span>
<span
className={SelectStyles['sbui-listbox-chevron-container']}
>
<svg
className={SelectStyles['sbui-listbox-chevron']}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fillRule="evenodd"
d="M10 3a1 1 0 01.707.293l3 3a1 1 0 01-1.414 1.414L10 5.414 7.707 7.707a1 1 0 01-1.414-1.414l3-3A1 1 0 0110 3zm-3.707 9.293a1 1 0 011.414 0L10 14.586l2.293-2.293a1 1 0 011.414 1.414l-3 3a1 1 0 01-1.414 0l-3-3a1 1 0 010-1.414z"
clipRule="evenodd"
/>
</svg>
</span>
{error && (
<div
className={SelectStyles['sbui-listbox-actions-container']}
>
{error && <InputErrorIcon size={size} />}
</div>
)}
</HeadlessListbox.Button>
<Transition
show={open}
as={Fragment}
leave={SelectStyles['sbui-listbox-transition--leave']}
leaveFrom={
SelectStyles['sbui-listbox-transition--leave-from']
}
leaveTo={SelectStyles['sbui-listbox-transition--leave-to']}
>
<HeadlessListbox.Options
static
className={SelectStyles['sbui-listbox-option-container']}
>
{children}
</HeadlessListbox.Options>
</Transition>
</div>
)
}}
</HeadlessListbox>
</div>
</FormLayout>
)
}
Example #23
Source File: ConnectedSites.tsx From pali-wallet with MIT License | 4 votes |
ConnectedSites = (): any => {
const { navigate } = useUtils();
const { activeAccount } = useStore();
const [selected, setSelected] = useState<string>('');
const disconnectSite = (id: any) => {
browser.runtime.sendMessage({
type: 'RESET_CONNECTION_INFO',
target: 'background',
id,
url: selected,
});
setSelected('');
};
return (
<Layout title="CONNECTED SITES">
<p className="m-4 max-w-xs text-white text-xs md:max-w-md">
{`${activeAccount?.label} is not connected to any sites. To connect to a SYS platform site, find the connect button on their site.`}
</p>
<div className="flex flex-col items-center justify-center w-full">
{/* {activeAccount?.connectedTo &&
activeAccount.connectedTo.map((url: string) => (
<ul
key={url}
className="scrollbar-styled px-4 py-2 w-full h-80 overflow-auto"
>
<li className="flex items-center justify-between my-2 py-3 w-full text-xs border-b border-dashed border-gray-500">
<p>{formatUrl(url, 25)}</p>
<IconButton onClick={() => setSelected(url)}>
<Icon name="edit" wrapperClassname="w-4" />
</IconButton>
</li>
</ul>
))} */}
{selected && (
<Transition appear show={selected !== ''} as={Fragment}>
<Dialog
as="div"
className="fixed z-10 inset-0 text-center overflow-y-auto"
onClose={() => setSelected('')}
>
<div className="fixed z-0 -inset-0 w-full bg-brand-black bg-opacity-50 transition-all duration-300 ease-in-out" />
<div className="px-4 min-h-screen">
<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 align-middle h-screen"
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"
>
<div className="inline-block align-middle my-8 py-6 w-full max-w-2xl text-left font-poppins bg-bkg-2 rounded-2xl shadow-xl overflow-hidden transform transition-all">
<Dialog.Title
as="h3"
className="pb-3 text-center text-brand-white text-lg font-medium leading-6 border-b border-dashed border-brand-white"
>
Edit connection
</Dialog.Title>
<div className="my-4">
<p className="m-3 text-brand-white text-sm">
Delete connected site:
</p>
<div className="flex items-center justify-between m-3 text-brand-white">
<p>{formatUrl(selected, 20)}</p>
<IconButton
onClick={() => disconnectSite(activeAccount?.id)}
>
<Icon name="delete" />
</IconButton>
</div>
<div className="p-4 bg-bkg-1">
<p className="mb-3 text-brand-white">Permissions</p>
<div className="flex items-center justify-between">
<p className="text-brand-white text-xs">
{activeAccount?.label}
</p>
<p className="text-brand-white text-xs">
{ellipsis(activeAccount?.address)}
</p>
</div>
<p className="mt-4 pt-3 text-brand-white border-t border-dashed border-brand-white opacity-60 cursor-not-allowed">
<input type="checkbox" />
<span className="mb-1 ml-3">
View the addresses of your permitted accounts
</span>
</p>
</div>
</div>
<div className="mt-4 text-center">
<button
type="button"
className="transparent inline-flex justify-center px-12 py-2 hover:text-bkg-4 text-brand-white text-sm font-medium hover:bg-white bg-repeat border border-white rounded-full focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-royalblue focus-visible:ring-offset-2"
onClick={() => setSelected('')}
>
Close
</button>
</div>
</div>
</Transition.Child>
</div>
</Dialog>
</Transition>
)}
<div className="absolute bottom-12 md:static">
<SecondaryButton type="button" onClick={() => navigate('/home')}>
Close
</SecondaryButton>
</div>
</div>
</Layout>
);
}
Example #24
Source File: SidePanel.tsx From ui with MIT License | 4 votes |
SidePanel = ({
className,
children,
title,
description,
visible,
wide = false,
loading,
align = 'right',
alignFooter = 'right',
hideFooter = false,
customFooter = undefined,
onConfirm,
onCancel,
confirmText = 'Confirm',
cancelText = 'Cancel',
triggerElement,
}: Props) => {
const [open, setOpen] = React.useState(visible ? visible : false)
useEffect(() => {
setOpen(visible)
}, [visible])
function stopPropagation(e: React.MouseEvent) {
e.stopPropagation()
}
const sidePanelClasses = [SlidePanelStyles['sbui-sidepanel']]
const left = align === 'left'
const containerClasses = [SlidePanelStyles['sbui-sidepanel-container']]
if (left) {
containerClasses.push(SlidePanelStyles['sbui-sidepanel--left'])
} else {
containerClasses.push(SlidePanelStyles['sbui-sidepanel--right'])
}
if (className) containerClasses.push(className)
let footerClasses = [SlidePanelStyles['sbui-sidepanel-footer-container']]
if (!customFooter) {
footerClasses.push(SlidePanelStyles['sbui-sidepanel-footer'])
}
const footerContent = customFooter ? (
<div className={footerClasses.join(' ')}>{customFooter}</div>
) : (
<div className={footerClasses.join(' ')}>
<Space
style={{
width: '100%',
justifyContent: alignFooter === 'right' ? 'flex-end' : 'flex-start',
}}
>
<Button
disabled={loading}
type="outline"
onClick={() => (onCancel ? onCancel() : null)}
>
{cancelText}
</Button>
<Button
loading={loading}
onClick={() => (onConfirm ? onConfirm() : null)}
>
{confirmText}
</Button>
</Space>
</div>
)
function handleOpenChange(open: boolean) {
if (visible !== undefined && !open) {
// controlled component behaviour
onCancel()
} else {
// un-controlled component behaviour
setOpen(open)
}
}
return (
<Dialog.Root open={open} onOpenChange={handleOpenChange}>
{triggerElement && (
<Dialog.Trigger className={SlidePanelStyles[`sbui-sidepanel__trigger`]}>
{triggerElement}
</Dialog.Trigger>
)}
<Transition show={open}>
<Dialog.Overlay forceMount>
<Transition.Child
enter={SlidePanelStyles[`sbui-sidepanel-overlay--enter`]}
enterFrom={SlidePanelStyles[`sbui-sidepanel-overlay--enterFrom`]}
enterTo={SlidePanelStyles[`sbui-sidepanel-overlay--enterTo`]}
leave={SlidePanelStyles[`sbui-sidepanel-overlay--leave`]}
leaveFrom={SlidePanelStyles[`sbui-sidepanel-overlay--leaveFrom`]}
leaveTo={SlidePanelStyles[`sbui-sidepanel-overlay--leaveTo`]}
>
<div
className={SlidePanelStyles['sbui-sidepanel-overlay-container']}
>
<div className={SlidePanelStyles['sbui-sidepanel-overlay']}></div>
</div>
</Transition.Child>
</Dialog.Overlay>
<Dialog.Content forceMount style={{ width: '100vw' }}>
<div className={containerClasses.join(' ')}>
<Transition.Child
enter={SlidePanelStyles[`sbui-sidepanel--enter`]}
enterFrom={
left
? SlidePanelStyles[`sbui-sidepanel--enterFrom--left`]
: SlidePanelStyles[`sbui-sidepanel--enterFrom`]
}
enterTo={SlidePanelStyles[`sbui-sidepanel--enterTo`]}
leave={SlidePanelStyles[`sbui-sidepanel--leave`]}
leaveFrom={SlidePanelStyles[`sbui-sidepanel--leaveFrom`]}
leaveTo={
left
? SlidePanelStyles[`sbui-sidepanel--leaveTo--left`]
: SlidePanelStyles[`sbui-sidepanel--leaveTo`]
}
>
<div
className={
wide
? SlidePanelStyles['sbui-sidepanel--wide']
: SlidePanelStyles['sbui-sidepanel--medium']
}
>
<div
className={sidePanelClasses.join(' ')}
onClick={stopPropagation}
>
<Space
size={6}
direction="vertical"
style={{
minHeight: '0',
flex: '1 1 0%',
overflowY: 'scroll',
}}
>
<header
className={SlidePanelStyles['sbui-sidepanel-header']}
>
<Space
size={3}
direction="row"
style={{
alignItems: 'center',
justifyContent: 'space-between',
}}
>
{title && (
<Typography.Title className="m-0" level={4}>
{title}
</Typography.Title>
)}
<div
className={
SlidePanelStyles['sbui-sidepanel-close-container']
}
>
<Button
aria-label="Close panel"
onClick={onCancel}
type="text"
shadow={false}
style={{ padding: 0 }}
icon={<IconX size="xlarge" strokeWidth={2} />}
/>
</div>
</Space>
<div>
{description && (
<Typography.Text type="secondary">
{description}
</Typography.Text>
)}
</div>
</header>
<div className={SlidePanelStyles['sbui-sidepanel-content']}>
{children}
</div>
</Space>
{!hideFooter && footerContent}
</div>
</div>
</Transition.Child>
</div>
</Dialog.Content>
</Transition>
</Dialog.Root>
)
}
Example #25
Source File: BlogNav.tsx From vignette-web with MIT License | 4 votes |
Nav: React.FC = () => {
const { t } = useTranslation([`nav`, `common`])
const [isOpen, setIsOpen] = useState<boolean>(false)
const toggleMenu = () => (isOpen ? setIsOpen(false) : setIsOpen(true))
const [mounted, setMounted] = useState(false)
const { resolvedTheme, setTheme } = useTheme()
const router = useRouter()
// A flag to know when the page has mounted so the theme can be accessed
useEffect(() => setMounted(true), [])
return (
<>
{` `}
<a
href="#content"
className="text-md absolute -top-7 z-50 ml-3 -translate-y-12 transform rounded-md border border-gray-300 bg-white px-3 py-2 tracking-tight outline-none transition-transform duration-100 focus:translate-y-12 dark:border-neutral-700 dark:bg-black lg:ml-8"
>
Skip to content
</a>
{` `}
<div className="relative z-30 mx-auto flex w-full max-w-7xl items-center justify-between bg-transparent py-6 px-4 sm:px-8 lg:px-4 ">
<div className="flex items-center">
<Link href="/blog" passHref>
<a className="text-lg font-bold lg:text-xl">
{t(`blog:nav-title`)}
</a>
</Link>
</div>
<div className=" mx-4 ml-auto hidden items-center gap-4 sm:flex ">
<MyListbox router={router} />
<button
className="outline-none"
onClick={() =>
setTheme(resolvedTheme === `dark` ? `light` : `dark`)
}
>
{mounted ? (
resolvedTheme == `dark` ? (
<BsSunFill size={18} />
) : (
<BsMoonFill size={18} />
)
) : (
<div className="w-[18px]" />
)}
</button>
<Link href="https://github.com/vignetteapp" passHref>
<a className="outline-none">
<AiFillGithub size={24} />
</a>
</Link>
<Link href="https://twitter.com/vignette_org" passHref>
<a className="outline-none">
<AiOutlineTwitter size={24} />
</a>
</Link>
<button className="rounded-full bg-pinkRed px-8 py-1 font-semibold text-white ">
{t(`download`)}
</button>
</div>
<div className="flex items-center lg:hidden">
<button className="" onClick={toggleMenu}>
<GiHamburgerMenu size="28" className="fill-neutral-100" />
</button>
<Transition appear show={isOpen} as={Fragment}>
<Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
className="fixed inset-0 z-50 lg:hidden"
>
<Transition.Child
as={Fragment}
enter="ease-out duration-100"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="ease-in duration-75"
leaveFrom="opacity-100"
leaveTo="opacity-0"
>
<Dialog.Overlay className="fixed inset-0 bg-black/20 backdrop-blur-sm dark:bg-neutral-900/80 " />
</Transition.Child>
<Transition.Child
as={Fragment}
enter="ease-out duration-100"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
leave="ease-in duration-75"
leaveFrom="opacity-100 scale-100"
leaveTo="opacity-0 scale-95"
>
<div className="dark:highlight-white/5 fixed top-4 right-4 w-full max-w-xs rounded-lg bg-white p-6 text-base font-semibold text-gray-900 shadow-lg dark:bg-neutral-900 dark:text-gray-300">
<button
onClick={() => setIsOpen(false)}
className="absolute top-5 right-5 flex h-8 w-8 items-center justify-center text-gray-500 hover:text-gray-600 dark:text-gray-200 dark:hover:text-gray-100"
>
<span className="sr-only">Close navigation</span>
<svg
viewBox="0 0 10 10"
className="h-2.5 w-2.5 overflow-visible"
aria-hidden="true"
>
<path
d="M0 0L10 10M10 0L0 10"
fill="none"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
></path>
</svg>
</button>
<ul className="space-y-6">
<li>
<Link href="/">
<a>{t(`nav:home`)}</a>
</Link>
</li>
<li>
<Link href="/features">
<a>{t(`nav:features`)}</a>
</Link>
</li>
<li>
<Link href="/about">
<a>{t(`nav:about`)}</a>
</Link>
</li>
<li>
<Link href="/blog">
<a>{t(`nav:blog`)}</a>
</Link>
</li>
<li>
<Link href="/contact">
<a>{t(`nav:contact`)}</a>
</Link>
</li>
<li>
<MyListbox router={router} />
</li>
</ul>
<div className="mt-6 border-t border-gray-200 pt-6 dark:border-gray-200/10">
<button
aria-label="Toggle Dark Mode"
type="button"
className="general-ring-state flex w-full items-center justify-center rounded-full bg-gray-200 py-3 dark:bg-neutral-700"
onClick={() =>
setTheme(resolvedTheme === `dark` ? `light` : `dark`)
}
>
{mounted && (
<>
<div>
{resolvedTheme === `dark` ? (
<BsSunFill size={18} />
) : (
<BsMoonFill size={18} />
)}
</div>
{resolvedTheme === `dark` ? (
<p className="ml-3 font-semibold">
{t(`common:switch-theme-light`)}
</p>
) : (
<p className="ml-3 font-semibold">
{t(`common:switch-theme-dark`)}
</p>
)}
</>
)}
</button>
</div>
</div>
</Transition.Child>
</Dialog>
</Transition>
</div>
</div>
</>
)
}
Example #26
Source File: Currency.tsx From pali-wallet with MIT License | 4 votes |
CurrencyView = () => {
const controller = getController();
const { navigate, handleRefresh } = useUtils();
const { getFiatAmount } = usePrice();
const { activeAccount } = useStore();
if (!activeAccount) throw new Error('No account');
const { accounts, activeAccountId, coins, fiat, activeNetwork, networks } =
useStore();
const { asset } = fiat;
const [selectedCoin, setSelectedCoin] = useState(String(asset));
const [checkValueCoin, setCheckValueCoin] = useState('usd');
const [confirmed, setConfirmed] = useState(false);
const [fiatAmountValue, setFiatAmountValue] = useState('');
const convertCurrency = (value: number, toCoin: string) =>
value * coins[toCoin];
const convertToCrypto = (value: number, fromCoin: string) =>
value / coins[fromCoin];
const isUnlocked =
controller.wallet.isUnlocked() && activeAccount.address !== '';
const isSyscoinChain = Boolean(networks.syscoin[activeNetwork.chainId]);
const balance = isSyscoinChain
? activeAccount.balances.syscoin
: activeAccount.balances.ethereum;
const [conversorValues, setConversorValues] = useState({
crypto: balance,
fiat: convertCurrency(balance, checkValueCoin),
});
const handleConvert = (value: number, toCoin: string) => {
setConversorValues({
crypto: value,
fiat: convertCurrency(value, toCoin),
});
};
const handleReverseConvert = (value: number, fromCoin: string) => {
setConversorValues({
crypto: convertToCrypto(value, fromCoin),
fiat: value,
});
};
const handleConfirmCurrencyChange = () => {
setConfirmed(true);
};
const fiatCurrency = asset ? String(asset).toUpperCase() : 'USD';
const getFiatAmountValue = async () => {
const value = await getFiatAmount(balance || 0, 4, String(selectedCoin));
setFiatAmountValue(value);
};
useEffect(() => {
if (isUnlocked && accounts && accounts[activeAccountId]) {
handleRefresh(true);
}
}, [isUnlocked, activeAccountId]);
useEffect(() => {
if (selectedCoin) {
controller.utils.setFiat(
selectedCoin,
isSyscoinChain ? 'syscoin' : 'ethereum'
);
getFiatAmountValue();
}
}, [selectedCoin]);
useEffect(() => {
getFiatAmountValue();
}, [selectedCoin, getFiatAmountValue]);
return (
<Layout title="FIAT CURRENCY" id="fiat-currency-title">
<DefaultModal
show={confirmed}
onClose={() => navigate('/home')}
title="Fiat currency set successfully"
description={`Now you will see the values in your wallet in SYS and ${
selectedCoin.toUpperCase() || 'USD'
}`}
/>
<p className="mx-4 my-3 max-w-xs text-left text-white text-sm md:max-w-full">
You can choose and set your preferred currency to see in your wallet.
</p>
<div className="flex flex-col items-center justify-center">
<Menu as="div" className="relative inline-block text-left">
<Menu.Button
disabled={!fiat || !coins}
className="inline-flex justify-center py-2 w-80 text-white text-sm font-medium bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-full"
>
<p className="ml-2">
{selectedCoin ? selectedCoin.toUpperCase() : fiatCurrency}
</p>
<Icon
name="select-down"
className="text-brand-royalblue"
wrapperClassname="w-8 absolute right-28 bottom-3"
/>
</Menu.Button>
<Transition
as={Fragment}
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"
>
{fiat && coins && (
<Menu.Items className="scrollbar-styled absolute z-10 mt-2 py-3 w-full h-44 text-brand-white font-poppins bg-bkg-4 border border-fields-input-border rounded-xl shadow-2xl overflow-auto origin-top-right">
{Object.entries(coins).map(([key]) => (
<Menu.Item key={key}>
<button
key={key}
onClick={() => setSelectedCoin(key)}
className="group flex gap-x-1 items-center justify-start px-4 py-2 w-full hover:text-brand-royalbluemedium text-brand-white font-poppins text-sm border-0 border-b border-dashed border-brand-royalblue border-transparent border-opacity-30 transition-all duration-300"
>
{getSymbolFromCurrency(key.toUpperCase())}
<p>{key.toUpperCase()}</p>
</button>
</Menu.Item>
))}
</Menu.Items>
)}
</Transition>
</Menu>
<div className="flex flex-col items-center justify-center text-center">
{activeNetwork.chainId === 5700 ? (
<div className="flex gap-x-0.5 items-center justify-center mt-8">
<p className="font-rubik text-5xl font-medium">
{formatNumber(Number(balance) || 0)}{' '}
</p>
<p className="font-poppins md:mt-4">TSYS</p>
</div>
) : (
<>
<div className="flex gap-x-0.5 items-center justify-center mt-8">
<p className="font-rubik text-5xl font-medium">
{formatNumber(balance || 0)}{' '}
</p>
<p className="font-poppins md:mt-4">
{activeNetwork.currency
? activeNetwork.currency.toUpperCase()
: ''}
</p>
</div>
<p>{fiatAmountValue ?? 0}</p>
</>
)}
</div>
<div className="mt-6 md:mt-8">
<SecondaryButton type="button" onClick={handleConfirmCurrencyChange}>
Save
</SecondaryButton>
</div>
</div>
<div className="fixed bottom-0 left-0 flex flex-col gap-y-3 items-center justify-center w-full max-w-2xl h-44 bg-bkg-4 md:bottom-8 md:left-auto">
<p className="mb-2 text-left text-white text-sm">
Check your balance in different currencies
</p>
<div className="standard relative text-brand-royalblue text-sm font-medium">
<Input
type="number"
onChange={(event) =>
handleConvert(Number(event.target.value), checkValueCoin)
}
maxLength={20}
value={Number(conversorValues.crypto)}
className="flex items-center justify-between px-4 py-2 w-80 bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-full outline-none"
/>
<div className="absolute bottom-1.5 right-4 flex gap-x-3 items-center justify-center">
<p
className="cursor-pointer"
onClick={() => handleConvert(Number(balance), checkValueCoin)}
>
MAX
</p>
<div className="flex gap-x-3 items-center justify-center border-l border-dashed border-gray-700">
<Icon
name="dolar"
wrapperClassname="w-2 ml-4 mb-1.5"
className="text-brand-royalblue"
/>
<p>SYS</p>
</div>
</div>
</div>
<div className="standard relative text-brand-royalblue text-sm font-medium">
<Input
type="number"
maxLength={20}
onChange={(event) => {
handleReverseConvert(Number(event.target.value), checkValueCoin);
}}
value={Number(conversorValues.fiat)}
className="flex items-center justify-between px-4 py-2 w-80 bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-full outline-none"
/>
<div className="absolute bottom-2 right-2 flex gap-x-3 items-center justify-center">
<Menu as="div" className="relative inline-block text-left">
<Menu.Button
disabled={!fiat || !coins}
className="flex gap-x-1 justify-center mr-5 text-brand-royalblue text-sm font-medium bg-fields-input-primary rounded-full"
>
{getSymbolFromCurrency(checkValueCoin.toUpperCase())}
{checkValueCoin.toUpperCase()}
<Icon
name="select-down"
className="text-brand-royalblue"
wrapperClassname="w-8 absolute -right-1 bottom-1"
/>
</Menu.Button>
<Transition
as={Fragment}
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"
>
{fiat && coins && (
<Menu.Items className="scrollbar-styled absolute z-10 bottom-10 right-0 mt-2 py-3 w-44 h-56 text-brand-white font-poppins bg-bkg-4 border border-fields-input-border rounded-xl shadow-2xl overflow-auto origin-bottom-right">
{Object.entries(coins).map(([key]) => (
<Menu.Item key={key}>
<button
key={key}
onClick={() => {
setCheckValueCoin(key);
handleConvert(conversorValues.crypto, key);
}}
className="group flex gap-x-1 items-center justify-start px-4 py-2 w-full hover:text-brand-royalbluemedium text-brand-white font-poppins text-sm border-0 border-b border-dashed border-brand-royalblue border-transparent border-opacity-30 transition-all duration-300"
>
{getSymbolFromCurrency(key.toUpperCase())}
<p>{key.toUpperCase()}</p>
</button>
</Menu.Item>
))}
</Menu.Items>
)}
</Transition>
</Menu>
</div>
</div>
</div>
</Layout>
);
}
Example #27
Source File: Navbar.tsx From ultimate-saas-ts with MIT License | 4 votes |
Component = () => {
const { data: session, status } = useSession();
const router = useRouter();
return (
<Disclosure as="nav" className="bg-white">
{({ open }) => (
<>
<div className="px-2 mx-auto max-w-7xl sm:px-6 lg:px-8">
<div className="relative flex justify-between h-16">
<div className="absolute inset-y-0 left-0 flex items-center sm:hidden">
<Disclosure.Button className="inline-flex items-center justify-center p-2 text-gray-400 rounded-md hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500">
<span className="sr-only">Open main menu</span>
{open ? (
<XIcon className="block w-6 h-6" aria-hidden="true" />
) : (
<MenuIcon className="block w-6 h-6" aria-hidden="true" />
)}
</Disclosure.Button>
</div>
<div className="flex items-center justify-center flex-1 sm:items-stretch sm:justify-start">
<div className="flex items-center flex-shrink-0">
<img
className="block w-auto h-8 lg:hidden"
src="https://tailwindui.com/img/logos/workflow-mark-indigo-600.svg"
alt="Workflow"
/>
<img
className="hidden w-auto h-8 lg:block"
src="https://tailwindui.com/img/logos/workflow-logo-indigo-600-mark-gray-800-text.svg"
alt="Workflow"
/>
</div>
<div className="hidden sm:ml-6 sm:flex sm:space-x-8">
<Link href="/">
<a
className={classNames(
'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium',
{
'border-indigo-500 text-gray-900':
router.pathname === '/',
'': router.pathname !== '/',
}
)}
>
Pricings
</a>
</Link>
<Link href="/account">
<a
className={classNames(
'border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium',
{
'border-indigo-500 text-gray-900':
router.pathname === '/account',
'': router.pathname !== '/account',
}
)}
>
Account
</a>
</Link>
</div>
</div>
<div className="absolute inset-y-0 right-0 flex items-center pr-2 sm:static sm:inset-auto sm:ml-6 sm:pr-0">
{/* Profile dropdown */}
{status === 'authenticated' ? (
<Menu as="div" className="relative ml-3">
<div>
<Menu.Button className="flex text-sm bg-white rounded-full focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
<span className="sr-only">Open user menu</span>
<img
className="w-8 h-8 rounded-full"
src={
session?.user?.image ||
'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'
}
alt=""
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-200"
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"
>
<Menu.Items className="absolute right-0 w-48 py-1 mt-2 origin-top-right bg-white rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
<Menu.Item>
{({ active }) => (
<Link href="/account">
<a
className={classNames(
active ? 'bg-gray-100' : '',
'block px-4 py-2 text-sm text-gray-700'
)}
>
Account
</a>
</Link>
)}
</Menu.Item>
<Menu.Item>
{({ active }) => (
<a
onClick={() => signOut()}
className={classNames(
active ? 'bg-gray-100' : '',
'block px-4 py-2 text-sm text-gray-700'
)}
>
Sign out
</a>
)}
</Menu.Item>
</Menu.Items>
</Transition>
</Menu>
) : (
<Link href="/api/auth/signin">
<a>Sign in</a>
</Link>
)}
</div>
</div>
</div>
<Disclosure.Panel className="sm:hidden">
<div className="pt-2 pb-4 space-y-1">
{/* Current: "bg-indigo-50 border-indigo-500 text-indigo-700", Default: "border-transparent text-gray-500 hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700" */}
<Link href="/">
<a className="block py-2 pl-3 pr-4 text-base font-medium text-indigo-700 border-l-4 border-indigo-500 bg-indigo-50">
Pricings
</a>
</Link>
<Link href="/account">
<a className="block py-2 pl-3 pr-4 text-base font-medium text-gray-500 border-l-4 border-transparent hover:bg-gray-50 hover:border-gray-300 hover:text-gray-700">
Account
</a>
</Link>
</div>
</Disclosure.Panel>
</>
)}
</Disclosure>
);
}
Example #28
Source File: SendEth.tsx From pali-wallet with MIT License | 4 votes |
SendEth = () => {
const controller = getController();
const { alert, navigate } = useUtils();
const { activeAccount } = useStore();
const [selectedAsset, setSelectedAsset] = useState<any | null>(null);
const [recommendedGasPrice, setRecommendedGasPrice] = useState(0);
const [recommendedGasLimit, setRecommendedGasLimit] = useState(0);
const [feeValue, setFeeValue] = useState(0);
const [editGas, setEditGas] = useState(false);
const [form] = Form.useForm();
const { convertGasFee } = feeUtils();
const getRecomendedFees = useCallback(async () => {
const gasPrice =
await controller.wallet.account.eth.tx.getRecommendedGasPrice(false);
const gasLimit = await controller.wallet.account.eth.tx.getGasLimit();
setRecommendedGasPrice(gasPrice);
setRecommendedGasLimit(gasLimit);
setFeeValue(gasPrice);
form.setFieldsValue({ baseFee: recommendedGasPrice, gasLimit, gasPrice });
}, [controller.wallet.account]);
useEffect(() => {
getRecomendedFees();
}, [getRecomendedFees]);
const hasAccountAssets = activeAccount && activeAccount.assets.length > 0;
const handleSelectedAsset = (item: string) => {
if (activeAccount?.assets) {
const getAsset = activeAccount?.assets.find(
(asset: any) => asset.contract_address === item
);
if (getAsset) {
setSelectedAsset(getAsset);
return;
}
setSelectedAsset(null);
}
};
const nextStep = ({ receiver, amount, gasPrice, gasLimit }: any) => {
try {
navigate('/send/confirm', {
state: {
tx: {
sender: activeAccount.address,
senderXprv: activeAccount.xprv,
receivingAddress: receiver,
amount,
gasPrice,
gasLimit,
fee: Number(convertGasFee(String(feeValue))),
token: null,
// token: {
// decimals: 18,
// contractAddress: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
// },
},
},
});
} catch (error) {
alert.removeAll();
alert.error('An internal error has occurred.');
}
};
return (
<>
{editGas ? (
<EditGasFee
setGasFee={setRecommendedGasPrice}
setEdit={setEditGas}
form={form}
setFee={setFeeValue}
/>
) : (
<div className="mt-4">
<p className="flex flex-col items-center justify-center text-center font-rubik">
<span className="text-brand-royalblue font-poppins font-thin">
Balance
</span>
{selectedAsset
? getAssetBalance(selectedAsset, activeAccount)
: activeAccount.balances.ethereum}
</p>
<Form
form={form}
id="send-form"
labelCol={{ span: 8 }}
wrapperCol={{ span: 8 }}
initialValues={{
baseFee: recommendedGasPrice,
gasLimit: recommendedGasLimit,
gasPrice: recommendedGasPrice,
}}
onFinish={nextStep}
autoComplete="off"
className="standard flex flex-col gap-3 items-center justify-center mt-4 text-center md:w-full"
>
<Form.Item
name="receiver"
className="md:w-full md:max-w-md"
hasFeedback
rules={[
{
required: true,
message: '',
},
() => ({
validator(_, value) {
if (!value || isValidEthereumAddress(value)) {
return Promise.resolve();
}
return Promise.reject();
},
}),
]}
>
<Input type="text" placeholder="Receiver" className="large" />
</Form.Item>
<div className="flex items-center justify-center md:w-full md:max-w-md">
{hasAccountAssets && (
<Form.Item
name="asset"
className=""
rules={[
{
required: false,
message: '',
},
]}
>
<Menu>
<div className="relative inline-block text-left">
<Menu.Button
disabled={!hasAccountAssets}
className="inline-flex justify-center mt-3 py-3 w-20 text-white text-sm font-medium bg-fields-input-primary hover:bg-opacity-30 border border-fields-input-border focus:border-fields-input-borderfocus rounded-full focus:outline-none focus-visible:ring-2 focus-visible:ring-white focus-visible:ring-opacity-75"
>
{selectedAsset?.symbol
? formatUrl(String(selectedAsset?.symbol), 2)
: 'ETH'}
<ChevronDoubleDownIcon
className="text-violet-200 hover:text-violet-100 -mr-1 ml-2 w-5 h-5"
aria-hidden="true"
/>
</Menu.Button>
<Transition
as={Fragment}
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"
>
{hasAccountAssets && (
<Menu.Items className="scrollbar-styled absolute z-10 left-0 mt-2 py-3 w-44 h-56 text-brand-white font-poppins bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-lg shadow-2xl overflow-auto origin-top-right">
{activeAccount &&
Object.values(activeAccount.assets).map(
(item: any) => (
<Menu.Item>
<button
onClick={() =>
handleSelectedAsset(
item.contract_address
)
}
className="group flex items-center justify-between px-2 py-2 w-full hover:text-brand-royalblue text-brand-white font-poppins text-sm border-0 border-transparent transition-all duration-300"
>
<p>{item.symbol}</p>
</button>
</Menu.Item>
)
)}
</Menu.Items>
)}
</Transition>
</div>
</Menu>
</Form.Item>
)}
<div className="flex flex-col">
<div className="flex w-full">
<label className="flex-1 mr-4 text-xs" htmlFor="gasPrice">
Gas Price
</label>
<label className="flex-1 mr-6 text-xs" htmlFor="gasLimit">
Gas Limit
</label>
</div>
<div
className={`${
hasAccountAssets ? 'w-48 ml-4' : 'w-72'
} flex gap-x-0.5 items-center justify-center md:w-full`}
>
<Form.Item
name="gasPrice"
className="flex-1 w-32 text-center bg-fields-input-primary rounded-l-full md:w-full"
rules={[
{
required: false,
message: '',
},
]}
>
<Input
type="text"
placeholder="Gas Price (GWEI)"
className="p-3 w-full text-sm bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-l-full outline-none md:w-full"
/>
</Form.Item>
<Form.Item
name="gasLimit"
className="flex-1 w-32 text-center bg-fields-input-primary rounded-r-full"
rules={[
{
required: false,
message: '',
},
]}
>
<Input
type="text"
placeholder="Gas Limit"
className="p-3 w-full text-sm bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-r-full outline-none md:w-full"
/>
</Form.Item>
</div>
</div>
</div>
<Form.Item
name="amount"
className="md:w-full md:max-w-md"
hasFeedback
rules={[
{
required: true,
message: '',
},
() => ({
validator(_, value) {
const balance = selectedAsset
? selectedAsset.balance / 10 ** selectedAsset.decimals
: Number(activeAccount?.balances.ethereum);
if (value > balance) {
return Promise.reject();
}
return Promise.resolve();
},
}),
]}
>
<Input className="large" type="number" placeholder="Amount" />
</Form.Item>
<div className="flex gap-x-0.5 items-center justify-center mx-2 md:w-full md:max-w-md">
<Form.Item
name="edit"
className="w-12 text-center bg-fields-input-primary border border-fields-input-border focus:border-fields-input-borderfocus rounded-l-full opacity-70 cursor-pointer"
rules={[
{
required: false,
message: '',
},
]}
>
<Tooltip content="Click to edit fee">
<div onClick={() => setEditGas(true)}>
<Icon
wrapperClassname="w-6 ml-3 mt-1 h-10"
name="edit"
className="text-brand-royalbluemedium cursor-pointer"
/>
</div>
</Tooltip>
</Form.Item>
<Form.Item
name="baseFee"
className="md:w-full"
hasFeedback
rules={[
{
required: true,
message: '',
},
]}
>
<Tooltip content="Recommended network base fee">
<Input
disabled
className="block pl-4 pr-8 py-3 w-60 text-brand-white text-sm bg-fields-input-primary border border-fields-input-border rounded-r-full outline-none opacity-50 cursor-not-allowed md:w-full"
id="baseFee-input"
type="number"
placeholder="Base fee"
value={recommendedGasPrice}
/>
</Tooltip>
</Form.Item>
</div>
<p className="flex flex-col items-center justify-center p-0 max-w-xs text-center text-brand-royalblue sm:w-full md:my-4">
<span className="text-xs">Amount + fee</span>
<span className="mt-0.5 text-brand-white font-rubik text-xs">
{'≈ '}
</span>
</p>
<SecondaryButton type="submit" id="next-btn">
Next
</SecondaryButton>
</Form>
</div>
)}
</>
);
}
Example #29
Source File: services.tsx From eventcatalog with MIT License | 4 votes |
export default function Page({ services }: PageProps) {
const [servicesToRender, setServicesToRender] = useState(services);
const [searchFilter, setSearchFilter] = useState('');
const getFilteredServices = (): any => {
let filteredServices = services;
if (searchFilter) {
filteredServices = filteredServices.filter((service) => service.name.toLowerCase().includes(searchFilter.toLowerCase()));
}
return filteredServices;
};
useEffect(() => {
setServicesToRender(getFilteredServices());
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [searchFilter]);
const debouncedFilter = useCallback(
debounce((e) => {
setSearchFilter(e.target.value);
}, 500),
[servicesToRender]
);
const filtersApplied = !!searchFilter;
const [showMermaidDiagrams, setShowMermaidDiagrams] = useState(false);
const { title } = useConfig();
return (
<>
<Head>
<title>{title} - All Services</title>
</Head>
<main className="max-w-7xl mx-auto md:min-h-screen px-4 xl:px-0">
<div className="relative z-10 flex items-baseline justify-between pt-8 pb-6 border-b border-gray-200">
<h1 className="text-2xl font-extrabold tracking-tight text-gray-900">Services ({services.length})</h1>
<div className="flex items-center">
<Menu as="div" className="relative hidden text-left">
<div>
<Menu.Button className="group inline-flex justify-center text-sm font-medium text-gray-700 hover:text-gray-900">
Sort
<ChevronDownIcon
className="flex-shrink-0 -mr-1 ml-1 h-5 w-5 text-gray-400 group-hover:text-gray-500"
aria-hidden="true"
/>
</Menu.Button>
</div>
<Transition
as={Fragment}
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"
>
<Menu.Items className="origin-top-right absolute right-0 mt-2 w-40 rounded-md shadow-2xl bg-white ring-1 ring-black ring-opacity-5 focus:outline-none">
<div className="py-1">
{sortOptions.map((option) => (
<Menu.Item key={option.name}>
{({ active }) => (
<a
href={option.href}
className={classNames(
option.current ? 'font-medium text-gray-900' : 'text-gray-500',
active ? 'bg-gray-100' : '',
'block px-4 py-2 text-sm'
)}
>
{option.name}
</a>
)}
</Menu.Item>
))}
</div>
</Menu.Items>
</Transition>
</Menu>
</div>
</div>
<section className="pt-6 pb-24">
<div className="grid grid-cols-4 gap-x-8 gap-y-10">
{/* Filters */}
<form className="hidden lg:block">
<div className="border-b border-gray-200 pb-6">
<label htmlFor="service" className="font-bold block text-sm font-medium text-gray-700">
Search Services
</label>
<div className="mt-1 relative rounded-md shadow-sm">
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<SearchIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
</div>
<input
type="text"
name="service"
id="service"
onChange={debouncedFilter}
className="focus:ring-gray-500 focus:border-gray-500 block w-full pl-10 sm:text-sm border-gray-300 rounded-md"
/>
</div>
</div>
<div className="border-b border-gray-200 pb-6">
<h3 className="-my-3 flow-root">
<div className="py-3 bg-white w-full flex items-center justify-between text-sm text-gray-400 hover:text-gray-500">
<span className="font-medium text-gray-900">Features</span>
</div>
</h3>
<div className="pt-6">
<div className="space-y-4">
<div className="flex items-center">
<input
id="show-mermaid"
type="checkbox"
onChange={(e) => setShowMermaidDiagrams(e.target.checked)}
defaultChecked={showMermaidDiagrams}
className="h-4 w-4 border-gray-300 rounded text-gray-600 focus:ring-gray-500"
/>
<label htmlFor="show-mermaid" className="ml-3 text-sm text-gray-600">
Show Mermaid Diagrams
</label>
</div>
</div>
</div>
</div>
</form>
<div className="col-span-4 lg:col-span-3">
<div>
<h2 className="text-gray-500 text-xs font-medium uppercase tracking-wide">
{filtersApplied
? `Filtered Services (${servicesToRender.length}/${services.length})`
: `All Services (${services.length})`}
</h2>
<ServiceGrid services={servicesToRender} showMermaidDiagrams={showMermaidDiagrams} />
{servicesToRender.length === 0 && (
<div className="text-gray-400 flex h-96 justify-center items-center">
<div>
<SearchIcon className="w-6 h-6 inline-block mr-1" />
No services found.
</div>
</div>
)}
</div>
</div>
</div>
</section>
</main>
</>
);
}