> ## Documentation Index
> Fetch the complete documentation index at: https://inertiajs-vi.tuantq.online/llms.txt
> Use this file to discover all available pages before exploring further.

# View Transition

Inertia hỗ trợ [View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions), cho phép tạo animation khi chuyển trang.

View Transitions API là [tính năng trình duyệt tương đối mới](https://caniuse.com/view-transitions). Với trình duyệt không hỗ trợ API này, Inertia tự động fallback về chuyển trang tiêu chuẩn một cách an toàn.

## Bật transition

Bạn có thể bật view transition cho một visit bằng cách đặt tùy chọn `viewTransition` thành `true`. Mặc định, một hiệu ứng cross-fade sẽ được áp dụng giữa các trang.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from "@inertiajs/vue3";

  router.visit("/another-page", { viewTransition: true });
  ```

  ```js React icon="react" theme={null}
  import { router } from "@inertiajs/react";

  router.visit("/another-page", { viewTransition: true });
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from "@inertiajs/svelte";

  router.visit("/another-page", { viewTransition: true });
  ```
</CodeGroup>

## Callback transition

Bạn cũng có thể truyền callback vào tùy chọn `viewTransition`; callback nhận instance [`ViewTransition`](https://developer.mozilla.org/en-US/docs/Web/API/ViewTransition) tiêu chuẩn do trình duyệt cung cấp. Điều này cho phép bạn hook vào các promise khác nhau của API.

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { router } from "@inertiajs/vue3";

  router.visit("/another-page", {
    viewTransition: (transition) => {
      transition.ready.then(() => console.log("Transition ready"));
      transition.updateCallbackDone.then(() => console.log("DOM updated"));
      transition.finished.then(() => console.log("Transition finished"));
    },
  });
  ```

  ```js React icon="react" theme={null}
  import { router } from "@inertiajs/react";

  router.visit("/another-page", {
    viewTransition: (transition) => {
      transition.ready.then(() => console.log("Transition ready"));
      transition.updateCallbackDone.then(() => console.log("DOM updated"));
      transition.finished.then(() => console.log("Transition finished"));
    },
  });
  ```

  ```js Svelte icon="s" theme={null}
  import { router } from "@inertiajs/svelte";

  router.visit("/another-page", {
    viewTransition: (transition) => {
      transition.ready.then(() => console.log("Transition ready"));
      transition.updateCallbackDone.then(() => console.log("DOM updated"));
      transition.finished.then(() => console.log("Transition finished"));
    },
  });
  ```
</CodeGroup>

## Liên kết

Tùy chọn `viewTransition` cũng có trên component `Link`.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  import { Link } from '@inertiajs/vue3'

  <Link href="/another-page" view-transition>Navigate</Link>
  ```

  ```jsx React icon="react" theme={null}
  import { Link } from "@inertiajs/react";

  <Link href="/another-page" viewTransition>
    Navigate
  </Link>;
  ```

  ```svelte Svelte icon="s" theme={null}
  import { Link } from '@inertiajs/svelte'

  <Link href="/another-page" viewTransition>Navigate</Link>
  ```
</CodeGroup>

Bạn cũng có thể truyền callback để truy cập instance `ViewTransition`.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  import { Link } from '@inertiajs/vue3'

  <Link
    href="/another-page"
    :view-transition="
      (transition) => transition.finished.then(() => console.log('Done'))
    "
  >
      Navigate
  </Link>
  ```

  ```jsx React icon="react" theme={null}
  import { Link } from "@inertiajs/react";

  <Link
    href="/another-page"
    viewTransition={(transition) =>
      transition.finished.then(() => console.log("Done"))
    }
  >
    Navigate
  </Link>;
  ```

  ```svelte Svelte icon="s" theme={null}
  import { Link } from '@inertiajs/svelte'

  <Link
      href="/another-page"
      viewTransition={(transition) => transition.finished.then(() => console.log('Done'))}
  >
      Navigate
  </Link>
  ```
</CodeGroup>

## Cấu hình toàn cục

Bạn có thể bật view transition trên toàn cục cho mọi visit bằng cách cấu hình callback `visitOptions` khi [khởi tạo ứng dụng Inertia](/v3/installation/client-side-setup#configuring-defaults).

<CodeGroup>
  ```js Vue icon="vuejs" theme={null}
  import { createInertiaApp } from "@inertiajs/vue3";

  createInertiaApp({
    // ...
    defaults: {
      visitOptions: (href, options) => {
        return { viewTransition: true };
      },
    },
  });
  ```

  ```jsx React icon="react" theme={null}
  import { createInertiaApp } from "@inertiajs/react";

  createInertiaApp({
    // ...
    defaults: {
      visitOptions: (href, options) => {
        return { viewTransition: true };
      },
    },
  });
  ```

  ```js Svelte icon="s" theme={null}
  import { createInertiaApp } from "@inertiajs/svelte";

  createInertiaApp({
    // ...
    defaults: {
      visitOptions: (href, options) => {
        return { viewTransition: true };
      },
    },
  });
  ```
</CodeGroup>

## Tùy chỉnh transition

Bạn có thể tùy chỉnh transition animation bằng CSS. View Transitions API dùng một số pseudo-element mà bạn có thể target bằng CSS để tạo animation riêng. Các ví dụ sau lấy từ [tài liệu Chrome](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#customize_the_transition).

```css theme={null}
@keyframes fade-in {
  from {
    opacity: 0;
  }
}
@keyframes fade-out {
  to {
    opacity: 0;
  }
}
@keyframes slide-from-right {
  from {
    transform: translateX(30px);
  }
}
@keyframes slide-to-left {
  to {
    transform: translateX(-30px);
  }
}
::view-transition-old(root) {
  animation:
    90ms cubic-bezier(0.4, 0, 1, 1) both fade-out,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-to-left;
}
::view-transition-new(root) {
  animation:
    210ms cubic-bezier(0, 0, 0.2, 1) 90ms both fade-in,
    300ms cubic-bezier(0.4, 0, 0.2, 1) both slide-from-right;
}
```

Bạn cũng có thể animate từng element riêng lẻ giữa các trang bằng cách gán `view-transition-name` duy nhất. Ví dụ, bạn có thể animate avatar từ kích thước lớn trên trang profile xuống kích thước nhỏ trên dashboard.

<CodeGroup>
  ```vue Vue icon="vuejs" theme={null}
  <!-- Profile.vue -->
  <template>
    <img src="/avatar.jpg" alt="User" class="avatar-large" />
  </template>

  <style>
  .avatar-large {
    view-transition-name: user-avatar;
    width: auto;
    height: 200px;
  }
  </style>

  <!-- Dashboard.vue -->
  <template>
    <img src="/avatar.jpg" alt="User" class="avatar-small" />
  </template>

  <style>
  .avatar-small {
    view-transition-name: user-avatar;
    width: auto;
    height: 40px;
  }
  </style>
  ```

  ```jsx React icon="react" theme={null}
  // Profile.jsx
  export default function Profile() {
      return <img src="/avatar.jpg" alt="User" className="avatar-large" />
  }

  // CSS
  .avatar-large {
      view-transition-name: user-avatar;
      width: auto;
      height: 200px;
  }

  // Dashboard.jsx
  export default function Dashboard() {
      return <img src="/avatar.jpg" alt="User" className="avatar-small" />
  }

  // CSS
  .avatar-small {
      view-transition-name: user-avatar;
      width: auto;
      height: 40px;
  }
  ```

  ```svelte Svelte icon="s" theme={null}
  <!-- Profile.svelte -->
  <img src="/avatar.jpg" alt="User" class="avatar-large" />

  <style>
  .avatar-large {
      view-transition-name: user-avatar;
      width: auto;
      height: 200px;
  }
  </style>

  <!-- Dashboard.svelte -->
  <img src="/avatar.jpg" alt="User" class="avatar-small" />

  <style>
  .avatar-small {
      view-transition-name: user-avatar;
      width: auto;
      height: 40px;
  }
  </style>
  ```
</CodeGroup>

Bạn có thể tùy chỉnh view transition theo ý muốn bằng bất kỳ CSS animation nào. Để biết thêm, xem [tài liệu View Transitions API](https://developer.chrome.com/docs/web-platform/view-transitions/same-document#customize_the_transition).

***

## Tài liệu chính thức

Bài dịch này được đối chiếu từ [tài liệu Inertia.js v3 chính thức](https://inertiajs.com/docs/v3/the-basics/view-transitions). Nếu có khác biệt do phiên bản hoặc cập nhật mới, hãy ưu tiên tài liệu chính thức làm nguồn tham chiếu.
