From 00323a7919e42717f0782090e2dc64a5ea614c5b Mon Sep 17 00:00:00 2001
From: Prospector <6166773+Prospector@users.noreply.github.com>
Date: Fri, 11 Sep 2026 13:48:50 -0700
Subject: [PATCH 1/2] in-house tooltips & floating menus
---
apps/app-frontend/package.json | 2 +-
apps/app-frontend/src/App.vue | 142 ++++----
.../src/components/ui/AppActionBar.vue | 12 +-
.../src/components/ui/NavButton.vue | 59 ++-
.../components/ui/QuickInstanceSwitcher.vue | 49 ++-
.../ui/skin/VirtualSkinSectionList.vue | 9 +-
.../src/components/ui/world/WorldItem.vue | 2 +-
.../app-frontend/src/locales/en-US/index.json | 3 +
apps/app-frontend/src/main.js | 18 +-
apps/frontend/nuxt.config.ts | 7 +-
apps/frontend/package.json | 2 +-
.../AnalyticsChartControls.vue | 63 +---
.../AnalyticsChartLegend.vue | 30 +-
.../stat-cards/StatCard.vue | 2 +-
.../ui/ProjectCollectionSaveButton.vue | 33 +-
.../ui/dashboard/RevenueTransaction.vue | 9 +-
.../checklist/ModerationChecklist.vue | 19 +-
apps/frontend/src/layouts/default.vue | 4 +
apps/frontend/src/pages/[type]/[project].vue | 6 +-
.../src/pages/dashboard/revenue/index.vue | 44 +--
.../src/pages/discover/[type]/index.vue | 2 +-
apps/frontend/src/plugins/floating.ts | 5 +
packages/assets/styles/classes.scss | 163 +++++----
packages/ui/.storybook/preview.ts | 29 +-
packages/ui/package.json | 2 +-
packages/ui/src/components/base/Combobox.vue | 2 +
.../src/components/base/DropdownFilterBar.vue | 2 +
.../ui/src/components/base/DropdownSelect.vue | 8 +
.../src/components/base/FloatingActionBar.vue | 34 +-
.../ui/src/components/base/FloatingPanel.vue | 3 +
.../ui/src/components/base/MultiSelect.vue | 15 +-
.../src/components/base/MultiStageModal.vue | 3 +-
.../ui/src/components/base/PopoutMenu.vue | 93 -----
.../ui/src/components/base/ToggleCard.vue | 4 +-
.../components/base/UnsavedChangesPopup.vue | 5 +-
.../base/buttons/TeleportOverflowMenu.vue | 109 +++---
.../base/buttons/TeleportPopoutMenu.vue | 132 +++----
packages/ui/src/components/base/index.ts | 1 -
.../ExternalProjectLookupCard.vue | 8 +-
.../src/components/floating/FloatingMenu.vue | 250 +++++++++++++
.../ui/src/components/floating/Tooltip.vue | 272 ++++++++++++++
.../components/floating/TooltipDirective.vue | 14 +
packages/ui/src/components/floating/index.ts | 3 +
packages/ui/src/components/index.ts | 1 +
packages/ui/src/components/modal/NewModal.vue | 177 +++++++--
.../project/ProjectPageVersions.vue | 34 +-
.../src/components/project/TagsOverflow.vue | 13 +-
.../servers/access/AuditLogTable.vue | 25 +-
.../servers/access/events/EventEntityList.vue | 18 +-
packages/ui/src/components/user/UserBadge.vue | 8 +-
packages/ui/src/composables/modal-stack.ts | 15 +
.../components/ContentSelectionBar.vue | 1 +
.../layouts/wrapped/hosting/manage/root.vue | 7 +-
packages/ui/src/providers/create-context.ts | 9 +-
packages/ui/src/providers/floating-menu.ts | 14 +
packages/ui/src/providers/index.ts | 6 +
packages/ui/src/providers/tooltip.ts | 344 ++++++++++++++++++
.../ui/src/utils/use-anchored-teleport.ts | 3 +
pnpm-lock.yaml | 69 ++--
web-types.json | 14 +-
60 files changed, 1638 insertions(+), 794 deletions(-)
create mode 100644 apps/frontend/src/plugins/floating.ts
delete mode 100644 packages/ui/src/components/base/PopoutMenu.vue
create mode 100644 packages/ui/src/components/floating/FloatingMenu.vue
create mode 100644 packages/ui/src/components/floating/Tooltip.vue
create mode 100644 packages/ui/src/components/floating/TooltipDirective.vue
create mode 100644 packages/ui/src/components/floating/index.ts
create mode 100644 packages/ui/src/providers/floating-menu.ts
create mode 100644 packages/ui/src/providers/tooltip.ts
diff --git a/apps/app-frontend/package.json b/apps/app-frontend/package.json
index 643a41d661..c35b5bb1ee 100644
--- a/apps/app-frontend/package.json
+++ b/apps/app-frontend/package.json
@@ -34,7 +34,7 @@
"@vueuse/core": "^11.1.0",
"ace-builds": "^1.43.5",
"dayjs": "^1.11.10",
- "floating-vue": "^5.2.2",
+ "@floating-ui/vue": "^2.0.1",
"fuse.js": "^6.6.2",
"intl-messageformat": "^10.7.7",
"ofetch": "^1.3.4",
diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue
index 3277a2ea13..a2ae0e6e5f 100644
--- a/apps/app-frontend/src/App.vue
+++ b/apps/app-frontend/src/App.vue
@@ -55,6 +55,7 @@ import {
providePopupNotificationManager,
TeleportOverflowMenu,
TextLogo,
+ TooltipDirective,
useDebugLogger,
useFormatBytes,
useHostingIntercom,
@@ -2189,6 +2190,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
+
@@ -2288,84 +2290,86 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
-
-
-
- {{ account.user.username }}
-
-
-
-
+ {{ account.user.username }}
+
+
+
+
+
+
-
-
-
- {{ account.user.username }}
-
-
-
-
-
-
-
+
+ {{ account.user.username }}
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/components/ui/AppActionBar.vue b/apps/app-frontend/src/components/ui/AppActionBar.vue
index 49101df43b..3ddf3706b9 100644
--- a/apps/app-frontend/src/components/ui/AppActionBar.vue
+++ b/apps/app-frontend/src/components/ui/AppActionBar.vue
@@ -29,13 +29,11 @@
>
{{ selectedProcess.instance.name }}
-
-
-
-
+
diff --git a/apps/frontend/src/components/analytics-dashboard/analytics-chart/analytics-chart-header/AnalyticsChartLegend.vue b/apps/frontend/src/components/analytics-dashboard/analytics-chart/analytics-chart-header/AnalyticsChartLegend.vue
index 6dd495c9c9..af4838cc19 100644
--- a/apps/frontend/src/components/analytics-dashboard/analytics-chart/analytics-chart-header/AnalyticsChartLegend.vue
+++ b/apps/frontend/src/components/analytics-dashboard/analytics-chart/analytics-chart-header/AnalyticsChartLegend.vue
@@ -62,15 +62,11 @@
{{ legendEntry.name }}
-
-
+
@@ -107,8 +103,7 @@
-
-
diff --git a/apps/frontend/src/components/analytics-dashboard/stat-cards/StatCard.vue b/apps/frontend/src/components/analytics-dashboard/stat-cards/StatCard.vue
index 9585972b1f..33588b0e55 100644
--- a/apps/frontend/src/components/analytics-dashboard/stat-cards/StatCard.vue
+++ b/apps/frontend/src/components/analytics-dashboard/stat-cards/StatCard.vue
@@ -38,7 +38,7 @@
-
+
-
-
+
-import { Menu } from 'floating-vue'
-import { useId } from 'vue'
-
-import { TagItem, TagTagItem } from '../base'
-
-const id = useId()
+import TagItem from '../base/TagItem.vue'
+import TagTagItem from '../base/TagTagItem.vue'
+import Tooltip from '../floating/Tooltip.vue'
defineProps<{
tags: string[]
@@ -16,7 +13,7 @@ defineOptions({
-
+
diff --git a/packages/ui/src/components/servers/access/AuditLogTable.vue b/packages/ui/src/components/servers/access/AuditLogTable.vue
index 7208df05a1..cfb714659d 100644
--- a/packages/ui/src/components/servers/access/AuditLogTable.vue
+++ b/packages/ui/src/components/servers/access/AuditLogTable.vue
@@ -35,16 +35,7 @@
{{ column.label }}
-
+
diff --git a/apps/frontend/src/pages/news/index.vue b/apps/frontend/src/pages/news/index.vue
index 1168d4d8d1..7c6178db4b 100644
--- a/apps/frontend/src/pages/news/index.vue
+++ b/apps/frontend/src/pages/news/index.vue
@@ -50,19 +50,13 @@ useSeoMeta({
-
+
diff --git a/packages/ui/src/components/base/Pagination.vue b/packages/ui/src/components/base/Pagination.vue
index cbf59a3051..b3cb4cd687 100644
--- a/packages/ui/src/components/base/Pagination.vue
+++ b/packages/ui/src/components/base/Pagination.vue
@@ -4,7 +4,6 @@
@@ -91,7 +89,6 @@
@@ -222,7 +221,6 @@ defineExpose({
v-tooltip="'Send as an email'"
:href="sendEmail"
:target="targetParameter"
- aria-label="Send as an email"
class="!w-9 !px-0 !rounded-full"
>
@@ -232,7 +230,6 @@ defineExpose({
v-tooltip="'Open link in browser'"
:target="targetParameter"
:href="url"
- aria-label="Open link in browser"
class="!w-9 !px-0 !rounded-full"
>
@@ -241,7 +238,6 @@ defineExpose({
v-tooltip="'Toot about it'"
:target="targetParameter"
:href="sendToot"
- aria-label="Toot about it"
class="!w-9 !px-0 !rounded-full"
>
@@ -250,7 +246,6 @@ defineExpose({
v-tooltip="'Tweet about it'"
:target="targetParameter"
:href="sendTweet"
- aria-label="Tweet about it"
class="!w-9 !px-0 !rounded-full"
>
@@ -259,7 +254,6 @@ defineExpose({
v-tooltip="'Share on Reddit'"
:target="targetParameter"
:href="postOnReddit"
- aria-label="Share on Reddit"
class="!w-9 !px-0 !rounded-full"
>
diff --git a/packages/ui/src/components/search/SearchDependsOnFilter.vue b/packages/ui/src/components/search/SearchDependsOnFilter.vue
index 996c3eb9c9..f52b5018bf 100644
--- a/packages/ui/src/components/search/SearchDependsOnFilter.vue
+++ b/packages/ui/src/components/search/SearchDependsOnFilter.vue
@@ -42,11 +42,6 @@
? 'text-red opacity-100 bg-highlight-red'
: 'text-secondary [@media(hover:hover)]:opacity-0 group-hover:opacity-100 bg-transparent hover:bg-button-bg hover:text-red active:scale-[0.96]'
"
- :aria-label="
- excludedProjectIds.has(projectId)
- ? formatMessage(messages.excluded)
- : formatMessage(messages.exclude)
- "
@click="toggleProjectExcluded(projectId)"
>
diff --git a/packages/ui/src/components/search/SearchFilterOption.vue b/packages/ui/src/components/search/SearchFilterOption.vue
index 2f662876e8..765b943311 100644
--- a/packages/ui/src/components/search/SearchFilterOption.vue
+++ b/packages/ui/src/components/search/SearchFilterOption.vue
@@ -38,11 +38,6 @@
"
class="flex border-none cursor-pointer items-center justify-center gap-2 rounded-xl bg-transparent px-2 py-1 text-sm font-semibold text-secondary transition-all hover:bg-button-bg hover:text-contrast focus-visible:bg-button-bg focus-visible:text-contrast active:scale-[0.96]"
:aria-expanded="expanded"
- :aria-label="
- expanded
- ? formatMessage(messages.collapseSubOptionsTooltip)
- : formatMessage(messages.expandSubOptionsTooltip)
- "
@click.stop="emit('toggleExpand')"
>
props.selected ?? props.isEquipped)
diff --git a/packages/ui/src/components/user/UserRoleIcon.vue b/packages/ui/src/components/user/UserRoleIcon.vue
index ddf0d7ae1c..21305d0f22 100644
--- a/packages/ui/src/components/user/UserRoleIcon.vue
+++ b/packages/ui/src/components/user/UserRoleIcon.vue
@@ -3,14 +3,12 @@
v-if="role === 'admin'"
v-tooltip="formatMessage(messages.modrinthTeamLabel)"
role="img"
- :aria-label="formatMessage(messages.modrinthTeamLabel)"
class="size-4 shrink-0 !text-green"
/>
diff --git a/packages/ui/src/layouts/shared/content-tab/components/ContentCardItem.vue b/packages/ui/src/layouts/shared/content-tab/components/ContentCardItem.vue
index b11bf1a5fd..348ef22936 100644
--- a/packages/ui/src/layouts/shared/content-tab/components/ContentCardItem.vue
+++ b/packages/ui/src/layouts/shared/content-tab/components/ContentCardItem.vue
@@ -239,7 +239,6 @@ const installTooltip = computed(() => {
{