diff --git a/cspell.json b/cspell.json index 4793b09..9ae77a3 100644 --- a/cspell.json +++ b/cspell.json @@ -4,6 +4,7 @@ "files": ["**/*.{ts,js,astro,html,css,json,yml,yaml,md}"], "words": [ "adam", + "animejs", "AMOLED", "Astronav", "Briel", diff --git a/package.json b/package.json index 950ecb9..bdcce8c 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@fortawesome/free-solid-svg-icons": "6.7.1", "@types/react": "^19.1.6", "@types/react-dom": "^19.1.5", + "animejs": "^4.0.2", "astro": "5.7.10", "astro-navbar": "2.3.7", "autoprefixer": "10.4.14", @@ -45,7 +46,6 @@ "free-astro-components": "1.2.0", "jiti": "^2.4.2", "lefthook": "^1.11.13", - "motion": "^12.15.0", "postcss": "8.5.1", "react": "^19.1.0", "react-dom": "^19.1.0", @@ -71,6 +71,7 @@ "@playwright/test": "1.52.0", "@testing-library/jest-dom": "6.6.3", "@testing-library/user-event": "14.6.1", + "@types/animejs": "^3.1.13", "@types/eslint-plugin-jsx-a11y": "6.10.0", "@types/jsdom": "21.1.7", "@types/node": "22.15.18", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4397a56..2274d06 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,9 @@ importers: '@types/react-dom': specifier: ^19.1.5 version: 19.1.5(@types/react@19.1.6) + animejs: + specifier: ^4.0.2 + version: 4.0.2 astro: specifier: 5.7.10 version: 5.7.10(@types/node@22.15.18)(jiti@2.4.2)(rollup@4.41.1)(typescript@5.6.3)(yaml@2.8.0) @@ -68,9 +71,6 @@ importers: lefthook: specifier: ^1.11.13 version: 1.11.13 - motion: - specifier: ^12.15.0 - version: 12.15.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) postcss: specifier: 8.5.1 version: 8.5.1 @@ -141,6 +141,9 @@ importers: '@testing-library/user-event': specifier: 14.6.1 version: 14.6.1(@testing-library/dom@10.4.0) + '@types/animejs': + specifier: ^3.1.13 + version: 3.1.13 '@types/eslint-plugin-jsx-a11y': specifier: 6.10.0 version: 6.10.0 @@ -370,8 +373,8 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/runtime@7.27.4': - resolution: {integrity: sha512-t3yaEOuGu9NlIZ+hIeGbBjFtZT7j2cb2tg0fuaJKeGotchRjjLfrBA9Kwf8quhpP1EUuxModQg04q/mBwyg8uA==} + '@babel/runtime@7.27.6': + resolution: {integrity: sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==} engines: {node: '>=6.9.0'} '@babel/template@7.27.2': @@ -1505,6 +1508,9 @@ packages: '@tybys/wasm-util@0.9.0': resolution: {integrity: sha512-6+7nlbMVX/PVDCwaIQ8nTOPveOcFLSt8GcXdx8hD0bt39uWxYT88uXzqTd4fTvqta7oeUJqudepapKNt2DYJFw==} + '@types/animejs@3.1.13': + resolution: {integrity: sha512-yWg9l1z7CAv/TKpty4/vupEh24jDGUZXv4r26StRkpUPQm04ztJaftgpto8vwdFs8SiTq6XfaPKCSI+wjzNMvQ==} + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -1826,6 +1832,9 @@ packages: ajv@8.17.1: resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + animejs@4.0.2: + resolution: {integrity: sha512-f0L/kSya2RF23iMSF/VO01pMmLwlAFoiQeNAvBXhEyLzIPd2/QTBRatwGUqkVCC6seaAJYzAkGir55N4SL+h3A==} + ansi-align@3.0.1: resolution: {integrity: sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==} @@ -2747,20 +2756,6 @@ packages: fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} - framer-motion@12.15.0: - resolution: {integrity: sha512-XKg/LnKExdLGugZrDILV7jZjI599785lDIJZLxMiiIFidCsy0a4R2ZEf+Izm67zyOuJgQYTHOmodi7igQsw3vg==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - free-astro-components@1.2.0: resolution: {integrity: sha512-bsT9dWsNlRGDNjqcoIlz6w8NcSCgOpx6oxiwZgYwq9RVbi3JqUImPc6c4Kico2wRJSIXc7HHyr71QgmgXv7nfg==} @@ -3575,26 +3570,6 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} - motion-dom@12.15.0: - resolution: {integrity: sha512-D2ldJgor+2vdcrDtKJw48k3OddXiZN1dDLLWrS8kiHzQdYVruh0IoTwbJBslrnTXIPgFED7PBN2Zbwl7rNqnhA==} - - motion-utils@12.12.1: - resolution: {integrity: sha512-f9qiqUHm7hWSLlNW8gS9pisnsN7CRFRD58vNjptKdsqFLpkVnX00TNeD6Q0d27V9KzT7ySFyK1TZ/DShfVOv6w==} - - motion@12.15.0: - resolution: {integrity: sha512-HLouXyIb1uQFiZgJTYGrtEzbatPc6vK+HP+Qt6afLQjaudiGiLLVsoy71CwzD/Stlh06FUd5OpyiXqn6XvqjqQ==} - peerDependencies: - '@emotion/is-prop-valid': '*' - react: ^18.0.0 || ^19.0.0 - react-dom: ^18.0.0 || ^19.0.0 - peerDependenciesMeta: - '@emotion/is-prop-valid': - optional: true - react: - optional: true - react-dom: - optional: true - mrmime@2.0.1: resolution: {integrity: sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==} engines: {node: '>=10'} @@ -5356,7 +5331,7 @@ snapshots: '@babel/core': 7.27.4 '@babel/helper-plugin-utils': 7.27.1 - '@babel/runtime@7.27.4': {} + '@babel/runtime@7.27.6': {} '@babel/template@7.27.2': dependencies: @@ -6289,7 +6264,7 @@ snapshots: '@testing-library/dom@10.4.0': dependencies: '@babel/code-frame': 7.27.1 - '@babel/runtime': 7.27.4 + '@babel/runtime': 7.27.6 '@types/aria-query': 5.0.4 aria-query: 5.3.0 chalk: 4.1.2 @@ -6316,6 +6291,8 @@ snapshots: tslib: 2.8.1 optional: true + '@types/animejs@3.1.13': {} + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -6704,6 +6681,8 @@ snapshots: json-schema-traverse: 1.0.0 require-from-string: 2.0.2 + animejs@4.0.2: {} + ansi-align@3.0.1: dependencies: string-width: 4.2.3 @@ -7950,15 +7929,6 @@ snapshots: fraction.js@4.3.7: {} - framer-motion@12.15.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): - dependencies: - motion-dom: 12.15.0 - motion-utils: 12.12.1 - tslib: 2.8.1 - optionalDependencies: - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - free-astro-components@1.2.0(@types/node@22.15.18)(jiti@2.4.2)(prettier-plugin-astro@0.14.1)(prettier@3.5.3)(rollup@4.41.1)(yaml@2.8.0): dependencies: '@astrojs/check': 0.9.4(prettier-plugin-astro@0.14.1)(prettier@3.5.3)(typescript@5.6.3) @@ -9038,20 +9008,6 @@ snapshots: minipass@7.1.2: {} - motion-dom@12.15.0: - dependencies: - motion-utils: 12.12.1 - - motion-utils@12.12.1: {} - - motion@12.15.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0): - dependencies: - framer-motion: 12.15.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) - tslib: 2.8.1 - optionalDependencies: - react: 19.1.0 - react-dom: 19.1.0(react@19.1.0) - mrmime@2.0.1: {} ms@2.1.3: {} diff --git a/src/components/Community.astro b/src/components/Community.astro index 10f9571..9c9277a 100644 --- a/src/components/Community.astro +++ b/src/components/Community.astro @@ -1,10 +1,7 @@ --- import Image from 'astro/components/Image.astro' -import { motion } from 'motion/react' -import { getTitleAnimation } from '~/animations' import ComImage from '~/assets/ComImage.png' import Button from '~/components/Button.astro' -import Description from '~/components/Description.astro' import CheckIcon from '~/icons/CheckIcon.astro' import GitHubIcon from '~/icons/GitHubIcon.astro' import { getLocale, getUI } from '~/utils/i18n' @@ -19,50 +16,85 @@ const { ---
- +

{ - community.title.map((title, index) => + community.title.map(title => title !== '\n' ? ( - + {title} - + ) : ( ) ) } - - - {community.description} - +

+

+ {community.description} +

- +
- - +
+
{community.lists.simpleYetPowerful.title} - - +
+
{community.lists.privateAndAlwaysUpToDate.title} - +
- + {community.images.community.alt} - +
+ + diff --git a/src/components/Features.astro b/src/components/Features.astro index 76efc5b..1f3fb5f 100644 --- a/src/components/Features.astro +++ b/src/components/Features.astro @@ -1,9 +1,5 @@ --- -import { motion } from 'motion/react' -import { getTitleAnimation } from '~/animations' import { getLocale, getUI } from '~/utils/i18n' -import Description from './Description.astro' - import Video from './Video.astro' const locale = getLocale(Astro) @@ -20,290 +16,137 @@ interface Props { const { titles } = Astro.props -const descriptions = Object.values(features.featureTabs).map(tab => tab.description) +const featureList = [ + { + key: 'workspaces', + title: features.featureTabs.workspaces.title, + description: features.featureTabs.workspaces.description, + video: 'workspaces', + }, + { + key: 'compact-mode', + title: features.featureTabs.compactMode.title, + description: features.featureTabs.compactMode.description, + video: 'compact-mode', + }, + { + key: 'glance', + title: features.featureTabs.glance.title, + description: features.featureTabs.glance.description, + video: 'glance', + }, + { + key: 'split-view', + title: features.featureTabs.splitView.title, + description: features.featureTabs.splitView.description, + video: 'split-views', + }, +] --- -
- +
+ +
+

+ { + (titles || features.titles).map(title => { + switch (title) { + case '\n': + return + default: + return ( + + {title} + + ) + } + }) + } +

+

+ {features.description} +

+
+ + +
{ - (titles || features.titles).map((title, index) => - title !== '\n' ? ( - - {title} - - ) : ( - - ) - ) - } - - - {features.description} - -
-
- -
- - {features.featureTabs.workspaces.title} - - - {features.featureTabs.compactMode.title} - - - {features.featureTabs.glance.title} - - - {features.featureTabs.splitView.title} - -
- - - - - -
-
-
- -
-
-
+ featureList.map((feature, index) => ( +
+
+

+ {feature.title} +

+

+ {feature.description} +

+
-
-
+ )) + }
- - diff --git a/src/components/Hero.astro b/src/components/Hero.astro index 6bb3b21..da2a619 100644 --- a/src/components/Hero.astro +++ b/src/components/Hero.astro @@ -1,24 +1,11 @@ --- -import { motion } from 'motion/react' -import { getTitleAnimation } from '~/animations' import Button from '~/components/Button.astro' -import Description from '~/components/Description.astro' import Title from '~/components/Title.astro' import ArrowRightIcon from '~/icons/ArrowRightIcon.astro' import { getLocale, getPath, getUI } from '~/utils/i18n' import SocialMediaStrip from './SocialMediaStrip.astro' import Video from './Video.astro' -let titleAnimationCounter = 0 -function getNewAnimationDelay() { - titleAnimationCounter++ - return titleAnimationCounter * 0.15 -} - -function getHeroTitleAnimation() { - return getTitleAnimation(getNewAnimationDelay()) -} - const locale = getLocale(Astro) const getLocalePath = getPath(locale) @@ -32,58 +19,54 @@ const { - + + + diff --git a/src/components/SocialMediaStrip.astro b/src/components/SocialMediaStrip.astro index ed22a5b..cbcf012 100644 --- a/src/components/SocialMediaStrip.astro +++ b/src/components/SocialMediaStrip.astro @@ -1,5 +1,5 @@ --- -const { gap = 4 } = Astro.props +const { class: className, ...props } = Astro.props import { icon, library } from '@fortawesome/fontawesome-svg-core' import { @@ -9,6 +9,7 @@ import { faReddit, faXTwitter, } from '@fortawesome/free-brands-svg-icons' +import { cn } from '~/utils/merge' library.add(faMastodon, faBluesky, faGithub, faXTwitter, faReddit) const Mastodon = icon({ prefix: 'fab', iconName: 'mastodon' }) @@ -18,7 +19,7 @@ const XTwitter = icon({ prefix: 'fab', iconName: 'x-twitter' }) const Reddit = icon({ prefix: 'fab', iconName: 'reddit' }) --- -
+ +