Files
AstralRinth/apps/frontend/src/components/ui/servers/FilesEditingNavbar.vue
Calum H. 099011a177 feat: modrinth hosting - files tab refactor (#4912)
* feat: api-client module for content v0

* feat: delete unused components + modules + setting

* feat: xhr uploading

* feat: fs module -> api-client

* feat: migrate files.vue to use tanstack

* fix: mem leak + other issues

* fix: build

* feat: switch to monaco

* fix: go back to using ace, but improve preloading + theme

* fix: styling + dead attrs

* feat: match figma

* fix: padding

* feat: files-new for ui page structure

* feat: finalize files.vue

* fix: lint

* fix: qa

* fix: dep

* fix: lint

* fix: lockfile merge

* feat: icons on navtab

* fix: surface alternating on table

* fix: hover surface color

---------

Signed-off-by: Calum H. <contact@cal.engineer>
Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
2026-01-06 00:35:51 +00:00

137 lines
4.2 KiB
Vue

<template>
<header
data-pyro-files-state="editing"
class="flex select-none items-center justify-between gap-2 sm:flex-row"
aria-label="File editor navigation"
>
<nav
aria-label="Breadcrumb navigation"
class="m-0 flex min-w-0 flex-shrink items-center p-0 text-contrast"
>
<ol class="m-0 flex min-w-0 flex-shrink list-none items-center p-0">
<li class="mr-4 flex-shrink-0">
<ButtonStyled circular>
<button
v-tooltip="'Back to home'"
type="button"
class="!size-10 bg-surface-4 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand"
@click="goHome"
>
<HomeIcon />
<span class="sr-only">Home</span>
</button>
</ButtonStyled>
</li>
<li class="m-0 -ml-2 p-0">
<ol class="m-0 flex items-center p-0">
<li
v-for="(segment, index) in breadcrumbSegments"
:key="index"
class="flex items-center text-sm"
>
<ButtonStyled type="transparent">
<button
class="cursor-pointer focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-brand"
:class="{
'!text-contrast': index === breadcrumbSegments.length - 1,
}"
@click="$emit('navigate', index)"
>
{{ segment || '' }}
</button>
</ButtonStyled>
<ChevronRightIcon
v-if="index < breadcrumbSegments.length"
class="size-4 text-secondary"
aria-hidden="true"
/>
</li>
<li class="flex items-center px-3 text-sm">
<span class="font-semibold !text-contrast" aria-current="location">{{
fileName
}}</span>
</li>
</ol>
</li>
</ol>
</nav>
<div v-if="!isImage" class="flex gap-2">
<Button
v-if="isLogFile"
v-tooltip="'Share to mclo.gs'"
icon-only
transparent
aria-label="Share to mclo.gs"
@click="$emit('share')"
>
<ShareIcon />
</Button>
<ButtonStyled type="transparent">
<TeleportOverflowMenu
position="bottom"
direction="left"
aria-label="Save file"
:options="[
{ id: 'save', action: () => $emit('save') },
{ id: 'save-as', action: () => $emit('save-as') },
{ id: 'save&restart', action: () => $emit('save-restart') },
]"
>
<SaveIcon aria-hidden="true" />
<DropdownIcon aria-hidden="true" class="h-5 w-5 text-secondary" />
<template #save> <SaveIcon aria-hidden="true" /> Save </template>
<template #save-as> <SaveIcon aria-hidden="true" /> Save as... </template>
<template #save&restart>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M15.312 11.424a5.5 5.5 0 0 1-9.201 2.466l-.312-.311h2.433a.75.75 0 0 0 0-1.5H3.989a.75.75 0 0 0-.75.75v4.242a.75.75 0 0 0 1.5 0v-2.43l.31.31a7 7 0 0 0 11.712-3.138.75.75 0 0 0-1.449-.39Zm1.23-3.723a.75.75 0 0 0 .219-.53V2.929a.75.75 0 0 0-1.5 0V5.36l-.31-.31A7 7 0 0 0 3.239 8.188a.75.75 0 1 0 1.448.389A5.5 5.5 0 0 1 13.89 6.11l.311.31h-2.432a.75.75 0 0 0 0 1.5h4.243a.75.75 0 0 0 .53-.219Z"
clip-rule="evenodd"
/>
</svg>
Save & restart
</template>
</TeleportOverflowMenu>
</ButtonStyled>
</div>
</header>
</template>
<script setup lang="ts">
import { ChevronRightIcon, DropdownIcon, HomeIcon, SaveIcon, ShareIcon } from '@modrinth/assets'
import { Button, ButtonStyled } from '@modrinth/ui'
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import TeleportOverflowMenu from './TeleportOverflowMenu.vue'
const props = defineProps<{
breadcrumbSegments: string[]
fileName?: string
isImage: boolean
filePath?: string
}>()
const isLogFile = computed(() => {
return props.filePath?.startsWith('logs') || props.filePath?.endsWith('.log')
})
const route = useRoute()
const router = useRouter()
const emit = defineEmits<{
(e: 'cancel' | 'save' | 'save-as' | 'save-restart' | 'share'): void
(e: 'navigate', index: number): void
}>()
const goHome = () => {
emit('cancel')
router.push({ path: '/hosting/manage/' + route.params.id + '/files' })
}
</script>