diff --git a/.docs/composables/useNavigationMotion.ts b/.docs/composables/useNavigationMotion.ts index 974f14b..65acd85 100644 --- a/.docs/composables/useNavigationMotion.ts +++ b/.docs/composables/useNavigationMotion.ts @@ -39,13 +39,6 @@ function _useNavigation() { to: '/motion/examples', active: route.path.startsWith('/motion/examples'), }, - { - label: 'Community', - description: 'Find answers and support from the community.', - icon: 'i-ph-chats-teardrop-duotone', - to: '/motion/community', - active: route.path.startsWith('/motion/community'), - }, ], }, { diff --git a/.docs/content/motion/1.getting-started/_dir.yml b/.docs/content/motion/1.getting-started/_dir.yml index 7a3f0a8..e1056f7 100644 --- a/.docs/content/motion/1.getting-started/_dir.yml +++ b/.docs/content/motion/1.getting-started/_dir.yml @@ -1,3 +1,3 @@ title: Getting Started titleTemplate: '%s · Get Started with Vue3 and Nuxt3' -icon: i-ph-compass-tool-light +icon: i-ph-rocket-launch-duotone diff --git a/.docs/content/motion/2.guide/1.animation/1.simple-animations.md b/.docs/content/motion/2.guide/1.animation/1.simple-animations.md index a120a67..68e1317 100644 --- a/.docs/content/motion/2.guide/1.animation/1.simple-animations.md +++ b/.docs/content/motion/2.guide/1.animation/1.simple-animations.md @@ -3,10 +3,12 @@ title: 'Simple animations' description: '' --- +## Animation + Most animations will be performed with the `motion` component and the animate prop. ```html - + ``` When any value in `animate` changes, the component will automatically animate to the updated target. @@ -15,3 +17,79 @@ When any value in `animate` changes, the component will automatically animate to src="https://stackblitz.com/edit/vitejs-vite-wmhgda?embed=1&file=src%2FDemo.vue&hideExplorer=1&hideNavigation=1&view=preview" style="width:100%; height:500px; border:0; border-radius: 4px; overflow:hidden;" > + +## Enter animations + +When a `motion` component is first created, it'll automatically animate to the values in `animate` if they're different from those defined in `style` or `initial`. You can set the initial prop to `false` to disable enter animations. + +```html + +``` + + + +## Exit animations + +Oku Motion provides the `Presence component` to keep components in the DOM while they perform on exit animation. + +```html + + + +``` + + + +## Keyframes + +Values in `animate` can also be set as a series of keyframes. This will animate through each value in sequence. + +```html + +``` + + + +We can use the current value as the initial keyframe by passing a **wildcard keyframe**, `null`. + +```html + +``` + +This way, if a keyframes animation starts while the value is currently animating, the transition will be more natural. It also reduces duplication in our code. + + + +Each keyframe will be spaced evenly throughout the animaton. You can override this by setting the times option via transition. + +times is an array of the same length as the keyframes array, with numbers between 0 and 1 definining where in the animation each keyframe should be hit. + +```html + +``` diff --git a/.docs/content/motion/2.guide/1.animation/2.transition.md b/.docs/content/motion/2.guide/1.animation/2.transition.md new file mode 100644 index 0000000..299074f --- /dev/null +++ b/.docs/content/motion/2.guide/1.animation/2.transition.md @@ -0,0 +1,115 @@ +--- +title: 'Transition' +description: 'A transition defines how values animate from one state to another.' +--- + +A `transition` defines the type of animation used when animating between two values. + +```html + +``` + + + +## Value-specific transitions + +A different set of transition setting can be defined for each specific value. + +```html + +``` + + + +## Orchestration + +### delay + +- type: `number` + +Delay the animation by this duration (in seconds). Defaults to 0. + +```ts +const transition = { + delay: 0.2 +} +``` + +By setting `delay` to a negative value, the animation will start that long into the animation. For instance to start 1 second in, `delay` can be set to `-1`. + +### repeat + +- type: `number` + +The number of times to repeat the transition. Set to `Infinity` for perpetual repeating. + +Without setting `repeatType`, this will loop the animation. + +```html + +``` + +### repeatType + +- type: `"loop" | "reverse" | "mirror"` + +How to repeat the animation. This can be either: + +- `loop`: Repeats the animation from the start +- `reverse`: Alternates between forward and backwards playback +- `mirror`: Switches from and to alternately + +```html + +``` + +### repeatDelay + +- type: `number` + +When repeating an animation, `repeatDelay` will set the duration of the time to wait, in seconds, between each repetition. + +```html + +``` + +## Miscellaneous + +### TargetAndTransition + +An object that specifies values to animate to. Each value may be set either as a single value, or an array of values. + +It may also option contain these properties: + +- `transition`: Specifies transitions for all or individual values. +- `transitionEnd`: Specifies values to set when the animation finishes. diff --git a/.docs/content/motion/2.guide/1.animation/3.Gestures.md b/.docs/content/motion/2.guide/1.animation/3.Gestures.md new file mode 100644 index 0000000..cfb29e3 --- /dev/null +++ b/.docs/content/motion/2.guide/1.animation/3.Gestures.md @@ -0,0 +1,21 @@ +--- +title: 'Gestures' +description: 'A powerful gesture recognition system for the browser.' +--- + +Oku Motion extends the basic set of event listeners provided by Vue3 with a simple yet powerful set of UI gesture recognisers. + +It currently has support for hover, press and more. Each gesture has a series of event listeners that you can attach to your `motion` component. + +## Animation helpers + +`motion` components provide multiple gesture animation props: `whileHover`, `whileTap`, `whileFocus`, `whileDrag` and `whileInView`. These can define animation targets to temporarily animate to while a gesture is active. + +## Hover + +The hover gesture detects when a pointer hovers a component. + + diff --git a/.docs/content/motion/4.api/1.motion.md b/.docs/content/motion/2.guide/2.components/1.motion.md similarity index 100% rename from .docs/content/motion/4.api/1.motion.md rename to .docs/content/motion/2.guide/2.components/1.motion.md diff --git a/.docs/content/motion/4.api/2.presence.md b/.docs/content/motion/2.guide/2.components/2.presence.md similarity index 100% rename from .docs/content/motion/4.api/2.presence.md rename to .docs/content/motion/2.guide/2.components/2.presence.md diff --git a/.docs/content/motion/4.api/3.presence-group.md b/.docs/content/motion/2.guide/2.components/3.presence-group.md similarity index 100% rename from .docs/content/motion/4.api/3.presence-group.md rename to .docs/content/motion/2.guide/2.components/3.presence-group.md diff --git a/.docs/content/motion/2.guide/2.components/_dir.yml b/.docs/content/motion/2.guide/2.components/_dir.yml new file mode 100644 index 0000000..fe6ae65 --- /dev/null +++ b/.docs/content/motion/2.guide/2.components/_dir.yml @@ -0,0 +1,3 @@ +title: Components +icon: i-ph-brackets-curly-duotone +# navigation: false diff --git a/.docs/content/motion/3.api/1.motion.md b/.docs/content/motion/3.api/1.motion.md new file mode 100644 index 0000000..593c27d --- /dev/null +++ b/.docs/content/motion/3.api/1.motion.md @@ -0,0 +1,280 @@ +--- +title: Motion +description: Renders an animatable HTML or SVG element. +icon: i-ph-brackets-curly-duotone +--- + +Renders an animatable HTML or SVG element. + +```ts + +``` + +# Usage +Import Motion from "@oku-ui/motion" and register it with your component. + + +```ts + + + + + +``` + +Motion accepts an animate prop. Add the following to the editable example above: + +``` + +``` + +The animate prop accepts all the same values and keyframes as Motion One's [animate](https://motion.dev/dom/animate) function. + + +## Transition settings + +We can change the type of animation used by passing a `transition` prop. + +```ts + + +``` + +By default transition options are applied to all values, but we can also override on a per-value basis: + +```ts + + +``` + +All the same transition options from Motion One's [animate function](https://motion.dev/dom/animate#options) are accepted. You can even import custom easing from Motion One, like [spring](https://motion.dev/dom/spring): + +```ts + + + + + + + +``` + + +## Props + +### tag + +default: `div` + +Define a HTML or SVG tag to render. + +```ts + +``` + +### animate + +A target of values to animate to. + +``` + +``` + +Whenever a value in animate changes, the element will automatically animate to the latest value. + +The animate prop accepts all the same values and keyframes as Motion One's [animate function](https://motion.dev/dom/animate). + +### initial +A target of values to animate from when the element is first rendered. + +```ts + +``` + +If set to false, the target defined in animate will be immediately set when the element is first rendered. Only subsequent changes to animate will animate. + + +```ts + +``` + + +### exit + +A target of values to animate to when the element is hidden via v-if or v-show. + +The element must be a direct child of the Presence component. + +```ts + + + + + + +``` + +Note: This animation is only interruptible if the element is hidden via v-show. + +The exit prop accepts all the same values and keyframes as Motion One's [animate function](https://motion.dev/dom/animate). + +### transition + +Provides a default transition for all animations to use. + +```ts + + +``` + +Supports all [animate options.](https://motion.dev/dom/animate#options) + +The transition defined in this prop can be overridden for specific animation props by passing those a transition option: + +```ts + + +``` + +## Events + +The Motion components emit [custom DOM events](https://developer.mozilla.org/en-US/docs/Web/Events/Creating_and_triggering_events#adding_custom_data_%E2%80%93_customevent) to the rendered element. The detail prop is provided data on the related animation. + +```ts + + + + + +``` + +### motionstart + +Fires when any animation is started. + +### motioncomplete + +Fires when any animation is completed. + diff --git a/.docs/content/motion/3.api/2.presence.md b/.docs/content/motion/3.api/2.presence.md new file mode 100644 index 0000000..9e6ccf9 --- /dev/null +++ b/.docs/content/motion/3.api/2.presence.md @@ -0,0 +1,168 @@ +--- +title: Presence +description: Perform exit animations in Vue. +icon: i-ph-brackets-curly-duotone +--- + + +```ts + + + + +``` + +# Usage +Import Motion from "@oku-ui/motion" and register it with your component. + + +```ts + + + + + +``` + +Now, when a child `Motion` component is hidden with `v-if` or `v-show`, it will animate to the target defined in `exit` prop. + +Note: Presence currently only supports a single rendered child. + + +## Animate between elements + +By passing a different `key` to multiple children and rendering just one at a time, we can animate between them at a given time. + + +```ts + + + + + +``` + +In the above example, each element has the position: absolute CSS rule so when the incoming element is rendered it doesn't conflict with the element animating away. + +In situations where this isn't possible, `:exitBeforeEnter="true"` can be set on Presence to ensure the exiting element animates out before the entering element is rendered. + + +## Props + +### initial + +default: `true` + +If `false`, will disable the first animation on all child `Motion` elements the first time `Presence` is rendered. + + +### exitBeforeEnter + +default: `false` + +If `true`, Presence will wait for the exiting element to finish animating out before animating in the next one. \ No newline at end of file diff --git a/.docs/content/motion/3.api/3.presence-group.md b/.docs/content/motion/3.api/3.presence-group.md new file mode 100644 index 0000000..0a87c24 --- /dev/null +++ b/.docs/content/motion/3.api/3.presence-group.md @@ -0,0 +1,18 @@ +--- +title: PresenceGroup +description: Perform exit animations in Vue. Group multiple Motion components together. +icon: i-ph-brackets-curly-duotone +--- + + +```ts + + + +``` \ No newline at end of file diff --git a/.docs/content/motion/3.api/_dir.yml b/.docs/content/motion/3.api/_dir.yml new file mode 100644 index 0000000..4101839 --- /dev/null +++ b/.docs/content/motion/3.api/_dir.yml @@ -0,0 +1,2 @@ +title: API +icon: i-ph-app-window-duotone diff --git a/.docs/content/motion/3.api/index.md b/.docs/content/motion/3.api/index.md new file mode 100644 index 0000000..e69de29 diff --git a/.docs/content/motion/3.examples/_dir.yml b/.docs/content/motion/3.examples/_dir.yml deleted file mode 100644 index d6b9982..0000000 --- a/.docs/content/motion/3.examples/_dir.yml +++ /dev/null @@ -1,2 +0,0 @@ -title: Nuxt Module -icon: i-simple-icons-nuxtdotjs \ No newline at end of file diff --git a/.docs/content/motion/3.examples/1.index.md b/.docs/content/motion/4.examples/1.index.md similarity index 100% rename from .docs/content/motion/3.examples/1.index.md rename to .docs/content/motion/4.examples/1.index.md diff --git a/.docs/content/motion/4.examples/_dir.yml b/.docs/content/motion/4.examples/_dir.yml new file mode 100644 index 0000000..2379ec9 --- /dev/null +++ b/.docs/content/motion/4.examples/_dir.yml @@ -0,0 +1,2 @@ +title: Examples +icon: i-ph-app-window-duotone diff --git a/.docs/content/motion/3.examples/animate-between.md b/.docs/content/motion/4.examples/animate-between.md similarity index 100% rename from .docs/content/motion/3.examples/animate-between.md rename to .docs/content/motion/4.examples/animate-between.md diff --git a/.docs/content/motion/3.examples/exit.md b/.docs/content/motion/4.examples/exit.md similarity index 100% rename from .docs/content/motion/3.examples/exit.md rename to .docs/content/motion/4.examples/exit.md diff --git a/.docs/content/motion/3.examples/glide.md b/.docs/content/motion/4.examples/glide.md similarity index 100% rename from .docs/content/motion/3.examples/glide.md rename to .docs/content/motion/4.examples/glide.md diff --git a/.docs/content/motion/3.examples/spring.md b/.docs/content/motion/4.examples/spring.md similarity index 100% rename from .docs/content/motion/3.examples/spring.md rename to .docs/content/motion/4.examples/spring.md diff --git a/.docs/content/motion/3.examples/stagger.md b/.docs/content/motion/4.examples/stagger.md similarity index 100% rename from .docs/content/motion/3.examples/stagger.md rename to .docs/content/motion/4.examples/stagger.md diff --git a/.docs/content/motion/5.community/1.getting-help.md b/.docs/content/motion/5.community/1.getting-help.md deleted file mode 100644 index 19fb4b4..0000000 --- a/.docs/content/motion/5.community/1.getting-help.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Getting Help -description: We're a friendly community of developers and we'd love to help. -icon: 'i-ph-folder-simple-duotone' ---- - -## Community Support - -If you have questions or need help with Motion, please join our [Discord Server](https://chat.productdevbook.com) or [GitHub Discussions](https://github.com/oku-ui/motion/discussions). \ No newline at end of file diff --git a/.docs/content/motion/5.community/_dir.yml b/.docs/content/motion/5.community/_dir.yml deleted file mode 100644 index d2ff72d..0000000 --- a/.docs/content/motion/5.community/_dir.yml +++ /dev/null @@ -1,2 +0,0 @@ -title: Community -icon: i-ph-folder-notch-open-duotone \ No newline at end of file diff --git a/.docs/pages/index.vue b/.docs/pages/index.vue deleted file mode 100644 index 8787b3b..0000000 --- a/.docs/pages/index.vue +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/.docs/pages/motion/[...slug]/index.vue b/.docs/pages/motion/[...slug]/index.vue index a6f354b..60c8a01 100644 --- a/.docs/pages/motion/[...slug]/index.vue +++ b/.docs/pages/motion/[...slug]/index.vue @@ -16,7 +16,7 @@ if (!page.value) throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true }) const { data: surround } = await useAsyncData(`${route.path}-surround`, async () => { - if (page.value.surround === false) + if (page.value?.surround === false) return [] return queryContent('/motion') @@ -24,7 +24,6 @@ const { data: surround } = await useAsyncData(`${route.path}-surround`, async () .without(['body', 'excerpt']) .findSurround(withoutTrailingSlash(route.path)) }) - const breadcrumb = computed(() => { const links = mapContentNavigation(findPageBreadcrumb(navigation.value, page.value)).map(link => ({ label: link.label, @@ -33,11 +32,10 @@ const breadcrumb = computed(() => { return links }) - const titleTemplate = computed(() => { - if (page.value.titleTemplate) + if (page.value?.titleTemplate) return page.value.titleTemplate - const titleTemplate = navKeyFromPath(route.path, 'titleTemplate', navigation.value) + const titleTemplate = navKeyFromPath(route.path, 'titleTemplate', navigation!.value) if (titleTemplate) return titleTemplate return '%s · Motion · Oku' @@ -64,14 +62,12 @@ const communityLinks = computed(() => [{ to: 'https://github.com/sponsors/productdevbook', target: '_blank', }]) - const ecosystemLinks = [{ icon: 'i-ph-graduation-cap-duotone', label: 'Video Courses', to: 'https://masteringnuxt.com/nuxt3?ref=oku-ui.com', target: '_blank', }] - const title = page.value.head?.title || page.value.title const description = page.value.head?.description || page.value.description @@ -82,13 +78,6 @@ useSeoMeta({ ogDescription: description, ogTitle: titleTemplate.value?.includes('%s') ? titleTemplate.value.replace('%s', title) : title, }) - -// defineOgImage({ -// component: 'Pergel', -// title, -// description, -// headline: breadcrumb.value.length ? breadcrumb.value[breadcrumb.value.length - 1].label : '', -// })