Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const nextJest = require('next/jest');

const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
});

// Add any custom config to be passed to Jest
const customJestConfig = {
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
testEnvironment: 'jest-environment-jsdom',
moduleNameMapper: {
// Handle module aliases (this will be automatically configured for you soon)
'^@/(.*)$': '<rootDir>/$1',
},
};

// createJestConfig is exported this way to ensure that next/jest can load the Next.js config which is async
module.exports = createJestConfig(customJestConfig);
31 changes: 31 additions & 0 deletions jest.setup.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import '@testing-library/jest-dom';

Object.defineProperty(window, 'matchMedia', {
writable: true,
value: jest.fn().mockImplementation((query) => ({
matches: false,
media: query,
onchange: null,
addListener: jest.fn(), // deprecated
removeListener: jest.fn(), // deprecated
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
dispatchEvent: jest.fn(),
})),
});

class ResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
}

window.ResizeObserver = ResizeObserver;

class IntersectionObserver {
observe() {}
unobserve() {}
disconnect() {}
}

window.IntersectionObserver = IntersectionObserver;
11 changes: 11 additions & 0 deletions lib/ActionToggle/ActionToggle.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { axe, render } from '@/test-utils';
import { ActionToggle } from './ActionToggle';
import attributes from './attributes.json';

describe('ActionToggle', () => {
axe([<ActionToggle key="1" {...(attributes as any)} />]);

it('renders correctly', () => {
render(<ActionToggle {...(attributes as any)} />);
});
});
8 changes: 4 additions & 4 deletions lib/ActionsGrid/ActionsGrid.module.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.card {
background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-6));
background-color: light-dark(var(--mantine-color-gray-0), var(--mantine-color-dark-7));
}

.title {
Expand All @@ -15,13 +15,13 @@
text-align: center;
border-radius: var(--mantine-radius-md);
height: 90px;
background-color: var(--mantine-color-body);
background-color: light-dark(var(--mantine-color-white), var(--mantine-color-dark-6));
transition:
box-shadow 150ms ease,
transform 100ms ease;

@mixin hover {
box-shadow: var(--mantine-shadow-md);
transform: scale(1.05);
box-shadow: var(--mantine-shadow-sm);
transform: scale(1.02);
}
}
10 changes: 10 additions & 0 deletions lib/ActionsGrid/ActionsGrid.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { axe, render } from '@/test-utils';
import { ActionsGrid } from './ActionsGrid';

describe('ActionsGrid', () => {
axe([<ActionsGrid />]);

it('renders correctly', () => {
render(<ActionsGrid />);
});
});
2 changes: 1 addition & 1 deletion lib/ActionsGrid/ActionsGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export function ActionsGrid() {
<Card withBorder radius="md" className={classes.card}>
<Group justify="space-between">
<Text className={classes.title}>Services</Text>
<Anchor size="xs" c="dimmed" style={{ lineHeight: 1 }}>
<Anchor c="inherit" size="xs">
+ 21 other services
</Anchor>
</Group>
Expand Down
14 changes: 13 additions & 1 deletion lib/ArticleCard/ArticleCard.module.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.card {
position: relative;
background-color: var(--mantine-color-body);
overflow: visible;
}

.rating {
Expand All @@ -14,7 +15,18 @@
display: block;
font-family: Outfit, var(--mantine-font-family);
margin-top: var(--mantine-spacing-md);
margin-bottom: 5px;
margin-bottom: 7px;
color: var(--mantine-color-bright);
font-weight: 500;
}

.image {
border-top-left-radius: var(--mantine-radius-md);
border-top-right-radius: var(--mantine-radius-md);
margin-left: -1px;
margin-right: -1px;
margin-top: -1px;
width: calc(100% + 2px);
}

.action {
Expand Down
11 changes: 11 additions & 0 deletions lib/ArticleCard/ArticleCard.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { axe, render } from '@/test-utils';
import { ArticleCard } from './ArticleCard';
import attributes from './attributes.json';

describe('ArticleCard', () => {
axe([<ArticleCard key="1" {...(attributes as any)} />]);

it('renders correctly', () => {
render(<ArticleCard {...(attributes as any)} />);
});
});
99 changes: 53 additions & 46 deletions lib/ArticleCard/ArticleCard.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,73 @@
import { IconBookmark, IconHeart, IconShare } from '@tabler/icons-react';
import {
ActionIcon,
Avatar,
Badge,
Card,
Center,
Group,
Image,
Text,
useMantineTheme,
} from '@mantine/core';
import { IconBookmarkFilled, IconHeartFilled, IconShare2 } from '@tabler/icons-react';
import { ActionIcon, Avatar, Badge, Card, Group, Image, Text } from '@mantine/core';
import classes from './ArticleCard.module.css';

export function ArticleCard() {
const linkProps = { href: 'https://mantine.dev', target: '_blank', rel: 'noopener noreferrer' };
const theme = useMantineTheme();
interface ArticleCardData {
image: string;
title: string;
description: string;
authorName: string;
authorAvatar: string;
rating: string;
link: string;
}

const data: ArticleCardData = {
image: 'https://i.imgur.com/Cij5vdL.png',
title: 'Resident Evil Village review',
description:
'Resident Evil Village is a direct sequel to 2017’s Resident Evil 7, but takes a very different direction to its predecessor, namely the fact that this time round instead of fighting against various mutated zombies, you’re now dealing with more occult enemies like werewolves and vampires.',
authorName: 'Bill Wormeater',
authorAvatar:
'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-1.png',
rating: 'outstanding',
link: 'https://mantine.dev',
};

export function ArticleCard() {
return (
<Card withBorder radius="md" className={classes.card}>
<Card.Section>
<a {...linkProps}>
<Image src="https://i.imgur.com/Cij5vdL.png" height={180} />
</a>
<Card.Section component="a" href={data.link} target="_blank" rel="noreferrer">
<Image src={data.image} height={180} alt={data.title} className={classes.image} />
</Card.Section>

<Badge className={classes.rating} variant="gradient" gradient={{ from: 'yellow', to: 'red' }}>
outstanding
<Badge
className={classes.rating}
variant="gradient"
gradient={{ from: 'indigo', to: 'violet', deg: 145 }}
>
{data.rating}
</Badge>

<Text className={classes.title} fw={500} component="a" {...linkProps}>
Resident Evil Village review
<Text
className={classes.title}
component="a"
href={data.link}
target="_blank"
rel="noreferrer"
>
{data.title}
</Text>

<Text fz="sm" c="dimmed" lineClamp={4}>
Resident Evil Village is a direct sequel to 2017’s Resident Evil 7, but takes a very
different direction to its predecessor, namely the fact that this time round instead of
fighting against various mutated zombies, you’re now dealing with more occult enemies like
werewolves and vampires.
<Text fz="sm" lineClamp={4} opacity={0.9}>
{data.description}
</Text>

<Group justify="space-between" className={classes.footer}>
<Center>
<Avatar
src="https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-1.png"
size={24}
radius="xl"
mr="xs"
/>
<Text fz="sm" inline>
Bill Wormeater
</Text>
</Center>
<Group gap="xs">
<Avatar src={data.authorAvatar} size={24} alt={data.authorName} />
<Text fz="sm">{data.authorName}</Text>
</Group>

<Group gap={8} mr={0}>
<ActionIcon className={classes.action}>
<IconHeart size={16} color={theme.colors.red[6]} />
<Group gap={8}>
<ActionIcon className={classes.action} aria-label="Like">
<IconHeartFilled size={16} color="var(--mantine-color-red-6)" />
</ActionIcon>
<ActionIcon className={classes.action}>
<IconBookmark size={16} color={theme.colors.yellow[7]} />
<ActionIcon className={classes.action} aria-label="Bookmark">
<IconBookmarkFilled size={16} color="var(--mantine-color-yellow-7)" />
</ActionIcon>
<ActionIcon className={classes.action}>
<IconShare size={16} color={theme.colors.blue[6]} />
<ActionIcon className={classes.action} aria-label="Share">
<IconShare2 size={16} color="var(--mantine-color-cyan-6)" />
</ActionIcon>
</Group>
</Group>
Expand Down
2 changes: 2 additions & 0 deletions lib/ArticleCardFooter/ArticleCardFooter.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

.title {
font-family: Outfit, var(--mantine-font-family);
line-height: 1.35;
font-weight: 450;
margin-top: var(--mantine-spacing-xs);
color: var(--mantine-color-bright);
}

.footer {
Expand Down
11 changes: 11 additions & 0 deletions lib/ArticleCardFooter/ArticleCardFooter.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { axe, render } from '@/test-utils';
import { ArticleCardFooter } from './ArticleCardFooter';
import attributes from './attributes.json';

describe('ArticleCardFooter', () => {
axe([<ArticleCardFooter key="1" {...(attributes as any)} />]);

it('renders correctly', () => {
render(<ArticleCardFooter {...(attributes as any)} />);
});
});
72 changes: 47 additions & 25 deletions lib/ArticleCardFooter/ArticleCardFooter.tsx
Original file line number Diff line number Diff line change
@@ -1,48 +1,70 @@
import { IconBookmark, IconHeart, IconShare } from '@tabler/icons-react';
import { IconBookmarkFilled, IconHeartFilled, IconShare2 } from '@tabler/icons-react';
import { ActionIcon, Avatar, Badge, Card, Group, Image, Text } from '@mantine/core';
import classes from './ArticleCardFooter.module.css';

interface ArticleCardFooterData {
category: string;
image: string;
authorName: string;
authorAvatar: string;
link: string;
title: string;
postedTime: string;
description: string;
footer: string;
}

const data: ArticleCardFooterData = {
category: 'Decorations',
image:
'https://images.unsplash.com/photo-1483794344563-d27a8d18014e?ixlib=rb-4.1.0&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&q=80&w=500',
authorName: 'Elsa Gardenowl',
authorAvatar:
'https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-7.png',
link: 'https://mantine.dev',
title: 'Top 50 underrated plants for house decoration',
postedTime: 'posted 34 minutes ago',
description:
'Discover the best-kept secrets of home decor with our curated list of 50 underrated plants that will transform your living space into a green oasis.',
footer: '733 people liked this',
};

export function ArticleCardFooter() {
return (
<Card withBorder padding="lg" radius="md" className={classes.card}>
<Card.Section mb="sm">
<Image
src="https://images.unsplash.com/photo-1477554193778-9562c28588c0?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=500&q=80"
alt="Top 50 underrated plants for house decoration"
height={180}
/>
<Card.Section mb="lg">
<Image src={data.image} alt={data.title} height={180} />
</Card.Section>

<Badge variant="light">decorations</Badge>
<Text className={classes.title}>Top 50 underrated plants for house decoration</Text>
<Badge color="violet" variant="outline">
{data.category}
</Badge>

<Text className={classes.title}>{data.title}</Text>

<Group mt="lg">
<Avatar
src="https://raw.githubusercontent.com/mantinedev/mantine/master/.demo/avatars/avatar-7.png"
radius="sm"
/>
<Avatar src={data.authorAvatar} radius="sm" alt={data.authorName} />

<div>
<Text fw={500}>Elsa Gardenowl</Text>
<Text fz="xs" c="dimmed">
posted 34 minutes ago
<Text c="bright" fw={500}>
{data.authorName}
</Text>
<Text size="xs">{data.postedTime}</Text>
</div>
</Group>

<Card.Section className={classes.footer}>
<Group justify="space-between">
<Text fz="xs" c="dimmed">
733 people liked this
</Text>
<Text size="xs">{data.footer}</Text>
<Group gap={0}>
<ActionIcon variant="subtle" color="gray">
<IconHeart size={20} color="var(--mantine-color-red-6)" stroke={1.5} />
<ActionIcon variant="subtle" color="gray" aria-label="Like">
<IconHeartFilled size={20} color="var(--mantine-color-red-6)" />
</ActionIcon>
<ActionIcon variant="subtle" color="gray">
<IconBookmark size={20} color="var(--mantine-color-yellow-6)" stroke={1.5} />
<ActionIcon variant="subtle" color="gray" aria-label="Bookmark">
<IconBookmarkFilled size={20} color="var(--mantine-color-yellow-7)" />
</ActionIcon>
<ActionIcon variant="subtle" color="gray">
<IconShare size={20} color="var(--mantine-color-blue-6)" stroke={1.5} />
<ActionIcon variant="subtle" color="gray" aria-label="Share">
<IconShare2 size={20} color="var(--mantine-color-cyan-6)" />
</ActionIcon>
</Group>
</Group>
Expand Down
1 change: 0 additions & 1 deletion lib/ArticleCardImage/ArticleCardImage.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
align-items: flex-start;
background-size: cover;
background-position: center;
background-image: url(https://images.unsplash.com/photo-1508193638397-1c4234db14d8?ixlib=rb-1.2.1&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=crop&w=400&q=80);
}

.title {
Expand Down
Loading