@chakra-ui/react#Tag TypeScript Examples
The following examples show how to use
@chakra-ui/react#Tag.
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: ChipInput.test.tsx From ke with MIT License | 6 votes |
test('Chip Input backspace on empty input does not break on empty list', () => {
const handleChange = jest.fn()
const chipInput = mount(getComponent([], handleChange))
chipInput.find('input').simulate('keydown', { key: 'Backspace' })
expect(chipInput.find(Tag).length).toEqual(0)
expect(handleChange).toBeCalledTimes(0)
})
Example #2
Source File: SelectedFoodItem.tsx From calories-in with MIT License | 6 votes |
function SelectedFoodItem({ food, onUnselect }: Props) {
return (
<Fade in={true}>
<Tag
size="md"
borderRadius="full"
variant="outline"
colorScheme="teal"
maxWidth="250px"
>
<TagLabel>{food.name}</TagLabel>
<TagCloseButton onClick={() => onUnselect(food)} />
</Tag>
</Fade>
)
}
Example #3
Source File: PaymentMethodTag.tsx From coindrop with GNU General Public License v3.0 | 6 votes |
PaymentMethodTag: FunctionComponent<Props> = ({ label, iconName, iconSize = "16px", color, tagColorScheme }) => {
const Icon = paymentMethodIcons[iconName];
return (
<Box mx={1} my={1}>
<Tag size="lg" colorScheme={tagColorScheme}>
{iconName && (<Icon verticalAlign="top" color={color} boxSize={iconSize} mr={2} />)}
<TagLabel py={1}>{label}</TagLabel>
</Tag>
</Box>
);
}
Example #4
Source File: FileInput.tsx From coindrop with GNU General Public License v3.0 | 6 votes |
FileInput = forwardRef<FileInputRef, Props>((props, ref) => {
const { id, text, accept, onChange } = props;
return (
<div>
<input
type="file"
name={id}
id={id}
className={styles.input}
accept={accept}
onChange={onChange}
ref={ref}
data-cy="file-input"
/>
<label
className={styles.label}
htmlFor={id}
>
<Tag size="lg" variant="subtle" colorScheme="gray">
<TagLeftIcon as={CgSoftwareUpload} />
<Text>{text}</Text>
</Tag>
</label>
</div>
);
})
Example #5
Source File: ChipInput.test.tsx From ke with MIT License | 6 votes |
test('Chip Input adds value on blur event', () => {
fc.assert(
fc.property(stringArbitrary, (value) => {
const handleChange = jest.fn()
const chipInput = mount(getComponent([], handleChange))
chipInput.find('input').simulate('change', makeChangeEvent(value))
chipInput.find('input').simulate('blur')
expect(chipInput.find(Tag).length).toEqual(1)
expect(chipInput.find(TagLabel).text()).toEqual(value.trim())
expect(handleChange).toBeCalledWith([value.trim()])
})
)
})
Example #6
Source File: ChipInput.test.tsx From ke with MIT License | 6 votes |
test('Chip Input validation error', () => {
fc.assert(
fc.property(arrayArbitrary, stringArbitrary, stringArbitrary, (content, value, errorText) => {
const handleChange = jest.fn()
const validator = (): boolean => false
const chipInput = mount(getComponent(content, handleChange, validator, errorText))
chipInput.find('input').simulate('change', makeChangeEvent(value))
chipInput.find('input').simulate('keydown', { key: 'Enter' })
expect(chipInput.find(Tag).length).toEqual(content.length)
expect(chipInput.find('.error').first().text()).toEqual(errorText)
expect(handleChange).toBeCalledTimes(0)
})
)
})
Example #7
Source File: ChipInput.test.tsx From ke with MIT License | 6 votes |
test('Chip Input backspace on non-empty input removes last symbol', () => {
fc.assert(
fc.property(arrayArbitrary, stringArbitrary, (content, value) => {
const handleChange = jest.fn()
const chipInput = mount(getComponent(content, handleChange))
chipInput.find('input').simulate('change', makeChangeEvent(value))
chipInput.find('input').simulate('keydown', { key: 'Backspace' })
expect(chipInput.find(Tag).length).toEqual(content.length)
expect(handleChange).toBeCalledTimes(0)
})
)
})
Example #8
Source File: ChipInput.test.tsx From ke with MIT License | 6 votes |
test('Chip Input backspace on empty input removes last chip', () => {
fc.assert(
fc.property(arrayArbitrary, (content) => {
const handleChange = jest.fn()
const chipInput = mount(getComponent(content, handleChange))
chipInput.find('input').simulate('keydown', { key: 'Backspace' })
expect(chipInput.find(Tag).length).toEqual(content.length - 1)
expect(handleChange).toBeCalledWith(content.slice(0, -1))
})
)
})
Example #9
Source File: ChipInput.test.tsx From ke with MIT License | 6 votes |
test.each([['Enter'], ['Tab']])('Chip Input adds values on submitKeys pressed', (submitKey) => {
fc.assert(
fc.property(stringArbitrary, (value) => {
const handleChange = jest.fn()
const chipInput = mount(getComponent([], handleChange))
chipInput.find('input').simulate('change', makeChangeEvent(value))
chipInput.find('input').simulate('keydown', { key: submitKey })
expect(chipInput.find(Tag).length).toEqual(1)
expect(chipInput.find(TagLabel).text()).toEqual(value.trim())
expect(handleChange).toBeCalledWith([value.trim()])
})
)
})
Example #10
Source File: ChipInput.test.tsx From ke with MIT License | 6 votes |
test('Chip Input initial values are rendered', () => {
fc.assert(
fc.property(arrayArbitrary, (content) => {
const chipInput = mount(getComponent(content, jest.fn()))
expect(chipInput.find(Tag).length).toEqual(content.length)
})
)
})
Example #11
Source File: ReactSelectCustomization.tsx From ke with MIT License | 6 votes |
export function MultiValue<OptionType>(props: MultiValueProps<OptionType>): JSX.Element {
const { children, className, cx, getStyles, innerProps, isDisabled, removeProps, data, selectProps } = props
const { multiValueContainer, multiValueLabel, multiValueRemove } = useStyles()
const externalClassName = (selectProps as ExtendedProps).componentsClasses?.MultiValue
return (
<ClassNames>
{({ css, cx: emotionCx }) => (
<Tag data={data} sx={multiValueContainer} {...innerProps} className={classNames(className, externalClassName)}>
<TagLabel sx={multiValueLabel} className={className}>
{children}
</TagLabel>
<TagCloseButton
className={emotionCx(
css(getStyles('multiValueRemove', props)),
cx(
{
'multi-value__remove': true,
},
className
)
)}
isDisabled={isDisabled}
{...removeProps}
sx={multiValueRemove}
/>
</Tag>
)}
</ClassNames>
)
}
Example #12
Source File: CourseCard.tsx From fresh-coupons with GNU General Public License v3.0 | 6 votes |
function CourseTags({tags}: CourseTagsProps) {
if (!tags) {
return <></>
}
return (
<HStack my="2" spacing="3">
{tags && tags.map(tag => (
<Tag px="3" key={tag} color={useColorModeValue('gray.600', 'gray.300')}>
{tag || 'Misc'}
</Tag>
))}
</HStack>
)
}
Example #13
Source File: App.tsx From engine with MIT License | 5 votes |
App: view = ({
data = observe.structure.data,
viewsCount = observe.structure.count.views,
producersCount = observe.structure.count.producers,
}) => {
if (!data || !viewsCount || !producersCount) {
return;
}
return (
<ChakraProvider>
<SimpleGrid columns={2}>
<Box bg="gray.100" h="100vh">
<Tabs>
<TabList position="relative">
<Tab>State</Tab>
<Tab>
Views <Tag>{viewsCount}</Tag>
</Tab>
<Tab>
Producers <Tag>{producersCount}</Tag>
</Tab>
<Tab>Stats</Tab>
</TabList>
<TabPanels>
<TabPanel pr="0">
<List>
<Box overflowY="scroll" h="92vh">
<StateTree data={data} />
</Box>
</List>
</TabPanel>
<TabPanel pr="0">
<ViewsTab />
</TabPanel>
<TabPanel pr="0">
<ProducersTab />
</TabPanel>
<TabPanel pr="0">
<StatsTab />
</TabPanel>
</TabPanels>
</Tabs>
</Box>
<Box bg="gray.200" borderLeft="solid 1px" borderColor="gray.300">
<EditElement />
<ElementDescription />
</Box>
</SimpleGrid>
</ChakraProvider>
);
}
Example #14
Source File: about.tsx From portfolio with MIT License | 5 votes |
Card = (props: CardProps) => {
const { title, role, skills, period, logo, colorMode, alt } = props;
return (
<CardTransition>
<Box
px={4}
py={5}
borderWidth="1px"
_hover={{ shadow: "lg" }}
bg={useColorModeValue("white", "gray.800")}
position="relative"
rounded="md"
>
<Flex justifyContent="space-between">
<Flex>
<Image
rounded="full"
w={16}
h={16}
objectFit="cover"
fallbackSrc={placeholder}
src={logo}
alt={alt}
/>
<Stack spacing={2} pl={3} align="left">
<Heading
align="left"
fontSize="xl"
color={`mode.${colorMode}.career.text`}
>
{title}
</Heading>
<Heading
align="left"
fontSize="sm"
color={`mode.${colorMode}.career.subtext`}
>
{role}
</Heading>
<Stack
spacing={1}
mt={3}
isInline
alignItems="center"
display={["none", "none", "flex", "flex"]}
>
{skills.map(skill => (
<Tag size="sm" padding="0 3px" key={skill}>
{skill}
</Tag>
))}
</Stack>
</Stack>
</Flex>
<Stack display={["none", "none", "flex", "flex"]}>
<Text fontSize={14} color={`mode.${colorMode}.career.subtext`}>
{period}
</Text>
</Stack>
</Flex>
<Stack
spacing={1}
mt={3}
isInline
alignItems="center"
display={["flex", "flex", "none", "none"]}
>
{skills.map(skill => (
<Tag size="sm" padding="0 3px" key={skill}>
{skill}
</Tag>
))}
</Stack>
</Box>
</CardTransition>
);
}
Example #15
Source File: TrackTopic.tsx From takeout-app with MIT License | 5 votes |
TrackTopic: React.FC<Props> = ({ card, topicNav }) => {
const topic = card?.topic!;
if (!topic || !card) {
return (
<Flex justify="space-between" align="center" w="100%">
{topicNav}
</Flex>
);
}
return (
<VStack spacing="18px">
<Flex justify="space-between" align="center" w="100%" alignItems="top">
<HStack flexGrow={1} flexShrink={0} flexBasis={0} alignItems="top" spacing="12px">
{card.speakers && card.speakers.length > 0 ? (
<Box w="100%" maxW="64px">
<SpeakerAvatar speakers={card.speakers} />
</Box>
) : null}
<Box as="div">
<Heading as="h2" fontSize="30px" lineHeight="36px" fontWeight="500" mt="-4px">
{topic.title}
</Heading>
<Box mt="2px">
{topic.labels.map((v, i) => (
<Tag
key={i}
variant="solid"
size="sm"
mr={1}
css={{ backgroundColor: Colors.textMuted, color: "#ffffff" }}
>
{v}
</Tag>
))}
</Box>
{card.speakers && card.speakers.length > 0 ? (
<Box>
{card.speakers.map((s) => (
<TrackTopicSpeaker key={s.avatar_url} speaker={s} />
))}
</Box>
) : null}
</Box>
</HStack>
<Box>{topicNav}</Box>
</Flex>
<Box py="18px" borderTop="1px solid" borderColor={Colors.border} w="100%">
<Text as="p">{topic.description}</Text>
</Box>
</VStack>
);
}
Example #16
Source File: project-card.tsx From portfolio with MIT License | 4 votes |
ProjectCard: React.FC<ProjectCardProps> = ({
title,
description,
logo,
blurHash,
link,
technologies
}) => {
const textColor = useColorModeValue("gray.500", "gray.200");
const [isOpen, setIsOpen] = React.useState(false);
const toggleOpen = () => setIsOpen(!isOpen);
return (
<motion.div layout onClick={toggleOpen}>
<HStack
p={4}
bg={useColorModeValue("white", "gray.800")}
rounded="xl"
borderWidth="1px"
borderColor={useColorModeValue("gray.100", "gray.700")}
w="100%"
h="100%"
textAlign="left"
align="start"
spacing={4}
cursor="pointer"
_hover={{ shadow: "lg" }}
>
<LazyImage
src={logo}
blurHash={blurHash}
size="sm"
width={33}
height={33}
layout="fixed"
rounded="md"
/>
<VStack align="start" justify="flex-start">
<VStack spacing={0} align="start">
<motion.div layout>
<HStack>
<Text
as={Link}
href={link}
fontWeight="bold"
fontSize="md"
noOfLines={1}
onClick={e => e.stopPropagation()}
isExternal
>
{title}
</Text>
<HStack spacing="1">
{technologies.map(tech => (
<Tag size="sm" colorScheme={getTagColor(tech)}>
{tech}
</Tag>
))}
</HStack>
</HStack>
</motion.div>
<AnimatePresence>
<motion.div
layout
initial={{ opacity: 1 }}
animate={{ opacity: 1 }}
exit={{ opacity: 1 }}
>
{!isOpen && (
<Text fontSize="sm" color={textColor} noOfLines={{ base: 2 }}>
{description}
</Text>
)}
</motion.div>
</AnimatePresence>
<AnimatePresence>
<motion.div
layout
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
variants={{ exit: { transition: { staggerChildren: 0.1 } } }}
>
{isOpen && (
<Text
fontSize="sm"
color={textColor}
// noOfLines={{ base: isOpen ? 5 : 2 }}
>
{description}
</Text>
)}
</motion.div>
</AnimatePresence>
</VStack>
</VStack>
</HStack>
</motion.div>
);
}
Example #17
Source File: ContactDialog.tsx From bluebubbles-server with Apache License 2.0 | 4 votes |
ContactDialog = ({
onCancel,
onDelete,
onCreate,
onUpdate,
onClose,
onAddressAdd,
onAddressDelete,
isOpen,
modalRef,
existingContact,
}: ContactDialogProps): JSX.Element => {
const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [displayName, setDisplayName] = useState('');
const [currentAddress, setCurrentAddress] = useState('');
const [hasEdited, setHasEdited] = useBoolean(false);
const [phones, setPhones] = useState([] as ContactAddress[]);
const [emails, setEmails] = useState([] as ContactAddress[]);
const [firstNameError, setFirstNameError] = useState('');
const isNameValid = (firstNameError ?? '').length > 0;
useEffect(() => {
if (!existingContact) return;
if (existingContact.firstName) setFirstName(existingContact.firstName);
if (existingContact.lastName) setLastName(existingContact.lastName);
if (existingContact.displayName) setDisplayName(existingContact.displayName);
if (existingContact.phoneNumbers) setPhones(existingContact.phoneNumbers);
if (existingContact.emails) setEmails(existingContact.emails);
}, [existingContact]);
const addAddress = (address: string) => {
const existsPhone = phones.map((e: ContactAddress) => e.address).includes(address);
const existsEmail = emails.map((e: ContactAddress) => e.address).includes(address);
if (existsPhone || existsEmail) {
return showErrorToast({
id: 'contacts',
description: 'Address already exists!'
});
}
if (address.includes('@')) {
setEmails([{ address }, ...emails]);
} else {
setPhones([{ address }, ...phones]);
}
if (onAddressAdd && existingContact) {
onAddressAdd(existingContact.id, address);
}
};
const removeAddress = (address: string, addressId: number | null) => {
if (address.includes('@')) {
setEmails(emails.filter((e: NodeJS.Dict<any>) => e.address !== address));
} else {
setPhones(phones.filter((e: NodeJS.Dict<any>) => e.address !== address));
}
if (onAddressDelete && addressId) {
onAddressDelete(addressId);
}
};
const _onClose = () => {
setPhones([]);
setEmails([]);
setFirstName('');
setLastName('');
setDisplayName('');
setCurrentAddress('');
setHasEdited.off();
if (onClose) onClose();
};
return (
<AlertDialog
isOpen={isOpen}
leastDestructiveRef={modalRef}
onClose={() => onClose()}
>
<AlertDialogOverlay>
<AlertDialogContent>
<AlertDialogHeader fontSize='lg' fontWeight='bold'>
{(existingContact) ? 'Edit Contact' : 'Add a new Contact'}
</AlertDialogHeader>
<AlertDialogBody>
<Text>Add a custom contact to the server's database</Text>
<FormControl isInvalid={isNameValid} mt={5}>
<FormLabel htmlFor='firstName'>First Name</FormLabel>
<Input
id='firstName'
type='text'
value={firstName}
placeholder='Tim'
onChange={(e) => {
setFirstNameError('');
setFirstName(e.target.value);
if (!hasEdited) {
setDisplayName(`${e.target.value} ${lastName}`.trim());
}
}}
/>
{isNameValid ? (
<FormErrorMessage>{firstNameError}</FormErrorMessage>
) : null}
</FormControl>
<FormControl mt={5}>
<FormLabel htmlFor='lastName'>Last Name</FormLabel>
<Input
id='lastName'
type='text'
value={lastName}
placeholder='Apple'
onChange={(e) => {
setLastName(e.target.value);
if (!hasEdited) {
setDisplayName(`${firstName} ${e.target.value}`.trim());
}
}}
/>
</FormControl>
<FormControl mt={5}>
<FormLabel htmlFor='lastName'>Display Name</FormLabel>
<Input
id='displayName'
type='text'
value={displayName}
placeholder='Tim Apple'
onChange={(e) => {
setHasEdited.on();
setDisplayName(e.target.value);
}}
/>
</FormControl>
<FormControl mt={5}>
<FormLabel htmlFor='address'>Addresses</FormLabel>
<HStack>
<Input
id='address'
type='text'
value={currentAddress}
placeholder='Add Address'
onChange={(e) => {
setCurrentAddress(e.target.value);
}}
/>
<IconButton
onClick={() => {
if (!currentAddress || currentAddress.length === 0) return;
addAddress(currentAddress);
setCurrentAddress('');
}}
aria-label='Add'
icon={<AiOutlinePlus />}
/>
</HStack>
<Flex flexDirection="row" alignItems="center" justifyContent="flex-start" flexWrap="wrap" mt={2}>
{[...phones, ...emails].map(((e: ContactAddress) => {
return (
<Tag
mt={1}
mx={1}
size={'md'}
key={e.address}
borderRadius='full'
variant='solid'
>
<TagLabel>{e.address}</TagLabel>
<TagCloseButton
onClick={() => {
removeAddress(e.address, (e.id) ? e.id : null);
}}
/>
</Tag>
);
}))}
</Flex>
</FormControl>
</AlertDialogBody>
<AlertDialogFooter>
<Button
ref={modalRef as React.LegacyRef<HTMLButtonElement> | undefined}
onClick={() => {
if (!existingContact && onCancel) onCancel();
if (existingContact && onUpdate) {
existingContact.firstName = firstName;
existingContact.lastName = lastName;
existingContact.displayName = displayName;
onUpdate(existingContact);
}
_onClose();
}}
>
{(existingContact) ? 'Save & Close' : 'Cancel'}
</Button>
{(existingContact) ? (
<Button
ml={3}
bg='red'
ref={modalRef as React.LegacyRef<HTMLButtonElement> | undefined}
onClick={() => {
if (onDelete) {
onDelete(Number.parseInt(existingContact.id));
}
_onClose();
}}
>
Delete
</Button>
) : null}
{(!existingContact) ? (
<Button
ml={3}
bg='brand.primary'
ref={modalRef as React.LegacyRef<HTMLButtonElement> | undefined}
onClick={() => {
if (firstName.length === 0) {
setFirstNameError('Please enter a first name for the contact!');
return;
}
if (onCreate) {
onCreate({
firstName,
lastName,
phoneNumbers: phones,
emails: emails,
displayName,
birthday: '',
avatar: '',
id: '',
sourceType: 'db'
});
}
_onClose();
}}
>
Create
</Button>
) : null}
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialogOverlay>
</AlertDialog>
);
}
Example #18
Source File: offline-data-card.tsx From portfolio with MIT License | 4 votes |
RepositoryCard = (props: RepositoryCardProps) => {
const {
key,
title,
description,
cover,
blurHash,
technologies,
url,
live,
stars,
fork,
} = props;
const { isOpen, onOpen, onClose } = useDisclosure();
const handleClick = () => {
onOpen();
// window.open(link);
// if (type == "link" || type == "article") {
// window.open(link);
// } else {
// onOpen();
// }
};
const handleLinkClick = (
e: React.MouseEvent<HTMLParagraphElement, MouseEvent>,
link: string
) => {
window.open(link);
e.stopPropagation();
};
const transition = { duration: 0.5, ease: [0.43, 0.13, 0.23, 0.96] };
const thumbnailVariants = {
initial: { scale: 0.9, opacity: 0 },
enter: { scale: 1, opacity: 1, transition },
exit: {
scale: 0.5,
opacity: 0,
transition: { duration: 1.5, ...transition }
}
};
const imageVariants = {
hover: { scale: 1.1 }
};
return (
<CardTransition>
<Box onClick={handleClick} cursor="pointer" size="xl">
<VStack
// w="100%"
rounded="xl"
borderWidth="1px"
bg={useColorModeValue("white", "gray.800")}
borderColor={useColorModeValue("gray.100", "gray.700")}
_hover={{
shadow: "lg",
textDecoration: "none"
}}
overflow="hidden"
align="start"
spacing={0}
>
<Box position="relative" w="100%">
<MotionBox variants={thumbnailVariants}>
<MotionBox
whileHover="hover"
variants={imageVariants}
transition={transition}
>
<AspectRatio
ratio={1.85 / 1}
maxW="400px"
w="100%"
borderBottomWidth="1px"
borderColor={useColorModeValue("gray.100", "gray.700")}
>
{/* <Image
src={cover}
fallback={<Skeleton />}
objectFit="cover"
/> */}
<LazyImage
src={cover}
blurHash={blurHash}
/>
</AspectRatio>
</MotionBox>
</MotionBox>
</Box>
<VStack py={2} px={[2, 4]} spacing={1} align="start" w="100%">
<Flex justifyContent={"space-between"} width="100%">
<Tooltip hasArrow label="Github link" placement="top">
<HStack>
<Icon as={FiGithub} boxSize="0.9em" mt={"1px"} />
{/* <Link href={url} isExternal> */}
<Text
fontSize="sm"
noOfLines={1}
fontWeight="600"
align="left"
onClick={e => handleLinkClick(e, url)}
>
{title}
</Text>
</HStack>
</Tooltip>
{/* </Link> */}
<Flex>
<Icon as={AiOutlineStar} boxSize="0.9em" mt={"1px"} />
<Box as="span" ml="1" fontSize="sm">
{stars}
</Box>
</Flex>
</Flex>
<Flex justifyContent={"space-between"} width="100%">
<Box>
<HStack spacing="1">
{technologies.map(tech => (
<Tag size="sm" colorScheme={getTagColor(tech)}>
<Text fontSize={["0.55rem", "inherit", "inherit"]}>
{tech}
</Text>
</Tag>
))}
</HStack>
</Box>
</Flex>
{/* <Flex justifyContent={"space-between"} width="100%">
<Flex>
<AiOutlineStar color="teal.300" />
<Box as="span" ml="1" fontSize="sm">
{stars}
</Box>
</Flex>
<Box >
<Text
fontSize="xs"
fontWeight="400"
color={useColorModeValue("gray.400", "gray.500")}
>
{created}
</Text>
</Box>
</Flex> */}
</VStack>
</VStack>
<Modal isOpen={isOpen} onClose={onClose} isCentered allowPinchZoom>
<ModalOverlay />
<ModalContent bg="none" maxW={"28rem"} w="auto">
<ModalBody p={0} rounded="lg" overflow="hidden" bg="none">
<Center>
<Image src={cover} rounded="lg" />
{/* {type == "image" ? (
<Image src={cover} rounded="lg" />
) : (
<ReactPlayer url={link} controls playing />
)} */}
</Center>
</ModalBody>
</ModalContent>
</Modal>
</Box>
</CardTransition>
);
}
Example #19
Source File: live-data-card.tsx From portfolio with MIT License | 4 votes |
RepositoryCard = (props: RepositoryCardProps) => {
const {
title,
description,
language,
url,
stargazers_count,
forks_count,
} = props;
const handleLinkClick = (
e: React.MouseEvent<HTMLParagraphElement, MouseEvent>,
link: string
) => {
window.open(link);
e.stopPropagation();
};
return (
<MotionBox whileHover={{ y: -5 }}>
<Box
size="xl"
py={2}
px={[2, 4]}
mt={2}
rounded="xl"
borderWidth="1px"
bg={useColorModeValue("white", "gray.800")}
borderColor={useColorModeValue("gray.100", "gray.700")}
_hover={{
shadow: "lg",
textDecoration: "none"
}}
>
<VStack overflow="hidden" align="start" spacing={1}>
<VStack spacing={1} align="start" w="100%">
<Flex
justifyContent={"space-between"}
width="100%"
onClick={e => handleLinkClick(e, url)}
>
<Tooltip hasArrow label="Github link" placement="top">
<HStack cursor={"pointer"}>
<Icon as={FiGithub} boxSize="0.9em" mt={"1px"} />
<Text
fontSize="sm"
noOfLines={1}
fontWeight="600"
align="left"
color={"blue.500"}
>
{title}
</Text>
</HStack>
</Tooltip>
<HStack cursor={"pointer"} onClick={e => handleLinkClick(e, url)}>
{forks_count && (
<Box _hover={{ color: "blue.500" }}>
<Icon as={BiGitRepoForked} boxSize="0.9em" mt={"1px"} />
<Box as="span" ml="1" fontSize="sm">
{forks_count}
</Box>
</Box>
)}
<Box _hover={{ color: "blue.500" }}>
<Icon as={BiStar} boxSize="0.9em" mt={"1px"} />
<Box as="span" ml="1" fontSize="sm">
{stargazers_count}
</Box>
</Box>
</HStack>
</Flex>
{language && (
<Flex justifyContent={"space-between"} width="100%">
<Box>
<HStack spacing="1">
<Tag size="sm" colorScheme={getTagColor(language)}>
<Text fontSize={["0.55rem", "inherit", "inherit"]}>
{language}
</Text>
</Tag>
</HStack>
</Box>
</Flex>
)}
</VStack>
<Box>
<Text color="gray.500" fontSize="sm" noOfLines={2} textAlign="left">
{description}
</Text>
</Box>{" "}
</VStack>
</Box>
</MotionBox>
);
}
Example #20
Source File: post-card.tsx From portfolio with MIT License | 4 votes |
PostCard: React.SFC<PostCardProps> = ({ article }) => {
const textColor = useColorModeValue("gray.500", "gray.200");
const devIcon = useColorModeValue(dev, dev2);
return (
<CardTransition>
<VStack
spacing={1}
p={4}
isExternal
_hover={{ shadow: "md", textDecoration: "none" }}
borderWidth="1px"
position="relative"
rounded="md"
bg={useColorModeValue("white", "gray.800")}
align="left"
>
{article.external ? (
<Tooltip hasArrow label="Dev.to" placement="top">
<Image
src={devIcon}
width="2rem"
height="2rem"
position="absolute"
color="#cbd5e0"
right="0.5rem"
top="-14px"
/>
</Tooltip>
) : (
<Tooltip hasArrow label="mahmad.me" placement="top">
<Box position="absolute" color="#cbd5e0" right="0.5rem" top="-14px">
<Badge ml="1" variant="solid" colorScheme="blackAlpha">
Website
</Badge>
</Box>
</Tooltip>
)}
<Heading fontSize="lg" align="left" mt={0}>
{article.external ? (
<Text as={Link} href={article.link} target="_blank">
{article.title}
</Text>
) : (
<Link as={NavLink} to={article.link}>
{article.title}
</Link>
)}
{article.isNew && (
<Badge
ml="1"
mb="1"
colorScheme="green"
fontSize="0.7em"
lineHeight={1.5}
>
New
</Badge>
)}
</Heading>
<HStack spacing={2} isInline>
<Tooltip hasArrow label="Published" placement="top">
<Text fontSize="sm" fontWeight="400" color={textColor}>
{article.published}
</Text>
</Tooltip>
<Text fontSize="sm" fontWeight="400" color={textColor}>
•
</Text>
<Tooltip hasArrow label="Views" placement="top">
<Flex alignItems="center">
<Text
fontSize="sm"
noOfLines={1}
fontWeight="400"
align="left"
color={textColor}
>
{article.views}
</Text>
<Icon as={FaEye} ml={1} color={textColor} />
</Flex>
</Tooltip>
<Text fontSize="sm" fontWeight="600" color={textColor}>
•
</Text>
<Tooltip hasArrow label="Read time" placement="top">
<Text
fontSize="sm"
noOfLines={1}
fontWeight="400"
align="left"
color={textColor}
>
{article.readTime}
</Text>
</Tooltip>
<HStack spacing={1} alignItems="center" d={["none", "none", "flex"]}>
{article.tags.map(tag => (
<Tag
size="sm"
padding="0 3px"
key={tag}
colorScheme={getTagColor(tag)}
>
{tag}
</Tag>
))}
</HStack>
</HStack>
<HStack spacing={1} alignItems="center" d={["flex", "flex", "none"]}>
{article.tags.map(tag => (
<Tag
size="sm"
padding="0 3px"
key={tag}
colorScheme={getTagColor(tag)}
>
{tag}
</Tag>
))}
</HStack>
<Text align="left" fontSize="md" noOfLines={4} color={textColor}>
{article.desc}
</Text>
</VStack>
</CardTransition>
);
}
Example #21
Source File: ChipInput.tsx From ke with MIT License | 4 votes |
ChipInput = forwardRef<HTMLInputElement, ChipInputProps>((props, ref): JSX.Element => {
const {
value: inputValue,
onChange,
placeholder,
submitKeys = ['Enter', 'Tab'],
validator = () => true,
errorText = 'Invalid value',
chipClassName,
inputClassName,
} = props
const [chips, setChips] = usePropState<string[]>(inputValue)
const [value, setValue] = useState<string>('')
const [error, setError] = useState<string>('')
// TODO: Исправить
// eslint-disable-next-line react-hooks/rules-of-hooks
const inputRef = (ref as RefObject<HTMLInputElement>) ?? useRef<HTMLInputElement>(null)
const isValid = useCallback(
(val: string): boolean => {
if (!validator(val)) {
setError(errorText)
return false
}
setError('')
return true
},
[errorText, validator]
)
const deleteChip = useCallback(
(index: number): void => {
const newChips = chips.filter((_, chipIndex) => chipIndex !== index)
setChips(newChips)
onChange(newChips)
},
[onChange, chips, setChips]
)
const finishInput = useCallback((): void => {
const trimmedValue = value.trim()
if (trimmedValue && isValid(trimmedValue)) {
const newChips = [...chips, trimmedValue]
setChips(newChips)
onChange(newChips)
setValue('')
setError('')
}
}, [onChange, chips, setChips, isValid, value])
const handleKeyDown = useCallback(
(e: KeyboardEvent<HTMLInputElement>): void => {
if (submitKeys.includes(e.key)) {
e.preventDefault()
finishInput()
}
if (e.key === 'Backspace') {
if (!value && chips.length > 0) {
e.preventDefault()
deleteChip(chips.length - 1)
}
}
},
[chips.length, deleteChip, finishInput, submitKeys, value]
)
const { container, input, chip, chipLabel } = useMultiStyleConfig('ChipInput', props)
return (
<>
<Flex __css={container} onClick={() => inputRef?.current?.focus?.()}>
{chips.map((chipValue: string, index: number) => {
const key = index
return (
<Tag key={key} minWidth={undefined} minHeight={undefined} sx={chip} className={chipClassName}>
<TagLabel sx={chipLabel} width="100%">
{chipValue}
</TagLabel>
<TagCloseButton onClick={() => deleteChip(key)} />
</Tag>
)
})}
<Input
variant="unstyled"
sx={input}
value={value}
onChange={(e: ChangeEvent<HTMLInputElement>): void => setValue(e.target.value)}
placeholder={placeholder}
onKeyDown={handleKeyDown}
isInvalid={!!error}
ref={inputRef}
width="auto"
height="2rem"
borderRadius="0px"
onBlur={finishInput}
className={inputClassName}
/>
</Flex>
{error && (
<Text className="error" fontSize="0.7rem" color="red.400">
{error}
</Text>
)}
</>
)
})
Example #22
Source File: StateTree.tsx From engine with MIT License | 4 votes |
StateTree: view = ({
data,
path,
_viewId,
isBodyVisible = observe.views[prop._viewId].data.isBodyVisible,
updateIsBodyVisible = update.views[prop._viewId].data.isBodyVisible,
}) => {
if (!data) {
return null;
}
let isRoot = false;
if (path === undefined) {
path = "";
isRoot = true;
} else {
if (path === "") {
path = `${data.name}`;
} else {
path = `${path}.${data.name}`;
}
}
const hasChildren = data.children && Object.keys(data.children).length > 0;
const hasElements =
(data.elements?.view?.length || 0) +
(data.elements?.producer?.length || 0) >
0;
return (
<ListItem ml="0" key={_viewId}>
{!isRoot && hasChildren && (
<Flex mb="2">
<Tag
variant={isBodyVisible ? "solid" : "subtle"}
cursor="pointer"
size="sm"
userSelect="none"
onClick={() => updateIsBodyVisible.set(!isBodyVisible)}
>
<TagLeftIcon>
{!isBodyVisible && <ChevronDownIcon />}
{isBodyVisible && <ChevronUpIcon />}
</TagLeftIcon>
<TagLabel>{data.name}</TagLabel>
</Tag>
{hasElements && (
<ElementsSummary parentId={_viewId} elements={data.elements} />
)}
{path.split(".").length > 1 && (
<Text fontSize="sm" ml="4" color="gray.500">
{path}
</Text>
)}
</Flex>
)}
{!isRoot && !hasChildren && (
<Flex mb="2">
<Flex>
<Text fontSize="sm">{data.name}</Text>
{hasElements && (
<ElementsSummary parentId={_viewId} elements={data.elements} />
)}
</Flex>
{path.split(".").length > 1 && (
<Text fontSize="sm" ml="4" color="gray.500">
{path}
</Text>
)}
</Flex>
)}
{isRoot && (
<Text color="gray.500" fontWeight="bold">
Root
</Text>
)}
<ElementsList
elements={data.elements}
parentId={_viewId}
path={path}
></ElementsList>
{(isBodyVisible || isRoot) && (
<Children data={data.children} path={path} />
)}
</ListItem>
);
}
Example #23
Source File: Item.tsx From ksana.in with Apache License 2.0 | 4 votes |
export function Item({ user, data }: IUrlItemProps) {
const { showAlert, hideAlert } = useAlertContext()
const [updateId, setUpdateId] = useState<string>('')
const [updateSlug, setUpdateSlug] = useState<string>('')
const [isSuccessCopy, setSuccessCopy] = useState<boolean>(false)
const [isLoadingShare, setLoadingShare] = useState<boolean>(false)
const [isLoadingSave, setLoadingSave] = useState<boolean>(false)
const isSupportShare: boolean =
typeof window !== 'undefined' ? navigator.share !== undefined : false
const bgBox = useColorModeValue('white', 'gray.800')
const bgInput = useColorModeValue('blackAlpha.100', 'whiteAlpha.100')
const showSuccessCopy = () => {
setSuccessCopy(true)
setTimeout(() => {
setSuccessCopy(false)
}, 2000)
}
const handleCopy = async (text: string) => {
if (navigator.clipboard) {
await navigator.clipboard.writeText(text)
} else {
copy(text)
}
showSuccessCopy()
}
const handleShare = async (url: string) => {
if (navigator.share) {
setLoadingShare(true)
const jsonRes = await getMeta(url)
const shareObj = {
title: jsonRes.title,
text: jsonRes.description,
url: url
}
navigator
.share(shareObj)
// eslint-disable-next-line no-console
.then(() => setLoadingShare(false))
.catch((error) => {
setLoadingShare(false)
// eslint-disable-next-line no-console
console.error('Error sharing', error, shareObj)
})
}
}
const handleClickEdit = async (id: string) => {
if (updateId === id) {
setUpdateId('')
setUpdateSlug('')
} else {
setUpdateId(id)
setUpdateSlug('')
}
}
const handleChangeUpdatedSlug = async (e: ChangeEvent<HTMLInputElement>) => {
const value = e.target.value
setUpdateSlug(value)
}
const handleClickSave = async () => {
if (updateSlug) {
setLoadingSave(true)
const { error } = await patchSlug({
id: updateId,
slug: sanitizeSlug(updateSlug),
userId: user?.id
})
if (error) {
showAlert({
title: 'Terjadi galat pada saat memperbarui data',
message: `Pesan: ${error.message}`,
onClose: () => {
hideAlert()
setLoadingSave(false)
}
})
} else {
mutate(apiUrlsGet(user?.id))
setUpdateId('')
setUpdateSlug('')
setLoadingSave(false)
}
}
}
const onConfimDelete = async (id: string) => {
const { error } = await deleteUrl({ id: id, userId: user?.id })
if (error) {
hideAlert()
showAlert({
title: 'Terjadi galat pada saat berusaha menghapus data',
message: `Pesan: ${error.message}`,
onClose: () => {
hideAlert()
}
})
}
hideAlert()
mutate(apiUrlsGet(user?.id))
}
const handleDelete = async (id: string, slug: string) => {
showAlert({
title: 'Konfirmasi hapus',
message: `Apakah kamu yakin untuk menghapus data ${HOME}${slug}? Aksi ini juga akan menghilangkan semua data statistik terkait.`,
cancelText: 'Batalkan',
confirmText: 'Ya, hapus',
onConfirm: () => {
onConfimDelete(id)
},
onClose: hideAlert
})
}
return (
<Box
key={data.slug}
w={'full'}
bg={bgBox}
boxShadow={'2xl'}
rounded={'md'}
overflow={'hidden'}
p={{ base: '4', md: '6' }}
>
{!!data.is_dynamic && (
<Tag size="sm" colorScheme="green">
Tautan dinamis
</Tag>
)}
<Flex alignItems="center" mb="4">
<Link
as="a"
fontSize={{ base: 'md', md: 'lg' }}
fontWeight="700"
color="orange.400"
href={`${HOME}${data.slug}${!!data.is_dynamic ? '/{param}' : ''}`}
display="block"
>
{`/${data.slug}`}
{!!data.is_dynamic && '/{param}'}
</Link>
</Flex>
{updateId && updateId === data.id && (
<HStack alignItems="center" mb="4" mt="2">
<Input
size="lg"
name="slug"
placeholder={'Tulis slug baru'}
bg={bgInput}
border={0}
value={updateSlug}
onChange={handleChangeUpdatedSlug}
/>
<IconButton
onClick={handleClickSave}
aria-label="Simpan slug"
size="lg"
bg="orange.400"
borderRadius="md"
isLoading={isLoadingSave}
icon={<HiSave color="#FFF" />}
/>
</HStack>
)}
<Text fontSize="small" color="gray.400" display="block" mb="2">
{data.real_url}
</Text>
<Text fontSize="small" color="gray.400">
<Text as="span" fontWeight="bold" color="orange.400">
{new Intl.NumberFormat('id-ID').format(data.hit)}
</Text>
{` `} kunjungan
</Text>
<HStack spacing={2} mt={4} flexWrap="wrap">
<IconButton
onClick={() => {
handleCopy(`${HOME}${data.slug}`)
}}
aria-label="Copy"
variant="ghost"
borderRadius="md"
icon={isSuccessCopy ? <HiCheck color="#48BB78" /> : <HiDuplicate color="#ED8936" />}
/>
{isSupportShare ? (
<IconButton
onClick={() => {
handleShare(`${HOME}${data.slug}`)
}}
aria-label="Copy"
variant="ghost"
borderRadius="md"
isLoading={isLoadingShare}
icon={<HiShare color="#ED8936" />}
/>
) : (
<SharePopover url={`${HOME}${data.slug}`} />
)}
<IconButton
onClick={() => {
handleClickEdit(data.id)
}}
aria-label="Ubah"
variant="ghost"
borderRadius="md"
icon={<HiPencil color="#ED8936" />}
/>
<IconButton
onClick={() => {
handleDelete(data.id, data.slug)
}}
aria-label="Hapus"
variant="ghost"
borderRadius="md"
icon={<HiTrash color="#ED8936" />}
/>
</HStack>
</Box>
)
}
Example #24
Source File: notebook-post.tsx From portfolio with MIT License | 4 votes |
NotebookPost: React.SFC<PostProps> = () => {
const textColor = useColorModeValue("gray.500", "gray.200");
const post = articles[4];
return (
<>
<VStack mt={0} mb={6} spacing={1} align="start">
<Heading as="h1" fontSize="3xl" lineHeight="shorter" fontWeight="bold">
{post.title}
</Heading>
<Divider
orientation="horizontal"
opacity={1}
borderBottomWidth={0}
height={"1px"}
bg={"gray.200"}
/>
</VStack>
<Flex
justifyContent={"space-between"}
flexDirection={["column", "row", "row"]}
>
<HStack spacing={2} isInline>
<Text fontSize="sm" fontWeight="400" color={textColor}>
{post.published}
</Text>
<Text fontSize="sm" fontWeight="400" color={textColor}>
•
</Text>
<Tooltip hasArrow label="Views" placement="top">
<Flex alignItems="center">
<Text
fontSize="sm"
noOfLines={1}
fontWeight="400"
align="left"
color={textColor}
>
{post.views}
</Text>
<Icon as={FaEye} ml={1} color={textColor} />
</Flex>
</Tooltip>
<Text fontSize="sm" fontWeight="600" color={textColor}>
•
</Text>
<Tooltip hasArrow label="Read time" placement="top">
<Text
fontSize="sm"
noOfLines={1}
fontWeight="400"
align="left"
color={textColor}
>
{post.readTime}
</Text>
</Tooltip>
</HStack>
<HStack spacing={1} alignItems="center">
{post.tags.map(tag => (
<Tag
size="sm"
padding="0 3px"
key={tag}
colorScheme={getTagColor(tag)}
>
{tag}
</Tag>
))}
</HStack>
</Flex>
<HStack align="end" mt={5}>
<Link href={post.live} isExternal>
<Button
ml={2}
variant="outline"
size={["sm"]}
color={useColorModeValue("green.600", "green.200")}
bg={useColorModeValue("white", "gray.800")}
leftIcon={<BiLinkExternal size={18} />}
>
Demo
</Button>
</Link>
<Link href={post.github_url} isExternal>
<Button
ml={2}
variant="outline"
size={["sm"]}
color={useColorModeValue("green.600", "green.200")}
bg={useColorModeValue("white", "gray.800")}
leftIcon={<FiGithub size={18} />}
>
Github link
</Button>
</Link>
</HStack>
<Box height={["35vh", "45vh", "55vh", "70vh"]} marginTop={5}>
<Carousel images={post.images} />
</Box>
<VStack spacing={5} align={"start"} mt={6}>
<Header fontSize={"xl"} mt={0} mb={0}>
What will you learn?
</Header>
<Box fontSize="md">
<UnorderedList textAlign="left" paddingLeft={5} m={0}>
<ListItem>How to create a CRUD app with react</ListItem>
<ListItem>How to create a responsive app using ChakraUi</ListItem>
<ListItem>How to use animations with framer-motion</ListItem>
<ListItem>How to create slider with framer-motion</ListItem>
</UnorderedList>
</Box>
</VStack>
<VStack spacing={5} align={"start"} mt={6}>
<Header fontSize={"xl"} mt={0} mb={0}>
Built with
</Header>
<Box fontSize="md">
<UnorderedList textAlign="left" paddingLeft={5} m={0}>
<ListItem>
Programming language -{" "}
<Link
href="https://www.typescriptlang.org/"
isExternal
color={"blue.500"}
>
Typescript
</Link>
</ListItem>
<ListItem>
Front-end library -{" "}
<Link
href="https://github.com/facebook/react/"
isExternal
color={"blue.500"}
>
React
</Link>
</ListItem>
<ListItem>
UI components -{" "}
<Link href="https://chakra-ui.com/" isExternal color={"blue.500"}>
Chakra-ui
</Link>
</ListItem>
<ListItem>
Animation library -{" "}
<Link
href="https://www.framer.com/motion/"
isExternal
color={"blue.500"}
>
Framer motion
</Link>
</ListItem>
<ListItem>
Notes display -{" "}
<Link
href="https://github.com/tsuyoshiwada/react-stack-grid"
isExternal
color={"blue.500"}
>
react-stack-grid
</Link>
</ListItem>
<ListItem>
Forms Validation -{" "}
<Link
href="https://react-hook-form.com/"
isExternal
color={"blue.500"}
>
React hook form
</Link>
</ListItem>
<ListItem>
Icons -{" "}
<Link
href="https://react-icons.github.io/react-icons/"
isExternal
color={"blue.500"}
>
React icons
</Link>
</ListItem>
<ListItem>
Images placeholder -{" "}
<Link href="https://blurha.sh/" isExternal color={"blue.500"}>
blurhash
</Link>
</ListItem>
<ListItem>
Progressive image loading -{" "}
<Link
href="https://github.com/FormidableLabs/react-progressive-image"
isExternal
color={"blue.500"}
>
react-progressive-image
</Link>
</ListItem>
</UnorderedList>
</Box>
</VStack>
</>
);
}