Skip to content

Commit 8d2c0ab

Browse files
te6-inclaude
andcommitted
feat(stackflow): support custom background color for AppBar
- Add `bg` and `background` props to AppBar for custom background colors - Create `BoxBackgroundProps` utility in stackflow package (minimal subset of StyleProps) - Update app-bar recipe to use `--seed-box-background` CSS variable with fallback - Add documentation and example for AppBar customization Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 3a00ad3 commit 8d2c0ab

File tree

8 files changed

+69
-9
lines changed

8 files changed

+69
-9
lines changed

docs/content/react/stackflow/app-screen.mdx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,16 @@ Intersection Observer를 사용해 `AppBar`의 `tone` 속성을 동적으로 변
151151

152152
### Customizing App Bar
153153

154+
`tone="layer"`인 경우 `AppBar`의 색상을 변경할 수 있습니다.
155+
156+
`AppBarIconButton` 내에 `Icon` 컴포넌트를 사용하여 아이콘을 커스터마이징할 수 있습니다.
157+
158+
<Card href="/react/components/iconography/composition#icon-컴포넌트" title="Icon" icon={<IconComponent />}>
159+
160+
아이콘 컴포넌트에 대해 자세히 알아봅니다.
161+
162+
</Card>
163+
154164
<StackflowExample names={["react/app-screen/app-bar-customization"]}>
155165
```json doc-gen:file
156166
{

docs/examples/react/app-screen/app-bar-customization.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,11 @@ const AppScreenAppBarCustomizationActivity: ActivityComponentType<
1515
> = () => {
1616
return (
1717
<AppScreen theme="android">
18-
<AppBar>
18+
<AppBar bg="palette.blue200">
1919
<AppBarMain title="Preview" subtitle="This is a nice preview." />
2020
<AppBarRight>
2121
<AppBarIconButton aria-label="Notification">
22-
<Icon svg={<IconBellFill />} color="fg.informative" size="x5" />
22+
<Icon svg={<IconBellFill />} color="palette.blue500" size="x5" />
2323
</AppBarIconButton>
2424
</AppBarRight>
2525
</AppBar>

packages/css/all.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1671,7 +1671,7 @@
16711671
}
16721672

16731673
.seed-app-bar__root--tone_layer:before {
1674-
background-color: var(--seed-color-bg-layer-default);
1674+
background: var(--seed-box-background, var(--seed-color-bg-layer-default));
16751675
}
16761676

16771677
.seed-app-bar__icon--tone_layer {

packages/css/all.min.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/css/recipes/app-bar.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@
267267
--seed-exit-scale: 1;
268268
}
269269
.seed-app-bar__root--tone_layer:before {
270-
background-color: var(--seed-color-bg-layer-default);
270+
background: var(--seed-box-background, var(--seed-color-bg-layer-default));
271271
}
272272
.seed-app-bar__icon--tone_layer {
273273
color: var(--seed-icon-color, var(--seed-color-fg-neutral));

packages/qvism-preset/src/stackflow/app-bar.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ export const appBar = defineSlotRecipe({
292292
layer: {
293293
root: {
294294
"&:before": {
295-
backgroundColor: vars.toneLayer.enabled.root.color,
295+
background: `var(--seed-box-background, ${vars.toneLayer.enabled.root.color})`,
296296
},
297297
},
298298
icon: {

packages/stackflow/src/components/AppBar/AppBar.tsx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { useAppBarContext } from "../../primitive/AppBar/useAppBarContext";
1010
import { createStyleContext } from "../../utils/createStyleContext";
1111
import { useTopActivity } from "../../primitive/private/useTopActivity";
1212
import { useActivity } from "@stackflow/react";
13+
import { useBoxBackgroundProps, type BoxBackgroundProps } from "../../utils/styled";
1314

1415
const { PropsProvider, ClassNamesProvider, useProps, withContext, useClassNames } =
1516
createStyleContext(appBar);
@@ -21,11 +22,19 @@ const {
2122

2223
export const AppBarPropsProvider = PropsProvider;
2324

24-
export interface AppBarProps extends AppBarVariantProps, AppBarPrimitive.RootProps {}
25+
export interface AppBarProps
26+
extends AppBarVariantProps,
27+
AppBarPrimitive.RootProps,
28+
BoxBackgroundProps {}
2529

2630
export const AppBarRoot = forwardRef<HTMLDivElement, AppBarProps>((props, ref) => {
31+
const { style: boxStyle, restProps: propsWithoutBoxProps } = useBoxBackgroundProps(props);
32+
2733
const contextProps = useProps();
28-
const [variantProps, otherProps] = appBar.splitVariantProps({ ...contextProps, ...props });
34+
const [variantProps, otherProps] = appBar.splitVariantProps({
35+
...contextProps,
36+
...propsWithoutBoxProps,
37+
});
2938

3039
const topActivityTransitionStyle = useTopActivity().transitionStyle;
3140

@@ -46,7 +55,7 @@ export const AppBarRoot = forwardRef<HTMLDivElement, AppBarProps>((props, ref) =
4655
<MainPropsProvider value={resolvedVariantProps}>
4756
<AppBarPrimitive.Root
4857
ref={ref}
49-
{...mergeProps({ className: classNames.root }, otherProps)}
58+
{...mergeProps({ className: classNames.root, style: boxStyle }, otherProps)}
5059
/>
5160
</MainPropsProvider>
5261
</ClassNamesProvider>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { ScopedColorBg, ScopedColorPalette, ScopedColorBanner } from "@seed-design/css/vars";
2+
import { vars } from "@seed-design/css/vars";
3+
4+
/**
5+
* A minimal subset of `StyleProps` from `@seed-design/react`.
6+
* Copied here to avoid package dependency. May be extracted to a shared package later.
7+
*/
8+
export interface BoxBackgroundProps {
9+
/**
10+
* Shorthand for `background`.
11+
*/
12+
bg?: ScopedColorBg | ScopedColorPalette | ScopedColorBanner | (string & {});
13+
14+
background?: ScopedColorBg | ScopedColorPalette | ScopedColorBanner | (string & {});
15+
}
16+
17+
function handleColor(color: string | undefined) {
18+
if (!color) {
19+
return undefined;
20+
}
21+
const [type, value] = color.split(".");
22+
23+
// @ts-expect-error - dynamic access
24+
return vars.$color[type]?.[value] ?? color;
25+
}
26+
27+
export function useBoxBackgroundProps<T extends BoxBackgroundProps>(
28+
props: T,
29+
): {
30+
style: React.CSSProperties;
31+
restProps: Omit<T, keyof BoxBackgroundProps>;
32+
} {
33+
const { bg, background, ...restProps } = props;
34+
35+
return {
36+
style: {
37+
"--seed-box-background": handleColor(background ?? bg),
38+
} as React.CSSProperties,
39+
restProps: restProps as Omit<T, keyof BoxBackgroundProps>,
40+
};
41+
}

0 commit comments

Comments
 (0)