Blog
Newsletters
import React from 'react';
import {
Box,
chakra,
Container,
Link,
Text,
HStack,
VStack,
Flex,
Icon,
useColorModeValue
} from '@chakra-ui/react';
// Here we have used react-icons package for the icons
import { FaRegNewspaper } from 'react-icons/fa';
const articles = [
{
id: 1,
categories: ['Web Dev', 'Video'],
title: 'Passwordless login with Rails 7',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum is simply dummy text of the printing and typesetting industry. `,
created_at: 'MARCH 30, 2022'
},
{
id: 2,
categories: ['Web Dev', 'Article'],
title: 'The Complete Guide to Ruby on Rails',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.`,
created_at: 'July 30, 2022'
}
];
const Newsletters = () => {
return (
<Container maxWidth="4xl" p={{ base: 2, sm: 10 }}>
{articles.map((article, index) => (
<Flex key={index} mb="10px">
<LineWithDot />
<Card {...article} />
</Flex>
))}
</Container>
);
};
interface CardProps {
title: string;
categories: string[];
content: string;
created_at: string;
}
const Card = ({ title, categories, content, created_at }: CardProps) => {
return (
<HStack
p={{ base: 3, sm: 6 }}
bg={useColorModeValue('gray.100', 'gray.800')}
spacing={5}
rounded="lg"
alignItems="center"
pos="relative"
_before={{
content: `""`,
w: '0',
h: '0',
borderColor: `transparent ${useColorModeValue('#edf2f6', '#1a202c')} transparent`,
borderStyle: 'solid',
borderWidth: '15px 15px 15px 0',
position: 'absolute',
left: '-15px',
display: 'block'
}}
>
<Icon as={FaRegNewspaper} w={12} h={12} color="teal.400" />
<Box>
<HStack spacing={2} mb={1}>
{categories.map((cat) => (
<Text fontSize="sm" key={cat}>
{cat}
</Text>
))}
</HStack>
<VStack spacing={0} mb={3} textAlign="left">
<chakra.h1
as={Link}
_hover={{ color: 'teal.400' }}
fontSize="2xl"
lineHeight={1.2}
fontWeight="bold"
w="100%"
>
{title}
</chakra.h1>
<Text fontSize="md" noOfLines={2}>
{content}
</Text>
</VStack>
<Text fontSize="sm">{created_at}</Text>
</Box>
</HStack>
);
};
const LineWithDot = () => {
return (
<Flex pos="relative" alignItems="center" mr="40px">
<chakra.span
position="absolute"
left="50%"
height="calc(100% + 10px)"
border="1px solid"
borderColor={useColorModeValue('gray.200', 'gray.700')}
top="0px"
></chakra.span>
<Box pos="relative" p="10px">
<Box
pos="absolute"
width="100%"
height="100%"
bottom="0"
right="0"
top="0"
left="0"
backgroundSize="cover"
backgroundRepeat="no-repeat"
backgroundPosition="center center"
backgroundColor="rgb(255, 255, 255)"
borderRadius="100px"
border="3px solid rgb(4, 180, 180)"
backgroundImage="none"
opacity={1}
></Box>
</Box>
</Flex>
);
};
export default Newsletters;
With border
import React from 'react';
import {
Container,
Box,
HStack,
VStack,
Stack,
Link,
Text,
Icon,
Tag,
Avatar,
useColorModeValue
} from '@chakra-ui/react';
// Here we have used react-icons package for the icons
import { GoChevronRight } from 'react-icons/go';
const articles = [
{
id: 1,
tags: ['News', 'Product'],
title: 'Build a Modern User Interface with Chakra UI',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. simply dummy text...`,
userAvatar:
'https://images.unsplash.com/photo-1606513542745-97629752a13b?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80',
username: 'Danilo Leal',
created_at: 'Wed Apr 06 2022'
},
{
id: 2,
tags: ['Web Development', 'Video'],
title: 'The Complete Guide to Ruby on Rails Encrypted Credentials',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.`,
userAvatar:
'https://images.unsplash.com/photo-1531427186611-ecfd6d936c79?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&auto=format&fit=crop&w=334&q=80',
username: 'Timo Delangle',
created_at: 'Sun Apr 03 2022'
}
];
const BlogCards = () => {
return (
<Container p={{ base: 5, md: 10 }}>
<VStack spacing={8} w={{ base: 'auto', md: '2xl' }}>
{articles.map((article, index) => (
<Stack
key={index}
direction="column"
spacing={4}
p={4}
bg={useColorModeValue('gray.100', 'gray.800')}
border="1px solid"
borderColor="blue.100"
_hover={{
borderColor: 'blue.300',
boxShadow: useColorModeValue(
'0 4px 6px rgba(160, 174, 192, 0.6)',
'0 4px 6px rgba(9, 17, 28, 0.9)'
)
}}
rounded="lg"
>
<HStack spacing={2} mb={1}>
{article.tags.map((cat, index) => (
<Tag
key={index}
colorScheme={useColorModeValue('blackAlpha', 'gray')}
borderRadius="full"
>
{cat}
</Tag>
))}
</HStack>
<Box textAlign="left">
<Link
fontSize="xl"
lineHeight={1.2}
fontWeight="bold"
w="100%"
_hover={{ color: 'blue.400', textDecoration: 'underline' }}
>
{article.title}
</Link>
<Text fontSize="md" color="gray.500" noOfLines={2} lineHeight="normal">
{article.content}
</Text>
</Box>
<Box>
<Avatar size="sm" title="Author" mb={2} src={article.userAvatar} />
<Stack justifyContent="space-between" direction={{ base: 'column', sm: 'row' }}>
<Box>
<Text fontSize="sm" fontWeight="bold">
{article.username}
</Text>
<Text fontSize="sm" color="gray.500">
{article.created_at}
</Text>
</Box>
<HStack
as={Link}
spacing={1}
p={1}
alignItems="center"
height="2rem"
w="max-content"
margin="auto 0"
rounded="md"
color="blue.400"
_hover={{ bg: useColorModeValue('gray.200', 'gray.700') }}
>
<Text fontSize="sm"> Read more</Text>
<Icon as={GoChevronRight} w={4} h={4} />
</HStack>
</Stack>
</Box>
</Stack>
))}
</VStack>
</Container>
);
};
export default BlogCards;
Transparent bg
import React from 'react';
import {
chakra,
Container,
Box,
HStack,
VStack,
Link,
Text,
Avatar,
SimpleGrid,
useColorModeValue
} from '@chakra-ui/react';
const articles = [
{
id: 1,
title: 'Rust Is The Future',
content: `Why is Rust being used to replace parts of the JavaScript web ecosystem like minification (Terser), transpilation (Babel), formatting (Prettier), bundling (webpack), linting (ESLint), and more?`,
userAvatar:
'https://images.unsplash.com/photo-1531427186611-ecfd6d936c79?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&auto=format&fit=crop&w=334&q=80',
username: 'Tobias',
created_at: 'April 10, 2022'
},
{
id: 2,
title: 'Building with ChakraUI',
content: `Learn how to create an image gallery with dynamic content from a PostgreSQL database, with support for content updates without needing to redeploy.`,
userAvatar:
'https://images.unsplash.com/photo-1606513542745-97629752a13b?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80',
username: 'Timo',
created_at: 'April 1, 2022'
}
];
const Articles = () => {
return (
<Container maxWidth="1200px" mx="auto" my="auto" p={{ base: 5, md: 8 }}>
<SimpleGrid columns={{ base: 1, md: 2 }} spacing={5}>
{articles.map((article, index) => (
<Card key={index} {...article} />
))}
</SimpleGrid>
</Container>
);
};
interface CardProps {
title: string;
content: string;
userAvatar: string;
username: string;
created_at: string;
}
const Card = ({ title, content, username, userAvatar, created_at }: CardProps) => {
return (
<Box as={Link} p={4} _hover={{ bg: useColorModeValue('gray.100', 'gray.800') }} rounded="md">
<VStack spacing={2} mb={5} textAlign="left">
<chakra.h1 fontSize="2xl" lineHeight={1.2} fontWeight="bold" w="100%">
{title}
</chakra.h1>
<Text fontSize="md" noOfLines={2} color="gray.500">
{content}
</Text>
</VStack>
<HStack spacing={2} alignItems="center">
<Avatar size="md" title="Author" src={userAvatar} />
<Box>
<Text fontWeight="bold">{username}</Text>
<Text fontSize="sm" color="gray.500">
{created_at}
</Text>
</Box>
</HStack>
</Box>
);
};
export default Articles;
With tag
import React from 'react';
import {
chakra,
Container,
Box,
HStack,
VStack,
Link,
Text,
Icon,
Tag,
useColorModeValue
} from '@chakra-ui/react';
// Here we have used react-icons package for the icons
import { AiOutlineVideoCamera } from 'react-icons/ai';
const articles = [
{
id: 1,
categories: ['Web Development', 'Video'],
tag: 'RUBY ON RAILS',
title: 'Passwordless login with Rails 7',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. simply dummy text...`,
created_at: 'MARCH 30, 2022'
},
{
id: 2,
categories: ['Web Development', 'Video'],
tag: 'RUBY ON RAILS',
title: 'The Complete Guide to Ruby on Rails Encrypted Credentials',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.`,
created_at: 'MARCH 30, 2022'
}
];
const BlogCards = () => {
return (
<Container maxWidth="1200px" mx="auto" my="auto" p={{ base: 5, md: 10 }}>
<VStack spacing={8} w={{ base: 'auto', md: '2xl' }} margin="0 auto">
{articles.map((article, index) => (
<Card key={index} {...article} />
))}
</VStack>
</Container>
);
};
interface CardProps {
title: string;
content: string;
tag: string;
categories: string[];
created_at: string;
}
const Card = ({ title, content, tag, categories, created_at }: CardProps) => {
return (
<Box
p={{ base: 3, sm: 8 }}
bg={useColorModeValue('gray.100', 'gray.800')}
boxShadow={useColorModeValue(
'0 4px 6px rgba(160, 174, 192, 0.6)',
'0 4px 6px rgba(9, 17, 28, 0.9)'
)}
rounded="lg"
pos="relative"
>
<Box
pos="absolute"
d={{ base: 'none', sm: 'block' }}
right={2}
top={2}
rounded="3xl"
as={Link}
bg="red.500"
size="md"
color="white"
p={1}
px={3}
_hover={{ color: 'white' }}
>
<Text fontSize={{ base: 'xs', sm: '12px' }} fontWeight="700">
{tag}
</Text>
</Box>
<HStack spacing={2} mb={1}>
{categories.map((cat) => (
<Text fontSize="sm" key={cat}>
{cat}
</Text>
))}
</HStack>
<VStack spacing={0} mb={5} textAlign="left">
<chakra.h1
as={Link}
_hover={{ color: 'blue.400' }}
fontSize="2xl"
lineHeight={1.2}
fontWeight="bold"
w="100%"
>
{title}
</chakra.h1>
<Text fontSize="md" noOfLines={2}>
{content}
</Text>
</VStack>
<HStack justifyContent="space-between">
<Text fontSize="sm">{created_at}</Text>
<HStack spacing={2} alignItems="center">
<Icon as={AiOutlineVideoCamera} w={5} h={5} />
<Tag
as={Link}
color={useColorModeValue('black', 'white')}
colorScheme={useColorModeValue('blackAlpha', 'whiteAlpha')}
>
Save
</Tag>
</HStack>
</HStack>
</Box>
);
};
export default BlogCards;
Article Info
import React from 'react';
import {
VStack,
HStack,
Heading,
Text,
Link,
useColorModeValue,
Flex,
SimpleGrid,
Container
} from '@chakra-ui/react';
import NextLink from 'next/link';
import { MotionBox } from './motion';
import { CommentIcon, HeartIcon } from './icons';
const BASE_URL = 'https://mahmad.me';
const posts = [
{
title: 'Started 2022 by updating portfolio website',
description: `I was thinking about making some changes in my portfolio website since past few months. I couldn't...`,
slug: '/blog/started-2022-by-updating-portfolio-website-1jde-temp-slug-4553258',
positive_reactions_count: '189',
comments_count: '26',
published_at: '21st January 2021'
}
];
const FeaturedArticles = () => {
const linkColor = 'blue.400';
const textColor = useColorModeValue('gray.500', 'gray.200');
return (
<Container maxW="4xl" p={{ base: 5, md: 12 }}>
<VStack align="start" spacing={8} width="100%">
<SimpleGrid columns={1} spacing={4} w="100%">
{posts &&
posts.map(
(
{
description,
title,
slug,
positive_reactions_count,
comments_count,
published_at
},
i
) => (
<MotionBox whileHover={{ y: -5 }} key={i}>
<VStack
spacing={1}
p={4}
_hover={{ shadow: 'md', textDecoration: 'none' }}
borderWidth="1px"
position="relative"
rounded="md"
bg={useColorModeValue('white', 'gray.800')}
align="left"
>
<HStack justifyContent="space-between" isInline>
<Heading fontSize="lg" align="left" mt={0}>
<NextLink href={`${BASE_URL}/blog/${slug}`} passHref>
<Text as={Link} color={linkColor}>
{title}
</Text>
</NextLink>
</Heading>
<HStack spacing={2} isInline d={['none', 'flex', 'flex']}>
<Flex alignItems="center">
<Text
fontSize="sm"
noOfLines={1}
fontWeight="400"
align="left"
color={textColor}
>
{positive_reactions_count}
</Text>
<HeartIcon />
</Flex>
<Flex alignItems="center">
<Text
fontSize="sm"
noOfLines={1}
fontWeight="400"
align="left"
color={textColor}
>
{comments_count}
</Text>
<CommentIcon />
</Flex>
</HStack>
</HStack>
<HStack spacing={2} isInline>
<Text fontSize="sm" fontWeight="600" color={textColor}>
{published_at}
</Text>
<Flex alignItems="center" d={['flex', 'none', 'none']}>
<Text
fontSize="sm"
noOfLines={1}
fontWeight="400"
align="left"
color={textColor}
>
{positive_reactions_count}
</Text>
<HeartIcon />
</Flex>
<Flex alignItems="center" d={['flex', 'none', 'none']}>
<Text
fontSize="sm"
noOfLines={1}
fontWeight="400"
align="left"
color={textColor}
>
{comments_count}
</Text>
<CommentIcon />
</Flex>
</HStack>
<Text align="left" fontSize="md" noOfLines={1} color={textColor}>
{description}
</Text>
</VStack>
</MotionBox>
)
)}
</SimpleGrid>
</VStack>
</Container>
);
};
export default FeaturedArticles;
export const HeartIcon = () => (
<svg
id="Capa_1"
enableBackground="new 0 0 512 512"
height="20px"
viewBox="0 0 512 512"
width="20px"
xmlns="http://www.w3.org/2000/svg"
>
<g>
<path
d="m445.936 20.657h-379.872c-19.731 0-37.443 8.649-49.548 22.364l-6.403 43.701v239.535c0 36.486 19.465 66.064 55.951 66.064h89.427c6.57 0 12.872 10.817 17.518 15.463l77.704 77.704 16.721 2.268c.95-.664 1.856-1.42 2.704-2.268l77.704-77.704c4.646-4.646 10.948-7.256 17.518-7.256h80.577c36.486 0 66.064-29.578 66.064-66.064v-247.742c-.001-36.487-29.579-66.065-66.065-66.065z"
fill="#ff7e92"
/>
<path
d="m164.159 407.784 77.704 77.704c6.959 6.959 17.774 7.714 25.57 2.268l-91.595-91.65c-7.685-7.685-18.323-12.093-29.194-12.093h-80.579c-27.323 0-49.548-22.226-49.548-49.548v-291.444c-10.25 11.639-16.517 26.973-16.517 43.701v247.742c0 36.486 29.578 66.065 66.065 66.065h80.577c6.57-.001 12.872 2.609 17.517 7.255z"
fill="#ff5f7a"
/>
<path
d="m387.626 177.951c-4.003-35.677-34.163-63.99-69.988-66.315-21.701-1.408-41.538 6.405-56.107 19.853-3.135 2.894-7.926 2.894-11.062 0-14.569-13.448-34.406-21.261-56.107-19.853-8.653.562-16.976 2.639-24.679 5.971-24.19 10.461-40.655 60.344-40.655 60.344-8.486 75.632 93.735 136.686 124.126 154.751l21.005-.808c37.878-23.988 121.196-85.05 113.467-153.943z"
fill="#fff"
/>
<path
d="m142.235 167.09c2.224-19.818 12.594-37.402 27.447-49.483-24.153 10.475-42.275 33.311-45.309 60.344-8.485 75.632 92.757 141.829 123.148 159.894 5.245 3.117 11.712 3.117 16.957 0 2.702-1.606 5.985-3.61 9.68-5.95-19.374-10.919-141.105-82.962-131.923-164.805z"
fill="#ffdbde"
/>
</g>
</svg>
);
export const CommentIcon = () => (
<svg
id="Capa_1"
enableBackground="new 0 0 512 512"
height="20px"
viewBox="0 0 512 512"
width="20px"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="m438.983 11.549h-276.72c-36.094 0-65.625 29.531-65.625 65.625v22.33h250.317c36.094 0 65.625 29.531 65.625 65.625v163.609h26.404c36.094 0 65.625-29.531 65.625-65.625v-185.939c0-36.094-29.532-65.625-65.626-65.625z"
fill="#6c7ed6"
/>
<path
d="m392.454 96.504h-276.72c-6.636 0-13.047 1.006-19.096 2.86v.14h250.317c36.094 0 65.625 29.531 65.625 65.625v163.609h26.404c6.636 0 13.047-1.006 19.096-2.86v-163.748c0-36.094-29.532-65.626-65.626-65.626z"
fill="#4f67d2"
/>
<path
d="m349.954 96.504h-276.72c-36.094 0-65.625 29.531-65.625 65.625v185.939c0 36.094 29.531 65.625 65.625 65.625h166.083c7.12 0 12.435 6.626 10.807 13.557-4.404 18.751-11.144 38.581-21.107 58.908-4.474 9.129 5.704 18.41 14.349 13.06 24.997-15.47 60.562-41.362 90.512-77.964 3.937-4.811 9.858-7.561 16.075-7.561 36.094 0 65.625-29.531 65.625-65.625v-185.938c.002-36.094-29.53-65.626-65.624-65.626z"
fill="#60b8fe"
/>
<path
d="m292.624 427.25c1.628-6.932-3.687-13.557-10.807-13.557h-42.5c7.12 0 12.435 6.625 10.807 13.557-4.404 18.751-11.144 38.581-21.107 58.908-4.474 9.129 5.704 18.41 14.349 13.06 9.591-5.936 20.74-13.411 32.527-22.431 7.603-17.049 13.007-33.679 16.731-49.537z"
fill="#23a8fe"
/>
<path
d="m50.109 348.068v-185.938c0-36.094 29.531-65.625 65.625-65.625h-42.5c-36.094 0-65.625 29.531-65.625 65.625v185.938c0 36.094 29.531 65.625 65.625 65.625h42.5c-36.094 0-65.625-29.531-65.625-65.625z"
fill="#23a8fe"
/>
<g fill="#dfebfa">
<circle cx="98.577" cy="260.439" r="21.777" />
<circle cx="168.914" cy="260.439" r="21.777" />
<circle cx="239.251" cy="260.439" r="21.777" />
<circle cx="309.588" cy="260.439" r="21.777" />
</g>
<path
d="m98.577 260.439c0-8.059 4.381-15.091 10.888-18.856-3.204-1.854-6.92-2.921-10.888-2.921-12.027 0-21.777 9.75-21.777 21.777s9.75 21.777 21.777 21.777c3.968 0 7.685-1.066 10.888-2.92-6.507-3.767-10.888-10.798-10.888-18.857z"
fill="#b1dbfc"
/>
<path
d="m168.914 260.439c0-8.059 4.381-15.091 10.888-18.856-3.204-1.854-6.92-2.921-10.888-2.921-12.027 0-21.777 9.75-21.777 21.777s9.75 21.777 21.777 21.777c3.968 0 7.685-1.066 10.888-2.92-6.507-3.767-10.888-10.798-10.888-18.857z"
fill="#b1dbfc"
/>
<path
d="m239.251 260.439c0-8.059 4.381-15.091 10.888-18.856-3.204-1.854-6.921-2.921-10.888-2.921-12.027 0-21.777 9.75-21.777 21.777s9.75 21.777 21.777 21.777c3.968 0 7.685-1.066 10.888-2.92-6.507-3.767-10.888-10.798-10.888-18.857z"
fill="#b1dbfc"
/>
<path
d="m309.588 260.439c0-8.059 4.381-15.091 10.888-18.856-3.204-1.854-6.921-2.921-10.888-2.921-12.027 0-21.777 9.75-21.777 21.777s9.75 21.777 21.777 21.777c3.968 0 7.685-1.066 10.888-2.92-6.507-3.767-10.888-10.798-10.888-18.857z"
fill="#b1dbfc"
/>
<path d="m69.191 260.253c0 16.144 13.134 29.277 29.276 29.277 16.144 0 29.277-13.133 29.277-29.277 0-16.143-13.134-29.276-29.277-29.276-16.142 0-29.276 13.133-29.276 29.276zm43.554 0c0 7.872-6.405 14.277-14.277 14.277s-14.276-6.405-14.276-14.277 6.404-14.276 14.276-14.276 14.277 6.404 14.277 14.276z" />
<path d="m198.082 260.253c0-16.143-13.134-29.276-29.277-29.276s-29.276 13.133-29.276 29.276c0 16.144 13.134 29.277 29.276 29.277 16.143 0 29.277-13.133 29.277-29.277zm-43.554 0c0-7.872 6.404-14.276 14.276-14.276s14.277 6.404 14.277 14.276-6.405 14.277-14.277 14.277-14.276-6.405-14.276-14.277z" />
<path d="m268.419 260.253c0-16.143-13.134-29.276-29.277-29.276s-29.276 13.133-29.276 29.276c0 16.144 13.134 29.277 29.276 29.277 16.143 0 29.277-13.133 29.277-29.277zm-43.554 0c0-7.872 6.404-14.276 14.276-14.276s14.277 6.404 14.277 14.276-6.405 14.277-14.277 14.277-14.276-6.405-14.276-14.277z" />
<path d="m338.756 260.253c0-16.143-13.134-29.276-29.277-29.276s-29.276 13.133-29.276 29.276c0 16.144 13.134 29.277 29.276 29.277 16.143 0 29.277-13.133 29.277-29.277zm-43.554 0c0-7.872 6.404-14.276 14.276-14.276s14.277 6.404 14.277 14.276-6.405 14.277-14.277 14.277-14.276-6.405-14.276-14.277z" />
<path d="m438.874 3.863h-276.72c-40.321 0-73.126 32.804-73.126 73.125v11.83h-15.903c-40.321.001-73.125 32.805-73.125 73.126v185.938c0 40.322 32.804 73.125 73.125 73.125h78.18c4.143 0 7.5-3.358 7.5-7.5s-3.357-7.5-7.5-7.5h-78.18c-32.05 0-58.125-26.075-58.125-58.125v-185.938c0-32.05 26.075-58.125 58.125-58.125h276.721c32.05 0 58.125 26.075 58.125 58.125v185.938c0 32.05-26.075 58.125-58.125 58.125-8.543 0-16.518 3.758-21.881 10.312-29.417 35.95-64.447 61.355-88.653 76.336-2.257 1.393-4.855-.96-3.669-3.382 9.512-19.408 16.805-39.761 21.675-60.494 2.728-11.618-6.129-22.772-18.109-22.772h-52.903c-4.143 0-7.5 3.358-7.5 7.5s3.357 7.5 7.5 7.5h52.903c2.301 0 4.027 2.128 3.506 4.342-4.612 19.638-11.523 38.924-20.541 57.323-7.776 15.872 10.025 32.025 25.032 22.738 25.178-15.583 61.642-42.04 92.368-79.591 2.503-3.058 6.247-4.812 10.272-4.812 40.321 0 73.125-32.804 73.125-73.125v-11.83h15.903c40.322 0 73.126-32.804 73.126-73.125v-75.469c0-4.142-3.357-7.5-7.5-7.5s-7.5 3.358-7.5 7.5v75.469c0 32.05-26.075 58.125-58.126 58.125h-15.903v-159.108c0-40.321-32.804-73.125-73.125-73.125h-245.818v-11.83c0-32.05 26.075-58.125 58.126-58.125h276.72c32.051 0 58.126 26.075 58.126 58.125v75.469c0 4.142 3.357 7.5 7.5 7.5s7.5-3.358 7.5-7.5v-75.469c0-40.322-32.804-73.126-73.126-73.126z" />
</svg>
);
import { Box, forwardRef } from '@chakra-ui/react';
// Here we have used framer-motion package for animations
import { motion, isValidMotionProp } from 'framer-motion';
export const MotionBox = motion(
forwardRef((props, ref) => {
const chakraProps = Object.fromEntries(
Object.entries(props).filter(([key]) => !isValidMotionProp(key))
);
return <Box ref={ref} {...chakraProps} />;
})
);
Posts feed
import { Container, Box } from '@chakra-ui/react';
import { postsData } from './data';
import Card from './card';
const Index = () => {
return (
<Container maxW="4xl" px={{ base: 5, md: 8 }} py={16} mx="auto">
<Box borderRadius="md">
{postsData.map((post, index) => (
<Card
key={post.id}
title={post.title}
username={post.username}
tagList={post.tagList}
readingTime={post.readingTime}
commentsCount={post.commentsCount}
reactionsCount={post.reactionsCount}
postLink={post.postLink}
publishedDate={post.publishedDate}
userProfile={post.userProfile}
headerImage={index === 0 ? post.headerImage : ''}
/>
))}
</Box>
</Container>
);
};
export default Index;
import {
Box,
Heading,
Spacer,
Button,
VStack,
HStack,
Grid,
Text,
Link,
Image,
useColorModeValue
} from '@chakra-ui/react';
// Here we have used react-icons package for the icons
import { BsHeart } from 'react-icons/bs';
import { FaRegComment } from 'react-icons/fa';
interface CardProps {
title: string;
username: string;
userProfile: string;
publishedDate: string;
tagList: string[];
headerImage: string;
postLink: string;
readingTime: number;
reactionsCount: number;
commentsCount: number;
}
function Card({
title,
username,
userProfile,
publishedDate,
tagList,
headerImage,
postLink,
readingTime,
reactionsCount,
commentsCount
}: CardProps) {
return (
<Box
mt="3"
as="article"
bg="white"
borderRadius="md"
overflow="hidden"
border="1px solid #08090a1a"
>
{headerImage ? <Image alt="header image" src={headerImage} /> : ''}
<Grid
templateColumns={{ base: '1fr', sm: 'max-content 1fr' }}
gap={2}
p={4}
bg={useColorModeValue('gray.100', 'gray.800')}
>
<HStack d={{ base: 'flex', sm: 'block' }}>
<Image alt="user profile" src={userProfile} w="8" borderRadius="full" />
<VStack align="flex-start" spacing={0} d={{ base: 'flex', sm: 'none' }}>
<Text color="#4d5760" fontSize="14px" fontWeight="500">
{username}
</Text>
<Text color="#4d5760" fontSize="12px">
{publishedDate}
</Text>
</VStack>
</HStack>
<Box>
<VStack align="flex-start" spacing={0} d={{ base: 'none', sm: 'flex' }}>
<Text color="#4d5760" fontSize="14px" fontWeight="500">
{username}
</Text>
<Text color="#4d5760" fontSize="12px">
{publishedDate}
</Text>
</VStack>
<Heading fontSize={{ base: 'xl', sm: '3xl' }} mt="3">
<Link href={postLink} _hover={{ color: '#323ebe', textDecoration: 'none' }} isExternal>
{title}
</Link>
</Heading>
<HStack mt="3" fontSize="14px" color="#64707d">
{tagList!.map((tag, idx) => (
<Text as={Link} key={idx}>
#{tag}
</Text>
))}
</HStack>
<HStack mt={3}>
<Button
leftIcon={<BsHeart />}
ml={-2}
bg="transparent"
padding="6px 8px"
height="auto"
fontWeight="normal"
fontSize="14px"
lineHeight="1.2"
rounded="md"
_hover={{ bg: useColorModeValue('gray.200', 'gray.600') }}
>
{reactionsCount}
<Box ml="2" as="span" d={{ base: 'none', sm: 'block' }}>
reactions
</Box>
</Button>
<Button
leftIcon={<FaRegComment />}
bg="transparent"
padding="6px 8px"
height="auto"
fontWeight="normal"
fontSize="14px"
lineHeight="1.2"
rounded="md"
_hover={{ bg: useColorModeValue('gray.200', 'gray.600') }}
>
{commentsCount}{' '}
<Box ml="2" as="span" d={{ base: 'none', sm: 'block' }}>
comments
</Box>
</Button>
<Spacer />
<Text fontSize="12px">{readingTime} min read</Text>
<Button
bg={useColorModeValue('gray.200', 'gray.600')}
padding="8px 12px"
height="auto"
fontWeight="normal"
fontSize="14px"
rounded="md"
_hover={{ bg: useColorModeValue('gray.300', 'gray.500') }}
>
Save
</Button>
</HStack>
</Box>
</Grid>
</Box>
);
}
export default Card;
export const postsData = [
{
id: '1',
title: 'Started 2022 by updating portfolio website',
username: 'm_ahmad',
tagList: ['react', 'webdev', 'nextjs', 'showdev'],
readingTime: 1,
commentsCount: 26,
reactionsCount: 100,
postLink: 'https://dev.to/m_ahmad/started-2022-by-updating-portfolio-website-5181',
publishedDate: '31 Jan',
userProfile: 'https://avatars2.githubusercontent.com/u/37842853?v=4',
headerImage:
'https://res.cloudinary.com/practicaldev/image/fetch/s--kldFsj3---/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mgjwkg1hv24ou84eemhn.png'
},
{
id: '2',
title: 'I made changelog page for my portfolio website',
username: 'm_ahmad',
tagList: ['webdev', 'nextjs', 'showdev', 'react'],
readingTime: 1,
commentsCount: 5,
reactionsCount: 10,
postLink: 'https://dev.to/m_ahmad/i-made-changelog-page-for-my-portfolio-website-4jfe',
publishedDate: '31 Jan',
userProfile: 'https://avatars2.githubusercontent.com/u/37842853?v=4',
headerImage:
'https://res.cloudinary.com/practicaldev/image/fetch/s--kldFsj3---/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mgjwkg1hv24ou84eemhn.png'
},
{
id: '3',
title: 'Create professional portfolio website with Nextjs and ChakraUI',
username: 'm_ahmad',
tagList: ['nextjs', 'webdev', 'react', 'beginner'],
readingTime: 1,
commentsCount: 26,
reactionsCount: 300,
postLink: 'https://dev.to/m_ahmad/i-made-changelog-page-for-my-portfolio-website-4jfe',
publishedDate: '31 Jan',
userProfile: 'https://avatars2.githubusercontent.com/u/37842853?v=4',
headerImage:
'https://res.cloudinary.com/practicaldev/image/fetch/s--kldFsj3---/c_imagga_scale,f_auto,fl_progressive,h_420,q_auto,w_1000/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mgjwkg1hv24ou84eemhn.png'
}
];
Posts feed with transparent bg
import React, { Fragment } from 'react';
import {
chakra,
Container,
Box,
HStack,
VStack,
Stack,
Link,
Text,
Icon,
Tag,
Divider,
Avatar,
AvatarGroup,
useColorModeValue
} from '@chakra-ui/react';
// Here we have used react-icons package for the icons
import { GoChevronRight } from 'react-icons/go';
const articles = [
{
id: 1,
tags: ['News'],
title: 'Build a Modern User Interface with Chakra UI',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. simply dummy text...`,
userAvatar:
'https://images.unsplash.com/photo-1606513542745-97629752a13b?ixid=MXwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=334&q=80',
usernames: 'Danilo, Sam, Olivier, and more.',
created_at: 'Wed Apr 06 2022'
},
{
id: 2,
tags: ['Web Development', 'Video'],
title: 'The Complete Guide to Ruby on Rails Encrypted Credentials',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.`,
userAvatar:
'https://images.unsplash.com/photo-1531427186611-ecfd6d936c79?ixlib=rb-1.2.1&q=80&fm=jpg&crop=entropy&cs=tinysrgb&auto=format&fit=crop&w=334&q=80',
usernames: 'Timo Delangle, Olivier, and more.',
created_at: 'Sun Apr 03 2022'
}
];
const Posts = () => {
return (
<Container p={{ base: 5, md: 10 }}>
<chakra.h1 p={4} mb={5} fontSize="3xl" lineHeight={1.2} fontWeight="bold" w="100%">
Posts
</chakra.h1>
<VStack spacing={8} w={{ base: 'auto', md: '2xl' }}>
{articles.map((article, index) => (
<Fragment key={index}>
<Stack direction="column" spacing={4} p={4}>
<HStack spacing={2} mb={1}>
{article.tags.map((cat) => (
<Tag
key={cat}
colorScheme={useColorModeValue('blackAlpha', 'gray')}
borderRadius="full"
>
{cat}
</Tag>
))}
</HStack>
<Box textAlign="left">
<Link
fontSize="xl"
lineHeight={1.2}
fontWeight="bold"
w="100%"
_hover={{ color: 'blue.400', textDecoration: 'underline' }}
>
{article.title}
</Link>
<Text fontSize="md" color="gray.500" noOfLines={2} lineHeight="normal">
{article.content}
</Text>
</Box>
<Box>
<AvatarGroup size="sm" max={3} mb={1}>
<Avatar name="Ryan Florence" src={article.userAvatar} />
<Avatar name="Segun Adebayo" src="https://bit.ly/sage-adebayo" />
<Avatar name="Kent Dodds" src="https://bit.ly/kent-c-dodds" />
</AvatarGroup>
<Stack justifyContent="space-between" direction={{ base: 'column', sm: 'row' }}>
<Box>
<Text fontSize="sm" fontWeight="bold">
{article.usernames}
</Text>
<Text fontSize="sm" color="gray.500">
{article.created_at}
</Text>
</Box>
<HStack
as={Link}
spacing={1}
p={1}
alignItems="center"
height="2rem"
w="max-content"
margin="auto 0"
rounded="md"
color="blue.400"
_hover={{ bg: useColorModeValue('gray.200', 'gray.700') }}
>
<Text fontSize="sm"> Read more</Text>
<Icon as={GoChevronRight} w={4} h={4} />
</HStack>
</Stack>
</Box>
</Stack>
{articles.length - 1 !== index && <Divider />}
</Fragment>
))}
</VStack>
</Container>
);
};
export default Posts;
Blog card with image
import React from 'react';
import { Box, Badge, SimpleGrid, Container, Image, Link, Text } from '@chakra-ui/react';
const dataList = [
{
id: 1,
title: 'Rails ActiveAdmin',
authorName: 'Ali',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.`
},
{
id: 2,
title: 'Rails ActiveAdmin',
authorName: 'Ali',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.`
},
{
id: 3,
title: 'Rails ActiveAdmin',
authorName: 'Ali',
content: `Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.`
}
];
const BlogCards = () => {
return (
<Container maxWidth="1200px" mx="auto" my="auto" p={{ base: 5, md: 10 }}>
<SimpleGrid columns={[1, 2, 3]} spacing="15px">
{dataList.map((blog) => {
return (
<Box position="relative" key={blog.id}>
<Box fontSize="sm" position="absolute" right="5px" margin="5px" zIndex="1">
<Badge rounded="full" p="2px 8px" colorScheme="red" as="button">
Delete
</Badge>
</Box>
<Link to="#">
<Box
borderWidth="1px"
shadow="md"
rounded="lg"
overflow="hidden"
position="relative"
>
<Image src="https://bit.ly/2Z4KKcF" alt="Blog image" />
<Box p={{ base: 4, lg: 6 }}>
<Box d="flex" alignItems="baseline">
<Box
fontWeight="semibold"
as="h2"
letterSpacing="wide"
textTransform="uppercase"
ml="2"
>
{blog.title}
</Box>
</Box>
<Box>
<Box color="gray.600" fontSize="sm">
<Badge rounded="full" px="2" colorScheme="teal">
{blog.authorName}
</Badge>
</Box>
</Box>
<Text
mt="1"
fontWeight="semibold"
noOfLines={3}
lineHeight="tight"
color="gray.600"
fontSize="sm"
>
{blog.content}
</Text>
</Box>
</Box>
</Link>
</Box>
);
})}
</SimpleGrid>
</Container>
);
};
export default BlogCards;