├── src ├── components │ ├── Menu │ │ ├── index.ts │ │ ├── MenuItem.tsx │ │ └── Menu.tsx │ ├── Modal │ │ └── index.ts │ ├── Canvas │ │ ├── Wavy │ │ │ ├── index.ts │ │ │ ├── Point.ts │ │ │ ├── WaveGroup.ts │ │ │ ├── Wavy.tsx │ │ │ └── Wave.ts │ │ ├── MovingBox │ │ │ ├── index.ts │ │ │ ├── Point.ts │ │ │ └── Dialog.ts │ │ ├── BouncingBall │ │ │ ├── index.ts │ │ │ ├── Block.ts │ │ │ ├── BouncingBall.tsx │ │ │ └── Ball.ts │ │ ├── MovingGradation │ │ │ ├── index.ts │ │ │ ├── constants.ts │ │ │ ├── GlowParticle.ts │ │ │ └── MovingGradation.tsx │ │ ├── RotatingPolygon │ │ │ ├── index.ts │ │ │ ├── Polygon.ts │ │ │ └── RotatingPolygon.tsx │ │ └── index.ts │ ├── Portal │ │ ├── index.ts │ │ └── Portal.tsx │ ├── Accordion │ │ ├── index.ts │ │ └── Accordion.tsx │ ├── Drag │ │ ├── index.ts │ │ └── DragItemList.tsx │ ├── Dropdown │ │ └── index.ts │ ├── GhostText │ │ ├── index.ts │ │ └── GhostText.tsx │ ├── MiniWavy │ │ ├── index.ts │ │ └── MiniWavy.tsx │ ├── MoveSheep │ │ ├── index.ts │ │ ├── SheepController.ts │ │ ├── MoveSheep.tsx │ │ ├── Sun.ts │ │ └── Hill.ts │ ├── MovingText │ │ ├── index.ts │ │ └── MovingText.tsx │ ├── NeonButton │ │ ├── index.ts │ │ └── NeonButton.tsx │ ├── RangeInput │ │ ├── index.ts │ │ └── RangeInput.tsx │ ├── TextArea │ │ ├── index.ts │ │ └── TextArea.tsx │ ├── TextTyping │ │ ├── index.ts │ │ └── TextTyping.tsx │ ├── Timeline │ │ └── index.ts │ ├── ClimbEffects │ │ ├── index.ts │ │ ├── README.md │ │ └── ClimbEffects.tsx │ ├── GlowingRadio │ │ ├── index.ts │ │ └── GlowingRadio.tsx │ ├── GlowingText │ │ ├── index.ts │ │ ├── README.md │ │ └── GlowingText.tsx │ ├── MouseCursor │ │ ├── index.ts │ │ └── DotMouseCursor.tsx │ ├── SidebarMenu │ │ └── index.ts │ ├── WavySection │ │ ├── index.ts │ │ └── WavySection.tsx │ ├── ClipPathCircle │ │ ├── index.ts │ │ └── ClipPathCircle.tsx │ ├── CustomScrollbar │ │ └── index.ts │ ├── FakeScrollSpy │ │ ├── index.ts │ │ └── FakeScrollSpy.tsx │ ├── GlowingCheckbox │ │ ├── index.ts │ │ └── GlowingCheckbox.tsx │ ├── HeartAnimation │ │ ├── index.ts │ │ └── HeartAnimation.tsx │ ├── HoverEffectCard │ │ └── index.ts │ ├── LongTextShadow │ │ ├── index.ts │ │ └── LongTextShadow.tsx │ ├── NumberCounter │ │ ├── index.ts │ │ └── NumberCounter.tsx │ ├── PasswordInput │ │ ├── index.ts │ │ └── PasswordInput.tsx │ ├── ShadowEffects │ │ ├── index.ts │ │ └── ShadowEffects.tsx │ ├── WaveBorderCard │ │ ├── index.ts │ │ └── WaveBorderCard.tsx │ ├── GlowingBackground │ │ ├── index.ts │ │ └── GlowingBackground.tsx │ ├── ListHoverEffects │ │ ├── index.ts │ │ └── ListHoverEffects.tsx │ ├── ScrollProgressBar │ │ └── index.ts │ ├── RippleEffectsButton │ │ ├── index.ts │ │ └── RippleEffectsButton.tsx │ ├── ScrollDownIndicator │ │ └── index.ts │ ├── SlidingMenuIndicator │ │ ├── index.ts │ │ └── SlidingMenuIndicator.tsx │ ├── Banners │ │ ├── index.ts │ │ ├── type.ts │ │ └── Banners.tsx │ ├── HalfCircularBackground │ │ └── index.ts │ ├── HideScrollOnScrollDown │ │ └── index.ts │ ├── Skeleton │ │ ├── index.ts │ │ ├── Skeleton2.tsx │ │ └── Skeleton.tsx │ ├── ThreeDimensionBackground │ │ ├── index.ts │ │ └── ThreeDimensionBackground.tsx │ ├── ThreeDimensionDebitCard │ │ └── index.ts │ ├── Tooltip │ │ ├── index.ts │ │ └── Tooltip.tsx │ ├── AnimatedEyesFollowMouseCursor │ │ ├── index.ts │ │ └── AnimatedEyesFollowMouseCursor.tsx │ ├── StickyElementsScrollingEffects │ │ └── index.ts │ ├── Loader │ │ ├── index.ts │ │ ├── Loader.tsx │ │ ├── GradientLoader.tsx │ │ └── TwoRingLoader.tsx │ ├── WebGlAndThreeJS │ │ ├── index.ts │ │ ├── BasicScene.tsx │ │ ├── BasicScene2.tsx │ │ └── BasicScene3.tsx │ └── index.ts ├── react-app-env.d.ts ├── utils │ ├── index.ts │ ├── DomUtils.ts │ ├── RefUtils.ts │ └── WebGLUtils.ts ├── assets │ ├── sheep.png │ └── profile-with-circle.jpg ├── index.tsx ├── App.tsx ├── stories │ ├── SidebarMenu.stories.tsx │ ├── WavySection.stories.tsx │ ├── CustomScrollbar.stories.tsx │ ├── FakeScrollSpy.stories.tsx │ ├── ClipPathCircle.stories.tsx │ ├── ThreeDimensionBackground.stories.tsx │ ├── ScrollDownIndicator.stories.tsx │ ├── HideScrollOnScrollDown.stories.tsx │ ├── ScrollProgressBar.stories.tsx │ ├── StickyElementsScrollingEffects.stories.tsx │ ├── Modal.stories.tsx │ ├── canvasTutorial │ │ ├── Wavy.stories.tsx │ │ ├── BouncingBall.stories.tsx │ │ ├── MovingGradation.stories.tsx │ │ ├── MoveSheep.stories.tsx │ │ ├── MovingBox.stories.tsx │ │ ├── Readme.stories.mdx │ │ └── RotatingPolygon.stories.tsx │ ├── Accordion.stories.tsx │ ├── DropDown.stories.tsx │ ├── MiniWavy.stories.tsx │ ├── ListHoverEffects.stories.tsx │ ├── SlidingMenuIndicator.stories.tsx │ ├── MouseCursor.stories.tsx │ ├── GhostText.stories.tsx │ ├── HeartAnimation.stories.tsx │ ├── WaveBorderCard.stories.tsx │ ├── TextTyping.stories.tsx │ ├── MovingText.stories.tsx │ ├── NeonButton.stories.tsx │ ├── RangeInput.stories.tsx │ ├── RippleEffectsButton.stories.tsx │ ├── ShadowEffects.stories.tsx │ ├── LongBoxShadow.stories.tsx │ ├── TextArea.stories.tsx │ ├── HalfCircularBackground.stories.tsx │ ├── Timeline.stories.tsx │ ├── ClimbEffects.stories.tsx │ ├── HoverEffectCard.stories.tsx │ ├── NumberCounter.stories.tsx │ ├── PasswordInput.stories.tsx │ ├── Banners.stories.tsx │ ├── ThreeDimensionDebitCard.stories.tsx │ ├── GlowingText.stories.tsx │ ├── AnimatedEyesFollowMouseCursor.stories.tsx │ ├── Skeleton.stories.tsx │ ├── Menu.stories.tsx │ ├── assets │ │ ├── direction.svg │ │ ├── flow.svg │ │ ├── code-brackets.svg │ │ ├── comments.svg │ │ ├── repo.svg │ │ ├── plugin.svg │ │ └── stackalt.svg │ ├── GlowingBackground.stories.tsx │ ├── Loader.stories.tsx │ ├── Tooltip.stories.tsx │ ├── dummy │ │ └── dummyData.js │ ├── threejs │ │ └── BasicScene.stories.tsx │ └── GlowingCheckbox.stories.tsx ├── index.css ├── hooks │ └── useScreenSize.ts └── logo.svg ├── public ├── favicon.ico ├── logo192.png ├── logo512.png ├── robots.txt ├── manifest.json └── index.html ├── .prettierrc ├── .storybook ├── preview-head.html ├── preview.js └── main.js ├── .gitignore ├── tsconfig.json ├── LICENSE ├── README.md └── package.json /src/components/Menu/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Menu'; 2 | -------------------------------------------------------------------------------- /src/components/Modal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Modal'; 2 | -------------------------------------------------------------------------------- /src/components/Canvas/Wavy/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Wavy'; 2 | -------------------------------------------------------------------------------- /src/components/Portal/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Portal'; 2 | -------------------------------------------------------------------------------- /src/components/Accordion/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Accordion'; 2 | -------------------------------------------------------------------------------- /src/components/Drag/index.ts: -------------------------------------------------------------------------------- 1 | export * from './DragItemList'; 2 | -------------------------------------------------------------------------------- /src/components/Dropdown/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Dropdown'; 2 | -------------------------------------------------------------------------------- /src/components/GhostText/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GhostText'; 2 | -------------------------------------------------------------------------------- /src/components/MiniWavy/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MiniWavy'; 2 | -------------------------------------------------------------------------------- /src/components/MoveSheep/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MoveSheep'; 2 | -------------------------------------------------------------------------------- /src/components/MovingText/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MovingText'; 2 | -------------------------------------------------------------------------------- /src/components/NeonButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './NeonButton'; 2 | -------------------------------------------------------------------------------- /src/components/RangeInput/index.ts: -------------------------------------------------------------------------------- 1 | export * from './RangeInput'; 2 | -------------------------------------------------------------------------------- /src/components/TextArea/index.ts: -------------------------------------------------------------------------------- 1 | export * from './TextArea'; 2 | -------------------------------------------------------------------------------- /src/components/TextTyping/index.ts: -------------------------------------------------------------------------------- 1 | export * from './TextTyping'; 2 | -------------------------------------------------------------------------------- /src/components/Timeline/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Timeline'; 2 | -------------------------------------------------------------------------------- /src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /src/components/Canvas/MovingBox/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MovingBox'; 2 | -------------------------------------------------------------------------------- /src/components/ClimbEffects/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ClimbEffects'; 2 | -------------------------------------------------------------------------------- /src/components/GlowingRadio/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GlowingRadio'; 2 | -------------------------------------------------------------------------------- /src/components/GlowingText/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GlowingText'; 2 | -------------------------------------------------------------------------------- /src/components/MouseCursor/index.ts: -------------------------------------------------------------------------------- 1 | export * from './DotMouseCursor'; 2 | -------------------------------------------------------------------------------- /src/components/SidebarMenu/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SidebarMenu'; 2 | -------------------------------------------------------------------------------- /src/components/WavySection/index.ts: -------------------------------------------------------------------------------- 1 | export * from './WavySection'; 2 | -------------------------------------------------------------------------------- /src/components/ClipPathCircle/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ClipPathCircle'; 2 | -------------------------------------------------------------------------------- /src/components/CustomScrollbar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './CustomScrollbar'; 2 | -------------------------------------------------------------------------------- /src/components/FakeScrollSpy/index.ts: -------------------------------------------------------------------------------- 1 | export * from './FakeScrollSpy'; 2 | -------------------------------------------------------------------------------- /src/components/GlowingCheckbox/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GlowingCheckbox'; 2 | -------------------------------------------------------------------------------- /src/components/HeartAnimation/index.ts: -------------------------------------------------------------------------------- 1 | export * from './HeartAnimation'; 2 | -------------------------------------------------------------------------------- /src/components/HoverEffectCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './HoverEffectCard'; 2 | -------------------------------------------------------------------------------- /src/components/LongTextShadow/index.ts: -------------------------------------------------------------------------------- 1 | export * from './LongTextShadow'; 2 | -------------------------------------------------------------------------------- /src/components/NumberCounter/index.ts: -------------------------------------------------------------------------------- 1 | export * from './NumberCounter'; 2 | -------------------------------------------------------------------------------- /src/components/PasswordInput/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PasswordInput'; 2 | -------------------------------------------------------------------------------- /src/components/ShadowEffects/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ShadowEffects'; 2 | -------------------------------------------------------------------------------- /src/components/WaveBorderCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './WaveBorderCard'; 2 | -------------------------------------------------------------------------------- /src/components/Canvas/BouncingBall/index.ts: -------------------------------------------------------------------------------- 1 | export * from './BouncingBall'; 2 | -------------------------------------------------------------------------------- /src/components/GlowingBackground/index.ts: -------------------------------------------------------------------------------- 1 | export * from './GlowingBackground'; 2 | -------------------------------------------------------------------------------- /src/components/ListHoverEffects/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ListHoverEffects'; 2 | -------------------------------------------------------------------------------- /src/components/ScrollProgressBar/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ScrollProgressBar'; 2 | -------------------------------------------------------------------------------- /src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './RefUtils'; 2 | export * from './DomUtils'; 3 | -------------------------------------------------------------------------------- /src/components/Canvas/MovingGradation/index.ts: -------------------------------------------------------------------------------- 1 | export * from './MovingGradation'; 2 | -------------------------------------------------------------------------------- /src/components/Canvas/RotatingPolygon/index.ts: -------------------------------------------------------------------------------- 1 | export * from './RotatingPolygon'; 2 | -------------------------------------------------------------------------------- /src/components/RippleEffectsButton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './RippleEffectsButton'; 2 | -------------------------------------------------------------------------------- /src/components/ScrollDownIndicator/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ScrollDownIndicator'; 2 | -------------------------------------------------------------------------------- /src/components/SlidingMenuIndicator/index.ts: -------------------------------------------------------------------------------- 1 | export * from './SlidingMenuIndicator'; 2 | -------------------------------------------------------------------------------- /src/components/Banners/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Banners'; 2 | export * from './type'; 3 | -------------------------------------------------------------------------------- /src/components/HalfCircularBackground/index.ts: -------------------------------------------------------------------------------- 1 | export * from './HalfCircularBackground'; 2 | -------------------------------------------------------------------------------- /src/components/HideScrollOnScrollDown/index.ts: -------------------------------------------------------------------------------- 1 | export * from './HideScrollOnScrollDown'; 2 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JungKyuHyun/css-collection/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JungKyuHyun/css-collection/HEAD/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JungKyuHyun/css-collection/HEAD/public/logo512.png -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/components/Banners/type.ts: -------------------------------------------------------------------------------- 1 | export enum BannerTypes { 2 | Animated1 = 'Animated1', 3 | } 4 | -------------------------------------------------------------------------------- /src/components/Skeleton/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Skeleton'; 2 | export * from './Skeleton2'; 3 | -------------------------------------------------------------------------------- /src/components/ThreeDimensionBackground/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ThreeDimensionBackground'; 2 | -------------------------------------------------------------------------------- /src/components/ThreeDimensionDebitCard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ThreeDimensionDebitCard'; 2 | -------------------------------------------------------------------------------- /src/assets/sheep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JungKyuHyun/css-collection/HEAD/src/assets/sheep.png -------------------------------------------------------------------------------- /src/components/Tooltip/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Tooltip'; 2 | export * from './TooltipWithPortal'; 3 | -------------------------------------------------------------------------------- /src/components/AnimatedEyesFollowMouseCursor/index.ts: -------------------------------------------------------------------------------- 1 | export * from './AnimatedEyesFollowMouseCursor'; 2 | -------------------------------------------------------------------------------- /src/components/StickyElementsScrollingEffects/index.ts: -------------------------------------------------------------------------------- 1 | export * from './StickyElementsScrollingEffects'; 2 | -------------------------------------------------------------------------------- /src/assets/profile-with-circle.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JungKyuHyun/css-collection/HEAD/src/assets/profile-with-circle.jpg -------------------------------------------------------------------------------- /src/utils/DomUtils.ts: -------------------------------------------------------------------------------- 1 | export class DomUtils { 2 | static usableWindow() { 3 | return typeof window !== undefined; 4 | } 5 | } -------------------------------------------------------------------------------- /src/components/Loader/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Loader'; 2 | export * from './TwoRingLoader'; 3 | export * from './GradientLoader'; 4 | -------------------------------------------------------------------------------- /src/components/WebGlAndThreeJS/index.ts: -------------------------------------------------------------------------------- 1 | export * from './BasicScene'; 2 | export * from './BasicScene2'; 3 | export * from './BasicScene3'; 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "semi": true, 4 | "useTabs": false, 5 | "tabWidth": 2, 6 | "trailingComma": "es5", 7 | "printWidth": 120 8 | } 9 | -------------------------------------------------------------------------------- /src/components/ClimbEffects/README.md: -------------------------------------------------------------------------------- 1 | ### `ClimbEffects` 2 | 3 | ![ClimbEffects](https://user-images.githubusercontent.com/42884032/103213269-82774d00-4950-11eb-8c61-386b43d9094f.gif) 4 | -------------------------------------------------------------------------------- /src/components/GlowingText/README.md: -------------------------------------------------------------------------------- 1 | ### `Glowing Text` 2 | 3 | ![glowing-text](https://user-images.githubusercontent.com/42884032/103140359-02bb6980-4729-11eb-97d9-47c57d91ffa8.gif) 4 | -------------------------------------------------------------------------------- /src/components/Canvas/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Wavy'; 2 | export * from './RotatingPolygon'; 3 | export * from './BouncingBall'; 4 | export * from './MovingGradation'; 5 | export * from './MovingBox'; 6 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | import './index.css'; 4 | import App from './App'; 5 | 6 | ReactDOM.render( 7 | 8 | 9 | , 10 | document.getElementById('root') 11 | ); 12 | -------------------------------------------------------------------------------- /src/utils/RefUtils.ts: -------------------------------------------------------------------------------- 1 | export class RefUtils { 2 | 3 | static notNull(ref: React.RefObject | null): ref is React.RefObject { 4 | if(ref === null || ref.current === null || ref.current === undefined) { 5 | return false; 6 | } 7 | 8 | return true; 9 | } 10 | } -------------------------------------------------------------------------------- /.storybook/preview-head.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 12 | Jacob Css 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | .eslintcache 26 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | function App() { 5 | return ; 6 | } 7 | 8 | const LayoutContainer = styled.div` 9 | display: flex; 10 | flex-direction: column; 11 | justify-content: center; 12 | align-items: center; 13 | background-color: black; 14 | height: 100vh; 15 | overflow: hidden; 16 | `; 17 | 18 | export default memo(App); 19 | -------------------------------------------------------------------------------- /src/components/Canvas/Wavy/Point.ts: -------------------------------------------------------------------------------- 1 | export class Point { 2 | x; 3 | y; 4 | fixedY; 5 | speed = 0.01; 6 | cur; 7 | 8 | // 얼마나 움직일 것인가에 대한 프로퍼티 9 | max = Math.random() * 100 + 150; 10 | 11 | constructor(index: number, x: number, y: number) { 12 | this.x = x; 13 | this.y = y; 14 | this.fixedY = y; 15 | this.cur = index; 16 | } 17 | 18 | update() { 19 | this.cur += this.speed; 20 | this.y = this.fixedY + Math.sin(this.cur) * this.max; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/stories/SidebarMenu.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { SidebarMenu } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/SidebarMenu', 7 | component: SidebarMenu, 8 | parameters: { 9 | docs: { 10 | description: { component: '좌측 사이드바 컴포넌트입니다.' }, 11 | }, 12 | }, 13 | } as Meta; 14 | 15 | const Template: Story = (args) => ; 16 | 17 | export const BasicCss = Template.bind({}); 18 | -------------------------------------------------------------------------------- /src/stories/WavySection.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { WavySection } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/WavySection', 7 | component: WavySection, 8 | parameters: { 9 | docs: { 10 | description: { component: '물결 표시 애니메이션을 구현합니다.' }, 11 | }, 12 | }, 13 | } as Meta; 14 | 15 | const Template: Story = (args) => ; 16 | 17 | export const BasicCss = Template.bind({}); 18 | -------------------------------------------------------------------------------- /src/stories/CustomScrollbar.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { CustomScrollbar } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/CustomScrollbar', 7 | component: CustomScrollbar, 8 | parameters: { 9 | docs: { 10 | description: { component: '스크롤을 커스텀하였습니다.' }, 11 | }, 12 | }, 13 | } as Meta; 14 | 15 | const Template: Story = (args) => ; 16 | 17 | export const BasicCss = Template.bind({}); 18 | -------------------------------------------------------------------------------- /src/stories/FakeScrollSpy.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { FakeScrollSpy } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/FakeScrollSpy', 7 | component: FakeScrollSpy, 8 | parameters: { 9 | docs: { 10 | description: { component: '페이지 후버에 따라 네비게이션이 변합니다.' }, 11 | }, 12 | }, 13 | } as Meta; 14 | 15 | const Template: Story = (args) => ; 16 | 17 | export const BasicCss = Template.bind({}); 18 | -------------------------------------------------------------------------------- /.storybook/preview.js: -------------------------------------------------------------------------------- 1 | export const parameters = { 2 | actions: { argTypesRegex: '^on[A-Z].*' }, 3 | controls: { disable: true }, 4 | layout: 'fullscreen', 5 | backgrounds: { 6 | default: 'dark', 7 | values: [ 8 | { name: 'dark', value: 'black' }, 9 | { name: 'white', value: 'white' }, 10 | { name: 'dimgray', value: 'dimgray' }, 11 | { name: 'ghostwhite', value: 'ghostwhite' }, 12 | { name: 'whitesmoke', value: 'whitesmoke' }, 13 | ], 14 | }, 15 | options: { showPanel: false }, 16 | }; 17 | -------------------------------------------------------------------------------- /src/components/Banners/Banners.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import { AnimatedBanner1 } from './AnimatedBanner1'; 3 | import { BannerTypes } from './type'; 4 | 5 | const BANNERS_LOOKUP_TABLE = { 6 | [BannerTypes.Animated1]: AnimatedBanner1, 7 | }; 8 | 9 | export interface BannersProps { 10 | type?: BannerTypes; 11 | } 12 | 13 | export const Banners = memo(({ type }) => { 14 | if (type === undefined) { 15 | return null; 16 | } 17 | return React.createElement(BANNERS_LOOKUP_TABLE[type]); 18 | }); 19 | -------------------------------------------------------------------------------- /src/stories/ClipPathCircle.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { ClipPathCircle } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/ClipPathCircle', 7 | component: ClipPathCircle, 8 | parameters: { 9 | docs: { 10 | description: { component: 'clip-path을 이용한 scroll text 애니메이션' }, 11 | }, 12 | }, 13 | } as Meta; 14 | 15 | const Template: Story = (args) => ; 16 | 17 | export const BasicCss = Template.bind({}); 18 | -------------------------------------------------------------------------------- /src/stories/ThreeDimensionBackground.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { ThreeDimensionBackground } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/ThreeDimensionBackground', 7 | component: ThreeDimensionBackground, 8 | parameters: { 9 | docs: { 10 | description: { component: '3차원 배경을 제공합니다.' }, 11 | }, 12 | }, 13 | } as Meta; 14 | 15 | const Template: Story = (args) => ; 16 | 17 | export const BasicCss = Template.bind({}); 18 | -------------------------------------------------------------------------------- /src/stories/ScrollDownIndicator.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { ScrollDownIndicator } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/ScrollDownIndicator', 7 | component: ScrollDownIndicator, 8 | parameters: { 9 | docs: { 10 | description: { 11 | component: '화면 아래로 스크롤을 유도하는 표시자입니다.', 12 | }, 13 | }, 14 | }, 15 | } as Meta; 16 | 17 | const Template: Story = (args) => ; 18 | 19 | export const BasicCss = Template.bind({}); 20 | -------------------------------------------------------------------------------- /src/components/Canvas/MovingGradation/constants.ts: -------------------------------------------------------------------------------- 1 | export type RGB_TYPE = { r: number; g: number; b: number }; 2 | 3 | const COLORS: ReadonlyArray = [ 4 | { r: 45, g: 74, b: 227 }, // blue 5 | { r: 250, g: 255, b: 89 }, // yellow 6 | { r: 255, g: 104, b: 248 }, // pupple 7 | { r: 44, g: 209, b: 252 }, // skyblue 8 | { r: 54, g: 233, b: 84 }, // green 9 | ]; 10 | 11 | const TOTAL_PARTICLES = 15; 12 | 13 | const MAX_RADIUS = 900; 14 | 15 | const MIN_RADIUS = 400; 16 | 17 | const PI2 = Math.PI * 2; 18 | 19 | export { COLORS, TOTAL_PARTICLES, MAX_RADIUS, MIN_RADIUS, PI2 }; 20 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "preserve" 18 | }, 19 | "include": ["src"] 20 | } 21 | -------------------------------------------------------------------------------- /src/stories/HideScrollOnScrollDown.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { HideScrollOnScrollDown } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/HideScrollOnScrollDown', 7 | component: HideScrollOnScrollDown, 8 | parameters: { 9 | docs: { 10 | description: { 11 | component: '스크롤의 방향에 따라 헤더의 존재 유무가 결정됩니다.', 12 | }, 13 | }, 14 | }, 15 | } as Meta; 16 | 17 | const Template: Story = (args) => ; 18 | 19 | export const BasicCss = Template.bind({}); 20 | -------------------------------------------------------------------------------- /src/stories/ScrollProgressBar.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { ScrollProgressBar } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/ScrollProgressBar', 7 | component: ScrollProgressBar, 8 | parameters: { 9 | docs: { 10 | description: { 11 | component: 12 | '스크롤의 높이에 따라 커스텀된 진행바를 스크롤바 형식으로 제공합니다.', 13 | }, 14 | }, 15 | }, 16 | } as Meta; 17 | 18 | const Template: Story = (args) => ; 19 | 20 | export const BasicCss = Template.bind({}); 21 | -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /src/components/ShadowEffects/ShadowEffects.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | export const ShadowEffects = memo(() => { 5 | return ; 6 | }); 7 | 8 | const Circle = styled.div` 9 | position: relative; 10 | width: 200px; 11 | height: 200px; 12 | background: transparent; 13 | border-radius: 50%; 14 | box-shadow: 0 0 0 40px rgba(0, 255, 255, 0.3), 15 | 0 0 0 80px rgba(0, 255, 255, 0.3), 0 0 0 120px rgba(0, 255, 255, 0.3), 16 | 0 0 0 160px rgba(0, 255, 255, 0.3), 0 0 0 200px rgba(0, 255, 255, 0.3), 17 | 0 0 0 200px rgba(0, 255, 255, 0.1); 18 | `; 19 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | * { 2 | outline: 0; 3 | margin: 0; 4 | padding: 0; 5 | } 6 | 7 | html { 8 | width: 100%; 9 | height: 100%; 10 | } 11 | 12 | body { 13 | width: 100%; 14 | height: 100%; 15 | overflow: hidden; 16 | margin: 0; 17 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 18 | 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', 19 | sans-serif; 20 | -webkit-font-smoothing: antialiased; 21 | -moz-osx-font-smoothing: grayscale; 22 | } 23 | 24 | code { 25 | font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New', 26 | monospace; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/stories/StickyElementsScrollingEffects.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { StickyElementsScrollingEffects } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/StickyElementsScrollingEffects', 7 | component: StickyElementsScrollingEffects, 8 | parameters: { 9 | docs: { 10 | description: { 11 | component: '현재 페이지에 따라 sticky되는 헤더가 달라집니다.', 12 | }, 13 | }, 14 | }, 15 | } as Meta; 16 | 17 | const Template: Story = (args) => ; 18 | 19 | export const BasicCss = Template.bind({}); 20 | -------------------------------------------------------------------------------- /.storybook/main.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | typescript: { 3 | check: false, 4 | checkOptions: {}, 5 | reactDocgen: 'react-docgen-typescript', 6 | reactDocgenTypescriptOptions: { 7 | shouldExtractLiteralValuesFromEnum: true, 8 | propFilter: (prop) => 9 | prop.parent ? !/node_modules/.test(prop.parent.fileName) : true, 10 | }, 11 | }, 12 | stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], 13 | addons: [ 14 | '@storybook/addon-links', 15 | '@storybook/addon-essentials', 16 | '@storybook/preset-create-react-app', 17 | '@storybook/addon-storysource', 18 | '@storybook/addon-knobs', 19 | ], 20 | }; 21 | -------------------------------------------------------------------------------- /src/stories/Modal.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { Modal } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/Modal', 7 | component: Modal, 8 | parameters: { 9 | backgrounds: { 10 | default: 'dark', 11 | }, 12 | }, 13 | decorators: [ 14 | (Story) => { 15 | const style = { 16 | boxSizing: 'border-box', 17 | } as CSSProperties; 18 | 19 | return ( 20 |
21 | 22 |
23 | ); 24 | }, 25 | ], 26 | } as Meta; 27 | 28 | const Template: Story = (args) => ; 29 | 30 | export const BasicCss = Template.bind({}); 31 | -------------------------------------------------------------------------------- /src/stories/canvasTutorial/Wavy.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { Wavy } from '../../components'; 4 | 5 | export default { 6 | title: 'canvas-study/Wavy', 7 | component: Wavy, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | height: '100vh', 12 | width: '100%', 13 | overflow: 'hidden', 14 | background: '#fff', 15 | } as CSSProperties; 16 | 17 | return ( 18 |
19 | 20 |
21 | ); 22 | }, 23 | ], 24 | } as Meta; 25 | 26 | const Template: Story = (args) => ; 27 | 28 | export const BasicCss = Template.bind({}); 29 | -------------------------------------------------------------------------------- /src/stories/canvasTutorial/BouncingBall.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { BouncingBall } from '../../components'; 4 | 5 | export default { 6 | title: 'canvas-study/BouncingBall', 7 | component: BouncingBall, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | height: '100vh', 12 | width: '100%', 13 | overflow: 'hidden', 14 | } as CSSProperties; 15 | 16 | return ( 17 |
18 | 19 |
20 | ); 21 | }, 22 | ], 23 | } as Meta; 24 | 25 | const Template: Story = (args) => ; 26 | 27 | export const BasicCss = Template.bind({}); 28 | -------------------------------------------------------------------------------- /src/stories/canvasTutorial/MovingGradation.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { MovingGradation } from '../../components'; 4 | 5 | export default { 6 | title: 'canvas-study/MovingGradation', 7 | component: MovingGradation, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | height: '100vh', 12 | width: '100%', 13 | overflow: 'hidden', 14 | } as CSSProperties; 15 | 16 | return ( 17 |
18 | 19 |
20 | ); 21 | }, 22 | ], 23 | } as Meta; 24 | 25 | const Template: Story = (args) => ; 26 | 27 | export const BasicCss = Template.bind({}); 28 | -------------------------------------------------------------------------------- /src/stories/canvasTutorial/MoveSheep.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { MoveSheep } from '../../components'; 4 | 5 | export default { 6 | title: 'canvas-study/MoveSheep', 7 | component: MoveSheep, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | height: '100vh', 12 | width: '100%', 13 | overflow: 'hidden', 14 | background: '#ffcaec', 15 | } as CSSProperties; 16 | 17 | return ( 18 |
19 | 20 |
21 | ); 22 | }, 23 | ], 24 | } as Meta; 25 | 26 | const Template: Story = (args) => ; 27 | 28 | export const BasicCss = Template.bind({}); 29 | -------------------------------------------------------------------------------- /src/stories/canvasTutorial/MovingBox.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { MovingBox } from '../../components'; 4 | 5 | export default { 6 | title: 'canvas-study/MovingBox', 7 | component: MovingBox, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | height: '100vh', 12 | width: '100%', 13 | overflow: 'hidden', 14 | background: '#3de1f5', 15 | } as CSSProperties; 16 | 17 | return ( 18 |
19 | 20 |
21 | ); 22 | }, 23 | ], 24 | } as Meta; 25 | 26 | const Template: Story = (args) => ; 27 | 28 | export const BasicCss = Template.bind({}); 29 | -------------------------------------------------------------------------------- /src/stories/canvasTutorial/Readme.stories.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from '@storybook/addon-docs/blocks'; 2 | 3 | 4 | 5 | # CANVAS-STUDY 6 | 7 | 이 세션은 cavas 공부의 결과물을 담습니다. 8 | 9 | - 대부분의 cavas 예제 코드는 김종민님의 튜토리얼 강의에서 가져왔습니다. 10 | 11 | - 예제 코드(JS)를 React로 컨버팅하면서, React에서 인터렉티브한 화면을 만들기 위한 12 | 고민을 추가하였고, 13 | 14 | - Typescript 적용을 통해 cavas의 인터페이스를 더 이해하기 위한 용도로 사용했습니다. 15 | 16 |
17 | 18 | ## 참고 자료 19 | 20 | - [MDN](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Advanced_animations) 21 | 22 | - [sin, cos, radian에 대한 공부](https://code-masterjung.tistory.com/109) 23 | 24 | - 출처: [Interactive Developer](https://www.youtube.com/channel/UCdeWxKJuvtUG2xyN6pOJEvA) 25 | -------------------------------------------------------------------------------- /src/stories/Accordion.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { Accordion } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/Accordion', 7 | component: Accordion, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | display: 'flex', 12 | justifyContent: 'center', 13 | alignItems: 'center', 14 | height: '100vh', 15 | boxSizing: 'border-box', 16 | } as CSSProperties; 17 | 18 | return ( 19 |
20 | 21 |
22 | ); 23 | }, 24 | ], 25 | } as Meta; 26 | 27 | const Template: Story = (args) => ; 28 | 29 | export const BasicCss = Template.bind({}); 30 | -------------------------------------------------------------------------------- /src/stories/canvasTutorial/RotatingPolygon.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { RotatingPolygon } from '../../components'; 4 | 5 | export default { 6 | title: 'canvas-study/RotatingPolygon', 7 | component: RotatingPolygon, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | height: '100vh', 12 | width: '100%', 13 | overflow: 'hidden', 14 | background: '#fff', 15 | } as CSSProperties; 16 | 17 | return ( 18 |
19 | 20 |
21 | ); 22 | }, 23 | ], 24 | } as Meta; 25 | 26 | const Template: Story = (args) => ; 27 | 28 | export const BasicCss = Template.bind({}); 29 | -------------------------------------------------------------------------------- /src/components/LongTextShadow/LongTextShadow.tsx: -------------------------------------------------------------------------------- 1 | import React, { memo, useMemo, ReactText } from 'react'; 2 | import styled from 'styled-components'; 3 | 4 | export interface LongTextShadowProps { 5 | label?: ReactText; 6 | } 7 | 8 | export const LongTextShadow = memo(({ label }) => { 9 | const getShadow = useMemo(() => { 10 | let shadow = ''; 11 | for (let i = 0; i < 400; i++) { 12 | shadow += (i !== 0 ? ',' : '') + i + 'px ' + i + 'px 0 gray'; 13 | } 14 | return shadow; 15 | }, []); 16 | 17 | return {label}; 18 | }); 19 | 20 | const Text = styled.h2<{ shadow: string }>` 21 | font-size: 5.5em; 22 | color: white; 23 | font-weight: 600; 24 | text-shadow: ${(props) => props.shadow}; 25 | text-transform: uppercase; 26 | `; 27 | -------------------------------------------------------------------------------- /src/stories/DropDown.stories.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { Dropdown } from '../components'; 4 | import styled from 'styled-components'; 5 | 6 | export default { 7 | title: 'jacob-css/Dropdown', 8 | component: Dropdown, 9 | parameters: { 10 | docs: { 11 | description: { 12 | component: '오른쪽 위에 프로필 이미지를 누르면 드롭다운이 나옵니다.', 13 | }, 14 | }, 15 | }, 16 | } as Meta; 17 | 18 | const Template: Story = (args) => ( 19 | <> 20 | {`Click Here! -->`} 21 | 22 | 23 | ); 24 | 25 | const IndicateText = styled.h2` 26 | color: white; 27 | position: absolute; 28 | right: 120px; 29 | top: 12px; 30 | `; 31 | 32 | export const UserInfoDropdown = Template.bind({}); 33 | -------------------------------------------------------------------------------- /src/components/Portal/Portal.tsx: -------------------------------------------------------------------------------- 1 | import { memo, FC, useState, useEffect } from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | interface PortalProps { 5 | className?: string; 6 | element?: string; 7 | } 8 | 9 | export const Portal: FC = memo(({ children, className = 'jacob-portal', element = 'div' }) => { 10 | const [container] = useState(() => { 11 | const el = document.createElement(element); 12 | el.classList.add(className); 13 | return el; 14 | }); 15 | 16 | useEffect(() => { 17 | if (typeof window === 'undefined') { 18 | return; 19 | } 20 | document.body.appendChild(container); 21 | return () => { 22 | document.body.removeChild(container); 23 | }; 24 | }, [container]); 25 | 26 | return ReactDOM.createPortal(children, container); 27 | }); 28 | -------------------------------------------------------------------------------- /src/hooks/useScreenSize.ts: -------------------------------------------------------------------------------- 1 | import { debounce } from 'lodash'; 2 | import { useEffect, useState } from 'react'; 3 | import { DomUtils } from '../utils'; 4 | 5 | function useScreenSize() { 6 | const [size, setSize] = useState({ width: document.body.clientWidth, height: document.body.clientHeight }); 7 | 8 | useEffect(() => { 9 | if (!DomUtils.usableWindow()) return; 10 | 11 | const resize = debounce(() => { 12 | setSize((pre) => ({ ...pre, width: document.body.clientWidth, height: document.body.clientHeight })); 13 | }, 400); 14 | 15 | window.addEventListener('resize', resize, false); 16 | resize(); 17 | return () => window.removeEventListener('resize', resize, false); 18 | }, []); 19 | 20 | return { stageWidth: size.width, stageHeight: size.height }; 21 | } 22 | 23 | export default useScreenSize; 24 | -------------------------------------------------------------------------------- /src/components/Canvas/MovingBox/Point.ts: -------------------------------------------------------------------------------- 1 | export class Point { 2 | x; 3 | y; 4 | 5 | constructor(x?: number, y?: number) { 6 | this.x = x || 0; 7 | this.y = y || 0; 8 | } 9 | 10 | add(point: Point) { 11 | this.x += point.x; 12 | this.y += point.y; 13 | return this; 14 | } 15 | 16 | subtract(point: Point) { 17 | this.x -= point.x; 18 | this.y -= point.y; 19 | return this; 20 | } 21 | 22 | reduce(value: number) { 23 | this.x *= value; 24 | this.y *= value; 25 | return this; 26 | } 27 | 28 | collide(point: Point, width: number, height: number) { 29 | if (this.x >= point.x && this.x <= point.x + width && this.y >= point.y && this.y <= point.y + height) { 30 | return true; 31 | } 32 | return false; 33 | } 34 | 35 | clone() { 36 | return new Point(this.x, this.y); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/stories/MiniWavy.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { MiniWavy } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/MiniWavy', 7 | component: MiniWavy, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | display: 'flex', 12 | flexDirection: 'column', 13 | justifyContent: 'center', 14 | alignItems: 'center', 15 | height: '100vh', 16 | overflow: 'hidden', 17 | boxSizing: 'border-box', 18 | } as CSSProperties; 19 | 20 | return ( 21 |
22 | 23 |
24 | ); 25 | }, 26 | ], 27 | } as Meta; 28 | 29 | const Template: Story = () => { 30 | return ; 31 | }; 32 | 33 | export const BasicCss = Template.bind({}); 34 | -------------------------------------------------------------------------------- /src/stories/ListHoverEffects.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { ListHoverEffects } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/ListHoverEffects', 7 | component: ListHoverEffects, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | display: 'flex', 12 | flexDirection: 'column', 13 | justifyContent: 'center', 14 | alignItems: 'center', 15 | height: '100vh', 16 | overflow: 'auto', 17 | boxSizing: 'border-box', 18 | } as CSSProperties; 19 | 20 | return ( 21 |
22 | 23 |
24 | ); 25 | }, 26 | ], 27 | } as Meta; 28 | 29 | const Template: Story = () => { 30 | return ; 31 | }; 32 | 33 | export const BasicCss = Template.bind({}); 34 | -------------------------------------------------------------------------------- /src/stories/SlidingMenuIndicator.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { SlidingMenuIndicator } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/SlidingMenuIndicator', 7 | component: SlidingMenuIndicator, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | display: 'flex', 12 | flexDirection: 'column', 13 | justifyContent: 'center', 14 | alignItems: 'center', 15 | height: '100vh', 16 | overflow: 'auto', 17 | boxSizing: 'border-box', 18 | } as CSSProperties; 19 | 20 | return ( 21 |
22 | 23 |
24 | ); 25 | }, 26 | ], 27 | } as Meta; 28 | 29 | const Template: Story = (args) => ; 30 | 31 | export const BasicCss = Template.bind({}); 32 | -------------------------------------------------------------------------------- /src/stories/MouseCursor.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { DotMouseCursor } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/DotMouseCursor', 7 | component: DotMouseCursor, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | display: 'flex', 12 | flexDirection: 'column', 13 | justifyContent: 'center', 14 | alignItems: 'center', 15 | height: '100vh', 16 | overflow: 'hidden', 17 | boxSizing: 'border-box', 18 | cursor: 'none', 19 | } as CSSProperties; 20 | 21 | return ( 22 |
23 | 24 |
25 | ); 26 | }, 27 | ], 28 | } as Meta; 29 | 30 | const Template: Story = () => { 31 | return ; 32 | }; 33 | 34 | export const BasicCss = Template.bind({}); 35 | -------------------------------------------------------------------------------- /src/components/Canvas/Wavy/WaveGroup.ts: -------------------------------------------------------------------------------- 1 | import { Wave } from './Wave'; 2 | 3 | export class WaveGroup { 4 | totalWaves = 3; 5 | totalPoints = 6; 6 | 7 | color = ['rgba(255, 0, 0, 0.4)', 'rgba(255, 255, 0, 0.4)', 'rgba(0, 255, 255, 0.4)']; 8 | 9 | waves: Array; 10 | 11 | constructor() { 12 | this.waves = []; 13 | for (let i = 0; i < this.totalWaves; i++) { 14 | const wave = new Wave(i, this.totalPoints, this.color[i]); 15 | this.waves[i] = wave; 16 | } 17 | } 18 | 19 | resize(stageWidth: number, stageHeight: number) { 20 | for (let i = 0; i < this.totalWaves; i++) { 21 | const wave = this.waves[i]; 22 | wave.resize(stageWidth, stageHeight); 23 | } 24 | } 25 | 26 | draw(ctx: CanvasRenderingContext2D | null) { 27 | if (ctx === null) return; 28 | 29 | for (let i = 0; i < this.totalWaves; i++) { 30 | const wave = this.waves[i]; 31 | wave.draw(ctx); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/stories/GhostText.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { GhostText } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/GhostText', 7 | component: GhostText, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | display: 'flex', 12 | flexDirection: 'column', 13 | justifyContent: 'center', 14 | alignItems: 'center', 15 | height: '100vh', 16 | overflow: 'hidden', 17 | boxSizing: 'border-box', 18 | } as CSSProperties; 19 | 20 | return ( 21 |
22 | 23 |
24 | ); 25 | }, 26 | ], 27 | parameters: { 28 | docs: { 29 | description: { component: '고스트 효과' }, 30 | }, 31 | }, 32 | } as Meta; 33 | 34 | const Template: Story = (args) => ; 35 | 36 | export const BasicCss = Template.bind({}); 37 | -------------------------------------------------------------------------------- /src/stories/HeartAnimation.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { HeartAnimation } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/HeartAnimation', 7 | component: HeartAnimation, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | display: 'flex', 12 | flexDirection: 'column', 13 | justifyContent: 'center', 14 | alignItems: 'center', 15 | height: '100vh', 16 | overflow: 'hidden', 17 | boxSizing: 'border-box', 18 | } as CSSProperties; 19 | 20 | return ( 21 |
22 | 23 |
24 | ); 25 | }, 26 | ], 27 | parameters: { 28 | docs: { 29 | description: { component: '하트 하트~' }, 30 | }, 31 | }, 32 | } as Meta; 33 | 34 | const Template: Story = (args) => ; 35 | 36 | export const BasicCss = Template.bind({}); 37 | -------------------------------------------------------------------------------- /src/stories/WaveBorderCard.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { WaveBorderCard } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/WaveBorderCard', 7 | component: WaveBorderCard, 8 | parameters: { 9 | docs: { 10 | description: { component: '물결 표시 애니메이션을 구현합니다.' }, 11 | }, 12 | }, 13 | decorators: [ 14 | (Story) => { 15 | const style = { 16 | display: 'flex', 17 | flexDirection: 'column', 18 | justifyContent: 'center', 19 | alignItems: 'center', 20 | height: '100vh', 21 | overflow: 'auto', 22 | boxSizing: 'border-box', 23 | } as CSSProperties; 24 | 25 | return ( 26 |
27 | 28 |
29 | ); 30 | }, 31 | ], 32 | } as Meta; 33 | 34 | const Template: Story = (args) => ; 35 | 36 | export const BasicCss = Template.bind({}); 37 | -------------------------------------------------------------------------------- /src/stories/TextTyping.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { TextTyping } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/TextTyping', 7 | component: TextTyping, 8 | parameters: { 9 | docs: { 10 | description: { component: '글자 입력 애니메이션' }, 11 | }, 12 | }, 13 | decorators: [ 14 | (Story) => { 15 | const style = { 16 | display: 'flex', 17 | flexDirection: 'column', 18 | position: 'absolute', 19 | left: 0, 20 | right: 0, 21 | width: '100%', 22 | alignItems: 'center', 23 | height: '100vh', 24 | boxSizing: 'border-box', 25 | } as CSSProperties; 26 | 27 | return ( 28 |
29 | 30 |
31 | ); 32 | }, 33 | ], 34 | } as Meta; 35 | 36 | const Template: Story = (args) => ; 37 | 38 | export const BasicCss = Template.bind({}); 39 | -------------------------------------------------------------------------------- /src/stories/MovingText.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { MovingText, MovingTextProps } from '../components'; 4 | import { text } from '@storybook/addon-knobs'; 5 | 6 | export default { 7 | title: 'jacob-css/MovingText', 8 | component: MovingText, 9 | decorators: [ 10 | (Story) => { 11 | const style = { 12 | display: 'flex', 13 | flexDirection: 'column', 14 | justifyContent: 'center', 15 | alignItems: 'center', 16 | height: '100vh', 17 | overflow: 'auto', 18 | boxSizing: 'border-box', 19 | } as CSSProperties; 20 | 21 | return ( 22 |
23 | 24 |
25 | ); 26 | }, 27 | ], 28 | } as Meta; 29 | 30 | const Template: Story = () => { 31 | const label = text('label', 'jacob-css'); 32 | return ; 33 | }; 34 | 35 | export const BasicCss = Template.bind({}); 36 | -------------------------------------------------------------------------------- /src/stories/NeonButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { text } from '@storybook/addon-knobs'; 4 | import { NeonButton, NeonButtonProps } from '../components'; 5 | 6 | export default { 7 | title: 'jacob-css/NeonButton', 8 | component: NeonButton, 9 | decorators: [ 10 | (Story) => { 11 | const style = { 12 | display: 'flex', 13 | flexDirection: 'column', 14 | justifyContent: 'center', 15 | alignItems: 'center', 16 | height: '100vh', 17 | overflow: 'auto', 18 | boxSizing: 'border-box', 19 | } as CSSProperties; 20 | 21 | return ( 22 |
23 | 24 |
25 | ); 26 | }, 27 | ], 28 | } as Meta; 29 | 30 | const Template: Story = () => { 31 | const label = text('label', 'jacob button'); 32 | return ; 33 | }; 34 | 35 | export const BasicCss = Template.bind({}); 36 | -------------------------------------------------------------------------------- /src/stories/RangeInput.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { RangeInput } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/RangeInput', 7 | component: RangeInput, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | display: 'flex', 12 | flexDirection: 'column', 13 | justifyContent: 'center', 14 | alignItems: 'center', 15 | height: '100vh', 16 | overflow: 'auto', 17 | boxSizing: 'border-box', 18 | } as CSSProperties; 19 | 20 | return ( 21 |
22 | 23 |
24 | ); 25 | }, 26 | ], 27 | parameters: { 28 | docs: { 29 | description: { 30 | component: 'range타입 input의 스타일을 조작하는 기초를 제공합니다. ', 31 | }, 32 | }, 33 | }, 34 | } as Meta; 35 | 36 | const Template: Story = () => { 37 | return ; 38 | }; 39 | 40 | export const BasicCss = Template.bind({}); 41 | -------------------------------------------------------------------------------- /src/stories/RippleEffectsButton.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { RippleEffectsButton } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/RippleEffectsButton', 7 | component: RippleEffectsButton, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | display: 'flex', 12 | flexDirection: 'column', 13 | justifyContent: 'center', 14 | alignItems: 'center', 15 | height: '100vh', 16 | overflow: 'hidden', 17 | boxSizing: 'border-box', 18 | } as CSSProperties; 19 | 20 | return ( 21 |
22 | 23 |
24 | ); 25 | }, 26 | ], 27 | parameters: { 28 | docs: { 29 | description: { component: '버튼의 hover에 ripple효과를 줍니다.' }, 30 | }, 31 | }, 32 | } as Meta; 33 | 34 | const Template: Story = (args) => ; 35 | 36 | export const BasicCss = Template.bind({}); 37 | -------------------------------------------------------------------------------- /src/stories/ShadowEffects.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { ShadowEffects } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/ShadowEffects', 7 | component: ShadowEffects, 8 | decorators: [ 9 | (Story) => { 10 | const style = { 11 | display: 'flex', 12 | flexDirection: 'column', 13 | justifyContent: 'center', 14 | alignItems: 'center', 15 | height: '100vh', 16 | overflow: 'auto', 17 | boxSizing: 'border-box', 18 | } as CSSProperties; 19 | 20 | return ( 21 |
22 | 23 |
24 | ); 25 | }, 26 | ], 27 | parameters: { 28 | docs: { 29 | description: { 30 | component: '그림자 효과를 확인하기 위한 단순 도넛입니다.', 31 | }, 32 | }, 33 | }, 34 | } as Meta; 35 | 36 | const Template: Story = () => { 37 | return ; 38 | }; 39 | 40 | export const BasicCss = Template.bind({}); 41 | -------------------------------------------------------------------------------- /src/stories/LongBoxShadow.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { LongTextShadow, LongTextShadowProps } from '../components'; 4 | import { text } from '@storybook/addon-knobs'; 5 | 6 | export default { 7 | title: 'jacob-css/LongTextShadow', 8 | component: LongTextShadow, 9 | decorators: [ 10 | (Story) => { 11 | const style = { 12 | display: 'flex', 13 | flexDirection: 'column', 14 | justifyContent: 'center', 15 | alignItems: 'center', 16 | height: '100vh', 17 | overflow: 'auto', 18 | boxSizing: 'border-box', 19 | } as CSSProperties; 20 | 21 | return ( 22 |
23 | 24 |
25 | ); 26 | }, 27 | ], 28 | } as Meta; 29 | 30 | const Template: Story = (args) => { 31 | const label = text('label', 'jacob'); 32 | return ; 33 | }; 34 | 35 | export const BasicCss = Template.bind({}); 36 | -------------------------------------------------------------------------------- /src/stories/TextArea.stories.tsx: -------------------------------------------------------------------------------- 1 | import React, { CSSProperties } from 'react'; 2 | import { Meta, Story } from '@storybook/react'; 3 | import { TextArea } from '../components'; 4 | 5 | export default { 6 | title: 'jacob-css/TextArea', 7 | component: TextArea, 8 | parameters: { 9 | docs: { 10 | description: { component: '애니메이션이 살짝 추가된 Textarea' }, 11 | }, 12 | }, 13 | decorators: [ 14 | (Story) => { 15 | const style = { 16 | display: 'flex', 17 | flexDirection: 'column', 18 | top: '180px', 19 | position: 'absolute', 20 | left: 0, 21 | right: 0, 22 | alignItems: 'center', 23 | height: '100vh', 24 | overflow: 'auto', 25 | boxSizing: 'border-box', 26 | } as CSSProperties; 27 | 28 | return ( 29 |
30 | 31 |
32 | ); 33 | }, 34 | ], 35 | } as Meta; 36 | 37 | const Template: Story = (args) =>