Skip to content

Commit

Permalink
refactor: refactor demo-activity
Browse files Browse the repository at this point in the history
  • Loading branch information
te6-in committed Feb 3, 2025
1 parent c2bdbee commit 6e65f82
Show file tree
Hide file tree
Showing 7 changed files with 140 additions and 134 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,27 @@ import { ActionButton } from "seed-design/ui/action-button";
import { Snackbar, SnackbarProvider, useSnackbarAdapter } from "seed-design/ui/snackbar";
import { ExtendedFab } from "seed-design/ui/extended-fab";

import { ARTICLES, CATEGORIES } from "./data";
import { type Article } from "./types";

declare module "@stackflow/config" {
interface Register {
Demo: unknown;
}
}

export type Article = {
id: number;
title: string;
content: string;
author: string;
categoryId: string;
createdAt: string;
isPopular?: boolean;
};

export type Category = {
id: string;
name: string;
};

const TABS = [
{ label: "추천", value: "recommendations" },
{ label: "구독", value: "subscriptions" },
Expand Down Expand Up @@ -332,4 +344,115 @@ export function ArticleListItem({
);
}

export const CATEGORIES: Category[] = [
{ id: "travel", name: "여행" },
{ id: "food", name: "음식" },
{ id: "lifestyle", name: "라이프스타일" },
];

export const ARTICLES: Article[] = [
{
id: 1,
title: "산토리니의 일몰",
content:
"에게해의 푸른 바다와 하얀 건물들 사이로 지는 석양이 만드는 황홍빛 풍경. 산토리니에서 가장 로맨틱한 순간을 만날 수 있다.",
author: "mollit",
categoryId: "travel",
createdAt: "2023-02-15T09:30:00Z",
},

{
id: 2,
title: "교토의 대나무 숲",
content:
"아라시야마의 대나무 숲길을 걸으며 느끼는 고요함. 바람에 흔들리는 대나무 소리가 마음을 평온하게 만든다.",
author: "sunt",
categoryId: "travel",
createdAt: "2023-05-22T14:15:00Z",
isPopular: true,
},

{
id: 3,
title: "알프스 하이킹 가이드",
content:
"스위스 알프스의 초보자용 트레킹 코스. 그린델발트에서 시작하여 아이거 북벽을 감상하며 2시간 코스로 즐길 수 있다.",
author: "ullamco",
categoryId: "travel",
createdAt: "2023-10-15T12:10:00Z",
},
{
id: 4,
title: "홈메이드 파스타의 비밀",
content:
"신선한 면과 소스만 있다면 레스토랑 급 파스타를 만들 수 있다. 올리브오일과 마늘의 양이 맛을 결정한다.",
author: "dolore",
categoryId: "food",
createdAt: "2023-03-30T16:20:00Z",
},

{
id: 5,
title: "제철 딸기 고르는 법",
content:
"봄철 딸기는 꼭지가 선명한 초록색이어야 한다. 윤기 나는 빨간색과 은은한 향기가 좋은 딸기의 조건.",
author: "aliqua",
categoryId: "food",
createdAt: "2023-06-18T10:05:00Z",
},

{
id: 6,
title: "커피 브루잉 팁",
content:
"물 온도 92도, 분쇄도는 중간, 추출 시간 3분이 기본. 원두 양은 물 200ml당 15g이 황금비율이다.",
author: "consectetur",
categoryId: "food",
createdAt: "2023-09-25T13:40:00Z",
},

{
id: 7,
title: "미니멀 홈 데코",
content:
"불필요한 소품은 과감히 정리하고, 화이트 톤의 기본 가구만으로 깔끔한 공간을 연출할 수 있다.",
author: "adipisicing",
categoryId: "lifestyle",
createdAt: "2023-04-12T15:55:00Z",
isPopular: true,
},

{
id: 8,
title: "아침 루틴의 힘",
content:
"하루를 5분 일찍 시작하는 것부터. 따뜻한 물 한잔과 스트레칭으로 활기찬 아침을 맞이하자.",
author: "elit",
categoryId: "lifestyle",
createdAt: "2023-07-28T08:25:00Z",
isPopular: true,
},

{
id: 9,
title: "실내 공기 정화 식물",
content:
"스투키, 스파티필름, 산세베리아는 관리가 쉽고 공기정화 능력이 뛰어난 대표적인 실내식물이다.",
author: "exercitation",
categoryId: "lifestyle",
createdAt: "2023-08-07T11:45:00Z",
},

{
id: 10,
title: "독서 습관 만들기",
content:
"하루 10페이지부터 시작하자. 취침 전 20분 독서는 수면의 질도 높여주는 일석이조 습관이다.",
author: "magna",
categoryId: "lifestyle",
createdAt: "2023-12-03T17:35:00Z",
isPopular: true,
},
];

export default DemoActivity;
112 changes: 0 additions & 112 deletions docs/components/example/demo/data.tsx

This file was deleted.

14 changes: 0 additions & 14 deletions docs/components/example/demo/types.ts

This file was deleted.

5 changes: 3 additions & 2 deletions docs/components/example/index.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/content/docs/react/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
title: V3
---

<StackflowExample name="demo/index" />
<StackflowExample name="demo-activity" />
8 changes: 7 additions & 1 deletion docs/public/__registry__/ui/app-screen.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
{
"name": "app-screen",
"dependencies": [
"@seed-design/react",
"@seed-design/stackflow"
],
"registries": [
{
"name": "app-screen.tsx",
"type": "ui",
"content": "\"use client\";\n\nimport {\n IconChevronLeftLine,\n IconXmarkLine,\n} from \"@daangn/react-monochrome-icon\";\nimport {\n AppBar as SeedAppBar,\n AppScreen as SeedAppScreen,\n} from \"@seed-design/stackflow\";\nimport { useActions, useActivity } from \"@stackflow/react\";\nimport { forwardRef, useCallback } from \"react\";\n\nexport type AppBarProps = SeedAppBar.RootProps;\n\nexport type AppScreenProps = SeedAppScreen.RootProps;\n\nexport const AppBar = SeedAppBar.Root;\n\nexport const Left = SeedAppBar.Left;\n\nexport const Right = SeedAppBar.Right;\n\nexport const Title = SeedAppBar.Title;\n\nexport const IconButton = SeedAppBar.IconButton;\n\nexport const BackButton = forwardRef<\n HTMLButtonElement,\n SeedAppBar.IconButtonProps\n>(({ children = <IconChevronLeftLine />, onClick, ...otherProps }, ref) => {\n const activity = useActivity();\n const actions = useActions();\n\n const handleOnClick = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n\n if (!e.defaultPrevented) {\n actions.pop();\n }\n },\n [actions],\n );\n\n if (!activity) {\n return null;\n }\n if (activity.isRoot) {\n return null;\n }\n\n return (\n <SeedAppBar.IconButton\n ref={ref}\n aria-label=\"Go Back\"\n type=\"button\"\n onClick={handleOnClick}\n {...otherProps}\n >\n {children}\n </SeedAppBar.IconButton>\n );\n});\nBackButton.displayName = \"BackButton\";\n\nexport const CloseButton = forwardRef<\n HTMLButtonElement,\n SeedAppBar.IconButtonProps\n>(({ children = <IconXmarkLine />, onClick, ...otherProps }, ref) => {\n const activity = useActivity();\n\n const handleOnClick = useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n\n if (!e.defaultPrevented) {\n // you can do something here\n }\n },\n [],\n );\n\n const isRoot = !activity || activity.isRoot;\n\n if (!isRoot) {\n return null;\n }\n\n return (\n <IconButton\n ref={ref}\n aria-label=\"Close\"\n type=\"button\"\n onClick={handleOnClick}\n {...otherProps}\n >\n {children}\n </IconButton>\n );\n});\nCloseButton.displayName = \"CloseButton\";\n\nexport const AppScreen = forwardRef<HTMLDivElement, AppScreenProps>(\n ({ children, ...otherProps }, ref) => {\n return (\n <SeedAppScreen.Root ref={ref} {...otherProps}>\n <SeedAppScreen.Dim />\n <SeedAppScreen.Layer>{children}</SeedAppScreen.Layer>\n <SeedAppScreen.Edge />\n </SeedAppScreen.Root>\n );\n },\n);\nAppScreen.displayName = \"AppScreen\";\n"
"content": "\"use client\";\n\nimport { PullToRefresh } from \"@seed-design/react/primitive\";\nimport { AppScreen as SeedAppScreen } from \"@seed-design/stackflow\";\nimport { useActions } from \"@stackflow/react\";\nimport { forwardRef } from \"react\";\nimport { ProgressCircle } from \"../ui/progress-circle\";\n\nexport interface AppScreenProps extends SeedAppScreen.RootProps {}\n\nexport const AppScreen = forwardRef<HTMLDivElement, AppScreenProps>(\n ({ children, onSwipeBackEnd, ...otherProps }, ref) => {\n const { pop } = useActions();\n\n return (\n <SeedAppScreen.Root\n ref={ref}\n onSwipeBackEnd={({ swiped }) => {\n if (swiped) {\n pop();\n }\n onSwipeBackEnd?.({ swiped });\n }}\n {...otherProps}\n >\n <SeedAppScreen.Dim />\n {children}\n <SeedAppScreen.Edge />\n </SeedAppScreen.Root>\n );\n },\n);\nAppScreen.displayName = \"AppScreen\";\n\nexport interface AppScreenContentProps extends SeedAppScreen.LayerProps {\n ptr?: boolean;\n\n onPtrReady?: () => void;\n\n onPtrRefresh?: () => Promise<void>;\n}\n\nexport const AppScreenContent = forwardRef<\n HTMLDivElement,\n AppScreenContentProps\n>(({ children, ptr, onPtrReady, onPtrRefresh, ...otherProps }, ref) => {\n if (!ptr) {\n return (\n <SeedAppScreen.Layer ref={ref} {...otherProps}>\n {children}\n </SeedAppScreen.Layer>\n );\n }\n\n return (\n <PullToRefresh.Root\n asChild\n onPtrReady={onPtrReady}\n onPtrRefresh={onPtrRefresh}\n >\n <SeedAppScreen.Layer ref={ref} {...otherProps}>\n <PullToRefresh.Indicator>\n {(props) => <ProgressCircle tone=\"brand\" {...props} />}\n </PullToRefresh.Indicator>\n <PullToRefresh.Content asChild>{children}</PullToRefresh.Content>\n </SeedAppScreen.Layer>\n </PullToRefresh.Root>\n );\n});\n"
},
{
"name": "app-bar.tsx",
"type": "ui",
"content": "\"use client\";\n\nimport {\n IconChevronLeftLine,\n IconXmarkLine,\n} from \"@daangn/react-monochrome-icon\";\nimport { Stack } from \"@seed-design/react\";\nimport {\n AppBar as SeedAppBar,\n type AppBarIconButtonProps,\n} from \"@seed-design/stackflow\";\nimport { useActions, useActivity } from \"@stackflow/react\";\nimport * as React from \"react\";\nimport { forwardRef } from \"react\";\n\nexport interface AppBarProps extends SeedAppBar.RootProps {}\n\nexport const AppBar = SeedAppBar.Root;\n\nexport interface AppBarLeftProps extends SeedAppBar.LeftProps {}\n\nexport const AppBarLeft = SeedAppBar.Left;\n\nexport interface AppBarRightProps extends SeedAppBar.RightProps {}\n\nexport const AppBarRight = SeedAppBar.Right;\n\nexport interface AppBarMainProps extends Omit<SeedAppBar.MainProps, \"asChild\"> {\n /**\n * The title of the app bar.\n * If children is provided as ReactElement, this prop will be ignored.\n */\n title?: string;\n\n /**\n * The subtitle of the app bar.\n * If children is provided as ReactElement, this prop will be ignored.\n */\n subtitle?: string;\n}\n\nexport const AppBarMain = forwardRef<HTMLDivElement, AppBarMainProps>(\n ({ title, subtitle, children, ...otherProps }, ref) => {\n if (React.isValidElement(children)) {\n return (\n <SeedAppBar.Main {...otherProps} ref={ref}>\n {children}\n </SeedAppBar.Main>\n );\n }\n\n return (\n <SeedAppBar.Main\n layout={subtitle ? \"withSubtitle\" : \"titleOnly\"}\n {...otherProps}\n ref={ref}\n >\n <Stack overflowX=\"auto\">\n <SeedAppBar.Title>{children ?? title}</SeedAppBar.Title>\n {subtitle ? (\n <SeedAppBar.Subtitle>{subtitle}</SeedAppBar.Subtitle>\n ) : null}\n </Stack>\n </SeedAppBar.Main>\n );\n },\n);\nAppBarMain.displayName = \"AppBarMain\";\n\nexport const AppBarIconButton = SeedAppBar.IconButton;\n\nexport const AppBarBackButton = forwardRef<\n HTMLButtonElement,\n AppBarIconButtonProps\n>(({ children = <IconChevronLeftLine />, onClick, ...otherProps }, ref) => {\n const activity = useActivity();\n const actions = useActions();\n\n const handleOnClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n\n if (!e.defaultPrevented) {\n actions.pop();\n }\n };\n\n if (!activity) {\n return null;\n }\n if (activity.isRoot) {\n return null;\n }\n\n return (\n <SeedAppBar.IconButton\n ref={ref}\n aria-label=\"Go Back\"\n type=\"button\"\n onClick={handleOnClick}\n {...otherProps}\n >\n {children}\n </SeedAppBar.IconButton>\n );\n});\nAppBarBackButton.displayName = \"AppBarBackButton\";\n\nexport const AppBarCloseButton = forwardRef<\n HTMLButtonElement,\n AppBarIconButtonProps\n>(({ children = <IconXmarkLine />, onClick, ...otherProps }, ref) => {\n const activity = useActivity();\n\n const handleOnClick = (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n\n if (!e.defaultPrevented) {\n // you can do something here\n }\n };\n\n const isRoot = !activity || activity.isRoot;\n\n if (!isRoot) {\n return null;\n }\n\n return (\n <AppBarIconButton\n ref={ref}\n aria-label=\"Close\"\n type=\"button\"\n onClick={handleOnClick}\n {...otherProps}\n >\n {children}\n </AppBarIconButton>\n );\n});\nAppBarCloseButton.displayName = \"AppBarCloseButton\";\n"
}
]
}
4 changes: 3 additions & 1 deletion docs/public/__registry__/ui/index.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
{
"name": "app-screen",
"files": [
"ui:app-screen.tsx"
"ui:app-screen.tsx",
"ui:app-bar.tsx"
],
"dependencies": [
"@seed-design/react",
"@seed-design/stackflow"
]
},
Expand Down

0 comments on commit 6e65f82

Please sign in to comment.