diff --git a/src/app/_components/app-card/app-card.stories.tsx b/src/app/_components/app-card/app-card.stories.tsx index c37a4b92..d366439b 100644 --- a/src/app/_components/app-card/app-card.stories.tsx +++ b/src/app/_components/app-card/app-card.stories.tsx @@ -1,5 +1,6 @@ import type { Meta, StoryObj } from '@storybook/react'; import { AppCard } from './app-card'; +import { Link } from 'lucide-react'; const meta: Meta = { title: 'app/globals/app-card', @@ -17,3 +18,12 @@ export const Primary: Story = { description: '入力した文字列の長さをカウントします。', }, }; + +export const EmotionIsElement: Story = { + args: { + link: '/characters/counter', + emotion: , + title: '文字数カウンター', + description: '入力した文字列の長さをカウントします。', + }, +}; diff --git a/src/app/_components/app-card/app-card.tsx b/src/app/_components/app-card/app-card.tsx index e66bd05b..8106fdf0 100644 --- a/src/app/_components/app-card/app-card.tsx +++ b/src/app/_components/app-card/app-card.tsx @@ -1,6 +1,7 @@ import { Route } from 'next'; import Link from 'next/link'; import { Heading } from '../../../components/heading'; +import { ReactNode } from 'react'; export const AppCard = ({ link, @@ -9,7 +10,7 @@ export const AppCard = ({ description, }: { link: Route; - emotion: string; + emotion: ReactNode; title: string; description: string; }) => { diff --git a/src/app/_styles/globals.css b/src/app/_styles/globals.css index 1e1bfb7e..325196cb 100644 --- a/src/app/_styles/globals.css +++ b/src/app/_styles/globals.css @@ -48,6 +48,12 @@ /* chart */ --chart-primary: 45 212 191; --chart-empty: 243 244 246; + + /* group */ + --group-primary: 45 212 191; + --group-secondary: 56 189 248; + --group-tertiary: 129 140 248; + --group-quaternary: 232 121 249; } .dark { @@ -95,6 +101,12 @@ /* chart */ --chart-primary: 94 234 212; --chart-empty: 75 85 99; + + /* group */ + --group-primary: 94 234 212; + --group-secondary: 125 211 252; + --group-tertiary: 165 180 252; + --group-quaternary: 240 171 252; } .app-background { diff --git a/src/app/designs/_components/rounded-icon/index.ts b/src/app/designs/_components/rounded-icon/index.ts new file mode 100644 index 00000000..d5b2328b --- /dev/null +++ b/src/app/designs/_components/rounded-icon/index.ts @@ -0,0 +1 @@ +export * from './rounded-icon'; diff --git a/src/app/designs/_components/rounded-icon/rounded-icon.stories.tsx b/src/app/designs/_components/rounded-icon/rounded-icon.stories.tsx new file mode 100644 index 00000000..1dcedffe --- /dev/null +++ b/src/app/designs/_components/rounded-icon/rounded-icon.stories.tsx @@ -0,0 +1,12 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { RoundedIcon } from './rounded-icon'; + +const meta: Meta = { + title: 'app/designs/rounded-icon', + component: RoundedIcon, +}; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = {}; diff --git a/src/app/designs/_components/rounded-icon/rounded-icon.tsx b/src/app/designs/_components/rounded-icon/rounded-icon.tsx new file mode 100644 index 00000000..2e90074a --- /dev/null +++ b/src/app/designs/_components/rounded-icon/rounded-icon.tsx @@ -0,0 +1,15 @@ +import { FC } from 'react'; + +export const RoundedIcon: FC = () => { + return ( +
+ ); +}; diff --git a/src/app/designs/layout.tsx b/src/app/designs/layout.tsx new file mode 100644 index 00000000..64c2f732 --- /dev/null +++ b/src/app/designs/layout.tsx @@ -0,0 +1,35 @@ +import Link from 'next/link'; +import { Heading } from '@/components/heading'; + +export const metadata = { + title: 'Designs', + description: '自分だけのデザインを探すための場所です', + openGraph: { + title: 'Designs', + description: '自分だけのデザインを探すための場所です', + url: 'https://k8o.me/designs', + siteName: 'k8o', + locale: 'ja', + type: 'website', + }, + twitter: { + title: 'Designs', + card: 'summary', + description: '自分だけのデザインを探すための場所です', + }, +}; + +export default function Layout({ + children, +}: { + children: React.ReactNode; +}) { + return ( +
+ + Designs + + {children} +
+ ); +} diff --git a/src/app/designs/opengraph-image.tsx b/src/app/designs/opengraph-image.tsx new file mode 100644 index 00000000..f28f5f02 --- /dev/null +++ b/src/app/designs/opengraph-image.tsx @@ -0,0 +1,47 @@ +import { ImageResponse } from 'next/og'; + +export const runtime = 'edge'; + +export const alt = 'designs'; +export const size = { + width: 1200, + height: 600, +}; + +export const contentType = 'image/png'; + +export default async function OpenGraphImage() { + return new ImageResponse( + ( +
+
+ 🧑‍🎨 +
+
+ ), + { + ...size, + }, + ); +} diff --git a/src/app/designs/page.tsx b/src/app/designs/page.tsx new file mode 100644 index 00000000..612361d8 --- /dev/null +++ b/src/app/designs/page.tsx @@ -0,0 +1,15 @@ +import { AppCard } from '../_components/app-card'; +import { RoundedIcon } from './_components/rounded-icon'; + +export default function Page() { + return ( +
+ } + title="かどまるラボ" + description="角丸を決めてお気に入りの図形を探しましょう" + /> +
+ ); +} diff --git a/src/app/designs/rounded/_components/control-panel/control-panel.stories.tsx b/src/app/designs/rounded/_components/control-panel/control-panel.stories.tsx new file mode 100644 index 00000000..6b928ff7 --- /dev/null +++ b/src/app/designs/rounded/_components/control-panel/control-panel.stories.tsx @@ -0,0 +1,12 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { ControlPanel } from './control-panel'; + +const meta: Meta = { + title: 'app/designs/rounded/control-panel', + component: ControlPanel, +}; + +export default meta; +type Story = StoryObj; + +export const Primary: Story = {}; diff --git a/src/app/designs/rounded/_components/control-panel/control-panel.tsx b/src/app/designs/rounded/_components/control-panel/control-panel.tsx new file mode 100644 index 00000000..c81c3741 --- /dev/null +++ b/src/app/designs/rounded/_components/control-panel/control-panel.tsx @@ -0,0 +1,189 @@ +'use client'; + +import { FC, KeyboardEvent, MouseEvent, TouchEvent } from 'react'; +import { useControlPanel } from './use-control-panel'; +import clsx from 'clsx'; +import { IconButton } from '@/components/icon-button'; +import { ClipboardPenLine } from 'lucide-react'; +import { useClipboard } from '@/hooks/clipboard'; + +const OperateButton: FC<{ + label: string; + position: { + top?: string; + right?: string; + bottom?: string; + left?: string; + }; + variable: 'primary' | 'secondary' | 'quaternary' | 'tertiary'; + onMouseDown: (e: MouseEvent) => void; + onTouchStart: (e: TouchEvent) => void; + onKeyDown: (e: KeyboardEvent) => void; + isActive: boolean; +}> = ({ + label, + position, + variable, + onMouseDown, + onTouchStart, + onKeyDown, + isActive, +}) => { + return ( +