Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/app-frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
142 changes: 73 additions & 69 deletions apps/app-frontend/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import {
providePopupNotificationManager,
TeleportOverflowMenu,
TextLogo,
TooltipDirective,
useDebugLogger,
useFormatBytes,
useHostingIntercom,
Expand Down Expand Up @@ -2189,6 +2190,7 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
</script>

<template>
<TooltipDirective />
<SplashScreen v-if="!stateFailed" ref="splashScreen" data-tauri-drag-region />
<div id="teleports"></div>
<AccountSwitchOverlay :show="isSwitchingAccount" />
Expand Down Expand Up @@ -2288,84 +2290,86 @@ provideAppUpdateDownloadProgress(appUpdateDownload)
<ServerStackIcon />
</NavButton>
<suspense>
<QuickInstanceSwitcher />
<QuickInstanceSwitcher>
<NavButton
v-tooltip.right="formatMessage(messages.createNewInstance)"
:to="() => installationModal?.show()"
:disabled="offline"
>
<PlusIcon />
</NavButton>
</QuickInstanceSwitcher>
</suspense>
<NavButton
v-tooltip.right="formatMessage(messages.createNewInstance)"
:to="() => installationModal?.show()"
:disabled="offline"
>
<PlusIcon />
</NavButton>
<NavButton
v-tooltip.right="formatMessage(commonMessages.settingsLabel)"
:to="() => appSettingsModal?.show()"
>
<SettingsIcon />
</NavButton>
<span v-tooltip.right="profileButtonTooltip" class="inline-flex">
<IconButton
v-if="credentials === undefined"
type="quiet"
size="xl"
disabled
class="pointer-events-none"
:label="formatMessage(messages.loadingProfile)"
>
<SpinnerIcon class="animate-spin" />
</IconButton>
<TeleportOverflowMenu
v-else-if="credentials?.user"
type="quiet"
size="xl"
:label="formatMessage(messages.modrinthAccount)"
:options="modrinthAccountMenuOptions"
placement="right-end"
:distance="4"
class="brightness-100 hover:!brightness-100 focus-visible:!brightness-100"
<IconButton
v-if="credentials === undefined"
v-tooltip.right="profileButtonTooltip"
type="quiet"
size="xl"
disabled
class="pointer-events-none"
:label="formatMessage(messages.loadingProfile)"
>
<SpinnerIcon class="animate-spin" />
</IconButton>
<TeleportOverflowMenu
v-else-if="credentials?.user"
v-tooltip.right="profileButtonTooltip"
type="quiet"
size="xl"
:label="formatMessage(messages.modrinthAccount)"
:options="modrinthAccountMenuOptions"
placement="right-end"
:distance="4"
class="brightness-100 hover:!brightness-100 focus-visible:!brightness-100"
>
<Avatar
:src="credentials?.user?.avatar_url"
alt=""
size="32px"
circle
no-shadow
class="pointer-events-none !size-8"
/>
<template
v-for="account in accountSwitcherAccounts"
:key="account.user_id"
#[account.optionId]
>
<Avatar
:src="credentials?.user?.avatar_url"
alt=""
size="32px"
circle
no-shadow
class="pointer-events-none !size-8"
/>
<template
v-for="account in accountSwitcherAccounts"
:key="account.user_id"
#[account.optionId]
>
<Avatar :src="account.user.avatar_url" size="1.25rem" aria-hidden="true" circle />
{{ account.user.username }}
<UserRoleIcon :role="account.user.role" />
</template>
</TeleportOverflowMenu>
<TeleportOverflowMenu
v-else-if="accountSwitcherAccounts.length > 0"
type="quiet"
size="xl"
:label="formatMessage(messages.signInToModrinthAccount)"
:options="accountSwitcherOptions"
placement="right-end"
:distance="4"
<Avatar :src="account.user.avatar_url" size="1.25rem" aria-hidden="true" circle />
{{ account.user.username }}
<UserRoleIcon :role="account.user.role" />
</template>
</TeleportOverflowMenu>
<TeleportOverflowMenu
v-else-if="accountSwitcherAccounts.length > 0"
v-tooltip.right="profileButtonTooltip"
type="quiet"
size="xl"
:label="formatMessage(messages.signInToModrinthAccount)"
:options="accountSwitcherOptions"
placement="right-end"
:distance="4"
>
<LogInIcon class="!text-brand" />
<template
v-for="account in accountSwitcherAccounts"
:key="account.user_id"
#[account.optionId]
>
<LogInIcon class="!text-brand" />
<template
v-for="account in accountSwitcherAccounts"
:key="account.user_id"
#[account.optionId]
>
<Avatar :src="account.user.avatar_url" size="1.25rem" aria-hidden="true" circle />
{{ account.user.username }}
<UserRoleIcon :role="account.user.role" />
</template>
</TeleportOverflowMenu>
<NavButton v-else :to="() => requestSignIn()">
<LogInIcon class="text-brand" />
</NavButton>
</span>
<Avatar :src="account.user.avatar_url" size="1.25rem" aria-hidden="true" circle />
{{ account.user.username }}
<UserRoleIcon :role="account.user.role" />
</template>
</TeleportOverflowMenu>
<NavButton v-else v-tooltip.right="profileButtonTooltip" :to="() => requestSignIn()">
<LogInIcon class="text-brand" />
</NavButton>
</div>
<div data-tauri-drag-region class="app-grid-statusbar bg-bg-raised h-[--top-bar-height] flex">
<div data-tauri-drag-region class="flex min-w-0 flex-1 items-center overflow-hidden p-2">
Expand Down
12 changes: 5 additions & 7 deletions apps/app-frontend/src/components/ui/AppActionBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,11 @@
>
{{ selectedProcess.instance.name }}
</router-link>
<Dropdown
<FloatingMenu
v-if="currentProcesses.length > 1"
placement="bottom"
:triggers="['click']"
:hide-triggers="['click']"
@show="showInstances = true"
@hide="showInstances = false"
@open="showInstances = true"
@close="showInstances = false"
>
<IconButton
v-tooltip="
Expand Down Expand Up @@ -97,7 +95,7 @@
</div>
</div>
</template>
</Dropdown>
</FloatingMenu>
</div>
<button
v-tooltip="formatMessage(messages.stopInstance)"
Expand Down Expand Up @@ -135,14 +133,14 @@ import {
import { IconButton } from '@modrinth/ui'
import {
defineMessages,
FloatingMenu,
injectNotificationManager,
injectPopupNotificationManager,
type PopupNotificationProgressItem,
type PopupNotificationStandard,
useVIntl,
} from '@modrinth/ui'
import { convertFileSrc } from '@tauri-apps/api/core'
import { Dropdown } from 'floating-vue'
import { computed, onBeforeUnmount, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'

Expand Down
59 changes: 42 additions & 17 deletions apps/app-frontend/src/components/ui/NavButton.vue
Original file line number Diff line number Diff line change
@@ -1,38 +1,32 @@
<template>
<RouterLink
v-if="typeof to === 'string'"
:to="to"
<component
:is="isLink ? RouterLink : 'button'"
:to="isLink ? to : undefined"
v-bind="$attrs"
:active-class="isSubpage ? '' : undefined"
:disabled="isLink ? undefined : disabled"
:active-class="isLink && isSubpage ? '' : undefined"
:class="{
'router-link-active': isPrimary && isPrimary(route),
'subpage-active': isSubpage && isSubpage(route),
disabled: disabled,
}"
class="w-12 h-12 text-primary rounded-full flex items-center justify-center text-2xl transition-all bg-transparent hover:bg-button-bg hover:text-contrast"
class="nav-button border-none text-primary cursor-pointer w-12 rounded-full h-12 flex items-center justify-center text-2xl transition-all bg-transparent hover:bg-button-bg hover:text-contrast"
@click="onClick"
>
<slot />
</RouterLink>
<button
v-else
v-bind="$attrs"
class="button-animation border-none text-primary cursor-pointer w-12 h-12 rounded-full flex items-center justify-center text-2xl transition-all bg-transparent hover:bg-button-bg hover:text-contrast"
:disabled="disabled"
@click="to"
>
<slot />
</button>
</component>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import type { RouteLocationNormalizedLoaded } from 'vue-router'
import { RouterLink, useRoute } from 'vue-router'

const route = useRoute()

type RouteFunction = (route: RouteLocationNormalizedLoaded) => boolean

withDefaults(
const props = withDefaults(
defineProps<{
to: (() => void) | string
isPrimary?: RouteFunction
Expand All @@ -45,12 +39,38 @@ withDefaults(
},
)

const isLink = computed(() => typeof props.to === 'string')

function onClick() {
if (typeof props.to === 'function') {
props.to()
}
}

defineOptions({
inheritAttrs: false,
})
</script>

<style lang="scss" scoped>
.nav-button {
position: relative;

&::before {
content: '';
position: absolute;
inset: 0;
background-color: var(--color-button-bg-selected);
border-radius: 50%;
opacity: 0;
scale: 0.4;
z-index: -1;
transition:
opacity 0.25s var(--ease-out-expo),
scale 0.25s var(--ease-out-expo);
}
}

.router-link-active,
.subpage-active {
svg {
Expand All @@ -59,7 +79,12 @@ defineOptions({
}

.router-link-active {
@apply text-[--color-button-text-selected] bg-[--color-button-bg-selected];
@apply text-[--color-button-text-selected];
&::before {
background-color: var(--color-button-bg-selected);
scale: 1;
opacity: 1;
}
}

.subpage-active {
Expand Down
Loading
Loading