start status/player count info label, more style updates and fixes

This commit is contained in:
tdgao
2026-03-17 20:09:42 -06:00
parent 83df48a454
commit 2386b4df09
14 changed files with 93 additions and 34 deletions
+8
View File
@@ -16,6 +16,7 @@ import { QueryClient, VueQueryPlugin } from '@tanstack/vue-query'
import FloatingVue from 'floating-vue'
import { computed, defineComponent, h, ref } from 'vue'
import { createI18n } from 'vue-i18n'
import { createMemoryHistory, createRouter } from 'vue-router'
import NotificationPanel from '../src/components/nav/NotificationPanel.vue'
import PopupNotificationPanel from '../src/components/nav/PopupNotificationPanel.vue'
@@ -166,6 +167,13 @@ setup((app) => {
})
app.use(VueQueryPlugin, { queryClient })
app.use(i18n)
const router = createRouter({
history: createMemoryHistory(),
routes: [{ path: '/:pathMatch(.*)*', component: { render: () => null } }],
})
app.use(router)
app.component('NuxtLink', StorybookLink)
app.component('RouterLink', StorybookLink)
app.component('ClientOnly', StorybookClientOnly)
@@ -5,7 +5,7 @@
class="flex flex-row items-center overflow-x-hidden rounded-2xl border-[1px] border-solid border-surface-5 bg-bg-raised p-4 transition-transform duration-100"
:class="{
'!rounded-b-none border-b-0': status === 'suspended' || !!pendingChange,
'opacity-75': status === 'suspended',
'opacity-50 bg-surface-2': status === 'suspended',
'active:scale-95': status !== 'suspended' && !pendingChange,
}"
data-pyro-server-listing
@@ -23,9 +23,9 @@
<h2 class="m-0 text-xl font-bold text-contrast">{{ name }}</h2>
<div
v-if="isConfiguring"
class="flex min-w-0 items-center gap-2 truncate text-sm font-semibold text-brand rounded-full bg-brand-highlight border border-solid border-brand px-2.5 py-1"
class="flex min-w-0 items-center gap-2 truncate text-sm font-medium text-brand rounded-full bg-brand-highlight border border-solid border-brand px-2.5 h-[28px]"
>
<SparklesIcon class="size-5 shrink-0" /> New
<SparklesIcon class="size-5 shrink-0 font-semibold" /> New
</div>
</div>
@@ -44,12 +44,25 @@
<ServerInfoLabels
:server-data="
isConfiguring ? { net } : { game, mc_version, loader, loader_version, net }
isConfiguring
? { net }
: {
game,
mc_version,
loader,
loader_version,
net,
online,
players: playerCount
? { current: playerCount.current, max: playerCount.max }
: undefined,
}
"
:show-game-label="showGameLabel"
:show-loader-label="showLoaderLabel"
:show-player-count="showPlayerCount"
:linked="false"
class="pointer-events-none flex w-full flex-row flex-wrap items-center gap-4 text-secondary *:hidden sm:flex-row sm:*:flex"
class="pointer-events-none flex w-full flex-row flex-wrap items-center gap-2 text-primary *:hidden sm:flex-row sm:*:flex"
/>
</div>
</div>
@@ -146,11 +159,10 @@ type ServerListingProps = {
upstream?: Archon.Servers.v0.Upstream | null
flows?: Archon.Servers.v0.Flows
pendingChange?: PendingChange
ip?: string
online?: boolean
playerCount?: {
currentPlayerCount?: number
maxPlayerCount?: number
current?: number
max?: number
}
}
@@ -160,6 +172,7 @@ const { kyros, labrinth } = injectModrinthClient()
const showGameLabel = computed(() => !!props.game && !isConfiguring.value)
const showLoaderLabel = computed(() => !!props.loader && !isConfiguring.value)
const showPlayerCount = computed(() => !!props.playerCount && !isConfiguring.value)
const { data: projectData } = useQuery({
queryKey: ['project', props.upstream?.project_id] as const,
@@ -0,0 +1,3 @@
<template>
<div class="experimental-styles-within h-1.5 w-1.5 bg-button-border rounded-full"></div>
</template>
@@ -2,9 +2,11 @@
<div
v-if="game"
v-tooltip="'Change server version'"
class="min-w-0 flex-none flex-row items-center gap-2 first:!flex"
class="min-w-0 flex-none flex-row items-center gap-1.5 first:!flex"
>
<GameIcon aria-hidden="true" class="size-5 shrink-0" />
<Separator v-if="!noSeparator" />
<GameIcon aria-hidden="true" />
<AutoLink
v-if="isLink"
:to="serverId ? `/hosting/manage/${serverId}/options/loader` : ''"
@@ -30,11 +32,13 @@ import { GameIcon } from '@modrinth/assets'
import { useRoute } from 'vue-router'
import AutoLink from '../../base/AutoLink.vue'
import Separator from './Separator.vue'
defineProps<{
game: string
mcVersion: string
isLink?: boolean
noSeparator?: boolean
}>()
const route = useRoute()
@@ -1,9 +1,16 @@
<template>
<div>
<ServerPlayerCount
v-if="showPlayerCount"
:current-players="serverData.players.current"
:max-players="serverData.players.max"
:online="serverData.online"
/>
<ServerGameLabel
v-if="showGameLabel"
:game="serverData.game"
:mc-version="serverData.mc_version ?? ''"
:no-separator="column || !showPlayerCount"
:is-link="linked"
/>
<ServerLoaderLabel
@@ -30,6 +37,7 @@
<script setup lang="ts">
import ServerGameLabel from './ServerGameLabel.vue'
import ServerLoaderLabel from './ServerLoaderLabel.vue'
import ServerPlayerCount from './ServerPlayerCount.vue'
import ServerSubdomainLabel from './ServerSubdomainLabel.vue'
import ServerUptimeLabel from './ServerUptimeLabel.vue'
@@ -38,6 +46,7 @@ interface ServerInfoLabelsProps {
serverData: Record<string, any>
showGameLabel: boolean
showLoaderLabel: boolean
showPlayerCount?: boolean
uptimeSeconds?: number
column?: boolean
linked?: boolean
@@ -1,8 +1,8 @@
<template>
<div v-tooltip="'Change server loader'" class="flex min-w-0 flex-row items-center gap-4 truncate">
<div v-if="!noSeparator" class="experimental-styles-within h-1.5 w-1.5 bg-button-border"></div>
<div class="flex flex-row items-center gap-2">
<LoaderIcon v-if="loader" :loader="loader" class="flex shrink-0 [&&]:size-5" />
<div v-tooltip="'Change server loader'" class="flex min-w-0 flex-row items-center gap-2 truncate">
<Separator v-if="!noSeparator" />
<div class="flex flex-row items-center gap-1.5">
<LoaderIcon v-if="loader" :loader="loader" />
<div v-else class="size-5 shrink-0 animate-pulse rounded-full bg-button-border"></div>
<AutoLink
v-if="isLink"
@@ -38,6 +38,7 @@ import { useRoute } from 'vue-router'
import AutoLink from '../../base/AutoLink.vue'
import LoaderIcon from '../icons/LoaderIcon.vue'
import Separator from './Separator.vue'
defineProps<{
noSeparator?: boolean
@@ -0,0 +1,17 @@
<template>
<div class="flex gap-1">
<!-- indicator icon -->
{{ currentPlayers }} / {{ maxPlayers }} Players
</div>
</template>
<script setup lang="ts">
interface ServerPlayerCountProps {
currentPlayers: number
maxPlayers: number
online: boolean
}
defineProps<ServerPlayerCountProps>()
</script>
@@ -2,11 +2,12 @@
<div
v-if="subdomain && !isHidden"
v-tooltip="'Copy custom URL'"
class="flex min-w-0 flex-row items-center gap-4 truncate hover:cursor-pointer"
class="flex min-w-0 flex-row items-center gap-2 truncate hover:cursor-pointer"
>
<div v-if="!noSeparator" class="experimental-styles-within h-1.5 w-1.5 bg-button-border"></div>
<div class="flex flex-row items-center gap-2">
<LinkIcon class="flex size-5 shrink-0" />
<Separator v-if="!noSeparator" />
<div class="flex flex-row items-center gap-1.5">
<LinkIcon />
<div
class="flex min-w-0 text-sm font-semibold"
:class="serverId ? 'hover:underline' : ''"
@@ -24,6 +25,7 @@ import { injectNotificationManager } from '@modrinth/ui'
import { useStorage } from '@vueuse/core'
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import Separator from './Separator.vue'
const { addNotification } = injectNotificationManager()
@@ -2,13 +2,13 @@
<div
v-if="uptimeSeconds || uptimeSeconds !== 0"
v-tooltip="`Online for ${verboseUptime}`"
class="server-action-buttons-anim flex min-w-0 flex-row items-center gap-4"
class="server-action-buttons-anim flex min-w-0 flex-row items-center gap-2"
data-pyro-uptime
>
<div v-if="!noSeparator" class="experimental-styles-within h-1.5 w-1.5 bg-button-border"></div>
<Separator v-if="!noSeparator" />
<div class="flex gap-2">
<TimerIcon class="flex size-5 shrink-0" />
<div class="flex gap-1.5">
<TimerIcon />
<time class="truncate text-sm font-semibold" :aria-label="verboseUptime">
{{ formattedUptime }}
</time>
@@ -19,6 +19,7 @@
<script setup lang="ts">
import { TimerIcon } from '@modrinth/assets'
import { computed } from 'vue'
import Separator from './Separator.vue'
const props = defineProps<{
uptimeSeconds: number
@@ -75,7 +75,7 @@
:show-game-label="showGameLabel"
:show-loader-label="showLoaderLabel"
:linked="false"
class="pointer-events-none flex w-full flex-row flex-wrap items-center gap-4 text-secondary *:hidden sm:flex-row sm:*:flex"
class="pointer-events-none flex w-full flex-row flex-wrap items-center gap-4 text-primary *:hidden sm:flex-row sm:*:flex"
/>
</div>
</AutoLink>
@@ -13,7 +13,7 @@ const baseServer = {
net: {
ip: '203.0.113.42',
port: 25565,
domain: 'play.example.net',
domain: 'play',
},
} as const