diff --git a/packages/frontend/src/components/primitives/Tab.tsx b/packages/frontend/src/components/primitives/Tab.tsx new file mode 100644 index 0000000..0133ed1 --- /dev/null +++ b/packages/frontend/src/components/primitives/Tab.tsx @@ -0,0 +1,79 @@ +import React from 'react'; +import { useState } from 'react'; +import { useLayoutEffect } from 'react'; + +import { styled } from '@/libs/stitches'; + +export type TabProp = { + children: React.ReactElement | React.ReactElement[] + value?: string; + onChange?: (newValue: string) => void; +}; + +export type TabItem = { + value: string; + children: string; +}; + +export const TabItem: React.FC = (p: TabItem) => { + return { + props: p, + key: null, + type: null, + }; +}; + +const Container = styled('div', { + position: 'relative', +}); + +const Ul = styled('ul', { + display: 'flex', + margin: 0, + padding: 0, +}); + +const Li = styled('li', { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + padding: '$m', + margin: 0, + borderBottom: '2px solid $muted', + color: '$muted', + + variants: { + active: { + true: { + color: '$primary', + }, + }, + }, +}); + +export const Tab: React.FC = (p) => { + const c = Array.isArray(p.children) ? p.children.map(c => c.props) : [p.children.props]; + const [value, setValue] = useState(c[0].value); + + useLayoutEffect(() => { + if (!p.value) return; + setValue(p.value); + }, [p.value]); + + return ( + +
    + {c.map(item => ( +
  • { + if (item.value === value) return; + console.log(item.value); + setValue(item.value); + p.onChange?.(item.value); + }}> + {item.children} +
  • + ))} +
+
+ ); +}; diff --git a/packages/frontend/src/stories/components/primitives/Tab.stories.tsx b/packages/frontend/src/stories/components/primitives/Tab.stories.tsx new file mode 100644 index 0000000..6593835 --- /dev/null +++ b/packages/frontend/src/stories/components/primitives/Tab.stories.tsx @@ -0,0 +1,22 @@ +import React from 'react'; + +import type { Meta } from '@storybook/react'; + +import { Tab, TabItem } from '@/components/primitives/Tab'; + +const meta = { + component: Tab, + parameters: { + layouts: 'centered', + }, +} satisfies Meta; + +export default meta; + +export const Default = () => ( + + ホーム + 通知 + みつける + +);