Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/#46 Change Home page design(Homeページのデザインを変更する) #47

Merged
merged 43 commits into from
Dec 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
106a9fe
wip: :construction: change home design
Bear29ers Oct 28, 2023
f7a9b4e
refactor: :bulb: make SocialIcons global
Bear29ers Oct 28, 2023
098f711
config: :gear: add bear keyframes and animations setting
Bear29ers Oct 28, 2023
37894eb
feat: :sparkles: create a bear
Bear29ers Oct 28, 2023
61bded9
style: :art: add shadow to the bear
Bear29ers Oct 28, 2023
87b3449
feat: :sparkles: add the bear to Home
Bear29ers Oct 28, 2023
a22a722
feat: :sparkles: apply animation to the bear
Bear29ers Oct 28, 2023
aa7364c
feat: :sparkles: define usestate and pass it to Bear component
Bear29ers Oct 29, 2023
3b6bc9f
feat: :sparkles: set the bear animation
Bear29ers Oct 29, 2023
06dde25
feat: :sparkles: add dark background div and its animation
Bear29ers Oct 29, 2023
2c4b071
style: :art: also apply dark mode to threads icon
Bear29ers Oct 29, 2023
2e4b0fa
wip: :construction: creating home animation
Bear29ers Dec 10, 2023
aebd346
comments: :bulb: add a TODO comment to tailwind.config
Bear29ers Dec 16, 2023
7c1ca6d
ui: :lipstick: complete Intro component
Bear29ers Dec 16, 2023
dbc95ca
test: :white_check_mark: Update the Intro component test
Bear29ers Dec 16, 2023
2d1a2ef
:fire: rem: delete ProfileCard
Bear29ers Dec 16, 2023
4654da1
:bulb: cmt: add TODO direction comments
Bear29ers Dec 16, 2023
088f6d6
:rotating_light: lint: update eslint config
Bear29ers Dec 17, 2023
5a4d06e
:lipstick: ui: create an Icon component
Bear29ers Dec 17, 2023
3253d70
:white_check_mark: test: create the Icon component storybook
Bear29ers Dec 17, 2023
11d8cbc
:white_check_mark: test: update the Bear component storybook
Bear29ers Dec 17, 2023
45dbf71
:white_check_mark: test: update the SocialIcon component storybook
Bear29ers Dec 17, 2023
6f1ded2
:fire: rem: delete the Tbd component
Bear29ers Dec 17, 2023
4ad4eb0
:white_check_mark: test: update the GithubIcon component test
Bear29ers Dec 17, 2023
847f6e6
:white_check_mark: test: update the InstagramIcon component test
Bear29ers Dec 17, 2023
0f28545
:wrench: conf: update the test template file
Bear29ers Dec 17, 2023
5469e4f
:white_check_mark: test: update the ThreadsIcon component test
Bear29ers Dec 17, 2023
2d00544
:white_check_mark: test: update the FacebookIcon component test
Bear29ers Dec 17, 2023
43872b2
:white_check_mark: test: update some Icons storybook
Bear29ers Dec 17, 2023
d934d6c
:white_check_mark: test: update the Icon component test
Bear29ers Dec 17, 2023
6e505fb
:bulb: cmt: add some TODO comments
Bear29ers Dec 17, 2023
52debfe
:dizzy: anm: add framer motion setting
Bear29ers Dec 17, 2023
dc21eeb
:fire: rem: delete some layout components
Bear29ers Dec 17, 2023
0bfeabc
:wrench: conf: update tailwind.config
Bear29ers Dec 17, 2023
4b25429
:fire: rem: remove PageLayout
Bear29ers Dec 17, 2023
3451f21
:dizzy: anm: add initial animation in home
Bear29ers Dec 17, 2023
62cd22b
:dizzy: anm: add socialicon animation
Bear29ers Dec 17, 2023
588ca39
:bulb: cmt: add TODO comments for page transition
Bear29ers Dec 17, 2023
19a5ea0
:fire: rem: remove unnecessary files
Bear29ers Dec 23, 2023
95106cf
:white_check_mark: test: update the about page test
Bear29ers Dec 23, 2023
f6aff1a
:white_check_mark: test: add data-testid attributes for component test
Bear29ers Dec 23, 2023
023e4c5
:white_check_mark: test: update the Bear component test
Bear29ers Dec 24, 2023
62f8a11
:white_check_mark: test: add the SocialIcons component test
Bear29ers Dec 24, 2023
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
1 change: 1 addition & 0 deletions .eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ const config = {
'react/react-in-jsx-scope': 'off',
'react-hooks/exhaustive-deps': 'warn',
'react/no-unknown-property': ['error', { ignore: ['space'] }],
'react/require-default-props': 'off',
/* import */
'unused-imports/no-unused-imports': 'error',
'import/prefer-default-export': 'off',
Expand Down
2 changes: 1 addition & 1 deletion _templates/generator/components/component.test.ejs.t
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { render } from '@testing-library/react';
import <%= h.changeCase.pascal(component_name) %> from './<%= h.changeCase.pascal(component_name) %>';

describe('src/components/<%= h.changeCase.pascal(component_name) %>/<%= h.changeCase.pascal(component_name) %>.test.tsx', () => {
it('should render <%= h.changeCase.pascal(component_name) %> component', () => {
it('should render the <%= h.changeCase.pascal(component_name) %> component', () => {
const { getByRole } = render(<<%= h.changeCase.pascal(component_name) %> />);
});
});
Binary file modified public/images/memoji.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 4 additions & 6 deletions src/app/about/page.test.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import { render, screen } from '@testing-library/react';
import { render } from '@testing-library/react';

import Page from './page';

describe('src/app/about/page.test.tsx', () => {
it('should render About page with PageLayout and ContentLayout', () => {
render(<Page />);
const layouts = screen.getAllByRole('presentation');
expect(layouts).toHaveLength(2);
layouts.map((layout) => expect(layout).toBeInTheDocument());
it('should render About page with ContentLayout', () => {
const { getByRole } = render(<Page />);
expect(getByRole('presentation')).toBeInTheDocument();
});

it('should render Animated text heading', () => {
Expand Down
15 changes: 6 additions & 9 deletions src/app/about/page.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
import Profile from '@/components/Profile/Profile';
import AnimatedText from '@/components/commons/AnimatedText/AnimatedText';
import ContentsLayout from '@/components/layouts/ContentsLayout/ContentsLayout';
import PageLayout from '@/components/layouts/PageLayout/PageLayout';

import type { NextPage } from 'next';

const About: NextPage = () => {
return (
<PageLayout isNotHome>
<main className="flex-center w-full flex-col" role="main">
<ContentsLayout className="mt-40">
<AnimatedText text="Persistence pays off!" className="mb-16" />
<Profile />
</ContentsLayout>
</main>
</PageLayout>
<main className="flex-center w-full flex-col bg-light" role="main">
<ContentsLayout className="mt-40">
<AnimatedText text="Persistence pays off!" className="mb-16" />
<Profile />
</ContentsLayout>
</main>
);
};

Expand Down
60 changes: 60 additions & 0 deletions src/app/globals.scss
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,66 @@
.trapezoid {
clip-path: polygon(20% 0, 100% 0, 100% 100%, 0% 100%);
}

.bear {
&-body {
&-radius {
border-radius: 50% / 40% 40% 60% 60%;
}
}
&-eyes {
&-transition {
transition: all 0.3s linear;
}
}
&-eye {
&-transition {
transition: all 0.3s ease;
}
}
&-nose {
&-radius {
border-radius: 50% / 60% 60% 30% 30%;
}
&-transition {
transition: 0.4s ease;
}
&-inner {
&-radius {
border-radius: 50% / 40% 40% 60% 60%;
&::after {
content: '';
width: 10px;
height: 10px;
background: #2d120f;
position: absolute;
bottom: -5px;
left: 50%;
border-radius: 50%;
transform: translateX(-50%);
box-shadow: 10px 2.4px 0 #d1a68f, -10px 2.4px 0 #d1a68f;
}
}
}
}
}

.dark-bg {
transition: height 0.5s ease, width 1s ease 0.5s;
}

.intro {
&-dark {
&-bg {
background: linear-gradient(to right, #d2d8d9 50%, #202f55 50%) bottom,
linear-gradient(to right, #d2d8d9 50%, #202f55 50%) top;
background-repeat: no-repeat;
background-size: 100% 4px;
border-right: 4px solid #202f55;
border-left: 4px solid #d2d8d9;
}
}
}
}

.flex-center {
Expand Down
23 changes: 12 additions & 11 deletions src/app/page.test.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
import { render, screen } from '@testing-library/react';
import { render } from '@testing-library/react';
// import mockRouter from 'next-router-mock';
// import { MemoryRouterProvider } from 'next-router-mock/MemoryRouterProvider';

import Page from './page';

describe('src/app/page.test.tsx', () => {
it('should render Home pege with PageLayout and HomeContentsLayout', () => {
render(<Page />);
const layouts = screen.getAllByRole('presentation');
expect(layouts).toHaveLength(2);
layouts.map((layout) => expect(layout).toBeInTheDocument());
});
// it('should render Home pege with PageLayout and HomeContentsLayout', () => {
// render(<Page />);
// const layouts = screen.getAllByRole('presentation');
// expect(layouts).toHaveLength(2);
// layouts.map((layout) => expect(layout).toBeInTheDocument());
// });

it('should render Home page with main role', () => {
const { getByRole } = render(<Page />);
expect(getByRole('main')).toBeInTheDocument();
});

it('should render Home page with a profile image', () => {
const { getByAltText } = render(<Page />);
expect(getByAltText('Bear29ers')).toBeInTheDocument();
});
// TODO:プロフィール画像を入れたあとにコメントアウト
// it('should render Home page with a profile image', () => {
// const { getByAltText } = render(<Page />);
// expect(getByAltText('Bear29ers')).toBeInTheDocument();
// });

// TODO:HOMEページコンテンツを修正後にテスト対応
// it('should render Home page with the animated text', () => {
Expand Down
106 changes: 74 additions & 32 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,83 @@
import ProfileCard from '@/components/ProfileCard/ProfileCard';
import Tbd from '@/components/Tbd/Tbd';
import HomeContentsLayout from '@/components/layouts/HomeContentsLayout/HomeContentsLayout';
import PageLayout from '@/components/layouts/PageLayout/PageLayout';
'use client';

import { HOME_TEXT } from '@/constants/home';
import { useState } from 'react';

import { motion } from 'framer-motion';
import Link from 'next/link';

import Bear from '@/components/Bear/Bear';
import Intro from '@/components/Intro/Intro';
import SocialIcons from '@/components/SocialIcons/SocialIcons';

import type { NextPage } from 'next';

const MotionLink = motion(Link);

const variants = {
default: { x: '0%', y: '0%' },
clicked: { x: '40%', y: '32%' },
};

const Home: NextPage = () => {
const [isClicked, setIsClicked] = useState<boolean>(false);

return (
<div className="bg-iron">
<PageLayout isNotHome={false}>
<main className="flex min-h-screen w-full items-center" role="main">
<HomeContentsLayout>
<div className="flex w-full justify-between gap-x-8">
<div className="w-[38%]">
<ProfileCard />
</div>
<div className="flex w-[62%] flex-col gap-y-8">
<h2 className="text-6xl font-extrabold">{HOME_TEXT.quote}</h2>
<div className="flex h-72 w-full gap-x-8 rounded-2xl">
<div className="h-72 w-9/12 rounded-2xl bg-orange-200">Gallery</div>
<div className="flex h-72 w-3/12 flex-col rounded-2xl bg-yellow-200">
<div className="h-1/2 rounded-t-2xl bg-rose-200">Time</div>
<div className="h-1/2 rounded-b-2xl bg-fuchsia-200">Weather</div>
</div>
</div>
<div className="flex w-full grow gap-x-8 rounded-2xl">
<Tbd width="w-5/12" />
<Tbd width="w-7/12" />
</div>
</div>
</div>
</HomeContentsLayout>
</main>
</PageLayout>
</div>
<main role="main" className="relative h-screen w-screen bg-iron">
{/* Intro */}
<div className="absolute left-1/2 top-1/2 z-10 -translate-x-1/2 -translate-y-1/2">{isClicked && <Intro />}</div>
{/* Dark background */}
<div className={`dark-bg absolute inset-y-0 right-1/2 bg-dark ${isClicked ? 'h-full w-1/2' : 'h-0 w-2'}`} />
{/* Bear */}
<motion.div
className="flex-center absolute inset-0"
animate={isClicked ? 'clicked' : 'default'}
variants={variants}
transition={{
duration: 0.8,
ease: 'easeOut',
}}>
<Bear setIsClicked={setIsClicked} />
</motion.div>
{/* Social Icons */}
<SocialIcons isClicked={isClicked} />
{/* Page Navigation TODO: コンポーネント化したい */}
{/* TODO: AnimatePresenseでtransitionを実装 */}
{/* https://maxschmitt.me/posts/nextjs-page-transitions-framer-motion */}
<motion.div
className="absolute right-0 top-1/2 -translate-y-1/2 rotate-90 text-2xl font-semibold text-dark line-through"
initial={{ x: 200, rotate: 90 }}
animate={{ x: 0, rotate: 90 }}
transition={{ type: 'spring', duration: 1.5, delay: 1.0 }}>
Works
</motion.div>
<div className="absolute bottom-3 flex w-screen justify-around">
<MotionLink
href="/about"
className={`text-2xl font-semibold ${isClicked ? 'text-iron' : 'text-dark'}`}
initial={{ y: 200 }}
animate={{ y: 0, transition: { type: 'spring', duration: 1.5, delay: 1.0 } }}
whileHover={{ scale: 1.1, transition: { type: 'spring', stiffness: 400, damping: 10 } }}
whileTap={{ scale: 0.9, transition: { type: 'spring', stiffness: 400, damping: 10 } }}>
About
</MotionLink>
<motion.div
className="text-2xl font-semibold text-dark line-through"
initial={{ y: 200 }}
animate={{ y: 0 }}
transition={{ type: 'spring', duration: 1.5, delay: 1.0 }}>
Experience
</motion.div>
</div>
<motion.div
className={`absolute left-0 top-1/2 -translate-y-1/2 -rotate-90 text-2xl font-semibold line-through ${
isClicked ? 'text-iron' : 'text-dark'
}`}
initial={{ x: -200, rotate: -90 }}
animate={{ x: 0, rotate: -90 }}
transition={{ type: 'spring', duration: 1.5, delay: 1.0 }}>
Gallery
</motion.div>
</main>
);
};

Expand Down
24 changes: 24 additions & 0 deletions src/components/Bear/Bear.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { useState } from 'react';

import Bear from './Bear';

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

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

export default meta;

type Story = StoryObj<typeof Bear>;

export const Standard: Story = {
render: function Compo() {
const [_, setValue] = useState<boolean>(false);
return (
<div className="relative h-screen w-screen">
<Bear setIsClicked={setValue} />
</div>
);
},
};
54 changes: 54 additions & 0 deletions src/components/Bear/Bear.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import React from 'react';

import { fireEvent, render } from '@testing-library/react';

import Bear from './Bear';

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

describe('src/components/Bear/Bear.test.tsx', () => {
const setIsClickedMock = jest.fn();
let renderResult: RenderResult;

beforeEach(() => {
renderResult = render(<Bear setIsClicked={setIsClickedMock} />);
});

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

it('should render the Bear component with the button element', () => {
expect(renderResult.getByRole('button')).toBeInTheDocument();
});

it('should render the Bear component with the left-ear element', () => {
expect(renderResult.getByTestId('left-ear')).toBeInTheDocument();
});

it('should render the Bear component with the right-ear element', () => {
expect(renderResult.getByTestId('right-ear')).toBeInTheDocument();
});

it('should render the Bear component with the left-eye element', () => {
expect(renderResult.getByTestId('left-eye')).toBeInTheDocument();
});

it('should render the Bear component with the right-eye element', () => {
expect(renderResult.getByTestId('right-eye')).toBeInTheDocument();
});

it('should render the Bear component with the nose element', () => {
expect(renderResult.getByTestId('nose')).toBeInTheDocument();
});

it('should render the Bear component with the shadow element', () => {
expect(renderResult.getByTestId('shadow')).toBeInTheDocument();
});

it('should called props function when the button element clicked', () => {
const buttonElement = renderResult.getByRole('button');
fireEvent.click(buttonElement);
expect(setIsClickedMock).toHaveBeenCalledTimes(1);
});
});
Loading