Skip to content

Commit

Permalink
feat: Example Architecture
Browse files Browse the repository at this point in the history
  • Loading branch information
junghyeonsu committed Sep 27, 2024
1 parent a09c60d commit 32b9c5e
Show file tree
Hide file tree
Showing 61 changed files with 1,537 additions and 397 deletions.
6 changes: 3 additions & 3 deletions component-docs/metadatas/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ export const componentMetadatas: ComponentMetadataSchema[] = [
{
name: "alert-dialog",
type: "component",
innerDependencies: ["box-button"],
innerDependencies: ["action-button"],
snippets: ["component/alert-dialog.tsx"],
},
{
name: "box-button",
name: "action-button",
type: "component",
dependencies: ["@radix-ui/react-slot"],
snippets: ["component/box-button.tsx"],
snippets: ["component/action-button.tsx"],
},
{
name: "checkbox",
Expand Down
10 changes: 0 additions & 10 deletions component-docs/metadatas/example.ts

This file was deleted.

6 changes: 5 additions & 1 deletion component-docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"dev": "next dev",
"start": "next start",
"build": "yarn generate:registry && next build",
"generate:registry": "node --no-warnings=ExperimentalWarning --loader ts-node/esm scripts/generate-registry.ts"
"generate:registry": "node --no-warnings=ExperimentalWarning --loader ts-node/esm scripts/generate-registry.ts",
"watch:registry": "watchlist snippets -- yarn generate:registry"
},
"dependencies": {
"@radix-ui/react-slot": "^1.1.0",
Expand All @@ -23,6 +24,7 @@
"@stackflow/react": "^1.2.1",
"@vanilla-extract/css": "^1.15.5",
"@vanilla-extract/recipes": "^0.5.5",
"change-case": "^5.4.4",
"next": "^14.2.5",
"nextra": "^2.13.4",
"nextra-theme-docs": "^2.13.4",
Expand All @@ -39,10 +41,12 @@
"@vanilla-extract/next-plugin": "^2.4.5",
"autoprefixer": "^10.4.20",
"chalk": "^5.3.0",
"ts-dedent": "^2.2.0",
"ts-node": "^10.9.2",
"ts-pattern": "^5.3.1",
"tslib": "^2.6.3",
"typescript": "^5.5.4",
"watchlist": "^0.3.1",
"zod": "^3.23.8"
}
}
36 changes: 36 additions & 0 deletions component-docs/public/mdx/component/action-button.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
```tsx copy filename="action-button.tsx"
"use client";

import "@seed-design/stylesheet/actionButton.css";

import * as React from "react";
import clsx from "clsx";
import { Slot } from "@radix-ui/react-slot";
import { actionButton, type ActionButtonVariantProps } from "@seed-design/recipe/actionButton";

export interface ActionButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
ActionButtonVariantProps {
prefixIcon?: React.ReactNode;
}

/**
* @see https://component.seed-design.io/components/box-button
*/
export const ActionButton = React.forwardRef<HTMLButtonElement, ActionButtonProps>(
(
{ className, variant = "brandSolid", size = "medium", children, prefixIcon, ...otherProps },
ref,
) => {
const classNames = actionButton({ variant, size });
return (
<button ref={ref} className={clsx(classNames.root, className)} {...otherProps}>
{prefixIcon && <Slot className={classNames.prefix}>{prefixIcon}</Slot>}
<span className={classNames.label}>{children}</span>
</button>
);
},
);
ActionButton.displayName = "ActionButton";

```
71 changes: 71 additions & 0 deletions component-docs/public/mdx/component/alert-dialog.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
```tsx copy filename="alert-dialog.tsx"
"use client";

import "@seed-design/stylesheet/dialog.css";

import * as React from "react";
import { dialog } from "@seed-design/recipe/dialog";

import { ActionButton } from "./action-button";

export type AlertDialogProps = {
title: string;
description: string;
onInteractOutside?: React.MouseEventHandler;
};

/**
* @see https://component.seed-design.io/components/alert-dialog
*/
export const AlertDialog: React.FC<AlertDialogProps> = ({
title,
description,
onInteractOutside,
}) => {
const containerRef = React.useRef<HTMLDivElement>(null);
const backdropRef = React.useRef<HTMLDivElement>(null);

const popLock = React.useRef(false);

const onClickOutside: React.MouseEventHandler = (e) => {
onInteractOutside?.(e);

if (e.defaultPrevented) {
return;
}

if (popLock.current) {
return;
}
popLock.current = true;
};
const onClickContent: React.MouseEventHandler = (e) => {
e.stopPropagation();
};

const classNames = dialog();

return (
<div
ref={containerRef}
role="alertdialog"
className={classNames.container}
onClick={onClickOutside}
>
<div ref={backdropRef} className={classNames.backdrop} />
<div onClick={onClickContent} className={classNames.content}>
<div className={classNames.header}>
<h2 className={classNames.title}>{title}</h2>
<p className={classNames.description}>{description}</p>
</div>
<div className={classNames.footer}>
<ActionButton className={classNames.action}>lol</ActionButton>
<ActionButton className={classNames.action}>lol</ActionButton>
</div>
</div>
</div>
);
};
AlertDialog.displayName = "AlertDialog";

```
73 changes: 73 additions & 0 deletions component-docs/public/mdx/component/checkbox.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
```tsx copy filename="checkbox.tsx"
"use client";

import { type UseCheckboxProps, useCheckbox } from "@seed-design/react-checkbox";
import { type CheckboxVariantProps, checkbox } from "@seed-design/recipe/checkbox";
import clsx from "clsx";
import * as React from "react";
import type { CSSProperties } from "react";

import "@seed-design/stylesheet/checkbox.css";

type Assign<T, U> = Omit<T, keyof U> & U;

const visuallyHidden: CSSProperties = {
border: 0,
clip: "rect(0 0 0 0)",
height: "1px",
margin: "-1px",
overflow: "hidden",
padding: 0,
position: "absolute",
whiteSpace: "nowrap",
width: "1px",
};

const Checkmark = React.forwardRef<SVGSVGElement, React.SVGProps<SVGSVGElement>>((props, ref) => (
<svg
aria-hidden="true"
ref={ref}
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M17.5179 6.98877C17.9658 7.3118 18.0671 7.93681 17.7441 8.38478L11.7108 16.7515C11.5351 16.9952 11.2591 17.1469 10.9592 17.1648C10.6593 17.1827 10.3672 17.0647 10.1638 16.8436L6.33048 12.677C5.95655 12.2705 5.98291 11.6379 6.38935 11.264C6.7958 10.89 7.42841 10.9164 7.80234 11.3228L10.8056 14.5873L16.1219 7.21498C16.4449 6.76702 17.0699 6.66574 17.5179 6.98877Z"
fill="currentColor"
/>
</svg>
));

export interface CheckboxProps
extends Assign<React.HTMLAttributes<HTMLInputElement>, UseCheckboxProps>,
CheckboxVariantProps {
label: React.ReactNode;
}

export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
({ className, size = "medium", label, ...otherProps }, ref) => {
const { stateProps, restProps, controlProps, hiddenInputProps, rootProps } =
useCheckbox(otherProps);

const classNames = checkbox({ size });
return (
<label className={clsx(classNames.root, className)} {...rootProps}>
<div {...controlProps} className={classNames.control}>
<Checkmark {...stateProps} className={classNames.icon} />
</div>
<input ref={ref} {...hiddenInputProps} {...restProps} style={visuallyHidden} />
<span {...stateProps} className={classNames.label}>
{label}
</span>
</label>
);
},
);
Checkbox.displayName = "Checkbox";

```
139 changes: 139 additions & 0 deletions component-docs/public/mdx/component/chip-tabs.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
```tsx copy filename="chip-tabs.tsx"
"use client";

import clsx from "clsx";
import * as React from "react";
import {
useTabs,
type UseTabsProps,
type TriggerProps,
type ContentProps,
useLazyContents,
type UseLazyContentsProps,
} from "@seed-design/react-tabs";
import { chipTabs } from "@seed-design/recipe/chipTabs";
import { chipTab } from "@seed-design/recipe/chipTab";

import "@seed-design/stylesheet/chipTab.css";
import "@seed-design/stylesheet/chipTabs.css";

type Assign<T, U> = Omit<T, keyof U> & U;

interface ChipTabsContextValue {
api: ReturnType<typeof useTabs>;
classNames: ReturnType<typeof chipTabs>;
shouldRender: (value: string) => boolean;
}

const ChipTabsContext = React.createContext<ChipTabsContextValue | null>(null);

const useChipTabsContext = () => {
const context = React.useContext(ChipTabsContext);
if (!context) {
throw new Error("Tabs cannot be rendered outside the Tabs");
}
return context;
};

export interface ChipTabsProps
extends Assign<React.HTMLAttributes<HTMLDivElement>, Omit<UseTabsProps, "layout">>,
Omit<UseLazyContentsProps, "currentValue"> {}

export const ChipTabs = React.forwardRef<HTMLDivElement, ChipTabsProps>((props, ref) => {
const { className, lazyMode, isLazy } = props;
const api = useTabs(props);
const classNames = chipTabs();
const { rootProps, value, restProps } = api;
const { shouldRender } = useLazyContents({ currentValue: value, lazyMode, isLazy });

return (
<div ref={ref} {...rootProps} {...restProps} className={clsx(classNames.root, className)}>
<ChipTabsContext.Provider
value={{
api,
classNames,
shouldRender,
}}
>
{props.children}
</ChipTabsContext.Provider>
</div>
);
});
ChipTabs.displayName = "ChipTabs";

export const ChipTabTriggerList = React.forwardRef<
HTMLDivElement,
React.HTMLAttributes<HTMLDivElement>
>(({ className, children, ...otherProps }, ref) => {
const { api, classNames } = useChipTabsContext();
const { tabTriggerListProps, triggerSize } = api;
const { left } = triggerSize;
const { triggerList } = classNames;

const containerRef = React.useRef<HTMLDivElement>(null);
React.useImperativeHandle(ref, () => containerRef.current as HTMLDivElement);

React.useEffect(() => {
if (containerRef.current) {
containerRef.current?.scrollTo({
// NOTE: 27px is half of tab's min-width
left: left - 27,
behavior: "smooth",
});
}
}, [left]);

return (
<div
ref={containerRef}
{...tabTriggerListProps}
className={clsx(triggerList, className)}
{...otherProps}
>
{children}
</div>
);
});
ChipTabTriggerList.displayName = "ChipTabTriggerList";

export interface ChipTabTriggerProps
extends Assign<React.HTMLAttributes<HTMLButtonElement>, Omit<TriggerProps, "isDisabled">> {}

export const ChipTabTrigger = React.forwardRef<HTMLButtonElement, ChipTabTriggerProps>(
({ className, children, value, ...otherProps }, ref) => {
const { api } = useChipTabsContext();
const { getTabTriggerProps } = api;
const { label, root } = chipTab();
const { rootProps, labelProps } = getTabTriggerProps({ value });

return (
<button ref={ref} {...rootProps} className={clsx(root, className)} {...otherProps}>
<span className={label} {...labelProps}>
{children}
</span>
</button>
);
},
);
ChipTabTrigger.displayName = "ChipTabTrigger";

export const ChipTabContent = React.forwardRef<
HTMLDivElement,
Assign<React.HTMLAttributes<HTMLDivElement>, ContentProps>
>(({ className, children, value, ...otherProps }, ref) => {
const { api, classNames, shouldRender } = useChipTabsContext();
const { getTabContentProps } = api;
const { content } = classNames;
const tabContentProps = getTabContentProps({ value });
const isRender = shouldRender(value);

return (
<div ref={ref} {...tabContentProps} className={clsx(content, className)} {...otherProps}>
{isRender && children}
</div>
);
});
ChipTabContent.displayName = "ChipTabContent";

```
Loading

0 comments on commit 32b9c5e

Please sign in to comment.