home: replace app list tiles with cards, logos and descriptions

This commit is contained in:
axolotle 2024-01-20 14:37:35 +01:00
parent 4ece760ab6
commit a5d83ce76b
4 changed files with 47 additions and 71 deletions

View file

@ -43,6 +43,9 @@ defineProps<{
@apply mb-4; @apply mb-4;
} }
.intro h1 {
@apply text-6xl font-bold my-10 text-center;
}
.intro h2 { .intro h2 {
@apply text-5xl font-bold my-10; @apply text-5xl font-bold my-10;
} }

View file

@ -1,10 +1,12 @@
<script setup lang="ts"> <script setup lang="ts">
withDefaults( withDefaults(
defineProps<{ defineProps<{
tag?: string
text?: string text?: string
srOnly?: boolean srOnly?: boolean
}>(), }>(),
{ {
tag: 'h1',
text: undefined, text: undefined,
srOnly: false, srOnly: false,
}, },
@ -12,7 +14,8 @@ withDefaults(
</script> </script>
<template> <template>
<h1 <component
:tag="tag"
id="main-target" id="main-target"
tabindex="-1" tabindex="-1"
class="inline-block text-4xl font-bold" class="inline-block text-4xl font-bold"
@ -21,11 +24,11 @@ withDefaults(
<slot name="default"> <slot name="default">
{{ text }} {{ text }}
</slot> </slot>
</h1> </component>
</template> </template>
<style scoped> <style scoped>
h1 { #main-target {
/* Need some override here because of `not-sr-only` styles */ /* Need some override here because of `not-sr-only` styles */
margin-top: 2rem !important; margin-top: 2rem !important;
margin-bottom: 0.75rem !important; margin-bottom: 0.75rem !important;

View file

@ -81,13 +81,13 @@ export const useQueryMsg = () => useState<string | null>('queryMsg', () => null)
export interface Settings { export interface Settings {
domain: string domain: string
public: boolean public: boolean
portal_logo: string portal_logo?: string
portal_theme: string portal_theme: string
portal_title: string portal_title?: string
show_other_domains_apps: 0 | 1 show_other_domains_apps: 0 | 1
portal_user_intro: string portal_user_intro: string
portal_public_intro: string portal_public_intro: string
apps: Record<string, { label: string; url: string }> apps: Record<string, { label: string; url: string, description?: Record<string, string>, logo?: string }>
} }
const useSettingsState = () => useState<Settings>('settings') const useSettingsState = () => useState<Settings>('settings')

View file

@ -21,60 +21,43 @@ const intro = computed(() => {
return isLoggedIn.value ? userIntro : isPublic ? publicIntro : null return isLoggedIn.value ? userIntro : isPublic ? publicIntro : null
}) })
const apps = computed(() => { const apps = Object.entries(appsData.value).map(([id, app]) => {
const appTileVariant = [
'btn-primary',
'btn-secondary',
'btn-accent',
'btn-neutral',
'btn-info',
'btn-success',
'btn-warning',
'btn-error',
// FIXME currently using daisyui btn colors to get focus/hover styles,
// if we want more colors we need to add btn variants based on daisyui colors.
// 'bg-red-500'
// 'bg-orange-500'
// 'bg-yellow-500'
// 'bg-lime-500'
// 'bg-green-500'
// 'bg-teal-500'
// 'bg-indigo-500'
// 'bg-primary',
// 'bg-purple-500'
// 'bg-rose-500'
]
return Object.entries(appsData.value).map(([id, app]) => {
return { return {
...app, ...app,
id,
url: '//' + app.url, url: '//' + app.url,
variant: appTileVariant[parseInt(app.label, 36) % appTileVariant.length], description: app.description[locale.value] || app.description.en
} }
})
}) })
</script> </script>
<template> <template>
<div> <div>
<PageTitle :text="$t('app_list')" sr-only />
<CustomText v-if="intro" :content="intro" /> <CustomText v-if="intro" :content="intro" />
<section id="apps" class="my-10"> <section id="apps" class="my-16">
<div v-if="!apps.length" class="w-2/3"> <PageTitle :text="t('app_list')" tag="h2" sr-only class="mb-4" />
<div v-if="!apps.length">
<em>{{ t('no_apps') }}</em> <em>{{ t('no_apps') }}</em>
</div> </div>
<ul v-else class="grid md:grid-cols-2 xl:grid-cols-3 gap-4">
<ul v-else class="tile-container"> <li
<li v-for="app in apps" :key="app.id" class="tile relative"> v-for="app in apps"
<a :href="app.url" class="btn" :class="app.variant"> :key="app.label"
<span class="text-6xl font-extrabold" aria-hidden="true"> class="flex flex-auto border rounded p-4 relative hover:bg-neutral hover:text-neutral-content hover:border-neutral"
{{ app.label.substring(0, 2) }} >
</span> <img
<span class="leading-tight">{{ app.label }}</span> v-if="app.logo"
</a> aria-hidden="true"
:src="app.logo"
class="w-24 h-24 rounded me-4 bg-white"
/>
<div>
<h4 class="text-xl font-bold">
<a :href="app.url" class="">{{ app.label }}</a>
</h4>
<div v-if="app.description" v-html="app.description" />
</div>
</li> </li>
</ul> </ul>
</section> </section>
@ -82,25 +65,12 @@ const apps = computed(() => {
</template> </template>
<style scoped> <style scoped>
.tile-container { .grid li a::after {
display: grid; content: '';
grid-template-columns: repeat(auto-fit, 9rem); position: absolute;
grid-auto-rows: 9rem; top: 0px;
grid-gap: 1.5rem; left: 0px;
} right: 0px;
bottom: 0px;
.tile a {
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
align-items: center;
justify-content: center;
gap: 0;
}
.tile:hover a,
.tile a:focus {
transform: scale(1.05);
} }
</style> </style>