Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Safe Area #559

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open
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
6 changes: 6 additions & 0 deletions .changeset/healthy-dots-swim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@telegram-apps/bridge": minor
"@telegram-apps/sdk": minor
---

Add Safe Area functionality
1 change: 1 addition & 0 deletions apps/docs/.vitepress/packages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ export const packagesLinksGenerator = (prefix: string = "") => {
scope('mini-app'),
scope('popup'),
scope('qr-scanner', 'QR Scanner'),
scope('safe-area'),
scope('secondary-button'),
scope('settings-button'),
scope('swipe-behavior'),
Expand Down
1 change: 1 addition & 0 deletions apps/docs/.vitepress/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export const platformLinksGenerator = (prefix: string = "") => {
section("Functional Features", {
"Closing Behavior": "closing-behavior",
"Swipe Behavior": "swipe-behavior",
"Safe Area": "safe-area",
"Haptic Feedback": "haptic-feedback",
}),
section("Apps Communication", {
Expand Down
229 changes: 229 additions & 0 deletions apps/docs/packages/telegram-apps-sdk/2-x/components/safe-area.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
# Safe Area

The 💠[component](../scopes.md) responsible for the Telegram Mini
Apps [safe area](../../../../platform/safe-area.md).

## Mounting

Before using the component, it is necessary to mount it to work with properly configured properties.
To do so, use the `mount` method. It will update the `isMounted` signal property.

::: code-group

```ts [Variable]
import { safeArea } from '@telegram-apps/sdk';

if (safeArea.mount.isAvailable()) {
safeArea.mount();
safeArea.isMounted(); // true
}
```

```ts [Functions]
import {
mountSafeArea,
isSafeAreaMounted,
} from '@telegram-apps/sdk';

if (mountSafeArea.isAvailable()) {
mountSafeArea();
isSafeAreaMounted(); // true
}
```

:::

To unmount, use the `unmount` method:

::: code-group

```ts [Variable]
safeArea.unmount();
safeArea.isMounted(); // false
```

```ts [Functions]
import {
unmountSafeArea,
isSafeAreaMounted,
} from '@telegram-apps/sdk';

unmountSafeArea();
isSafeAreaMounted(); // false
```

:::

## Binding CSS Variables

To expose the `safeArea` properties via CSS variables, use the `bindCssVars` method.
The `isCssVarsBound` signal property is updated after the method is called.

This method optionally accepts a function that transforms the values `top`, `bottom`, `left`
and `right` into CSS variable names. By default, values are converted to kebab case with the
prefix `--tg-safe-area-` and `--tg-content-safe-area`.

::: code-group

```ts [Variable]
import { safeArea } from '@telegram-apps/sdk';

if (safeArea.bindCssVars.isAvailable()) {
safeArea.bindCssVars();
// Creates CSS variables like:
// --tg-safe-area-inset-top: 0px;
// --tg-safe-area-inset-bottom: 30px;
// --tg-safe-area-inset-left: 40px;
// --tg-safe-area-inset-right: 40px;

// --tg-content-safe-area-inset-top: 40px;
// --tg-content-safe-area-inset-bottom: 0px;
// --tg-content-safe-area-inset-left: 0px;
// --tg-content-safe-area-inset-right: 0px;

safeArea.bindCssVars((component, property) => `--my-prefix-${component}-${property}`);
// Creates CSS variables like:
// --my-prefix-safeArea-top: 0px;
// --my-prefix-safeArea-bottom: 30px;
// --my-prefix-safeArea-bottom: 40px;
// --my-prefix-safeArea-right: 40px;

// --my-prefix-contentSafeArea-top: 40px;
// --my-prefix-contentSafeArea-bottom: 0px;
// --my-prefix-contentSafeArea-left: 0px;
// --my-prefix-contentSafeArea-right: 0px;

safeArea.isCssVarsBound(); // true
}
```

```ts [Functions]
import {
bindSafeAreaCssVars,
isSafeAreaCssVarsBound,
} from '@telegram-apps/sdk';

if (bindSafeAreaCssVars.isAvailable()) {
bindSafeAreaCssVars();
// Creates CSS variables like:
// --tg-safe-area-inset-top: 0px;
// --tg-safe-area-inset-bottom: 30px;
// --tg-safe-area-inset-left: 40px;
// --tg-safe-area-inset-right: 40px;

// --tg-content-safe-area-inset-top: 40px;
// --tg-content-safe-area-inset-bottom: 0px;
// --tg-content-safe-area-inset-left: 0px;
// --tg-content-safe-area-inset-right: 0px;

bindSafeAreaCssVars((component, property) => `--my-prefix-${component}-${property}`);
// Creates CSS variables like:
// --my-prefix-safeArea-top: 0px;
// --my-prefix-safeArea-bottom: 30px;
// --my-prefix-safeArea-bottom: 40px;
// --my-prefix-safeArea-right: 40px;

// --my-prefix-contentSafeArea-top: 40px;
// --my-prefix-contentSafeArea-bottom: 0px;
// --my-prefix-contentSafeArea-left: 0px;
// --my-prefix-contentSafeArea-right: 0px;

isSafeAreaCssVarsBound(); // true
}
```

:::

## Types

### SafeAreaInset

Type representing `safe area` and `content safe area` paddings:

```ts [Variable]
type SafeAreaInset = {
top: number,
bottom: number,
left: number,
right: number
};
```

### State

Type representing `full state` of `safe area`:

```ts [Variable]
type State = {
inset: SafeAreaInset,
contentSafeArea: SafeAreaInset
};
```

## Signals

This section provides a complete list of signals related to the init data.

## `inset`

Return type: `SafeAreaInset`

To get safeArea state, use the `inset` method.

::: code-group

```ts [Variable]
safeArea.inset(); // { top: 0, bottom: 30, left: 40, right: 40 }
```

```ts [Functions]
import { safeAreaInset } from '@telegram-apps/sdk';

safeAreaInset(); // { top: 0, bottom: 30, left: 40, right: 40 }
```

:::

## `contentInset`

To get contentSafeArea state, use the `contentInset` method.

::: code-group

```ts [Variable]
safeArea.contentInset(); // { top: 40, bottom: 0, left: 0, right: 0 }
```

```ts [Functions]
import { contentSafeAreaInset } from '@telegram-apps/sdk';

contentSafeAreaInset(); // { top: 40, bottom: 0, left: 0, right: 0 }
```

:::

## `state`

To get full safe area state, use the `state` method.

::: code-group

```ts [Variable]
safeArea.state();
// {
// inset: { top: 0, bottom: 30, left: 40, right: 40 }
// contentInset: { top: 40, bottom: 0, left: 0, right: 0 }
// }
```

```ts [Functions]
import { safeAreaState } from '@telegram-apps/sdk';

safeAreaState();
// {
// inset: { top: 0, bottom: 30, left: 40, right: 40 }
// contentInset: { top: 40, bottom: 0, left: 0, right: 0 }
// }
```

:::
37 changes: 32 additions & 5 deletions apps/docs/platform/events.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ interface MessageJSON {
Then, lets imagine how we could process an event from Telegram application:

```typescript
window.addEventListener('message', ({ data }) => {
const { eventType, eventData } = JSON.parse(data);
window.addEventListener('message', ({data}) => {
const {eventType, eventData} = JSON.parse(data);
console.log(eventType, eventData);
});
```
Expand Down Expand Up @@ -84,7 +84,7 @@ package, which greatly eases integration.
Here's how to use it:

```ts
import { on } from '@telegram-apps/sdk';
import {on} from '@telegram-apps/sdk';

// Start listening to "viewport_changed" event. Returned value
// is a function, which removes this event listener.
Expand Down Expand Up @@ -239,8 +239,8 @@ Available since: **v6.9**

Application received phone access request status.

| Field | Type | Description |
|--------|----------|-----------------------------------------|
| Field | Type | Description |
|--------|----------|----------------------------------------------------|
| status | `string` | Request status. Can only be `sent` or `cancelled`. |

### `popup_closed`
Expand Down Expand Up @@ -298,6 +298,33 @@ including switching to night mode).
|--------------|--------------------------|--------------------------------------------------------------------------------------------------------|
| theme_params | `Record<string, string>` | Map where the key is a theme stylesheet key and value is the corresponding color in `#RRGGBB` format. |

### `safe_area_changed`

Occurs whenever [the safe area](safe_area.md) was changed in the user's Telegram app.
For example, user switched to landscape mode.
Safe area helps to avoid overlap with system UI elements like notches or navigation bars.

| Field | Type | Description |
|--------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------|
| top | `number` | The top inset in pixels, representing the space to avoid at the top of the screen. Also available as the CSS variable var(--tg-safe-area-inset-top). |
| bottom | `number` | The bottom inset in pixels, representing the space to avoid at the bottom of the screen. Also available as the CSS variable var(--tg-safe-area-inset-bottom). |
| left | `number` | The left inset in pixels, representing the space to avoid on the left side of the screen. Also available as the CSS variable var(--tg-safe-area-inset-left). |
| right | `number` | The right inset in pixels, representing the space to avoid on the right side of the screen. Also available as the CSS variable var(--tg-safe-area-inset-right). |

### `content_safe_area_changed`

Occurs whenever [the content safe area](safe_area.md) was changed in the user's Telegram app.
For example, user switched to landscape mode.
Safe area helps to avoid overlap with avoiding overlap with Telegram UI elements.
Content Safe Area is inside Device Safe Area and only covers Telegram UI.

| Field | Type | Description |
|--------|----------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| top | `number` | The top inset in pixels, representing the space to avoid at the top of the content area. Also available as the CSS variable var(--tg-content-safe-area-inset-top). |
| bottom | `number` | The bottom inset in pixels, representing the space to avoid at the bottom of the content area. Also available as the CSS variable var(--tg-content-safe-area-inset-bottom). |
| left | `number` | The left inset in pixels, representing the space to avoid on the left side of the content area. Also available as the CSS variable var(--tg-content-safe-area-inset-left). |
| right | `number` | The right inset in pixels, representing the space to avoid on the right side of the content area. Also available as the CSS variable var(--tg-content-safe-area-inset-right). |

### `viewport_changed`

Occurs whenever the [viewport](viewport.md) has been changed. For example, when the
Expand Down
14 changes: 14 additions & 0 deletions apps/docs/platform/methods.md
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,20 @@ Requests access to current user's phone.
Requests current [theme](theming.md) from Telegram. As a result, Telegram will
create [theme_changed](events.md#theme-changed) event.

### `web_app_request_safe_area`

Available since: **v8.0**

Requests current [safe area](safe-area.md) information from Telegram. As a result,
Telegram will create [safe_area_changed](events.md#safe-area-changed) event.

### `web_app_request_content_safe_area`

Available since: **v8.0**

Requests current [content safe area](content-safe-area.md) information from Telegram. As a result,
Telegram will create [content_safe_area_changed](events.md#content-safe-area-changed) event.

### `web_app_request_viewport`

Requests current [viewport](viewport.md) information from Telegram. As a result,
Expand Down
20 changes: 20 additions & 0 deletions apps/docs/platform/safe-area.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Safe Area

The **safe area** ensures your app's content on mobile screens is fully visible and usable
by preventing it from being obscured by device features like notches or bottom dock (navigation bars) and Telegram UI features like buttons in [full screen mode](full-screen.md).

In TMA there are 2 different Safe Area objects:
- Safe Area Inset
- Content Safe Area Inset

## Safe Area Inset

This Safe Area represents paddings from **Device UI** like notches, bottom dock (navigation bars) and other possible **System UI** elements.

![Safe Area Inset](/components/safe-area/inset.jpg)

## Content Safe Area Inset

This Safe Area represents paddings from **Telegram UI** like buttons in [full screen mode](full-screen.md).

![Content Safe Area Inset](/components/safe-area/content-inset.jpg)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/docs/public/components/safe-area/inset.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions packages/bridge/src/events/types/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type {
BiometryAuthRequestStatus,
BiometryType,
BiometryTokenUpdateStatus,
SafeAreaInset,
} from './misc.js';

/**
Expand Down Expand Up @@ -217,6 +218,20 @@ export interface Events {
* @see https://docs.telegram-mini-apps.com/platform/events#settings-button-pressed
*/
settings_button_pressed: never;
/**
* Occurs when the device's safe area insets change
* (e.g., due to orientation change or screen adjustments).
* @since 8.0
* @see https://docs.telegram-mini-apps.com/platform/events#safe_area_changed
* */
safe_area_changed: SafeAreaInset;
/**
* Occurs when the safe area for content changes
* (e.g., due to orientation change or screen adjustments).
* @since 8.0
* @see https://docs.telegram-mini-apps.com/platform/events#content_safe_area_changed
* */
content_safe_area_changed: SafeAreaInset;
/**
* Occurs whenever theme settings are changed in the user's Telegram app
* (including switching to night mode).
Expand Down
Loading