{"id":13515085,"url":"https://github.com/domchristie/turn","last_synced_at":"2025-04-06T13:11:54.703Z","repository":{"id":61124226,"uuid":"388324988","full_name":"domchristie/turn","owner":"domchristie","description":"📖 Animate page transitions in Turbo Drive apps","archived":false,"fork":false,"pushed_at":"2024-01-27T11:59:28.000Z","size":490,"stargazers_count":179,"open_issues_count":9,"forks_count":6,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-03-30T11:08:55.553Z","etag":null,"topics":["animation","animations","css","transitions","viewtransitions"],"latest_commit_sha":null,"homepage":"https://domchristie.github.io/turn/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/domchristie.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-22T04:23:15.000Z","updated_at":"2025-03-02T03:23:40.000Z","dependencies_parsed_at":"2024-01-27T13:05:25.493Z","dependency_job_id":"8308541d-0d27-41a0-9328-2fba28a3e6d6","html_url":"https://github.com/domchristie/turn","commit_stats":{"total_commits":61,"total_committers":1,"mean_commits":61.0,"dds":0.0,"last_synced_commit":"519b80478f916a074f6e1e8fec2e2df696ff8515"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/domchristie%2Fturn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/domchristie%2Fturn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/domchristie%2Fturn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/domchristie%2Fturn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/domchristie","download_url":"https://codeload.github.com/domchristie/turn/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247485290,"owners_count":20946398,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["animation","animations","css","transitions","viewtransitions"],"created_at":"2024-08-01T05:01:06.134Z","updated_at":"2025-04-06T13:11:54.668Z","avatar_url":"https://github.com/domchristie.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# Turn\nAnimate page transitions in [Turbo Drive](https://turbo.hotwired.dev/) apps.\n\n## Installation\nInstall [@hotwired/turbo](https://www.npmjs.com/package/@hotwired/turbo), then\n```\nnpm install @domchristie/turn\n```\n\n## Usage\n\n1. Include Turbo, `dist/turn.js` and `dist/turn.css` however you build your JavaScript \u0026 CSS\n2. Add `data-turn-enter` and `data-turn-exit` to the elements you wish to animate (optional if you're only using View Transitions)\n3. `import Turn from '@domchristie/turn'` and call `Turn.start()` in your application JavaScript\n4. Navigate between pages … ✨\n\n## Customizing Animations\n\nTurn adds `turn-before-exit`, `turn-exit`, and `turn-enter` classes to the HTML element at the appropriate times. Apply your own animations by scoping your animation rules with this selector. For example:\n\n```css\nhtml.turn-advance.turn-exit [data-turn-exit] {\n  animation-name: MY_ANIMATE_OUT;\n  animation-duration: .3s;\n  animation-fill-mode: forwards;\n}\n\nhtml.turn-advance.turn-enter [data-turn-enter] {\n  animation-name: MY_ANIMATE_IN;\n  animation-duration: .6s;\n  animation-fill-mode: forwards;\n}\n\n@keyframes MY_ANIMATE_OUT {\n  …\n}\n\n@keyframes MY_ANIMATE_IN {\n  …\n}\n```\n\nThis is how `turn.css` is organized, so you may want to get rid of that file altogether. `animation-fill-mode: forwards` is recommended to prevent your transitions from jumping back.\n\n### Custom Class Names\n\nThe values set in the `data-turn-exit` and `data-turn-enter` attributes will be applied as class names to that element. This lets you customize animations for each element. Styles should still be scoped by `html.turn-exit` and `html.turn-enter`.\n\n## Class List\n\nThe following class names are added to the HTML element at various time during a navigation lifecycle.\n\n### `turn-view-transitions`\nAdded on start if the device supports View Transitions, and View Transitions are enabled.\n\n### `turn-no-view-transitions`\nAdded on start if the device does not support View Transitions, or View Transitions are disabled.\n\n### `turn-advance`\nAdded when a visit starts and the action is `advance`. You'll probably want to scope most animations with this class. Removed when the navigation has completed and all animations have ended.\n\n### `turn-restore`\nAdded when a visit starts and the action is `restore`. Given the number of ways it's possible to navigate back/forward (back button, swipe left/right, `history.back()`), it's generally recommended that restoration visits are not animated. Removed when the navigation has completed and all animations have ended.\n\n### `turn-replace`\nAdded when a visit starts and the action is `replace`. Removed when the navigation has completed and all animations have ended.\n\n### `turn-before-exit`\nAdded when a visit starts. Useful for optimising animations with `will-change`. (See `turn.css` for an example.) Removed when the exit animations start.\n\n### `turn-exit`\nAdded when a visit starts. Use this to scope exit animations. Removed when the exit animations complete.\n\n### `turn-before-transition` (if View Transitions supported \u0026 enabled)\nAdded after the exit animations and any request has completed, but before the View Transitions have taken their snapshot. Useful when combining View Transitions with custom exit/enter animations. To avoid a flash of content, use this class to target exited elements, and style them in their final \"exit\" state. (See `turn.css` for an example.) Removed when the transition starts.\n\n### `turn-transition` (if View Transitions supported \u0026 enabled)\nAdding during a View Transition. Useful when combining View Transitions with custom exit/enter animations.\n\n### `turn-enter`\nAdded after any requests have completed and previous animations/transitions have completed. Removed once the animations have completed.\n\n## Events\n\n`event.details` may contain:\n- `action`: the action of the visit (`advance` or `restore`)\n- `initiator`: the element the visit was triggered from (an `a`, `form`, or `html` element if a Back/Forward navigation)\n- `referrer`: the URL the page is transitioning from\n- `url`: the URL the page is transitioning to\n- `newBody`: the incoming `\u003cbody\u003e` that will be transitioned to\n\n### `turn:before-exit`\nDispatched before exit animations are started. `event.detail` includes:\n- `action`\n- `initiator`\n- `referrer`\n- `url`\n\n### `turn:before-transition`\nDispatched before a View Transition is started (after exit animations if present). Ideal for setting up `view-transition-name`s before the View Transition performs its capturing. `event.detail` includes:\n- `action`\n- `initiator`\n- `newBody`\n- `referrer`\n\n### `turn:before-enter`\nDispatched before enter animations are started (after Vire Transitions if present). `event.detail` includes:\n- `action`\n- `initiator`\n- `newBody`\n- `referrer`\n\n### `turn:enter`\nDispatched after the all transitions and animations have completed. `event.detail` includes:\n- `action`\n- `referrer`\n- `url`\n- `timing`: the visit's timing metrics\n\n\n### Usage with Tailwind CSS\n\nDefine animations in `tailwind.config.js`, and add a plugin that scopes the styles, e.g.:\n\n```js\nconst plugin = require('tailwindcss/plugin')\n\nmodule.exports = {\n  theme: {\n    extend: {\n      animation: {\n        exit: 'fade-out-up 0.3s cubic-bezier(0.65, 0.05, 0.35, 1) forwards',\n        enter: 'fade-in-up 0.6s cubic-bezier(0.65, 0.05, 0.35, 1) forwards'\n      },\n      keyframes: {\n        'fade-out-up': {/* … */},\n        'fade-in-up': {/* … */}\n      }\n    }\n  },\n\n  plugins: [\n    plugin(function ({ addVariant }) {\n      addVariant('turn-exit', 'html.turn-exit \u0026')\n      addVariant('turn-enter', 'html.turn-enter \u0026')\n    })\n  ]\n}\n```\n\nThen in your HTML:\n\n```html\n\u003cmain data-turn-exit=\"turn-exit:animate-exit\" data-turn-enter=\"turn-enter:animate-enter\"\u003e\n  \u003c!-- … --\u003e\n\u003c/main\u003e\n```\n\n## Disabling Animations\n\nAdd `data-turn=\"false\"` to the `\u003cbody\u003e` to opt out of animations from that page.\n\n(This currently rather basic, but is limited by the information available in Turbo events. Hopefully improvable if [`turbo:visit` events are fired on the initiating element](https://github.com/hotwired/turbo/pull/750).)\n\n## Tip \u0026 Tricks\n\n### 1. Animate Changes\nAvoid animating the whole `body`. Animations should target elements that change on navigation. So avoid animating persistent headers and instead animate the `main` element or just the panels/cards within it.\n\n### 2. Nesting\nNesting animating elements draws attention and brings screens to life. Add `data-turn-exit`/`data-turn-enter` attributes to elements such as headings and key images within an animating container. The compound animation effects means they'll exit faster, and enter slower than other elements. For example:\n```html\n\u003cmain data-turn-exit data-turn-enter\u003e\n  \u003ch1 data-turn-exit data-turn-enter\u003eHello, world!\u003c/h1\u003e\n\u003c/main\u003e\n```\n\n### 3. Optimizing Animations\nJumpy exit animations can be prevented using the `will-change` CSS property. Turn adds a `turn-before-exit` class to the HTML element just before adding the exit classes. This provides an opportunity to notify the browser of upcoming changes. For example, by default `turn.css` does the following:\n\n```css\nhtml.turn-before-exit [data-turn-exit],\nhtml.turn-exit [data-turn-exit] {\n  will-change: transform, opacity;\n}\n```\n\n### 4. Loading Spinner\nExit animations on slow requests can leave users with a blank screen. Improve the experience with a loading spinner that appears a short time after the exit animation. For example, if your exit animation take 600ms, add a spinner that starts appearing 700ms after that by using `transition-delay`. This spinner can live permanently in the `body` and only transition when the `turn-exit` class is applied:\n\n```css\n.spinner {\n  position: fixed;\n  top: 15%;\n  left: 50%;\n  transform: translateX(-50%);\n  opacity: 0;\n  transition: opacity 100ms;\n}\nhtml.turn-exit .spinner {\n  opacity: 1;\n  transition-delay: 700ms\n}\n```\n\n## Not seeing animations?\n\nCheck your device preferences to see if you have requested reduced motion. Turn will only animate transitions when the `prefers-reduced-motion` media query does not match `reduce`.\n\n## How does it work?\n\nTurn adds exit and enter classes at the appropriate times like so:\n1. on `turbo:visit` add the exit classes\n2. pause `turbo:before-render` _(wait for exit animations to complete before resuming)_\n3. on `turbo:render`, remove exit classes and add the enter classes\n4. on `turbo:load`, wait for the enter animations to complete before removing the enter classes\n\n## Credits\n\nDefault fade in/out animations adapted from [Jon Yablonski](https://jonyablonski.com/)'s [Humane By Design](https://humanebydesign.com/).\n\n## License\nCopyright © 2021+ Dom Christie and released under the MIT license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdomchristie%2Fturn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdomchristie%2Fturn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdomchristie%2Fturn/lists"}