Convert Figma logo to code with AI

antfu logovue-starport

🛰 Shared component across routes with animations

1,843
97
1,843
8

Top Related Projects

23,338

Open source, production-ready animation and gesture library for React

A zero-config, drop-in animation utility that adds smooth transitions to your web app. You can use it with React, Vue, or any other JavaScript application.

🚦 The official router for Vue 2

Composition API plugin for Vue 2

ES / TypeScript decorator for class-style Vue components.

22,531

📝 Minimalistic Vue-powered static site generator

Quick Overview

Vue Starport is a component library for Vue 3 that enables seamless element teleportation between different views or components. It allows for smooth transitions and animations when moving elements across the application, creating a more fluid and engaging user experience.

Pros

  • Enhances user experience with smooth transitions between views
  • Easy to implement and integrate into existing Vue 3 projects
  • Supports both Vue 3 and Nuxt 3
  • Highly customizable with various transition options

Cons

  • Limited to Vue 3 and Nuxt 3 projects, not compatible with older versions
  • May introduce complexity in component structure and state management
  • Performance impact on larger applications with many teleported elements
  • Learning curve for developers unfamiliar with teleportation concepts

Code Examples

  1. Basic usage of Starport component:
<template>
  <Starport :port="42">
    <MyComponent />
  </Starport>
</template>
  1. Using Starport with custom transition:
<template>
  <Starport :port="42" :duration="500" transition="fade">
    <MyComponent />
  </Starport>
</template>
  1. Implementing Starport with proxy component:
<template>
  <StarportProxy :port="42">
    <template #default="{ ready }">
      <MyComponent v-if="ready" />
      <PlaceholderComponent v-else />
    </template>
  </StarportProxy>
</template>

Getting Started

  1. Install the package:
npm install vue-starport
  1. Import and use in your Vue 3 app:
import { createApp } from 'vue'
import { StarportPlugin } from 'vue-starport'
import App from './App.vue'

const app = createApp(App)
app.use(StarportPlugin())
app.mount('#app')
  1. Use Starport components in your Vue templates:
<template>
  <Starport :port="uniqueId">
    <YourComponent />
  </Starport>
</template>

Competitor Comparisons

23,338

Open source, production-ready animation and gesture library for React

Pros of Motion

  • More comprehensive animation library with a wider range of features
  • Supports React, making it suitable for a larger ecosystem
  • Extensive documentation and community support

Cons of Motion

  • Larger bundle size due to its comprehensive feature set
  • Steeper learning curve for beginners
  • Not specifically designed for Vue.js applications

Code Comparison

Motion:

<motion.div
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
  exit={{ opacity: 0 }}
>
  Content
</motion.div>

Vue Starport:

<Starport port="uniqueId">
  <Component />
</Starport>

Key Differences

  • Vue Starport is specifically designed for Vue.js, while Motion is React-focused
  • Vue Starport specializes in component transitions between routes, while Motion offers a broader range of animation capabilities
  • Motion provides more granular control over animations, while Vue Starport aims for simplicity in route transitions

Use Cases

  • Choose Motion for complex animations in React applications
  • Opt for Vue Starport when working with Vue.js and focusing on smooth component transitions between routes

Community and Maintenance

  • Motion has a larger community and more frequent updates
  • Vue Starport is maintained by a respected Vue.js developer but has a smaller user base

A zero-config, drop-in animation utility that adds smooth transitions to your web app. You can use it with React, Vue, or any other JavaScript application.

Pros of Auto Animate

  • Framework-agnostic, works with any JavaScript project
  • Simpler API, easier to implement for basic animations
  • Supports a wider range of element types and scenarios

Cons of Auto Animate

  • Less control over animation specifics
  • May not handle complex, multi-step animations as well
  • Lacks built-in support for shared element transitions between routes

Code Comparison

Vue Starport:

<Starport port="my-element">
  <MyComponent />
</Starport>

Auto Animate:

import { autoAnimate } from '@formkit/auto-animate'

onMounted(() => {
  autoAnimate(parentElement)
})

Summary

Vue Starport is specifically designed for Vue.js applications and excels at shared element transitions between routes. It offers more fine-grained control over animations but requires more setup.

Auto Animate, on the other hand, is a simpler, more versatile solution that works across different frameworks. It's easier to implement for basic animations but may lack some advanced features for complex scenarios.

The choice between the two depends on the specific project requirements, the desired level of animation control, and the framework being used.

🚦 The official router for Vue 2

Pros of vue-router

  • Official routing solution for Vue.js, ensuring compatibility and long-term support
  • Extensive documentation and large community support
  • Advanced features like nested routes, navigation guards, and lazy loading

Cons of vue-router

  • More complex setup and configuration for simple use cases
  • Heavier bundle size compared to lightweight alternatives

Code Comparison

vue-router:

import { createRouter, createWebHistory } from 'vue-router'

const router = createRouter({
  history: createWebHistory(),
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About }
  ]
})

vue-starport:

import { createStarport } from 'vue-starport'

const Starport = createStarport()

// In component template
<Starport port="my-component">
  <MyComponent />
</Starport>

Key Differences

  • vue-router focuses on application-wide routing and navigation
  • vue-starport specializes in smooth component transitions between routes
  • vue-router requires more setup but offers more comprehensive routing features
  • vue-starport provides a simpler API for specific transition use cases

Use Cases

  • Choose vue-router for full-featured routing in large Vue.js applications
  • Opt for vue-starport when prioritizing smooth component transitions between views

Composition API plugin for Vue 2

Pros of composition-api

  • Core part of Vue 3, providing a more flexible and reusable code structure
  • Offers better TypeScript support and type inference
  • Allows for better code organization and separation of concerns

Cons of composition-api

  • Steeper learning curve for developers familiar with Options API
  • Can lead to more verbose code in simpler components
  • Requires careful management to avoid callback hell in complex scenarios

Code Comparison

composition-api:

import { ref, computed } from 'vue'

export default {
  setup() {
    const count = ref(0)
    const doubleCount = computed(() => count.value * 2)
    return { count, doubleCount }
  }
}

vue-starport:

import { Starport } from 'vue-starport'

<template>
  <Starport port="my-component">
    <MyComponent />
  </Starport>
</template>

Key Differences

  • composition-api focuses on component logic organization, while vue-starport specializes in component transitions
  • vue-starport provides a unique solution for seamless component state preservation during navigation
  • composition-api is integral to Vue 3 development, whereas vue-starport is an additional utility for specific use cases

Use Cases

composition-api is ideal for:

  • Large-scale applications with complex component logic
  • Projects requiring extensive code reuse and composition

vue-starport excels in:

  • Creating smooth transitions between routes or states
  • Preserving component state across different views or pages

ES / TypeScript decorator for class-style Vue components.

Pros of vue-class-component

  • Provides a more familiar, class-based syntax for developers coming from object-oriented backgrounds
  • Offers better TypeScript integration and type inference
  • Allows for easier use of decorators and mixins

Cons of vue-class-component

  • Requires additional setup and dependencies
  • May have a steeper learning curve for developers new to class-based components
  • Less flexible than the composition API used in vue-starport

Code Comparison

vue-class-component:

import { Vue, Component, Prop } from 'vue-property-decorator'

@Component
export default class MyComponent extends Vue {
  @Prop() private message!: string
}

vue-starport:

<script setup>
import { useStarport } from 'vue-starport'

const { createStarport } = useStarport()
const MyStarport = createStarport('my-starport')
</script>

<template>
  <MyStarport :id="id">
    <!-- Component content -->
  </MyStarport>
</template>

vue-class-component focuses on providing a class-based approach to Vue components, which can be beneficial for developers familiar with object-oriented programming. It offers better TypeScript integration and supports decorators. However, it requires additional setup and may have a steeper learning curve.

In contrast, vue-starport is designed to provide smooth element transitions between routes, using the composition API. It offers a more flexible and lightweight approach, making it easier to implement specific transition effects without the need for complex class structures.

22,531

📝 Minimalistic Vue-powered static site generator

Pros of VuePress

  • Designed specifically for creating documentation websites
  • Built-in markdown support and theme system
  • Large ecosystem with plugins and themes

Cons of VuePress

  • Heavier and more complex setup for simple use cases
  • Less flexible for non-documentation projects
  • Steeper learning curve for customization

Code Comparison

VuePress (config file):

module.exports = {
  title: 'My Documentation',
  description: 'A VuePress site',
  themeConfig: {
    nav: [{ text: 'Home', link: '/' }]
  }
}

Vue Starport (usage):

<template>
  <Starport :port="'my-component'">
    <MyComponent />
  </Starport>
</template>

Key Differences

Vue Starport is a lightweight library focused on providing smooth transitions for components across routes, while VuePress is a full-fledged static site generator tailored for documentation. Vue Starport offers more flexibility for general Vue.js applications, whereas VuePress excels in creating documentation websites with minimal configuration.

Use Cases

  • Choose VuePress for comprehensive documentation sites or blogs
  • Opt for Vue Starport when you need seamless component transitions in a Vue.js application

Both projects serve different purposes and can be valuable depending on your specific requirements and project goals.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README



Vue Starport

Shared Vue component across routes with animations

NPM version

Live Demo

English | 简体中文



Note: With the View Transitions API coming to the browsers, you may not this library anymore (even tho it's not a 1:1 replacement as View Transition does not preseve dom and state).

Why?

It's quite common you might have a same component used in different routes (pages) with a bit different sizes and positions. Sometimes you might want to animate them when user navigates between routes to provide a smooth UX. While such animation is common to be seen in native apps, it's could be a bit challenging to do it in Web.

Vue's component structure is presented as a tree, and the child components are in different branches with their own instances. Meaning when users navigate between routes, the components are not shared across routes.

By that means you can't directly animate the changes because they are in two different instances. The good news is, there is a technique called FLIP to enumerate the transitions between them.

However, FLIP only solves the problem of transitions, the components are still not the same. During the navigation, the internal state of the component will lost.

Thus I started this new approach Starport to experiment with a better solution to fit this requirement.

How?

So since we can't share the components across different branches in the component tree, we could actually hoist them to the root so they become independent from the routes.

To allow each page to still have control of the components, we introduced a Proxy component to present the expected size and position of that component. The proxy will pass the props and position information to the actual component and let it "fly over" the proxy with animations.

When the transition ends and it arrived to the expected position, it will then "land down" to the actual component using the <Teleport/> component.

With this "landing" mechanism, the DOM tree will be preserved as what you will have with the original tree structure. When navigating to another route, the component then will "lift off" back to the floating state, "fly" to the new proxy's position and "land" again.

This is very similar to Terran's Buildings in StarCraft (able to leave the ground and fly to new locations). It's also the inspiration source of the project name Starport.

Install

⚗️ Experimental

npm i vue-starport

Vue Starport only works for Vue 3

Usage

Add <StarportCarrier> component from vue-starport to your root component (app.vue). All <Starport> usage should be inside <StarportCarrier> component.

<script setup>
import { StarportCarrier } from 'vue-starport'
</script>

<template>
  <StarportCarrier> <!-- here -->
    <RouterView />
  </StarportCarrier>
</template>

In routes, wrap the component with the <Starport> component.

<!-- PageA.vue -->
<script setup>
import { Starport } from 'vue-starport'
</script>

<template>
  <div>
    <!-- ... -->
    <Starport port="my-id" style="height:400px"> 
      <MyComponent :prop="value"/>
    </Starport>
  </div>
</template>

On the other page, we do the same thing with the same port id to identify the instance.

<!-- PageB.vue -->
<script setup>
import { Starport } from 'vue-starport'
</script>

<template>
  <div>
    <!-- ... -->
    <Starport port="my-id" style="height:600px">
      <MyComponent :prop="value"/>
    </Starport>
  </div>
</template>

Note that you might need to apply some styles to <Starport> to make it have a defined size indicating the area for the "floating starcraft" to land.

Checkout the Playground for more examples.

Register Components Globally

// main.ts
import StarportPlugin from 'vue-starport'

app.use(StarportPlugin())

And then you can use Starport and StarportCarrier components without importing.

Keep Alive

By default, when navigating to a page without a corresponding <Starport> proxy to land, the component will be destroyed. If you want to keep the component alive even when it's not presented in the current route, you can set keepAlive to true for that specific instance.

<Starport keep-alive port="my-id">
  <MyComponent />
</Starport>

To configure it globally, you can pass options to the plugin:

// main.ts
import StarportPlugin from 'vue-starport'

app.use(StarportPlugin({ keepAlive: true }))

Debug

To debug what happens during the transition, you can add the follow CSS to highlight the parts

[data-starport-craft] {
  background: #0805;
}
[data-starport-proxy]:not([data-starport-landed]) {
  background: #8005;
}

Special Thanks

Thanks to @hangsman who helped to provide the initial solution of proper teleport the element and made this idea valid. Also thanks to the viewers of my live-streaming on Bilibili, those who spend time with me to working on this idea and provided useful feedback during the live.

You can check the recordings of my live-streams (in Chinese), where I wrote this project from scratch.

你可以在哔哩哔哩观看我实现此项目的 直播录像。

Sponsors

License

MIT License © 2022 Anthony Fu

NPM DownloadsLast 30 Days