@chakra-ui/react#Modal JavaScript Examples
The following examples show how to use
@chakra-ui/react#Modal.
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: AddModalDialog.js From web-client with Apache License 2.0 | 7 votes |
VulnerabilityCategoryAddModalDialog = ({ isOpen, onClose, onCancel }) => {
const emptyCategory = { name: '', description: '' };
const [newCategory, updateNewCategory] = useState(emptyCategory);
const onCreateCategoryFormSubmit = ev => {
if (!document.getElementById('vulnerability_category_form').checkValidity()) {
return false;
}
ev.preventDefault();
secureApiFetch(`/vulnerabilities/categories`, {
method: 'POST',
body: JSON.stringify(newCategory)
}).then(() => {
onClose();
actionCompletedToast(`The vulnerability category has been created.`);
})
.finally(() => {
updateNewCategory(emptyCategory)
})
}
return <Modal size="xl" isOpen={isOpen} onClose={onCancel}>
<ModalOverlay />
<ModalContent>
<ModalHeader>New vulnerability category details</ModalHeader>
<ModalCloseButton />
<ModalBody>
<VulnerabilityCategoryForm category={newCategory} onFormSubmit={onCreateCategoryFormSubmit} categorySetter={updateNewCategory} />
</ModalBody>
<ModalFooter>
<Button onClick={onCancel} mr={3}>Cancel</Button>
<Button type="submit" form="vulnerability_category_form" colorScheme="blue" onClick={onCreateCategoryFormSubmit}>Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
Example #2
Source File: Modal.js From interspace.chat with GNU General Public License v3.0 | 6 votes |
MFModal = (children) => {
const { isOpen, onOpen, onClose } = useDisclosure();
return (
<>
<Button onClick={onOpen} colorScheme="pink">Delegate application</Button>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalCloseButton />
<ModalBody>{children}</ModalBody>
</ModalContent>
</Modal>
</>
);
}
Example #3
Source File: EditModalDialog.js From web-client with Apache License 2.0 | 6 votes |
VulnerabilityCategoryEditModalDialog = ({ category, isOpen, onClose, onCancel }) => {
const [newCategory, updateNewCategory] = useState(category);
const onCreateCategoryFormSubmit = ev => {
if (!document.getElementById('vulnerability_category_form').checkValidity()) {
return false;
}
ev.preventDefault();
secureApiFetch(`/vulnerabilities/categories/${category.id}`, {
method: 'PUT',
body: JSON.stringify(newCategory)
}).then(() => {
onClose();
actionCompletedToast(`The vulnerability category has been updated.`);
})
.finally(() => {
})
}
return <Modal size="xl" isOpen={isOpen} onClose={onCancel}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Vulnerability category details</ModalHeader>
<ModalCloseButton />
<ModalBody>
<VulnerabilityCategoryForm category={newCategory} onFormSubmit={onCreateCategoryFormSubmit} categorySetter={updateNewCategory} />
</ModalBody>
<ModalFooter>
<Button onClick={onCancel} mr={3}>Cancel</Button>
<Button type="submit" form="vulnerability_category_form" colorScheme="blue" onClick={onCreateCategoryFormSubmit}>Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
Example #4
Source File: ModalDialog.js From web-client with Apache License 2.0 | 6 votes |
TargetModalDialog = ({ project, isOpen, onSubmit, onCancel }) => {
const emptyTarget = { project_id: project.id, name: null, kind: TargetKinds[0].value };
const [target, setTarget] = useState(emptyTarget)
const onAddTargetFormSubmit = ev => {
ev.preventDefault();
secureApiFetch(`/targets`, { method: 'POST', body: JSON.stringify(target) })
.then(() => {
onSubmit();
actionCompletedToast(`The target "${target.name}" has been added.`);
})
.catch(err => {
errorToast(err);
})
.finally(() => {
setTarget(emptyTarget)
})
}
return <Modal size="xl" isOpen={isOpen} onClose={onCancel}>
<ModalOverlay />
<ModalContent>
<ModalHeader><HStack><TargetIcon style={{ width: '24px' }} /> <h4>New target details</h4></HStack></ModalHeader>
<ModalCloseButton />
<ModalBody>
<TargetForm newTarget={target} onFormSubmit={onAddTargetFormSubmit} targetSetter={setTarget} />
</ModalBody>
<ModalFooter>
<Button onClick={onCancel} mr={3}>Cancel</Button>
<Button colorScheme="blue" onClick={onAddTargetFormSubmit}>Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
Example #5
Source File: containers.js From idena-web with MIT License | 6 votes |
export function AdPreview({ad, ...props}) {
return (
<Modal isCentered {...props}>
<ModalOverlay />
<ModalContent w={400} mb={0} mt="14">
<Portal>
<Box
bg="white"
fontSize="md"
p="2"
pr="4"
position="fixed"
top={0}
left={0}
right={0}
zIndex="modal"
>
<Flex justifyContent="space-between">
<AdBannerContent ad={ad} />
<HStack spacing="10" align="center">
<AdBannerAuthor ad={ad} />
<ModalCloseButton position="initial" />
</HStack>
</Flex>
</Box>
</Portal>
<AdPromotion {...ad} />
</ModalContent>
</Modal>
)
}
Example #6
Source File: components.js From idena-web with MIT License | 6 votes |
export function Dialog({
title,
children,
shouldShowCloseButton = false,
// eslint-disable-next-line no-unused-vars
isDesktop = true,
...props
}) {
const variant = useBreakpointValue(['mobile', 'initial'])
return (
<Modal isCentered variant={variant} size="sm" {...props}>
<ModalOverlay bg="xblack.080" />
<ModalContent
bg="white"
color="brandGray.500"
fontSize={['mobile', 'md']}
px={[6, 8]}
pb={[4, 8]}
pt={6}
mt={0}
mx={[4, 'auto']}
mb={[9, 0]}
rounded="lg"
>
{title && <DialogHeader>{title}</DialogHeader>}
{shouldShowCloseButton && <ModalCloseButton />}
{children}
</ModalContent>
</Modal>
)
}
Example #7
Source File: components.js From idena-web with MIT License | 6 votes |
export function QrScanner({isOpen, onScan, onClose}) {
const QrReader = dynamic(() => import('react-qr-reader'), {
ssr: false,
})
return (
<Modal variant="mobile" isOpen={isOpen} size="sm">
<ModalOverlay bg="gray.980" />
<ModalContent bg="white" color="brandGray.500" fontSize="md" rounded="lg">
<Heading fontSize="20px" margin="20px 0 20px 24px">
Scan QR code
</Heading>
<QrReader style={{color: 'blue'}} delay={300} onScan={onScan} />
<Flex w="100%" justify="center">
<FlatButton syze="lg" mt="26px" mb="26px" onClick={onClose}>
Cancel
</FlatButton>
</Flex>
</ModalContent>
</Modal>
)
}
Example #8
Source File: Header.js From DAOInsure with MIT License | 5 votes |
function Header(props) {
const { isOpen, onOpen, onClose } = useDisclosure();
const web3Context = useContext(Web3Context);
const { connectWallet, signerAddress, checkIfMemberExists } = web3Context;
function connect() {
connectWallet().then(async (data) => {
console.log(data.provider.networkVersion);
if (data.provider.networkVersion == "80001") {
checkIfMemberExists(data).then((value) => {
if (value === true) {
props.setIsMember(true);
}
});
} else {
onOpen();
}
});
}
return (
<HStack
backgroundColor='white'
zIndex='1'
position='fixed'
width='100vw'
boxShadow='base'
px='250px'
py={3}>
<Modal
isOpen={isOpen}
onClose={onClose}
closeOnOverlayClick={false}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Invalid Network</ModalHeader>
<ModalBody>Please connect to Mumbai Testnet.</ModalBody>
</ModalContent>
</Modal>
<Link to='/'>
<Image height='35px' src='../assets/DAOInsure.png' />
</Link>
<Spacer />
<Link to='/profile'>
<Button colorScheme='whatsapp'>Profile</Button>
</Link>
<Link to='/activity'>
<Button colorScheme='whatsapp'>Activity</Button>
</Link>
{signerAddress !== "" && signerAddress !== undefined ? (
<Button colorScheme='whatsapp' variant='solid'>
{`${signerAddress.substr(0, 6)}...${signerAddress.substr(
-6
)}`}
</Button>
) : (
<Button
onClick={connect}
colorScheme='whatsapp'
variant='solid'>
Connect Wallet
</Button>
)}
</HStack>
);
}
Example #9
Source File: Todos.jsx From fastapi-react with MIT License | 5 votes |
function UpdateTodo({item, id}) {
const {isOpen, onOpen, onClose} = useDisclosure()
const [todo, setTodo] = useState(item)
const {fetchTodos} = React.useContext(TodosContext)
const updateTodo = async () => {
await fetch(`http://localhost:8000/todo/${id}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ item: todo })
})
onClose()
await fetchTodos()
}
return (
<>
<Button h="1.5rem" size="sm" onClick={onOpen}>Update Todo</Button>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay/>
<ModalContent>
<ModalHeader>Update Todo</ModalHeader>
<ModalCloseButton/>
<ModalBody>
<InputGroup size="md">
<Input
pr="4.5rem"
type="text"
placeholder="Add a todo item"
aria-label="Add a todo item"
value={todo}
onChange={e => setTodo(e.target.value)}
/>
</InputGroup>
</ModalBody>
<ModalFooter>
<Button h="1.5rem" size="sm" onClick={updateTodo}>Update Todo</Button>
</ModalFooter>
</ModalContent>
</Modal>
</>
)
}
Example #10
Source File: about.js From handsign-tensorflow with BSD 2-Clause "Simplified" License | 5 votes |
export default function About() {
const { isOpen, onOpen, onClose } = useDisclosure()
return (
<div>
<Button onClick={onOpen} colorScheme="orange">
Learn More
</Button>
<Modal onClose={onClose} isOpen={isOpen} isCentered>
<ModalOverlay />
<ModalContent>
<ModalHeader>American Sign Language (ASL)</ModalHeader>
<ModalCloseButton />
<ModalBody>
<Text fontSize="sm">
American Sign Language (ASL) is a visual language that serves as
the predominant sign language of Deaf communities in the United
States and most of Canada.<br></br>
Here's the list of ASL hand gestures for alphabet.
</Text>
<Image src={handImages} />
<Text fontSize="sm">
This sign language illustration is created by{" "}
<Link
href="https://thenounproject.com/pelodrome/"
isExternal
color="orange.300"
>
Pelin Kahraman
</Link>
</Text>
</ModalBody>
<ModalFooter>
<Button onClick={onClose}>Close</Button>
</ModalFooter>
</ModalContent>
</Modal>
</div>
)
}
Example #11
Source File: ModalDialog.js From web-client with Apache License 2.0 | 5 votes |
ReportModalDialog = ({ isOpen, onSubmit, onCancel }) => {
const fileRef = useRef();
const emptyReportTemplate = {
version_name: "",
version_description: null,
resultFile: null,
}
const [reportTemplate, setReportTemplate] = useState(emptyReportTemplate)
const onCreateReportFormSubmit = ev => {
ev.preventDefault();
const formData = new FormData();
formData.append('version_name', reportTemplate.version_name);
formData.append('version_description', reportTemplate.version_description);
formData.append('resultFile', fileRef.current.files[0]);
secureApiFetch(`/reports/templates`, { method: 'POST', body: formData })
.then(() => {
onSubmit();
actionCompletedToast(`The report template "${reportTemplate.version_name}" has been added.`);
})
.catch(err => {
errorToast(err);
})
.finally(() => {
setReportTemplate(emptyReportTemplate)
})
}
const onFormChange = ev => {
setReportTemplate({ ...reportTemplate, [ev.target.name]: ev.target.value })
}
return <Modal size="xl" isOpen={isOpen} onClose={onCancel}>
<ModalOverlay />
<ModalContent>
<ModalHeader><h4>New report template details</h4></ModalHeader>
<ModalCloseButton />
<ModalBody>
<form id="reportTemplateForm" onSubmit={onCreateReportFormSubmit}>
<FormControl isRequired>
<FormLabel>Version name</FormLabel>
<Input type="text" name="version_name" onChange={onFormChange} autoFocus />
</FormControl>
<FormControl>
<FormLabel>Version description</FormLabel>
<Input type="text" name="version_description" onChange={onFormChange} />
</FormControl>
<FormControl isRequired>
<FormLabel>File</FormLabel>
<Input type="file" ref={fileRef} name="resultFile" onChange={onFormChange} />
</FormControl>
</form>
</ModalBody>
<ModalFooter>
<Button onClick={onCancel} mr={3}>Cancel</Button>
<Button form="reportTemplateForm" type="submit" colorScheme="blue">Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
Example #12
Source File: ModalDialog.js From web-client with Apache License 2.0 | 5 votes |
NoteModalDialog = ({ parentType, parent, isOpen, onClose, onCancel }) => {
const emptyNote = { ...NoteModel, parent_type: parentType, parent_id: parent.id }
const [newNote, updateNewNote] = useState(emptyNote)
const beforeCancelCallback = ev => {
updateNewNote(emptyNote)
onCancel(ev);
}
const onCreateNoteFormSubmit = async (ev) => {
ev.preventDefault();
await secureApiFetch(`/notes`, {
method: 'POST',
body: JSON.stringify(newNote)
}).then(() => {
onClose();
actionCompletedToast(`The note has been created.`);
})
.finally(() => {
updateNewNote(emptyNote)
})
}
return <Modal size="xl" isOpen={isOpen} onClose={beforeCancelCallback}>
<ModalOverlay />
<ModalContent>
<ModalHeader>New notes details</ModalHeader>
<ModalCloseButton />
<ModalBody>
<NotesForm note={newNote} onFormSubmit={onCreateNoteFormSubmit} noteSetter={updateNewNote} />
</ModalBody>
<ModalFooter>
<Button onClick={beforeCancelCallback} mr={3}>Cancel</Button>
<Button colorScheme="blue" onClick={onCreateNoteFormSubmit}>Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
Example #13
Source File: ChallengeStatusTag.jsx From scaffold-directory with MIT License | 5 votes |
ChallengeStatusTag = ({ status, comment, autograding }) => {
const { isOpen, onOpen, onClose } = useDisclosure();
let colorScheme;
let label;
switch (status) {
case CHALLENGE_SUBMISSION_STATUS.ACCEPTED: {
colorScheme = "green";
label = "Accepted";
break;
}
case CHALLENGE_SUBMISSION_STATUS.REJECTED: {
colorScheme = "red";
label = "Rejected";
break;
}
case CHALLENGE_SUBMISSION_STATUS.SUBMITTED: {
label = "Submitted";
break;
}
default:
// do nothing
}
return (
<>
<Flex align="center">
<Box>
<Badge borderRadius="xl" colorScheme={colorScheme} textTransform="none" py={0.5} px={2.5}>
{label}
</Badge>
</Box>
<Spacer />
{status !== CHALLENGE_SUBMISSION_STATUS.SUBMITTED && comment && (
<Tooltip label="See comment">
<Button variant="ghost" onClick={onOpen} p={0} ml={1}>
<QuestionOutlineIcon ml="2px" />
</Button>
</Tooltip>
)}
</Flex>
<Modal isOpen={isOpen} onClose={onClose} size="xl">
<ModalOverlay />
<ModalContent maxW="56rem">
<ModalHeader>Review feedback</ModalHeader>
<ModalCloseButton />
<ModalBody p={6} overflowX="auto">
{autograding ? (
<Box className="autograding-feedback">
<style>
{`
.autograding-feedback a { text-decoration: underline; color: var(--chakra-colors-teal-500) }
`}
</style>
<chakra.pre fontSize={14} whiteSpace="pre-wrap" dangerouslySetInnerHTML={{ __html: comment }} />
</Box>
) : (
<ReactMarkdown components={ChakraUIRenderer(chakraMarkdownComponents)} remarkPlugins={[remarkBreaks]}>
{comment}
</ReactMarkdown>
)}
</ModalBody>
</ModalContent>
</Modal>
</>
);
}
Example #14
Source File: components.js From idena-web with MIT License | 5 votes |
function CardMenuModal({
address,
wallet,
onClose,
onSendClick,
onReceiveClick,
...props
}) {
const {t} = useTranslation()
return (
<Modal variant="mobile" {...props}>
<ModalOverlay />
<ModalContent backgroundColor="transparent" mb={10}>
<ModalBody px={2}>
<Flex
direction="column"
align="center"
backgroundColor="white"
borderRadius="14px"
>
<Text my={4} fontSize="mdx" fontWeight="normal" color="muted">
{t('Choose an option')}
</Text>
<Divider />
<Button
onClick={async () => {
onSendClick(wallet)
onClose()
}}
size="lgx"
variant="primaryFlat"
w="100%"
color="brandBlue.800"
>
Send
</Button>
<Divider />
<Button
onClick={async () => {
onReceiveClick(wallet)
onClose()
}}
size="lgx"
variant="primaryFlat"
w="100%"
color="brandBlue.800"
>
Receive
</Button>
<Divider />
<Button
onClick={() => {
onClose()
openExternalUrl(`https://scan.idena.io/address/${address}`)
}}
size="lgx"
variant="primaryFlat"
w="100%"
color="brandBlue.800"
>
Details
</Button>
</Flex>
<Flex backgroundColor="white" borderRadius="14px" mt={2}>
<Button
onClick={onClose}
size="lgx"
variant="primaryFlat"
w="100%"
color="brandBlue.800"
>
Cancel
</Button>
</Flex>
</ModalBody>
</ModalContent>
</Modal>
)
}
Example #15
Source File: Toolbar.js From sided.news.web with MIT License | 5 votes |
export default function Toolbar() {
const { isOpen, onOpen, onClose } = useDisclosure();
const install = usePWAInstall();
return (
<div className={styles.title}>
<>
<Modal size="3xl" isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader style={{ textAlign: "center" }}>
Media Bias in Sri Lanka
</ModalHeader>
<ModalCloseButton />
<ModalBody>
<p className={styles.para}>
Presenting data analysed by the Ministry of Mass Media on the
news reporting of eight television stations, during presidention
election 2019, Sri Lanka
</p>
<img src="/election.jpg" />
</ModalBody>
<ModalFooter>
<Button
mr={3}
variant="outline"
onClick={(e) => {
e.preventDefault();
window.location.href =
"https://economynext.com/worst-media-behaviour-in-election-history-election-commissioner-47087/";
}}
>
Source
</Button>
<Button colorScheme="blue" onClick={onClose}>
Close
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</>
<div className={styles.wrapper}>
<div className={styles.hide_button}>
<Button colorScheme="teal">Media Bias in Sri Lanka</Button>
{/* <Button ml={3} onClick={onOpen} colorScheme="teal">
Download
</Button> */}
</div>
<span>
<span className={styles.fliph}>s</span>ided.
<span className={styles.news_span}>news</span>
</span>
<div>
<Button onClick={onOpen} colorScheme="teal" leftIcon={<InfoIcon />}>
Media Bias in Sri Lanka
</Button>
{/* <Button
ml={3}
onClick={install}
colorScheme="gray"
leftIcon={<GetAppIcon />}
>
App
</Button> */}
</div>
</div>
</div>
);
}
Example #16
Source File: BuilderProfileCard.jsx From scaffold-directory with MIT License | 4 votes |
BuilderProfileCard = ({ builder, mainnetProvider, isMyProfile, userProvider, fetchBuilder, userRole }) => {
const address = useUserAddress(userProvider);
const ens = useDisplayAddress(mainnetProvider, builder?.id);
const [updatedSocials, setUpdatedSocials] = useState({});
const [isUpdatingReachedOutFlag, setIsUpdatingReachedOutFlag] = useState(false);
const [isUpdatingSocials, setIsUpdatingSocials] = useState(false);
const { isOpen, onOpen, onClose } = useDisclosure();
const { hasCopied, onCopy } = useClipboard(builder?.id);
const { borderColor, secondaryFontColor } = useCustomColorModes();
const shortAddress = ellipsizedAddress(builder?.id);
const hasEns = ens !== shortAddress;
const toast = useToast({ position: "top", isClosable: true });
const toastVariant = useColorModeValue("subtle", "solid");
const joinedDate = new Date(builder?.creationTimestamp);
const joinedDateDisplay = joinedDate.toLocaleString("default", { month: "long" }) + " " + joinedDate.getFullYear();
// INFO: conditional chaining and coalescing didn't work when also checking the length
const hasProfileLinks = builder?.socialLinks ? Object.keys(builder.socialLinks).length !== 0 : false;
const isAdmin = userRole === USER_ROLES.admin;
useEffect(() => {
if (builder) {
setUpdatedSocials(builder.socialLinks ?? {});
}
}, [builder]);
const handleUpdateSocials = async () => {
setIsUpdatingSocials(true);
// Avoid sending socials with empty strings.
const socialLinkCleaned = Object.fromEntries(Object.entries(updatedSocials).filter(([_, value]) => !!value));
const invalidSocials = validateSocials(socialLinkCleaned);
if (invalidSocials.length !== 0) {
toast({
description: `The usernames for the following socials are not correct: ${invalidSocials
.map(([social]) => social)
.join(", ")}`,
status: "error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
let signMessage;
try {
signMessage = await getUpdateSocialsSignMessage(address);
} catch (error) {
toast({
description: " Sorry, the server is overloaded. ???",
status: "error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
let signature;
try {
signature = await userProvider.send("personal_sign", [signMessage, address]);
} catch (error) {
toast({
description: "Couldn't get a signature from the Wallet",
status: "error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
try {
await postUpdateSocials(address, signature, socialLinkCleaned);
} catch (error) {
if (error.status === 401) {
toast({
status: "error",
description: "Access error",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
toast({
status: "error",
description: "Can't update your socials. Please try again.",
variant: toastVariant,
});
setIsUpdatingSocials(false);
return;
}
toast({
description: "Your social links have been updated",
status: "success",
variant: toastVariant,
});
fetchBuilder();
setIsUpdatingSocials(false);
onClose();
};
const handleUpdateReachedOutFlag = async reachedOut => {
setIsUpdatingReachedOutFlag(true);
let signMessage;
try {
signMessage = await getUpdateReachedOutFlagSignMessage(builder.id, reachedOut);
} catch (error) {
toast({
description: " Sorry, the server is overloaded. ???",
status: "error",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
return;
}
let signature;
try {
signature = await userProvider.send("personal_sign", [signMessage, address]);
} catch (error) {
toast({
description: "Couldn't get a signature from the Wallet",
status: "error",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
return;
}
try {
await postUpdateReachedOutFlag(address, builder.id, reachedOut, signature);
} catch (error) {
if (error.status === 401) {
toast({
status: "error",
description: "Access error",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
return;
}
toast({
status: "error",
description: "Can't update the reached out flag. Please try again.",
variant: toastVariant,
});
setIsUpdatingReachedOutFlag(false);
return;
}
toast({
description: 'Updated "reached out" flag successfully',
status: "success",
variant: toastVariant,
});
fetchBuilder();
setIsUpdatingReachedOutFlag(false);
};
return (
<>
<BuilderProfileCardSkeleton isLoaded={!!builder}>
{() => (
/* delay execution */
<Flex
borderRadius="lg"
borderColor={borderColor}
borderWidth={1}
justify={{ base: "space-around", xl: "center" }}
direction={{ base: "row", xl: "column" }}
p={4}
pb={6}
maxW={{ base: "full", lg: "50%", xl: 60 }}
margin="auto"
>
<Link as={RouteLink} to={`/builders/${builder.id}`}>
<QRPunkBlockie
withQr={false}
address={builder.id?.toLowerCase()}
w={52}
borderRadius="lg"
margin="auto"
/>
</Link>
<Flex alignContent="center" direction="column" mt={4}>
{hasEns ? (
<>
<Text fontSize="2xl" fontWeight="bold" textAlign="center">
{ens}
</Text>
<Text textAlign="center" mb={4} color={secondaryFontColor}>
{shortAddress}{" "}
<Tooltip label={hasCopied ? "Copied!" : "Copy"} closeOnClick={false}>
<CopyIcon cursor="pointer" onClick={onCopy} />
</Tooltip>
</Text>
</>
) : (
<Text fontSize="2xl" fontWeight="bold" textAlign="center" mb={8}>
{shortAddress}{" "}
<Tooltip label={hasCopied ? "Copied!" : "Copy"} closeOnClick={false}>
<CopyIcon cursor="pointer" onClick={onCopy} />
</Tooltip>
</Text>
)}
{isAdmin && (
<Center mb={4}>
{builder.reachedOut ? (
<Badge variant="outline" colorScheme="green" alignSelf="center">
Reached Out
</Badge>
) : (
<Button
colorScheme="green"
size="xs"
onClick={() => handleUpdateReachedOutFlag(true)}
isLoading={isUpdatingReachedOutFlag}
alignSelf="center"
>
Mark as reached out
</Button>
)}
</Center>
)}
<Divider mb={6} />
{hasProfileLinks ? (
<Flex mb={4} justifyContent="space-evenly" alignItems="center">
{Object.entries(builder.socialLinks)
.sort(bySocialWeight)
.map(([socialId, socialValue]) => (
<SocialLink id={socialId} value={socialValue} />
))}
</Flex>
) : (
isMyProfile && (
<Alert mb={3} status="warning">
<Text style={{ fontSize: 11 }}>
You haven't set your socials{" "}
<Tooltip label="It's our way of reaching out to you. We could sponsor you an ENS, offer to be part of a build or set up an ETH stream for you.">
<QuestionOutlineIcon />
</Tooltip>
</Text>
</Alert>
)
)}
{isMyProfile && (
<Button mb={3} size="xs" variant="outline" onClick={onOpen}>
Update socials
</Button>
)}
<Text textAlign="center" color={secondaryFontColor}>
Joined {joinedDateDisplay}
</Text>
</Flex>
</Flex>
)}
</BuilderProfileCardSkeleton>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Update your socials</ModalHeader>
<ModalCloseButton />
<ModalBody p={6}>
{Object.entries(socials).map(([socialId, socialData]) => (
<FormControl id="socialId" key={socialId} mb={3}>
<FormLabel htmlFor={socialId} mb={0}>
<strong>{socialData.label}:</strong>
</FormLabel>
<Input
type="text"
name={socialId}
value={updatedSocials[socialId] ?? ""}
placeholder={socialData.placeholder}
onChange={e => {
const value = e.target.value;
setUpdatedSocials(prevSocials => ({
...prevSocials,
[socialId]: value,
}));
}}
/>
</FormControl>
))}
<Button colorScheme="blue" onClick={handleUpdateSocials} isLoading={isUpdatingSocials} isFullWidth mt={4}>
Update
</Button>
</ModalBody>
</ModalContent>
</Modal>
</>
);
}
Example #17
Source File: ChallengeReviewRow.jsx From scaffold-directory with MIT License | 4 votes |
export default function ChallengeReviewRow({ challenge, isLoading, approveClick, rejectClick, userProvider }) {
const [comment, setComment] = useState(challenge.reviewComment ?? "");
const [testPassed, setTestPassed] = useState(null);
const [isRunningTests, setIsRunningTests] = useState(false);
const { isOpen, onOpen, onClose } = useDisclosure();
const address = useUserAddress(userProvider);
if (!challengeInfo[challenge.id]) {
return null;
}
// We asume that rejected challenges will always have review Comments.
const isAutograded = challenge.autograding;
// ToDo. Use the stored events.
const isResubmitted = !isAutograded && !!challenge.reviewComment;
const runTests = async () => {
try {
console.log("Testing challenge with the auto-grader");
setIsRunningTests(true);
setTestPassed(null);
const result = await runAutograderTest(challenge.id, challenge.contractUrl, address);
const resultData = result.data;
console.log("Testing results", resultData);
setTestPassed(resultData.success);
setComment(resultData.feedback ?? resultData.error);
} catch (e) {
console.log("Error calling the auto-grader", e);
} finally {
setIsRunningTests(false);
}
};
const challengeReviewDisplay = (
<Link as={RouteLink} to={`/challenge/${challenge.id}`}>
{challengeInfo[challenge.id].label}
{isResubmitted && (
<>
<br />
<Text fontSize="xs">(Resubmitted)</Text>
</>
)}
{isAutograded && (
<>
<br />
<Text fontSize="xs" color="orange.500">
(Autograded)
</Text>
</>
)}
</Link>
);
const submittedMoment = moment(challenge.submittedTimestamp);
const reviewRow = (
<>
<Td>
<Link as={RouteLink} to={`/builders/${challenge.userAddress}`} pos="relative">
<Address address={challenge.userAddress} w="12.5" fontSize="16" />
</Link>
</Td>
<Td>{challengeReviewDisplay}</Td>
<Td>
<DateWithTooltip timestamp={challenge.submittedTimestamp} />
</Td>
</>
);
return (
<Tr>
{reviewRow}
<Td>
<Button type="button" colorScheme="blue" disabled={isLoading} className="danger" onClick={onOpen} size="xs">
Review
</Button>
</Td>
<Modal isOpen={isOpen} onClose={onClose} size="xl">
<ModalOverlay />
<ModalContent maxW="56rem">
<ModalHeader>Review Challenge</ModalHeader>
<ModalCloseButton />
<Table mb={4}>
<Thead>
<Tr>
<Th>Builder</Th>
<Th>Challenge & Links</Th>
</Tr>
</Thead>
<Tbody>
<Tr>
<Td>
<Link as={RouteLink} to={`/builders/${challenge.userAddress}`} pos="relative">
<Address address={challenge.userAddress} w="12.5" fontSize="16" />
</Link>
</Td>
<Td>
{challengeReviewDisplay}
<UnorderedList>
<ListItem>
<Link
// Legacy branchUrl
href={challenge.contractUrl || challenge.branchUrl}
color="teal.500"
target="_blank"
rel="noopener noreferrer"
>
Contract
</Link>
</ListItem>
<ListItem>
<Link href={challenge.deployedUrl} color="teal.500" target="_blank" rel="noopener noreferrer">
Demo
</Link>
</ListItem>
<ListItem>
Submitted{" "}
<Tooltip label={submittedMoment.format("YYYY-MM-DD, HH:mm")}>
<chakra.span cursor="pointer">{submittedMoment.fromNow()}</chakra.span>
</Tooltip>
</ListItem>
<ListItem listStyleType="none" mt={2}>
<Flex align="center">
<Button onClick={runTests} isLoading={isRunningTests} mr={2}>
Run tests
</Button>
{isBoolean(testPassed) && (
<Badge colorScheme={testPassed ? "green" : "red"}>
{testPassed ? "Accepted" : "Rejected"}
</Badge>
)}
</Flex>
</ListItem>
</UnorderedList>
</Td>
</Tr>
</Tbody>
</Table>
<ModalBody px={6} pb={0}>
<Tabs variant="enclosed-colored">
<TabList>
<Tab>Write</Tab>
<Tab>Preview</Tab>
</TabList>
<TabPanels align="left">
<TabPanel p={0}>
<Textarea
onChange={e => {
const value = e.target.value;
setComment(value);
}}
placeholder="Comment"
style={{ marginBottom: 10 }}
rows={10}
value={comment}
borderTopRadius={0}
/>
</TabPanel>
<TabPanel>
<ReactMarkdown components={ChakraUIRenderer(chakraMarkdownComponents)}>{comment}</ReactMarkdown>
</TabPanel>
</TabPanels>
</Tabs>
</ModalBody>
<ModalFooter>
<Button
type="button"
colorScheme="red"
disabled={isLoading}
className="danger"
onClick={() => rejectClick(challenge.userAddress, challenge.id, comment)}
size="sm"
isFullWidth
>
Reject
</Button>
<Button
type="button"
colorScheme="green"
disabled={isLoading}
ml={3}
onClick={() => approveClick(challenge.userAddress, challenge.id, comment)}
size="sm"
isFullWidth
>
Approve
</Button>
</ModalFooter>
</ModalContent>
</Modal>
</Tr>
);
}
Example #18
Source File: ChallengeDetailView.jsx From scaffold-directory with MIT License | 4 votes |
export default function ChallengeDetailView({ serverUrl, address, userProvider, userRole, loadWeb3Modal }) {
const [descriptionJs, setDescriptionJs] = useState(null);
const [descriptionTs, setDescriptionTs] = useState(null);
const { challengeId } = useParams();
const history = useHistory();
const { isOpen, onOpen, onClose } = useDisclosure();
const [openModalOnLoad, setOpenModalOnLoad] = useState(false);
const challenge = challengeInfo[challengeId];
const isWalletConnected = !!userRole;
const isAnonymous = userRole && USER_ROLES.anonymous === userRole;
// Fetch challenge description from local files.
// In the future, this might be a fetch to the repos/branchs README
// (Ideally fetched at build time)
useEffect(() => {
getChallengeReadme(challengeId, "js")
.then(text => setDescriptionJs(parseGithubReadme(text)))
.catch(() => setDescriptionJs(challenge.description));
getChallengeReadme(challengeId, "ts")
.then(text => setDescriptionTs(parseGithubReadme(text)))
.catch(() => setDescriptionTs(challenge.description));
}, [challengeId, challenge]);
useEffect(() => {
if (!isWalletConnected || isAnonymous) return;
if (openModalOnLoad) {
onOpen();
setOpenModalOnLoad(false);
}
}, [isAnonymous, isWalletConnected, onOpen, userRole, openModalOnLoad, setOpenModalOnLoad]);
if (!challenge) {
// TODO implement a 404 page
// this looks good: https://ant.design/components/result/#components-result-demo-404
history.push("/404");
}
const handleSubmitChallengeModal = async () => {
if (isWalletConnected && !isAnonymous) {
return onOpen();
}
if (!isWalletConnected) {
await loadWeb3Modal();
setOpenModalOnLoad(true);
}
};
const challengeActionButtons = (type = "JS") => {
const repo = type === "JS" ? JS_CHALLENGE_REPO : TS_CHALLENGE_REPO;
return (
<Box>
<Button
as="a"
colorScheme="gray"
variant="outline"
href={`${repo}/tree/${challenge.branchName}`}
target="_blank"
rel="noopener noreferrer"
>
View it on Github <ExternalLinkIcon ml={1} />
</Button>
<Box pos="fixed" bottom={0} p={6} left={0} right={0}>
<Tooltip label={isAnonymous ? "You need to register as a builder" : "Submit Challenge"} shouldWrapChildren>
<Button colorScheme="blue" boxShadow="dark-lg" onClick={handleSubmitChallengeModal} disabled={isAnonymous}>
Submit challenge
</Button>
</Tooltip>
</Box>
</Box>
);
};
return (
// Magic number for maxW to match GitHub
<Container maxW="894px" mb="60px">
<Box textAlign="center" mb={6}>
<Heading as="h1" mb={4}>
{challenge.label}
</Heading>
</Box>
<Tabs variant="enclosed-colored" align="center">
<TabList>
<Tab>Javascript</Tab>
<Tab>Typescript</Tab>
</TabList>
<TabPanels align="left">
<TabPanel>
<SkeletonText mt="4" noOfLines={4} spacing="4" isLoaded={descriptionJs} />
<ReactMarkdown components={ChakraUIRenderer(chakraMarkdownComponents)}>{descriptionJs}</ReactMarkdown>
<Box textAlign="center" my={6}>
{challengeActionButtons("JS")}
</Box>
</TabPanel>
<TabPanel>
<SkeletonText mt="4" noOfLines={4} spacing="4" isLoaded={descriptionTs} />
<ReactMarkdown components={ChakraUIRenderer(chakraMarkdownComponents)}>{descriptionTs}</ReactMarkdown>
<Box textAlign="center" my={6}>
{challengeActionButtons("TS")}
</Box>
</TabPanel>
</TabPanels>
</Tabs>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Submit Challenge</ModalHeader>
<ModalCloseButton />
<ModalBody px={6} pb={8}>
<ChallengeSubmission
challenge={challenge}
serverUrl={serverUrl}
address={address}
userProvider={userProvider}
loadWeb3Modal={loadWeb3Modal}
/>
</ModalBody>
</ModalContent>
</Modal>
</Container>
);
}
Example #19
Source File: components.js From idena-web with MIT License | 4 votes |
export function BadFlipDialog({title, subtitle, isOpen, onClose, ...props}) {
const {t} = useTranslation()
const [flipCase, setFlipCase] = React.useState(0)
const isMobile = useBreakpointValue([true, false])
const BadFlipNotice = isMobile ? Drawer : Modal
const BadFlipNoticeBody = isMobile ? DrawerBody : ModalContent
const badFlipDialogHandlers = useSwipeable({
onSwipedLeft: () => {
if (isMobile) {
setFlipCase(flipCase === 4 ? flipCase : flipCase + 1)
}
},
onSwipedRight: () => {
if (isMobile) {
setFlipCase(flipCase === 0 ? flipCase : flipCase - 1)
}
},
preventDefaultTouchmoveEvent: true,
trackMouse: true,
})
const dirs = [
'1-keywords-vase-coffee',
'2-numbers',
'3-labels',
'4-text',
'5-inappropriate-content',
]
// eslint-disable-next-line no-shadow
const flipUrl = (flipCase, idx) =>
`/static/flips/${dirs[flipCase]}/${idx}.jpg`
React.useEffect(() => {
if (!isOpen) setFlipCase(0)
}, [isOpen])
const nextButtonRef = React.useRef()
return (
<BadFlipNotice
isOpen={isOpen}
isCentered
isCloseable={false}
initialFocusRef={nextButtonRef}
size={['full', 664]}
onClose={onClose}
{...props}
>
<ModalOverlay display={['none', 'block']} bg="xblack.080" />
<BadFlipNoticeBody
className="block-swipe-nav"
display={['flex', 'block']}
flexDirection="column"
bg="transparent"
color="brandGray.500"
fontSize="md"
rounded={['none', 'lg']}
w="auto"
>
<ChakraFlex display={['initial', 'none']} textAlign="center" w="100%">
<Text fontSize="base" fontWeight="bold" mb={9}>
{t('What is a bad flip?')}
</Text>
<Button
position="absolute"
top="14px"
right={4}
p={0}
fontSize="base"
fontWeight="normal"
variant="primaryFlat"
onClick={onClose}
>
{t('Done')}
</Button>
</ChakraFlex>
<div
style={{display: 'flex', flexGrow: '1'}}
{...badFlipDialogHandlers}
>
<ChakraFlex
direction={['column', 'row']}
justify="center"
align="center"
flexGrow={1}
>
<Stack
spacing={0}
borderColor="brandGray.016"
borderWidth={[0, 1]}
flexGrow={1}
h="100%"
minW={['42%', 120]}
position="relative"
>
<BadFlipPartFrame flipCase={flipCase} />
<BadFlipImage src={flipUrl(flipCase, 1)} roundedTop="md" />
<BadFlipImage src={flipUrl(flipCase, 2)} />
<BadFlipImage src={flipUrl(flipCase, 3)} />
<BadFlipImage src={flipUrl(flipCase, 4)} roundedBottom="md" />
</Stack>
<ChakraFlex
direction="column"
justify="space-between"
spacing={7}
bg="white"
borderRadius="lg"
ml={[0, 7]}
p={[0, 8]}
w={['100%', 440]}
>
<Stack mt={[4, 0]} spacing={[5, 4]}>
<ChakraBox display={['none', 'block']}>
<Heading fontSize="lg" fontWeight={500} lineHeight="32px">
{title}
</Heading>
<Text color="muted">{subtitle}</Text>
</ChakraBox>
<List
as="ul"
id="bad-flips"
p={['28px', 0]}
borderRadius={['8px', 0]}
backgroundColor={['gray.50', 'transparent']}
>
<BadFlipListItem
flipCase={0}
description={
<Trans t={t} i18nKey="badFlipKeywordsVaseCoffee">
Vase /{' '}
<Text as="span" color="red.500">
Coffee
</Text>
. 'Coffee' keyword can not be found on the images
</Trans>
}
isActive={flipCase === 0}
onClick={() => {
setFlipCase(0)
}}
>
{t(
'One of the keywords is not clearly visible in the story'
)}
</BadFlipListItem>
<BadFlipListItem
flipCase={1}
isActive={flipCase === 1}
onClick={() => {
setFlipCase(1)
}}
>
{t('There are numbers or letters indicating the order')}
</BadFlipListItem>
<BadFlipListItem
flipCase={2}
isActive={flipCase === 2}
onClick={() => {
setFlipCase(2)
}}
>
{t('There is a sequence of enumerated objects')}
</BadFlipListItem>
<BadFlipListItem
flipCase={3}
description={t(
'Some of the Idena users can not not read your the text in your local language'
)}
isActive={flipCase === 3}
onClick={() => {
setFlipCase(3)
}}
>
{t(
'There is text that is necessary to read to solve the flip'
)}
</BadFlipListItem>
<BadFlipListItem
flipCase={4}
isActive={flipCase === 4}
onClick={() => {
setFlipCase(4)
}}
>
{t('There is inappropriate content')}
</BadFlipListItem>
</List>
<ChakraFlex
display={['flex', 'none']}
justify="center"
h={12}
w="100%"
>
<BadFlipListItemMobile
isActive={flipCase === 0}
number={1}
onClick={() => {
setFlipCase(0)
}}
/>
<BadFlipListItemMobile
isActive={flipCase === 1}
number={2}
onClick={() => {
setFlipCase(1)
}}
/>
<BadFlipListItemMobile
isActive={flipCase === 2}
number={3}
onClick={() => {
setFlipCase(2)
}}
/>
<BadFlipListItemMobile
isActive={flipCase === 3}
number={4}
onClick={() => {
setFlipCase(3)
}}
/>
<BadFlipListItemMobile
isActive={flipCase === 4}
number={5}
onClick={() => {
setFlipCase(4)
}}
/>
</ChakraFlex>
</Stack>
<Stack display={['none', 'flex']} isInline justify="flex-end">
<SecondaryButton onClick={onClose}>{t('Skip')}</SecondaryButton>
<PrimaryButton
ref={nextButtonRef}
onClick={() => {
if (flipCase === dirs.length - 1) onClose()
else setFlipCase(flipCase + 1)
}}
>
{flipCase === dirs.length - 1
? t('Ok, I understand')
: t('Next')}
</PrimaryButton>
</Stack>
</ChakraFlex>
</ChakraFlex>
</div>
</BadFlipNoticeBody>
</BadFlipNotice>
)
}
Example #20
Source File: ModalDialog.js From web-client with Apache License 2.0 | 4 votes |
ReportVersionModalDialog = ({ projectId, isOpen, onSubmit, onCancel }) => {
const defaultFormValues = { reportTemplateId: 0, name: "", description: "" };
const [formValues, setFormValues] = useState(defaultFormValues);
const [templates] = useFetch('/reports/templates');
const onFormValueChange = ev => {
ev.preventDefault();
setFormValues({ ...formValues, [ev.target.name]: ev.target.value });
};
const beforeCancelCallback = ev => {
setFormValues(defaultFormValues);
onCancel(ev);
}
const onFormSubmit = ev => {
ev.preventDefault();
const params = {
projectId: projectId,
reportTemplateId: formValues.reportTemplateId,
name: formValues.name,
description: formValues.description
};
secureApiFetch(`/reports`, { method: 'POST', body: JSON.stringify(params) })
.then(() => {
onSubmit();
actionCompletedToast(`The report version "${formValues.name}" has been added.`);
})
.catch(err => {
console.error(err);
})
.finally(() => {
setFormValues(defaultFormValues)
})
}
useEffect(() => {
if (templates !== null && templates.length > 0) {
setFormValues((prev) => ({ ...prev, reportTemplateId: templates[0].id }))
}
}, [templates]);
return <Modal size="xl" isOpen={isOpen} onClose={beforeCancelCallback}>
<ModalOverlay />
<ModalContent>
<ModalHeader><HStack><TargetIcon style={{ width: '24px' }} /> <h4>New report version details</h4></HStack></ModalHeader>
<ModalCloseButton />
<ModalBody>
<form id="reportVersionReportForm" onSubmit={onFormSubmit} className="crud" style={{ marginTop: '20px' }}>
<FormControl isRequired>
<FormLabel>Template</FormLabel>
{templates && <Select name="reportTemplateId" value={formValues.reportTemplateId} onChange={onFormValueChange}>
{templates.map(template => <option key={template.id} value={template.id}>{template.version_name}</option>)}
</Select>}
</FormControl>
<FormControl isRequired>
<FormLabel>Name</FormLabel>
<Input type="text" name="name" value={formValues.name} onChange={onFormValueChange}
placeholder="eg 1.0, 202103" autoFocus />
</FormControl>
<FormControl isRequired>
<FormLabel>Description</FormLabel>
<Input type="text" name="description" value={formValues.description}
onChange={onFormValueChange}
placeholder="eg Initial version, Draft"
/>
</FormControl>
</form>
</ModalBody>
<ModalFooter>
<Button onClick={beforeCancelCallback} mr={3}>Cancel</Button>
<Button form="reportVersionReportForm" type="submit" colorScheme="blue">Save</Button>
</ModalFooter>
</ModalContent>
</Modal>
}
Example #21
Source File: components.js From idena-web with MIT License | 4 votes |
export function Flip({
hash,
images,
orders,
fetched,
failed,
decoded,
option,
variant,
timerDetails,
onChoose,
onImageFail,
isTrainingValidation,
}) {
const radius = useBreakpointValue(['12px', '8px'])
const windowHeight = use100vh()
const isDesktop = useIsDesktop()
const refFlipHover = useRef(null)
const refZoomIconHover = useRef(null)
const isFlipHovered = useHover(refFlipHover.current)
const isZoomIconHovered = useHover(refZoomIconHover.current)
const {
isOpen: isOpenFlipZoom,
onOpen: onOpenFlipZoom,
onClose: onCloseFlipZoom,
} = useDisclosure()
const scrollToZoomedFlip = flipId => {
scroller.scrollTo(`flipId-${flipId}`, {
containerId: 'zoomedFlips',
horizontal: false,
offset: -80,
})
}
const onFLipClick = e => {
if (e.ctrlKey || e.metaKey) {
onOpenFlipZoom()
} else {
onChoose(hash)
}
}
if ((fetched && !decoded) || failed) return <FailedFlip />
if (!fetched) return <LoadingFlip />
return (
<div ref={refFlipHover}>
<FlipHolder
isZoomHovered={isZoomIconHovered}
css={
// eslint-disable-next-line no-nested-ternary
option
? option === variant
? {
border: `solid ${rem(2)} ${theme.colors.primary}`,
boxShadow: `0 0 ${rem(2)} ${rem(3)} ${transparentize(
0.75,
theme.colors.primary
)}`,
transition: 'all .3s cubic-bezier(.5, 0, .5, 1)',
}
: {
opacity: 0.3,
transform: 'scale(0.98)',
transition: 'all .3s cubic-bezier(.5, 0, .5, 1)',
}
: {}
}
>
{reorderList(images, orders[variant - 1]).map((src, idx) => (
<ChakraBox
key={idx}
h={[
`calc((${windowHeight}px - 290px) / 4)`,
'calc((100vh - 260px) / 4)',
]}
borderRadius={getFlipBorderRadius(idx, images.length - 1, radius)}
css={{
// height: 'calc((100vh - 260px) / 4)',
position: 'relative',
overflow: 'hidden',
}}
onClick={
isDesktop
? e => {
console.log('START')
onFLipClick(e)
console.log('OPENED')
setTimeout(() => scrollToZoomedFlip(idx), 100)
console.log('AFTER TIMEOUT')
}
: () => onChoose(hash)
}
>
{isDesktop && idx === 0 && (
<div ref={refZoomIconHover}>
<ChakraFlex
display={isFlipHovered ? 'flex' : 'none'}
align="center"
justify="center"
borderRadius="8px"
backgroundColor="rgba(17, 17, 17, 0.5)"
position="absolute"
top={1}
right={1}
h={8}
w={8}
opacity={0.5}
_hover={{opacity: 1}}
zIndex={2}
onClick={e => {
e.stopPropagation()
onOpenFlipZoom()
}}
>
<ZoomFlipIcon h={5} w={5} />
</ChakraFlex>
</div>
)}
<FlipBlur src={src} />
<FlipImage
src={src}
alt="current-flip"
height="100%"
width="100%"
style={{
...borderRadius('top', idx === 0 ? rem(8) : 'none'),
...borderRadius(
'bottom',
idx === images.length - 1 ? rem(8) : 'none'
),
position: 'relative',
zIndex: 1,
}}
onError={onImageFail}
/>
</ChakraBox>
))}
<Modal size="xl" isOpen={isOpenFlipZoom} onClose={onCloseFlipZoom}>
<ModalOverlay />
<ChakraFlex
zIndex={1401}
position="fixed"
top={0}
left={0}
right={0}
h={20}
justify="space-between"
align="center"
backgroundColor="gray.980"
>
<ChakraBox />
<ChakraFlex zIndex={2} justify="center">
<ValidationTimer
key={
isShortSession(timerDetails.state)
? 'short-timer'
: 'long-timer'
}
validationStart={timerDetails.validationStart}
duration={
timerDetails.shortSessionDuration -
(isTrainingValidation ? 0 : 10) +
(isShortSession(timerDetails.state)
? 0
: timerDetails.longSessionDuration)
}
color="white"
/>
</ChakraFlex>
<CrossSmallIcon
color="white"
boxSize={8}
mr={10}
onClick={onCloseFlipZoom}
/>
</ChakraFlex>
<ModalContent
mt={20}
bg="transparent"
border="none"
boxShadow="none"
containerProps={{id: 'zoomedFlips'}}
>
<ModalBody py={0}>
<ChakraFlex h="100%" w="100%" direction="column" align="center">
<ChakraBox w="100%">
{reorderList(images, orders[variant - 1]).map((src, idx) => (
<ElementFlipImage
name={`flipId-${idx}`}
ratio={4 / 3}
bg="gray.50"
>
{src ? (
<ChakraBox position="relative">
<ChakraBox
style={{
background: `center center / cover no-repeat url(${src})`,
filter: `blur(${rem(24)})`,
...cover(),
zIndex: 1,
}}
/>
<FlipImage
src={src}
alt="current-flip"
height="100%"
width="100%"
style={{
position: 'relative',
zIndex: 1,
}}
onError={onImageFail}
/>
</ChakraBox>
) : (
<EmptyFlipImage />
)}
</ElementFlipImage>
))}
</ChakraBox>
</ChakraFlex>
</ModalBody>
</ModalContent>
</Modal>
</FlipHolder>
</div>
)
}
Example #22
Source File: Todo.js From benjamincarlson.io with MIT License | 4 votes |
Todo = () => {
const toast = useToast()
const { colorMode } = useColorMode()
const { isOpen, onOpen, onClose } = useDisclosure()
const colorSecondary = {
light: 'gray.600',
dark: 'gray.400',
}
const borderColor = {
light: 'gray.200',
dark: 'gray.600',
}
const colorSmall = {
light: 'gray.400',
dark: 'gray.600',
}
const myTodos = [
{
completed: false,
title: 'Improve Final Cut Pro skills ?',
},
{
completed: false,
title: 'Finish my degree ?',
},
{
completed: false,
title: 'Grow my YouTube channel ?',
},
{
completed: false,
title: 'Grow coffeeclass.io ☕',
},
]
const [todos, setTodos] = useState(myTodos)
const [input, setInput] = useState('')
const removeTodo = todo => {
setTodos(todos.filter(t => t !== todo))
}
const toggleCompleted = todo => {
todo.completed = !todo.completed
setTodos([...todos])
}
const addTodo = () => {
setTodos(todos.concat({
completed: false,
title: input,
}))
setInput('')
}
return (
<>
<Box as="section" w="100%" mt={10} mb={20}>
<Stack spacing={4} w="100%">
<Heading letterSpacing="tight" size="lg" fontWeight={700} as="h2">Todo List ?</Heading>
<Text color={colorSecondary[colorMode]}>Here is a list of things I plan to accomplish over the next year. Try it out yourself!</Text>
<InputGroup size="md" mt={4} borderColor="gray.500" borderColor={borderColor[colorMode]}>
<InputLeftElement
pointerEvents="none"
children={<Search2Icon color={useColorModeValue("gray.500", "gray.600")} />}
/>
<Input
aria-label="Enter a Todo!"
placeholder="Improve Python skills ?"
value={input}
onChange={e => setInput(e.target.value)}
/>
<InputRightElement width="6.75rem">
<Button
aria-label="Add a TODO!"
fontWeight="bold"
h="1.75rem"
size="md"
colorScheme="gray"
mr={2}
variant="outline"
px={10}
onClick={() => {
if (input == '')
toast({
title: 'Whoops! There\'s an error!',
description: "Input can't be empty!",
status: "error",
duration: 2000,
isClosable: true,
})
else {
addTodo(input)
}
}}
>
Add Todo!
</Button>
</InputRightElement>
</InputGroup>
<Flex flexDir="column">
{todos.map((todo, index) => (
<Flex
key={index}
justify="space-between"
align="center"
my={1}
>
<Flex align="center">
<Icon fontSize="xl" mr={2} as={ChevronRightIcon} color={colorSecondary[colorMode]} />
<Tooltip label={`Click "${todo.title}" to mark as completed.`} placement="top" hasArrow>
<Text color={colorSecondary[colorMode]} textDecor={todo.completed && "line-through"} _hover={{ cursor: 'pointer' }} onClick={() => toggleCompleted(todo)}>{todo.title}</Text>
</Tooltip>
</Flex>
<Tooltip label={`Delete "${todo.title}"`} placement="top" hasArrow>
<IconButton aria-label={`Delete "${todo.title}" from Todo list.`} icon={<DeleteIcon color="red.400" />} onClick={() => removeTodo(todo)} />
</Tooltip>
</Flex>
))}
</Flex>
<Flex align="center">
<Text onClick={() => setTodos(myTodos)} _hover={{ cursor: 'pointer' }} color={colorSmall[colorMode]}>Reset</Text>
<Divider orientation="vertical" mx={2} h={4} />
<Text onClick={onOpen} _hover={{ cursor: 'pointer' }} color={colorSmall[colorMode]}>Help</Text>
</Flex>
</Stack>
</Box>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Todo List Help</ModalHeader>
<ModalCloseButton />
<ModalBody>
<OrderedList>
<ListItem>
<Text fontWeight="bold">Add a Todo</Text>
<Text>Input your Todo and click the "Add Todo!" button to add a new Todo.</Text>
</ListItem>
<ListItem>
<Text fontWeight="bold">Reset</Text>
<Text>Click the "Reset" button to reset the list.</Text>
</ListItem>
<ListItem>
<Text fontWeight="bold">Delete</Text>
<Text>Click the "Delete" button to delete a Todo.</Text>
</ListItem>
<ListItem>
<Text fontWeight="bold">Completed</Text>
<Text>Click a Todo to mark it as completed.</Text>
</ListItem>
<ListItem>
<Text fontWeight="bold">View Code</Text>
<Text>Click the "View Code" button to view the code on GitHub for this simple TODO list.</Text>
</ListItem>
</OrderedList>
<Divider my={6} />
<Text><strong>Current state of Todo List:</strong> [{todos.map(t => { return `{"${t.title}",${t.completed}},` })}]</Text>
</ModalBody>
<ModalFooter>
<Button colorScheme="blue" mr={3} onClick={onClose}>
Close
</Button>
<Link
href="https://github.com/bjcarlson42/benjamincarlson.io/blob/master/components/Todo.js"
_hover={{ textDecor: 'none' }}
isExternal
>
<Button variant="ghost">View Code</Button>
</Link>
</ModalFooter>
</ModalContent>
</Modal>
</>
)
}
Example #23
Source File: Player.jsx From bottle-radio with MIT License | 4 votes |
Player = () => {
const variables = window._env_ ? window._env_ : { REACT_ICECAST_URL: "" };
const [playing, setPlaying] = useState(false);
const [loading, setLoading] = useState(false);
const [muted, setMuted] = useState(false);
const [firstLoad, setFirstLoad] = useState(true);
const [nowPlaying, setNowPlaying] = useState(["No data", "No data"]);
const [listeners, setListeners] = useState([0, 0]);
const { colorMode } = useColorMode();
const colorHover = { light: "white", dark: "black" };
const { isOpen, onOpen, onClose } = useDisclosure();
const trackLinks = useSaveTrack(
nowPlaying[0],
nowPlaying[1]
);
const audioRef = useRef(null);
const { setPlayer } = useContext(VisualiserContext);
useEffect(() => {
const audio = document.getElementById("player");
if (audio) {
setPlayer(audioRef);
}
}, [setPlayer]);
useEffect(() => {
const updateStats = async () => {
let url = variables.REACT_ICECAST_URL + "status-json.xsl";
let response = await fetch(url);
let json = await response.json();
let track = json.icestats.source.title;
if (track && track !== "") {
let artist = track.split(" - ")[0];
track = track.split(" - ").slice(1).join(" - ");
setNowPlaying([track, artist]);
}
let listeners = json.icestats.source.listeners;
let peakListeners = json.icestats.source.listener_peak;
if (listeners && listeners) {
setListeners([listeners, peakListeners]);
}
};
updateStats();
setInterval(() => {
updateStats();
}, 10000);
}, [variables.REACT_ICECAST_URL]);
const togglePlay = () => {
let player = document.getElementById("player");
if (firstLoad) {
setFirstLoad(false);
}
if (player.paused) {
setPlaying(true);
player.load();
player.play();
} else {
setPlaying(false);
player.pause();
}
};
const changeVolume = (value) => {
let player = document.getElementById("player");
value <= 0 ? setMuted(true) : setMuted(false);
player.volume = value / 100;
};
const TrackModal = (props) => {
const { modal, setModal } = useContext(ModalContext);
useEffect(() => {
if (!modal) {
setModal(trackLinks);
}
}, [modal, setModal]);
return (
<div>
<Modal
isOpen={isOpen}
onClose={() => {
onClose();
setModal();
}}
size="sm"
isCentered
>
<ModalOverlay>
<ModalContent>
<ModalCloseButton />
<ModalBody>
<Grid templateColumns="1fr 1fr" justifyItems="center" gap={0}>
{modal && modal.length > 0 ? (
modal.map((link) => (
<Link key={link.url} href={link.url} isExternal>
<Button variant="ghost">{link.displayName}</Button>
</Link>
))
) : (
<div>
<Spinner size="sm" /> Loading...
</div>
)}
</Grid>
</ModalBody>
</ModalContent>
</ModalOverlay>
</Modal>
</div>
);
};
return (
<div>
<Flex
direction="column"
justify="center"
align="center"
width="100%"
height="100%"
>
<Box>
<Grid
m={2}
p={2}
templateColumns="auto 1fr auto"
alignItems="center"
gap={1}
>
<Box
gridRow="1/4"
w="80px"
h="80px"
aria-label="Play toggle"
as={loading ? FaSpinner : playing ? FaPauseCircle : FaPlayCircle}
onClick={togglePlay}
_hover={{ color: colorHover[colorMode] }}
mr={1}
className={loading ? "icon-spin" : ""}
/>
<Text m={0} align="center">
<strong>{nowPlaying[0]}</strong>
</Text>
<Text m={0} align="center">
{nowPlaying[1]}
</Text>
<Flex direction="row" justify="center" maxWidth={400} p={2}>
<Slider
defaultValue={100}
min={0}
max={100}
step={10}
onChange={changeVolume}
width="80px"
>
<SliderTrack>
<SliderFilledTrack bg="tomato" />
</SliderTrack>
<SliderThumb size={2} />
</Slider>
<Box
w="20px"
h="20px"
as={muted ? FaVolumeMute : FaVolumeUp}
ml={3}
/>
<audio
id="player"
crossOrigin="anonymous"
autoPlay
preload="none"
ref={audioRef}
onPlay={() => setPlaying(true)}
onPause={() => setPlaying(false)}
onLoadStart={() => {
if (!firstLoad) {
setLoading(true);
}
}}
onCanPlay={() => setLoading(false)}
>
<source
src={variables.REACT_ICECAST_URL + "radio.mp3"}
type="audio/mp3"
/>
Your browser does not support the audio element.
</audio>
</Flex>
<Text gridColumn="1/4">
<strong>Listeners: </strong>
{listeners[0]} <strong>Peak: </strong>
{listeners[1]}
</Text>
<Box gridColumn="3" gridRow="1/4" alignItems="center">
<Box
w="25px"
h="25px"
as={FaHeart}
mx={1}
onClick={onOpen}
_hover={{ color: "tomato" }}
/>
{isOpen ? <TrackModal /> : null}
</Box>
</Grid>
</Box>
</Flex>
</div>
);
}
Example #24
Source File: BecomeMember.js From DAOInsure with MIT License | 4 votes |
function BecomeMember() {
const { signerAddress, provider, signer } = useContext(Web3Context);
const { isOpen, onOpen, onClose } = useDisclosure();
const [latitude, setLatitude] = useState();
const [longitude, setLongitude] = useState();
const handleChange = (e, setter) => {
setter(e.target.value);
};
const web3 = new Web3(provider);
console.log(web3);
const joinDao = async () => {
let contract = new ethers.Contract(
SUPERAPP_CONTRACT_ADDRESS,
SUPERAPP_CONTRACT_ABI,
signer
);
const walletAddress = await window.ethereum.request({
method: "eth_requestAccounts",
params: [
{
eth_accounts: {},
},
],
});
// this sdk has a lot of changes (breaking changes) from the version we used.
const sf = new SuperfluidSDK.Framework({
ethers: provider,
});
await sf.initialize();
// creating user from unlocked address. token is super token.
const carol = sf.user({
address: walletAddress[0],
token: "0x5D8B4C2554aeB7e86F387B4d6c00Ac33499Ed01f",
});
// creating a flow, user data can contain arbitary data.
await carol.flow({
recipient: SUPERAPP_CONTRACT_ADDRESS,
flowRate: "3858024691358",
userData: web3.eth.abi.encodeParameters(
["string", "string"],
[latitude, longitude]
),
});
// details of the user like incoming and outgoing flow rates, and the various active flows along with types.
const details = await carol.details();
console.log(details);
// // Call the host with the batch call parameters
// await sf.host.batchCall(createPlayBatchCall(100));
function createPlayBatchCall(upgradeAmount = 0) {
return [
[
202, // upgrade 100 daix to play the game
"0x5D8B4C2554aeB7e86F387B4d6c00Ac33499Ed01f",
// adding latitude and longitude to the encoded data.
contract.interface.encodeFunctionData("setCoordinates", [
parseInt(latitude),
parseInt(longitude),
]),
],
[
1, // approve the ticket fee
{
token: "0x5D8B4C2554aeB7e86F387B4d6c00Ac33499Ed01f", // Super Tokens only
amount: "1000000000000000000",
spender: SUPERAPP_CONTRACT_ADDRESS,
},
],
];
}
// Call the host with the batch call parameters
await sf.host.batchCall(createPlayBatchCall(100));
};
return (
<VStack spacing={5} mt='20px'>
<Modal
isOpen={isOpen}
onClose={onClose}
closeOnOverlayClick={false}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Enter the following Details</ModalHeader>
<ModalCloseButton />
<ModalBody>
<HStack>
<Input
onChange={(e) => handleChange(e, setLatitude)}
placeholder='Latitude'
/>
<Input
onChange={(e) => handleChange(e, setLongitude)}
placeholder='Longitude'
/>
</HStack>
</ModalBody>
<ModalFooter>
<Button onClick={joinDao} colorScheme='whatsapp'>
Join DAO (10 DAIx / Month)
</Button>
</ModalFooter>
</ModalContent>
</Modal>
<Heading fontSize='32px'>Become A Member</Heading>
<Heading fontSize='24px'>How it works?</Heading>
<UnorderedList>
<ListItem>
DAOInsure provides insurances to its members based on DAO
voting
</ListItem>
<ListItem>
DAO members stream insurance premium to the treasury.
</ListItem>
<ListItem>
In exchange for premium paid the members get voting power.
</ListItem>
<ListItem>
Use voting power to approve other fellow member's claim.
</ListItem>
</UnorderedList>
<Heading fontSize='24px'>
Become A Member just 10 DAIx / Month
</Heading>
{signerAddress ? (
<Button colorScheme='whatsapp' onClick={onOpen}>
Join the DAO
</Button>
) : (
<GreenTag>Please connect wallet first</GreenTag>
)}
</VStack>
);
}
Example #25
Source File: showreel.js From react-table-library with MIT License | 4 votes |
Component = () => {
const [data, setData] = React.useState({ nodes });
//* Theme *//
const chakraTheme = getTheme({
...DEFAULT_OPTIONS,
striped: true,
});
const customTheme = {
Table: `
--data-table-library_grid-template-columns: 64px repeat(5, minmax(0, 1fr));
margin: 16px 0px;
`,
};
const theme = useTheme([chakraTheme, customTheme]);
//* Resize *//
const resize = { resizerHighlight: '#dee2e6' };
//* Pagination *//
const pagination = usePagination(data, {
state: {
page: 0,
size: 4,
},
onChange: onPaginationChange,
});
function onPaginationChange(action, state) {
console.log(action, state);
}
//* Search *//
const [search, setSearch] = React.useState('');
useCustom('search', data, {
state: { search },
onChange: onSearchChange,
});
function onSearchChange(action, state) {
console.log(action, state);
pagination.fns.onSetPage(0);
}
//* Filter *//
const [isHide, setHide] = React.useState(false);
useCustom('filter', data, {
state: { isHide },
onChange: onFilterChange,
});
function onFilterChange(action, state) {
console.log(action, state);
pagination.fns.onSetPage(0);
}
//* Select *//
const select = useRowSelect(data, {
onChange: onSelectChange,
});
function onSelectChange(action, state) {
console.log(action, state);
}
//* Tree *//
const tree = useTree(
data,
{
onChange: onTreeChange,
},
{
clickType: TreeExpandClickTypes.ButtonClick,
treeYLevel: 1,
treeIcon: {
margin: '4px',
iconDefault: null,
iconRight: <FaChevronRight />,
iconDown: <FaChevronDown />,
},
},
);
function onTreeChange(action, state) {
console.log(action, state);
}
//* Sort *//
const sort = useSort(
data,
{
onChange: onSortChange,
},
{
sortIcon: {
iconDefault: null,
iconUp: <FaChevronUp />,
iconDown: <FaChevronDown />,
},
sortFns: {
TASK: (array) => array.sort((a, b) => a.name.localeCompare(b.name)),
DEADLINE: (array) => array.sort((a, b) => a.deadline - b.deadline),
TYPE: (array) => array.sort((a, b) => a.type.localeCompare(b.type)),
COMPLETE: (array) => array.sort((a, b) => a.isComplete - b.isComplete),
TASKS: (array) => array.sort((a, b) => (a.nodes || []).length - (b.nodes || []).length),
},
},
);
function onSortChange(action, state) {
console.log(action, state);
}
//* Drawer *//
const [drawerId, setDrawerId] = React.useState(null);
const [edited, setEdited] = React.useState('');
const handleEdit = (event) => {
setEdited(event.target.value);
};
const handleCancel = () => {
setEdited('');
setDrawerId(null);
};
const handleSave = () => {
const node = findNodeById(data.nodes, drawerId);
const editedNode = { ...node, name: edited };
const nodes = insertNode(data.nodes, editedNode);
setData({
nodes,
});
setEdited('');
setDrawerId(null);
};
//* Modal *//
const [modalOpened, setModalOpened] = React.useState(false);
//* Custom Modifiers *//
let modifiedNodes = data.nodes;
// search
modifiedNodes = modifiedNodes.filter((node) =>
node.name.toLowerCase().includes(search.toLowerCase()),
);
// filter
modifiedNodes = isHide ? modifiedNodes.filter((node) => !node.isComplete) : modifiedNodes;
//* Columns *//
const COLUMNS = [
{
label: 'Task',
renderCell: (item) => item.name,
resize,
sort: { sortKey: 'TASK' },
select: {
renderHeaderCellSelect: () => (
<Checkbox
colorScheme="teal"
isChecked={select.state.all}
isIndeterminate={!select.state.all && !select.state.none}
onChange={select.fns.onToggleAll}
/>
),
renderCellSelect: (item) => (
<Checkbox
colorScheme="teal"
style={{ backgroundColor: '#ffffff' }}
isChecked={select.state.ids.includes(item.id)}
onChange={() => select.fns.onToggleById(item.id)}
/>
),
},
tree: true,
},
{
label: 'Deadline',
renderCell: (item) =>
item.deadline.toLocaleDateString('en-US', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
}),
resize,
sort: { sortKey: 'DEADLINE' },
},
{ label: 'Type', renderCell: (item) => item.type, resize, sort: { sortKey: 'TYPE' } },
{
label: 'Complete',
renderCell: (item) => item.isComplete.toString(),
resize,
sort: { sortKey: 'COMPLETE' },
},
{
label: 'Tasks',
renderCell: (item) => (
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<span>{item.nodes?.length}</span>
<IconButton
aria-label="edit"
icon={<FaPen />}
size="xs"
variant="ghost"
colorScheme="teal"
onClick={() => setDrawerId(item.id)}
/>
</div>
),
resize,
sort: { sortKey: 'TASKS' },
},
];
return (
<>
<Modal isOpen={modalOpened} onClose={() => setModalOpened(false)}>
<ModalOverlay />
<ModalContent>
<ModalHeader>Not all features included here, but we got ...</ModalHeader>
<ModalCloseButton />
<ModalBody>
<div>
<Checkbox colorScheme="teal" isChecked>
Resize
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Sort
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Search
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Filter
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Select
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Tree
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Drawer on Edit
</Checkbox>
</div>
<div>
<Checkbox colorScheme="teal" isChecked>
Pagination
</Checkbox>
</div>
</ModalBody>
</ModalContent>
</Modal>
{/* Form */}
<HStack m={3}>
<Button colorScheme="teal" onClick={() => setModalOpened(true)}>
Features?
</Button>
<InputGroup>
<InputLeftElement
pointerEvents="none"
children={<FaSearch style={{ color: '#4a5568' }} />}
/>
<Input
placeholder="Search Task"
value={search}
onChange={(event) => setSearch(event.target.value)}
/>
</InputGroup>
<Checkbox
style={{ whiteSpace: 'nowrap' }}
colorScheme="teal"
isChecked={isHide}
onChange={(event) => setHide(event.target.checked)}
>
Hide Complete
</Checkbox>
</HStack>
{/* Table */}
<Box p={3} borderWidth="1px" borderRadius="lg">
<CompactTable
columns={COLUMNS}
data={{ ...data, nodes: modifiedNodes }}
theme={theme}
layout={{ custom: true }}
select={select}
tree={tree}
sort={sort}
pagination={pagination}
/>
</Box>
<br />
<HStack justify="flex-end">
<IconButton
aria-label="previous page"
icon={<FaChevronLeft />}
colorScheme="teal"
variant="ghost"
disabled={pagination.state.page === 0}
onClick={() => pagination.fns.onSetPage(pagination.state.page - 1)}
/>
{pagination.state.getPages(modifiedNodes).map((_, index) => (
<Button
key={index}
colorScheme="teal"
variant={pagination.state.page === index ? 'solid' : 'ghost'}
onClick={() => pagination.fns.onSetPage(index)}
>
{index + 1}
</Button>
))}
<IconButton
aria-label="next page"
icon={<FaChevronRight />}
colorScheme="teal"
variant="ghost"
disabled={pagination.state.page + 1 === pagination.state.getTotalPages(data.nodes)}
onClick={() => pagination.fns.onSetPage(pagination.state.page + 1)}
/>
</HStack>
<Drawer isOpen={drawerId} onClose={handleCancel} placement="right">
<DrawerOverlay />
<DrawerContent>
<DrawerCloseButton />
<DrawerHeader>Create your account</DrawerHeader>
<DrawerBody>
<Text>Name: </Text>
<Input
autoFocus
value={
edited || fromTreeToList(data.nodes).find((node) => node.id === drawerId)?.name
}
onChange={handleEdit}
data-autofocus
/>
</DrawerBody>
<DrawerFooter>
<Button variant="outline" mr={3} onClick={handleCancel}>
Cancel
</Button>
<Button onClick={handleSave} colorScheme="teal">
Save
</Button>
</DrawerFooter>
</DrawerContent>
</Drawer>
</>
);
}
Example #26
Source File: SponsorCard.js From codeursenseine.com with MIT License | 4 votes |
SponsorCard = ({ logoSrc, link, name, excerpt, children }) => {
const containerRef = React.useRef();
const contentRef = React.useRef();
const [isExpandable, setIsExpandable] = React.useState(false);
const { isOpen, onOpen, onClose } = useDisclosure();
React.useEffect(() => {
if (containerRef.current && contentRef.current) {
setIsExpandable(
contentRef.current.offsetHeight - containerRef.current.offsetHeight > 0
);
}
}, [setIsExpandable]);
return (
<>
<Card
ref={containerRef}
as="article"
maxH="22rem"
position="relative"
p={0}
>
<Box ref={contentRef} p={6}>
{logoSrc && (
<>
<Link
d="block"
href={link}
title={name}
target="_blank"
rel="noopener noreferrer"
>
<AspectRatio ratio={320 / 190}>
<Image src={logoSrc} alt={name} objectFit="fit" />
</AspectRatio>
</Link>
<Divider />
</>
)}
<Box d="flex" alignItems="baseline">
<A href={link} title={name} target="_blank">
{name}
</A>
</Box>
<Text fontSize="sm">{excerpt}</Text>
</Box>
{isExpandable && (
<Box
position="absolute"
bottom={0}
left={0}
right={0}
pt={16}
textAlign="center"
background="linear-gradient(0deg, rgba(255,255,255,1) 50%, rgba(255,255,255,0) 100%)"
>
<Button
onClick={onOpen}
variant="unstyled"
d="inline-block"
fontSize="sm"
h="auto"
m={4}
p={4}
py={2}
_hover={{ color: "brand.600" }}
>
Lire la suite
</Button>
</Box>
)}
</Card>
<Modal motionPreset="scale" isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent>
<ModalHeader fontSize="xl">
<Box>
<Text>{name}</Text>
</Box>
</ModalHeader>
<ModalCloseButton />
<ModalBody>
<MDXRenderer>{children}</MDXRenderer>
</ModalBody>
</ModalContent>
</Modal>
</>
);
}