diff --git a/component-docs/activities/skeleton/SkeletonPulseActivitiy.tsx b/component-docs/activities/skeleton/SkeletonWaveActivity.tsx similarity index 59% rename from component-docs/activities/skeleton/SkeletonPulseActivitiy.tsx rename to component-docs/activities/skeleton/SkeletonWaveActivity.tsx index d64070cde..a6ac96907 100644 --- a/component-docs/activities/skeleton/SkeletonPulseActivitiy.tsx +++ b/component-docs/activities/skeleton/SkeletonWaveActivity.tsx @@ -3,11 +3,11 @@ import * as React from "react"; import Layout from "@/activities/ActivityLayout"; import { Skeleton } from "@/seed-design/ui/skeleton"; -import { useSkeletonLoading } from "@/stores/skeleton"; +import { useSkeletonDuration, useSkeletonLoading } from "@/stores/skeleton"; declare module "@stackflow/config" { interface Register { - SkeletonPulse: unknown; + SkeletonWave: unknown; } } @@ -24,16 +24,26 @@ const Fallback = () => { ); }; -const SkeletonPulseActivitiy: ActivityComponentType<"SkeletonPulse"> = () => { +const SkeletonWaveActivity: ActivityComponentType<"SkeletonWave"> = () => { const isLoading = useSkeletonLoading(); + const animationDuration = useSkeletonDuration(); return ( -
{isLoading ? :
content
}
+
+ {isLoading ? :
content
} +
); }; -export default SkeletonPulseActivitiy; +export default SkeletonWaveActivity; -SkeletonPulseActivitiy.displayName = "SkeletonPulseActivitiy"; +SkeletonWaveActivity.displayName = "SkeletonWaveActivity"; diff --git a/component-docs/components/LoadingTrigger.tsx b/component-docs/components/LoadingTrigger.tsx deleted file mode 100644 index 2eaf02d61..000000000 --- a/component-docs/components/LoadingTrigger.tsx +++ /dev/null @@ -1,21 +0,0 @@ -import { BoxButton } from "@/seed-design/ui/box-button"; -import { useSkeletonActions, useSkeletonLoading } from "@/stores/skeleton"; -import * as React from "react"; - -export const LoadingTrigger = () => { - const isLoading = useSkeletonLoading(); - const { toggleLoading } = useSkeletonActions(); - return ( - - {isLoading ? "Stop Loading" : "Start Loading"} - - ); -}; diff --git a/component-docs/components/SkeletonControls.css.ts b/component-docs/components/SkeletonControls.css.ts new file mode 100644 index 000000000..8dd481d2a --- /dev/null +++ b/component-docs/components/SkeletonControls.css.ts @@ -0,0 +1,13 @@ +import { style } from "@vanilla-extract/css"; + +export const controlBlock = style({ + display: "flex", + gap: "8px", +}); + +export const controlLabel = style({}); + +export const controlInput = style({ + flex: 1, + border: "1px solid #e5e5e5", +}); diff --git a/component-docs/components/SkeletonControls.tsx b/component-docs/components/SkeletonControls.tsx new file mode 100644 index 000000000..f353ce629 --- /dev/null +++ b/component-docs/components/SkeletonControls.tsx @@ -0,0 +1,51 @@ +import { BoxButton } from "@/seed-design/ui/box-button"; +import { + useSkeletonActions, + useSkeletonDuration, + useSkeletonGradient, + useSkeletonLoading, +} from "@/stores/skeleton"; +import * as React from "react"; +import { controlBlock, controlInput, controlLabel } from "./SkeletonControls.css"; + +export const SkeletonControls = () => { + const isLoading = useSkeletonLoading(); + const { toggleLoading, setControls } = useSkeletonActions(); + const [duration, setDuration] = React.useState(useSkeletonDuration()); + const [gradient, setGradient] = React.useState(useSkeletonGradient()); + + return ( +
+ + {isLoading ? "Stop Loading" : "Start Loading"} + +
+
+ + setDuration(e.target.value)} + /> +
+
+ + setGradient(e.target.value)} + /> +
+ setControls({ duration, gradient })}> + 적용 + +
+
+ ); +}; diff --git a/component-docs/pages/patterns/skeleton.mdx b/component-docs/pages/patterns/skeleton.mdx index 56d56417d..28871f15c 100644 --- a/component-docs/pages/patterns/skeleton.mdx +++ b/component-docs/pages/patterns/skeleton.mdx @@ -1,11 +1,11 @@ import { Stackflow } from "@/components/Stackflow"; -import { LoadingTrigger } from '@/components/LoadingTrigger'; -import SkeletonPulseActivity from "@/activities/skeleton/SkeletonPulseActivitiy"; +import { SkeletonControls } from '@/components/SkeletonControls'; +import SkeletonWaveActivity from "@/activities/skeleton/SkeletonWaveActivity"; # Skeleton -### Pulse +### Wave - + - + diff --git a/component-docs/seed-design/ui/skeleton.css.ts b/component-docs/seed-design/ui/skeleton.css.ts index 164cd9157..bc2d3784c 100644 --- a/component-docs/seed-design/ui/skeleton.css.ts +++ b/component-docs/seed-design/ui/skeleton.css.ts @@ -3,7 +3,7 @@ import { recipe } from "@vanilla-extract/recipes"; // #F7F8F9 // #F7F8F950 -const pulse = keyframes({ +const wave = keyframes({ "0%": { backgroundPositionX: "100%", }, @@ -22,13 +22,14 @@ export const skeleton = recipe({ variants: { type: { - pulse: { - backgroundImage: "linear-gradient(90deg, #F7F8F9 0%, #F7F8F950 20%, #F7F8F9 40%)", + wave: { + backgroundImage: + "var(--skeleton-gradient, linear-gradient(90deg, #F7F8F9 0%, #F7F8F950 20%, #F7F8F9 40%))", backgroundSize: "200% 100%", animationFillMode: "forwards", - animationName: pulse, - animationDuration: "1.5s", + animationName: wave, + animationDuration: "var(--skeleton-animation-duration, 1.5s)", animationTimingFunction: "ease-in-out", animationIterationCount: "infinite", }, diff --git a/component-docs/seed-design/ui/skeleton.tsx b/component-docs/seed-design/ui/skeleton.tsx index 900a5d7b2..140f82a73 100644 --- a/component-docs/seed-design/ui/skeleton.tsx +++ b/component-docs/seed-design/ui/skeleton.tsx @@ -8,13 +8,13 @@ interface SkeletonProps { width: number | string; height: number | string; borderRadius: "circle" | "rounded" | "square"; - type?: "pulse"; + type?: "wave"; } // TODO: Spec // TODO: Recipe export const Skeleton = React.forwardRef((props, ref) => { - const { width, height, borderRadius, type = "pulse" } = props; + const { width, height, borderRadius, type = "wave" } = props; return (
void; + setControls: (state: { duration: string; gradient: string }) => void; }; } const useSkeleton = create((set) => ({ isLoading: true, + duration: "1.5s", + gradient: "linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%)", actions: { toggleLoading: () => set((state) => ({ isLoading: !state.isLoading })), + setControls: set, }, })); export const useSkeletonLoading = () => useSkeleton((state) => state.isLoading); export const useSkeletonActions = () => useSkeleton((state) => state.actions); +export const useSkeletonDuration = () => useSkeleton((state) => state.duration); +export const useSkeletonGradient = () => useSkeleton((state) => state.gradient);