diff --git a/web/components/bet-panel.tsx b/web/components/bet-panel.tsx index 574fdd53..57d4a60c 100644 --- a/web/components/bet-panel.tsx +++ b/web/components/bet-panel.tsx @@ -26,13 +26,17 @@ import { AmountInput } from './amount-input' import { InfoTooltip } from './info-tooltip' import { OutcomeLabel } from './outcome-label' -export function BetPanel(props: { contract: Contract; className?: string }) { +export function BetPanel(props: { + contract: Contract + className?: string + title?: string +}) { useEffect(() => { // warm up cloud function placeBet({}).catch() }, []) - const { contract, className } = props + const { contract, className, title } = props const user = useUser() @@ -113,10 +117,7 @@ export function BetPanel(props: { contract: Contract; className?: string }) { - + <Title className="mt-0 text-neutral" text={title ?? `Buy ${betChoice}`} /> <div className="mt-2 mb-1 text-sm text-gray-500">Outcome</div> <YesNoSelector diff --git a/web/components/bet-row.tsx b/web/components/bet-row.tsx new file mode 100644 index 00000000..689aab8f --- /dev/null +++ b/web/components/bet-row.tsx @@ -0,0 +1,79 @@ +/* This example requires Tailwind CSS v2.0+ */ +import { Fragment, useState } from 'react' +import { Dialog, Transition } from '@headlessui/react' +import { CheckIcon } from '@heroicons/react/outline' +import { Contract } from '../lib/firebase/contracts' +import { BetPanel } from './bet-panel' + +// Inline version of a bet panel. Opens BetPanel in a new modal. +export default function BetRow(props: { contract: Contract }) { + // Button to open the modal + const [open, setOpen] = useState(false) + + return ( + <> + <button + className="flex items-center justify-center w-full h-full p-2 text-white bg-blue-500 hover:bg-blue-700 rounded-lg" + onClick={() => setOpen(true)} + > + Trade + </button> + <Modal open={open} setOpen={setOpen}> + <BetPanel contract={props.contract} title={props.contract.question} /> + </Modal> + </> + ) +} + +export function Modal(props: { + children: React.ReactNode + open: boolean + setOpen: (open: boolean) => void +}) { + const { children, open, setOpen } = props + + return ( + <Transition.Root show={open} as={Fragment}> + <Dialog + as="div" + className="fixed z-10 inset-0 overflow-y-auto" + onClose={setOpen} + > + <div className="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"> + <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-gray-500 bg-opacity-75 transition-opacity" /> + </Transition.Child> + + {/* This element is to trick the browser into centering the modal contents. */} + <span + className="hidden sm:inline-block sm:align-middle sm:h-screen" + aria-hidden="true" + > + ​ + </span> + <Transition.Child + as={Fragment} + enter="ease-out duration-300" + enterFrom="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" + enterTo="opacity-100 translate-y-0 sm:scale-100" + leave="ease-in duration-200" + leaveFrom="opacity-100 translate-y-0 sm:scale-100" + leaveTo="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95" + > + <div className="inline-block align-bottom text-left overflow-hidden transform transition-all sm:my-8 sm:align-middle sm:max-w-sm sm:w-full sm:p-6"> + {children} + </div> + </Transition.Child> + </div> + </Dialog> + </Transition.Root> + ) +} diff --git a/web/components/contract-feed.tsx b/web/components/contract-feed.tsx index 99a4edb0..ddb2f208 100644 --- a/web/components/contract-feed.tsx +++ b/web/components/contract-feed.tsx @@ -38,6 +38,7 @@ import { JoinSpans } from './join-spans' import Textarea from 'react-expanding-textarea' import { outcome } from '../../common/contract' import { fromNow } from '../lib/util/time' +import BetRow from './bet-row' export function AvatarWithIcon(props: { username: string; avatarUrl: string }) { const { username, avatarUrl } = props @@ -648,7 +649,7 @@ export function ContractFeed(props: { return ( <div className="flow-root"> - <ul role="list" className="-mb-8"> + <ul role="list" className=""> {items.map((activityItem, activityItemIdx) => ( <li key={activityItem.id}> <div className="relative pb-8"> @@ -687,6 +688,7 @@ export function ContractFeed(props: { </li> ))} </ul> + <BetRow contract={contract} /> </div> ) }