Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fruity-drinks-mate.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@seed-design/css": patch
---

ImageFrame 내부 요소에 width, height 100%를 추가합니다
154 changes: 154 additions & 0 deletions docs/stories/ImageFrame.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import type { Meta, StoryObj } from "@storybook/nextjs";

import { ImageFrame } from "@seed-design/react";

import { imageFrameVariantMap } from "@seed-design/css/recipes/image-frame";
import { createStoryWithParameters } from "@/stories/utils/parameters";
import { SeedThemeDecorator } from "./components/decorator";
import { VariantTable } from "./components/variant-table";

const meta = {
component: ImageFrame,
decorators: [SeedThemeDecorator],
} satisfies Meta<typeof ImageFrame>;

export default meta;

type Story = StoryObj<typeof meta>;

type ImageFrameCase = {
caseLabel: string;
src: string;
width: string;
ratio: number;
height?: string;
};

type ImageFrameCaseProps = ImageFrameCase & {
rounded?: boolean;
stroke?: boolean;
};

const IMAGE_CASES: ImageFrameCase[] = [
{
caseLabel: "ratio=1, width=96",
src: "https://placehold.co/320x180/ff7a00/ffffff?text=16:9",
width: "96px",
ratio: 1,
},
{
caseLabel: "ratio=4/3, width=120",
src: "https://placehold.co/180x320/4c6fff/ffffff?text=9:16",
width: "120px",
ratio: 4 / 3,
},
{
caseLabel: "ratio=16/9, width=160",
src: "https://placehold.co/240x240/00b894/ffffff?text=1:1",
width: "160px",
ratio: 16 / 9,
},
{
caseLabel: "ratio=4/3, width=160, height=120",
src: "https://placehold.co/320x180/ffb300/ffffff?text=16:9",
width: "160px",
height: "120px",
ratio: 4 / 3,
},
{
caseLabel: "ratio=1, width=120, height=80",
src: "https://placehold.co/320x180/8e44ad/ffffff?text=16:9",
width: "120px",
height: "80px",
ratio: 1,
},
{
caseLabel: "ratio=3/4, width=120",
src: "https://placehold.co/180x320/2d3436/ffffff?text=9:16",
width: "120px",
ratio: 3 / 4,
},
];

const conditionMap = {
caseLabel: IMAGE_CASES.reduce(
(acc, item) => {
acc[item.caseLabel] = {
src: item.src,
width: item.width,
height: item.height,
ratio: item.ratio,
};

return acc;
},
{} as Record<string, Omit<ImageFrameCase, "caseLabel">>,
),
};

const ImageFrameCase = ({
caseLabel,
src,
width,
height,
ratio,
rounded,
stroke,
}: ImageFrameCaseProps) => {
return (
<div style={{ display: "flex", alignItems: "center", gap: "12px" }}>
<ImageFrame
src={src}
alt={caseLabel}
ratio={ratio}
width={width}
height={height}
rounded={rounded}
stroke={stroke}
/>
<div style={{ display: "flex", flexDirection: "column", gap: "4px" }}>
<span style={{ fontSize: "12px", color: "var(--seed-color-fg-placeholder)" }}>
{caseLabel}
</span>
<code style={{ fontSize: "12px", fontFamily: "Courier", wordBreak: "break-all" }}>
src: {src}
</code>
<code style={{ fontSize: "12px", fontFamily: "Courier" }}>width: {width}</code>
<code style={{ fontSize: "12px", fontFamily: "Courier" }}>ratio: {ratio}</code>
<code style={{ fontSize: "12px", fontFamily: "Courier" }}>height: {height ?? "-"}</code>
</div>
</div>
);
};

const CommonStoryTemplate: Story = {
args: {
src: "https://placehold.co/1x1/000000/ffffff",
alt: "ImageFrame placeholder",
},
render: (args) => (
<VariantTable
Component={ImageFrameCase}
variantMap={imageFrameVariantMap}
conditionMap={conditionMap}
{...args}
/>
),
};

export const LightTheme = CommonStoryTemplate;

export const DarkTheme = createStoryWithParameters({
...CommonStoryTemplate,
parameters: { theme: "dark" },
});

export const FontScalingExtraSmall = createStoryWithParameters({
...CommonStoryTemplate,
parameters: { fontScale: "Extra Small" },
});

export const FontScalingExtraExtraExtraLarge = createStoryWithParameters({
...CommonStoryTemplate,
parameters: { fontScale: "Extra Extra Extra Large" },
});
1 change: 1 addition & 0 deletions examples/stackflow-spa/src/activities/ActivityHome.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ const ActivityHome: StaticActivityComponentType<"ActivityHome"> = ({ params }) =
title: "List",
items: [
{ title: "ListItem", onClick: () => push("ActivityListItem", {}) },
{ title: "ListImageFrame", onClick: () => push("ActivityListImageFrame", {}) },
{ title: "ListButtonItem", onClick: () => push("ActivityListButtonItem", {}) },
{ title: "ListLinkItem", onClick: () => push("ActivityListLinkItem", {}) },
{ title: "ListSwitchItem", onClick: () => push("ActivityListSwitchItem", {}) },
Expand Down
136 changes: 136 additions & 0 deletions examples/stackflow-spa/src/activities/ActivityListImageFrame.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { IconHouseLine } from "@karrotmarket/react-monochrome-icon";
import { ImageFrame } from "@seed-design/react";
import type { StaticActivityComponentType } from "@stackflow/react/future";
import { useFlow } from "@stackflow/react/future";
import { Fragment } from "react";
import {
AppBar,
AppBarBackButton,
AppBarIconButton,
AppBarLeft,
AppBarMain,
AppBarRight,
} from "seed-design/ui/app-bar";
import { AppScreen, AppScreenContent } from "seed-design/ui/app-screen";
import { List, ListDivider, ListItem } from "seed-design/ui/list";

type ImageCase = {
key: string;
title: string;
detail: string;
width: string;
ratio: number;
src: string;
height?: string;
};

const IMAGE_CASES: ImageCase[] = [
{
key: "square-frame-wide-image",
title: "ratio=1, width=96",
detail: "src 320x180",
width: "96px",
ratio: 1,
src: "https://placehold.co/320x180/ff7a00/ffffff?text=16:9",
},
{
key: "landscape-frame-portrait-image",
title: "ratio=4/3, width=120",
detail: "src 180x320",
width: "120px",
ratio: 4 / 3,
src: "https://placehold.co/180x320/4c6fff/ffffff?text=9:16",
},
{
key: "wide-frame-square-image",
title: "ratio=16/9, width=160",
detail: "src 240x240",
width: "160px",
ratio: 16 / 9,
src: "https://placehold.co/240x240/00b894/ffffff?text=1:1",
},
{
key: "width-height-match",
title: "ratio=4/3, width=160, height=120",
detail: "src 320x180",
width: "160px",
height: "120px",
ratio: 4 / 3,
src: "https://placehold.co/320x180/ffb300/ffffff?text=16:9",
},
{
key: "width-height-mismatch",
title: "ratio=1, width=120, height=80",
detail: "src 320x180",
width: "120px",
height: "80px",
ratio: 1,
src: "https://placehold.co/320x180/8e44ad/ffffff?text=16:9",
},
{
key: "portrait-frame-portrait-image",
title: "ratio=3/4, width=120",
detail: "src 180x320",
width: "120px",
ratio: 3 / 4,
src: "https://placehold.co/180x320/2d3436/ffffff?text=9:16",
},
];

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

const ActivityListImageFrame: StaticActivityComponentType<"ActivityListImageFrame"> = () => {
const { push } = useFlow();

return (
<AppScreen>
<AppBar>
<AppBarLeft>
<AppBarBackButton />
</AppBarLeft>
<AppBarMain title="ListImageFrame" />
<AppBarRight>
<AppBarIconButton aria-label="Home" onClick={() => push("ActivityHome", {})}>
<IconHouseLine />
</AppBarIconButton>
</AppBarRight>
</AppBar>
<AppScreenContent
ptr
onPtrRefresh={async () => {
await new Promise((resolve) => setTimeout(resolve, 1000));
}}
>
<List>
{IMAGE_CASES.map((item, index) => (
<Fragment key={item.key}>
<ListItem
alignItems="center"
title={item.title}
detail={item.detail}
prefix={
<ImageFrame
src={item.src}
alt={item.title}
ratio={item.ratio}
width={item.width}
height={item.height}
rounded
stroke
/>
}
/>
{index < IMAGE_CASES.length - 1 && <ListDivider />}
</Fragment>
))}
</List>
</AppScreenContent>
</AppScreen>
);
};

export default ActivityListImageFrame;
1 change: 1 addition & 0 deletions examples/stackflow-spa/src/stackflow/Stack.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ export const { Stack, actions, stepActions } = stackflow({
ActivityListButtonItem: lazy(() => import("../activities/ActivityListButtonItem")),
ActivityListCheckItem: lazy(() => import("../activities/ActivityListCheckItem")),
ActivityListItem: lazy(() => import("../activities/ActivityListItem")),
ActivityListImageFrame: lazy(() => import("../activities/ActivityListImageFrame")),
ActivityListLinkItem: lazy(() => import("../activities/ActivityListLinkItem")),
ActivityListRadioItem: lazy(() => import("../activities/ActivityListRadioItem")),
ActivityListSwitchItem: lazy(() => import("../activities/ActivityListSwitchItem")),
Expand Down
1 change: 1 addition & 0 deletions examples/stackflow-spa/src/stackflow/stackflow.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export const config = defineConfig({
{ route: "/list-item-radio", name: "ActivityListRadioItem" },
{ route: "/list-item-switch", name: "ActivityListSwitchItem" },
{ route: "/list-item", name: "ActivityListItem" },
{ route: "/list-image-frame", name: "ActivityListImageFrame" },
{ route: "/manner-temp-level", name: "ActivityMannerTempLevel" },
{ route: "/menu-sheet", name: "ActivityMenuSheet" },
{ route: "/menu-sheet-activity", name: "ActivityMenuSheetActivity" },
Expand Down
3 changes: 3 additions & 0 deletions packages/css/all.css
Original file line number Diff line number Diff line change
Expand Up @@ -4575,6 +4575,9 @@

.seed-image-frame > img, .seed-image-frame > video {
object-fit: cover;
width: 100%;
height: 100%;
display: block;
}

.seed-image-frame--rounded_true {
Expand Down
2 changes: 1 addition & 1 deletion packages/css/all.min.css

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions packages/css/recipes/image-frame.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
position: relative;
}
.seed-image-frame > img, .seed-image-frame > video {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.seed-image-frame--rounded_true {
Expand Down
3 changes: 3 additions & 0 deletions packages/qvism-preset/src/recipes/image-frame.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ const imageFrame = defineRecipe({
position: "relative",

"& > img, & > video": {
display: "block",
width: "100%",
height: "100%",
objectFit: "cover",
},
},
Expand Down