mirror of
https://github.com/unraid/api.git
synced 2026-05-08 08:00:19 -05:00
88087d5201
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Standalone web bundle with auto-mount utilities and a self-contained test page. * New responsive modal components for consistent mobile/desktop dialogs. * Header actions to copy OS/API versions. * **Improvements** * Refreshed UI styles (muted borders), accessibility and animation refinements. * Theming updates and Tailwind v4–aligned, component-scoped styles. * Runtime GraphQL endpoint override and CSRF header support. * **Bug Fixes** * Safer network fetching and improved manifest/asset loading with duplicate protection. * **Tests/Chores** * Parallel plugin tests, new extractor test suite, and updated build/test scripts. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
75 lines
2.2 KiB
Vue
75 lines
2.2 KiB
Vue
<script setup lang="ts">
|
|
import { computed } from 'vue';
|
|
import { ArrowTopRightOnSquareIcon } from '@heroicons/vue/24/solid';
|
|
import { Button } from '@unraid/ui';
|
|
import type { ComposerTranslation } from 'vue-i18n';
|
|
|
|
import type { ServerStateDataAction } from '~/types/server';
|
|
import type { UserProfileLink } from '~/types/userProfile';
|
|
|
|
export interface Props {
|
|
item: ServerStateDataAction | UserProfileLink;
|
|
rounded?: boolean;
|
|
t: ComposerTranslation;
|
|
}
|
|
|
|
const props = withDefaults(defineProps<Props>(), {
|
|
rounded: true,
|
|
});
|
|
|
|
const showExternalIconOnHover = computed(() => props.item?.external && props.item.icon !== ArrowTopRightOnSquareIcon);
|
|
|
|
const buttonClass = computed(() => {
|
|
const classes = ['text-left', 'text-sm', 'w-full', 'flex', 'flex-row', 'items-center', 'justify-between', 'gap-x-2', 'px-2', 'py-2', 'h-auto'];
|
|
|
|
if (!props.item?.emphasize) {
|
|
classes.push('dropdown-item-hover');
|
|
}
|
|
if (props.item?.emphasize) {
|
|
classes.push('dropdown-item-emphasized');
|
|
}
|
|
if (showExternalIconOnHover.value) {
|
|
classes.push('group');
|
|
}
|
|
if (props.rounded) {
|
|
classes.push('rounded-md');
|
|
}
|
|
|
|
return classes.join(' ');
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<Button
|
|
:as="item?.click ? 'button' : 'a'"
|
|
:disabled="item?.disabled"
|
|
:href="item?.href ?? null"
|
|
:target="item?.external ? '_blank' : null"
|
|
:rel="item?.external ? 'noopener noreferrer' : null"
|
|
variant="ghost"
|
|
:class="buttonClass"
|
|
@click.stop="item?.click ? item?.click(item?.clickParams ?? []) : null"
|
|
>
|
|
<span class="leading-snug inline-flex flex-row items-center gap-x-2">
|
|
<component :is="item?.icon" class="shrink-0 text-current w-4 h-4" aria-hidden="true" />
|
|
{{ t(item?.text, item?.textParams ?? []) }}
|
|
</span>
|
|
<ArrowTopRightOnSquareIcon
|
|
v-if="showExternalIconOnHover"
|
|
class="text-white fill-current shrink-0 w-4 h-4 ml-2 opacity-0 group-hover:opacity-100 transition-opacity duration-200 ease-in-out"
|
|
/>
|
|
</Button>
|
|
</template>
|
|
|
|
<style>
|
|
.dropdown-item-hover:hover,
|
|
.dropdown-item-hover:focus {
|
|
background: linear-gradient(to right, #e22828, #ff8c2f);
|
|
}
|
|
|
|
.dropdown-item-emphasized:hover,
|
|
.dropdown-item-emphasized:focus {
|
|
background: linear-gradient(to right, rgba(226, 40, 40, 0.6), rgba(255, 140, 47, 0.6));
|
|
}
|
|
</style>
|