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/tidy-safe-area-insets.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stackflow/plugin-basic-ui": minor
---

Apply left and right safe area insets to AppScreen content and AppBar controls. Keep the Cupertino title centered within the safe area while backgrounds continue to fill the screen.
2 changes: 1 addition & 1 deletion demo/src/activities/Article/Article.content.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { style } from "@vanilla-extract/css";
import { f } from "../../styles";

export const container = style([
f.posAbsFull,
f.fullHeight,
f.overflowScroll,
f.rootLineHeight,
]);
Expand Down
2 changes: 1 addition & 1 deletion demo/src/activities/Main/Main.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { style } from "@vanilla-extract/css";

import { f } from "../../styles";

export const wrapper = style([f.posAbsFull, f.flexColumn, f.rootLineHeight]);
export const wrapper = style([f.fullHeight, f.flexColumn, f.rootLineHeight]);

export const appBarLeft = style([
f.flex,
Expand Down
19 changes: 19 additions & 0 deletions docs/pages/api-references/plugins/plugin-basic-ui.en.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,25 @@ const Something = () => {
};
```

### Safe Area

`AppScreen` automatically applies the device's left and right safe area insets to its content and app bar in both themes. The Cupertino title is centered within the safe area. Backgrounds and navigation transitions still span the full screen.

Include `viewport-fit=cover` in the viewport meta tag so the browser exposes the safe area insets.

```html copy
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
```

To extend media or other content to the screen edges, wrap it in a block element and cancel the insets with negative margins on the wrapper:

```css copy
.full-bleed {
margin-left: calc(-1 * env(safe-area-inset-left, 0px));
margin-right: calc(-1 * env(safe-area-inset-right, 0px));
}
```

### `appBar`
<APITable>
| | | |
Expand Down
19 changes: 19 additions & 0 deletions docs/pages/api-references/plugins/plugin-basic-ui.ko.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,25 @@ const Something = () => {
);
};
```
### Safe Area

`AppScreen`은 두 테마 모두에서 본문과 앱 바에 기기의 좌우 Safe Area Inset을 자동으로 반영해요. Cupertino 제목은 안전 영역 안에서 가운데에 배치돼요. 배경과 화면 전환은 화면 전체 너비를 유지해요.

브라우저가 Safe Area Inset을 제공하도록 viewport 메타 태그에 `viewport-fit=cover`를 포함해 주세요.

```html copy
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
```

이미지 등 본문 요소를 화면 끝까지 넓히려면 블록 요소로 감싸고, 감싼 요소에 음수 마진을 지정해 Inset을 상쇄해 주세요.

```css copy
.full-bleed {
margin-left: calc(-1 * env(safe-area-inset-left, 0px));
margin-right: calc(-1 * env(safe-area-inset-right, 0px));
}
```

### `appBar`
<APITable>
| | | |
Expand Down
23 changes: 18 additions & 5 deletions extensions/plugin-basic-ui/src/components/AppBar.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,9 +192,18 @@ export const safeArea = style({

export const container = style([
f.flexAlignEnd,
f.posRel,
appBarOverflow,
{
height: globalVars.appBar.height,
marginLeft: [
"constant(safe-area-inset-left)",
"env(safe-area-inset-left, 0px)",
],
marginRight: [
"constant(safe-area-inset-right)",
"env(safe-area-inset-right, 0px)",
],
transition: transitions({
height: globalVars.appBar.heightTransitionDuration,
}),
Expand Down Expand Up @@ -249,7 +258,14 @@ export const backButton = style([

export const closeButton = style([backButton]);

export const center = style([f.flexAlignCenter, f.flex1, appBarMinHeight]);
export const center = style([
f.flexAlignCenter,
f.flex1,
appBarMinHeight,
{
minWidth: 0,
},
]);

export const centerMain = style({
display: "flex",
Expand Down Expand Up @@ -277,10 +293,7 @@ export const centerMain = style({
left: "50%",
transform: "translate(-50%)",
height: globalVars.appBar.height,
top: [
`max(${globalVars.appBar.minSafeAreaInsetTop}, constant(safe-area-inset-top))`,
`max(${globalVars.appBar.minSafeAreaInsetTop}, env(safe-area-inset-top))`,
],
top: 0,
},
},
});
Expand Down
5 changes: 3 additions & 2 deletions extensions/plugin-basic-ui/src/components/AppBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,10 +118,11 @@ const AppBar = forwardRef<HTMLDivElement, AppBarProps>(
const globalCloseButton = globalOptions.appBar?.closeButton;
const globalBackButton = globalOptions.appBar?.backButton;

const containerRef = useRef<HTMLDivElement>(null);
const centerRef = useRef<any>(null);

const { maxWidth } = useAppBarTitleMaxWidth({
outerRef: ref,
outerRef: containerRef,
innerRef: centerRef,
enable: globalOptions.theme === "cupertino",
});
Expand Down Expand Up @@ -347,7 +348,7 @@ const AppBar = forwardRef<HTMLDivElement, AppBarProps>(
{...activityDataAttributes}
>
<div className={css.safeArea} />
<div className={css.container}>
<div ref={containerRef} className={css.container}>
<div className={css.left}>
{closeButtonLocation === "left" && renderCloseButton()}
{renderBackButton()}
Expand Down
9 changes: 9 additions & 0 deletions extensions/plugin-basic-ui/src/components/AppScreen.css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,16 @@ export const paper = recipe({
export const paperContent = recipe({
base: [
f.posAbsFull,
f.borderBox,
{
paddingLeft: [
"constant(safe-area-inset-left)",
"env(safe-area-inset-left, 0px)",
],
paddingRight: [
"constant(safe-area-inset-right)",
"env(safe-area-inset-right, 0px)",
],
overflowY: "scroll",
WebkitOverflowScrolling: "touch",
"::-webkit-scrollbar": {
Expand Down
Loading