Skip to content

Commit

Permalink
Merge pull request #71 from Bear29ers/feature/#70_cursor_effect
Browse files Browse the repository at this point in the history
Feature/#70 cursor effect(カーソルエフェクトを実装する)
  • Loading branch information
Bear29ers authored Apr 20, 2024
2 parents 904591f + f68a28d commit 3493fa7
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { ReactNode } from 'react';

import { Montserrat } from 'next/font/google';

import Cursor from '@/components/Cursor/Cursor';
import PageAnimatePresence from '@/components/HOC/PageAnimatePresence/PageAnimatePresence';
import Menu from '@/components/Menu/Menu';

Expand Down Expand Up @@ -30,6 +31,7 @@ const RootLayout = ({
<body className={`${montserrat.variable} relative size-full font-mont`}>
<Menu />
<PageAnimatePresence>{children}</PageAnimatePresence>
<Cursor />
</body>
</html>
);
Expand Down
15 changes: 15 additions & 0 deletions src/components/Cursor/Cursor.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Cursor from './Cursor';

import type { Meta, StoryObj } from '@storybook/react';

const meta: Meta<typeof Cursor> = {
component: Cursor,
};

export default meta;

type Story = StoryObj<typeof Cursor>;

export const Default: Story = {
render: () => <Cursor />,
};
44 changes: 44 additions & 0 deletions src/components/Cursor/Cursor.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { screen, render, fireEvent, waitFor } from '@testing-library/react';
import '@testing-library/jest-dom';

import Cursor from './Cursor';

import type { RenderResult } from '@testing-library/react';

describe('src/components/Cursor/Cursor.test.tsx', () => {
let renderResult: RenderResult;

beforeEach(() => {
renderResult = render(<Cursor />);
});

afterEach(() => {
renderResult.unmount();
});

it('should render the Cursor component without crashing', () => {
const cursorElement = screen.getByTestId('cursor');
expect(cursorElement).toBeInTheDocument();
});

it('should render the Cursor component with mouse movement', async () => {
const cursorElement = screen.getByTestId('cursor');
const initialPosition = {
x: cursorElement.style.left,
y: cursorElement.style.top,
};

fireEvent.mouseMove(document, {
clientX: 100,
clinetY: 200,
});

await waitFor(() => {
expect(cursorElement.style.left).not.toBe(initialPosition.x);
});

await waitFor(() => {
expect(cursorElement.style.top).not.toBe(initialPosition.y);
});
});
});
43 changes: 43 additions & 0 deletions src/components/Cursor/Cursor.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
'use client';

import { useEffect, type FC } from 'react';

import { useMotionValue, useSpring, motion } from 'framer-motion';

const Cursor: FC = () => {
const cursorSize = 15;

const mouse = {
x: useMotionValue(0),
y: useMotionValue(0),
};

const smoothOptions = { damping: 20, stiffness: 300, mass: 0.5 };
const smoothMouse = {
x: useSpring(mouse.x, smoothOptions),
y: useSpring(mouse.y, smoothOptions),
};

const manageMouseMove = (e: MouseEvent) => {
const { clientX, clientY } = e;
mouse.x.set(clientX - cursorSize / 2);
mouse.y.set(clientY - cursorSize / 2);
};

useEffect(() => {
window.addEventListener('mousemove', manageMouseMove);
return () => {
window.removeEventListener('mousemove', manageMouseMove);
};
}, []);

return (
<motion.div
style={{ left: smoothMouse.x, top: smoothMouse.y }}
className="pointer-events-none fixed z-50 size-4 rounded-full bg-dark"
data-testid="cursor"
/>
);
};

export default Cursor;

0 comments on commit 3493fa7

Please sign in to comment.