Skip to content

Commit

Permalink
chore: make the search form and app header responsive for mobile
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviareichl committed Oct 15, 2024
1 parent bf5f778 commit 3100912
Show file tree
Hide file tree
Showing 14 changed files with 269 additions and 55 deletions.
86 changes: 58 additions & 28 deletions components/app-header.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<script lang="ts" setup>
import { MenuIcon } from "lucide-vue-next";
import type { NavLinkProps } from "@/components/nav-link.vue";
import { Separator } from "@/components/ui/separator";
const t = useTranslations();
const route = useRoute();
const homeLink = { href: { path: "/" } };
Expand All @@ -17,40 +17,70 @@ const links = computed(() => {
</script>

<template>
<header class="border-b bg-frisch-marine px-12">
<div class="w-full pb-4 pt-12">
<nav :aria-label="t('AppHeader.navigation-main')">
<div class="grid items-end gap-4 lg:grid-cols-2">
<div class="text-4xl font-semibold text-frisch-orange">
<header class="border-b bg-frisch-marine px-6 lg:px-12">
<div class="w-full pb-4 pt-8 lg:pt-12">
<nav>
<div class="grid grid-cols-[1fr_auto] items-center gap-4 lg:items-end">
<div class="text-2xl font-semibold text-frisch-orange lg:text-4xl">
<NavLink :href="homeLink.href">
Digitales Archiv
<br aria-hidden="true" />
Barbara Frischmuth
</NavLink>
</div>
<ul
:class="
route.path !== '/'
? 'opacity-100 translate-y-0'
: 'opacity-0 translate-y-5 pointer-events-none'
"
class="ml-auto flex gap-x-4 font-bold transition"
role="list"
>
<li
v-for="(link, key, index) of links"
:key="key"
class="flex shrink-0 gap-x-4 text-xl"
<div class="hidden lg:flex">
<ul
:class="
route.path !== '/'
? 'opacity-100 translate-y-0'
: 'opacity-0 translate-y-5 pointer-events-none'
"
class="ml-auto flex gap-x-4 font-bold transition"
role="list"
>
<Separator v-if="index > 0" class="h-full w-0.5 bg-frisch-orange" />
<NavLink
:href="link.href"
class="text-frisch-orange transition hover:text-frisch-indigo aria-[current]:text-frisch-indigo"
<li
v-for="(link, key, index) of links"
:key="key"
class="flex shrink-0 gap-x-4 text-xl"
>
{{ link.label }}
</NavLink>
</li>
</ul>
<Separator v-if="index > 0" class="h-full w-0.5 bg-frisch-orange" />
<NavLink
:href="link.href"
class="text-frisch-orange transition hover:text-frisch-indigo aria-[current]:text-frisch-indigo"
>
{{ link.label }}
</NavLink>
</li>
</ul>
</div>
<div class="flex shrink-0 lg:hidden">
<Sheet>
<SheetTrigger
aria-label="Toggle navigation menu"
class="flex font-bold transition"
:class="
route.path !== '/'
? 'opacity-100 translate-y-0'
: 'opacity-0 translate-x-5 pointer-events-none'
"
>
<MenuIcon :size="32" class="bg-frisch-orange p-1 text-white" />
</SheetTrigger>
<SheetContent class="overflow-y-auto">
<SheetTitle class="sr-only">Navigationsmenü</SheetTitle>
<ul class="grid py-8" role="list">
<li v-for="(link, key) of links" :key="key">
<NavLink
class="flex py-2 font-medium text-frisch-orange transition-opacity hover:opacity-100 focus-visible:opacity-100 aria-[current]:text-frisch-indigo"
:href="link.href"
>
{{ link.label }}
</NavLink>
</li>
</ul>
</SheetContent>
</Sheet>
</div>
</div>
</nav>
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/search-data-table/data-table.vue
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ function getCellClass<T>(columnDef?: CustomColumnDef<T>): string {

<template>
<div>
<div class="w-full border">
<div class="w-full overflow-x-hidden border">
<Table>
<TableHeader class="table-fixed">
<TableCaption class="sr-only">
Expand Down
21 changes: 3 additions & 18 deletions components/search-form.vue
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,16 @@ function onChange(event: Event) {
topic: formData.getAll("topic") as Array<string>,
});
}
// TODO: kill me
const containerHeight = ref(0);
onMounted(async () => {
await nextTick();
const searchForm = document.getElementById("search-container");
if (searchForm != null) {
containerHeight.value = searchForm.offsetHeight;
}
});
</script>

<template>
<div class="grid max-h-full grid-cols-[1fr_auto]">
<div id="search-container" class="relative w-full bg-frisch-orange-searchform">
<div class="relative flex h-full">
<div class="absolute inset-0 w-full overflow-auto bg-frisch-orange-searchform">
<form role="search" @submit.stop.prevent="onChange" @submit.prevent="onChange">
<div :style="{ height: containerHeight + 'px' }" class="overflow-y-auto">
<div class="overflow-y-auto">
<slot />
</div>
</form>
</div>
<div
class="size-0 border-y-[85px] border-l-[85px] border-y-transparent border-l-frisch-orange"
/>
</div>
</template>
18 changes: 18 additions & 0 deletions components/ui/drawer/Drawer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<script lang="ts" setup>
import { useForwardPropsEmits } from "radix-vue";
import type { DrawerRoot, DrawerRootEmits, DrawerRootProps } from "vaul-vue";
const props = withDefaults(defineProps<DrawerRootProps>(), {
shouldScaleBackground: true,
});
const emits = defineEmits<DrawerRootEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>

<template>
<DrawerRoot v-bind="forwarded">
<slot />
</DrawerRoot>
</template>
32 changes: 32 additions & 0 deletions components/ui/drawer/DrawerContent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<script lang="ts" setup>
import { type DialogContentEmits, type DialogContentProps, useForwardPropsEmits } from "radix-vue";
import { DrawerContent, DrawerPortal } from "vaul-vue";
import type { HtmlHTMLAttributes } from "vue";
import { cn } from "@/utils/styles";
import DrawerOverlay from "./DrawerOverlay.vue";
const props = defineProps<DialogContentProps & { class?: HtmlHTMLAttributes["class"] }>();
const emits = defineEmits<DialogContentEmits>();
const forwarded = useForwardPropsEmits(props, emits);
</script>

<template>
<DrawerPortal>
<DrawerOverlay />
<DrawerContent
v-bind="forwarded"
:class="
cn(
'fixed inset-x-0 bottom-0 z-50 mt-24 flex h-full pt-1.5 flex-col border bg-background',
props.class,
)
"
>
<div class="mx-auto mb-1.5 h-1 w-[100px] bg-frisch-marine" />
<slot />
</DrawerContent>
</DrawerPortal>
</template>
23 changes: 23 additions & 0 deletions components/ui/drawer/DrawerDescription.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts" setup>
import type { DrawerDescription, DrawerDescriptionProps } from "vaul-vue";
import { computed, type HtmlHTMLAttributes } from "vue";
import { cn } from "@/utils/styles";
const props = defineProps<DrawerDescriptionProps & { class?: HtmlHTMLAttributes["class"] }>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>

<template>
<DrawerDescription
v-bind="delegatedProps"
:class="cn('text-sm text-muted-foreground', props.class)"
>
<slot />
</DrawerDescription>
</template>
15 changes: 15 additions & 0 deletions components/ui/drawer/DrawerFooter.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script lang="ts" setup>
import type { HtmlHTMLAttributes } from "vue";
import { cn } from "@/utils/styles";
const props = defineProps<{
class?: HtmlHTMLAttributes["class"];
}>();
</script>

<template>
<div :class="cn('mt-auto flex flex-col gap-2 p-4', props.class)">
<slot />
</div>
</template>
15 changes: 15 additions & 0 deletions components/ui/drawer/DrawerHeader.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<script lang="ts" setup>
import type { HtmlHTMLAttributes } from "vue";
import { cn } from "@/utils/styles";
const props = defineProps<{
class?: HtmlHTMLAttributes["class"];
}>();
</script>

<template>
<div :class="cn('grid gap-1.5 p-4 text-center sm:text-left', props.class)">
<slot />
</div>
</template>
22 changes: 22 additions & 0 deletions components/ui/drawer/DrawerOverlay.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script lang="ts" setup>
import type { DialogOverlayProps } from "radix-vue";
import { DrawerOverlay } from "vaul-vue";
import { computed, type HtmlHTMLAttributes } from "vue";
import { cn } from "@/utils/styles";
const props = defineProps<DialogOverlayProps & { class?: HtmlHTMLAttributes["class"] }>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>

<template>
<DrawerOverlay
v-bind="delegatedProps"
:class="cn('fixed inset-0 z-50 bg-frisch-indigo/40', props.class)"
/>
</template>
23 changes: 23 additions & 0 deletions components/ui/drawer/DrawerTitle.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<script lang="ts" setup>
import type { DrawerTitle, DrawerTitleProps } from "vaul-vue";
import { computed, type HtmlHTMLAttributes } from "vue";
import { cn } from "@/utils/styles";
const props = defineProps<DrawerTitleProps & { class?: HtmlHTMLAttributes["class"] }>();
const delegatedProps = computed(() => {
const { class: _, ...delegated } = props;
return delegated;
});
</script>

<template>
<DrawerTitle
v-bind="delegatedProps"
:class="cn('text-lg font-semibold leading-none tracking-tight', props.class)"
>
<slot />
</DrawerTitle>
</template>
8 changes: 8 additions & 0 deletions components/ui/drawer/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
export { default as Drawer } from "./Drawer.vue";
export { default as DrawerContent } from "./DrawerContent.vue";
export { default as DrawerDescription } from "./DrawerDescription.vue";
export { default as DrawerFooter } from "./DrawerFooter.vue";
export { default as DrawerHeader } from "./DrawerHeader.vue";
export { default as DrawerOverlay } from "./DrawerOverlay.vue";
export { default as DrawerTitle } from "./DrawerTitle.vue";
export { DrawerClose, DrawerPortal, DrawerTrigger } from "vaul-vue";
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@
"tailwind-merge": "^2.4.0",
"tailwindcss-animate": "^1.0.7",
"valibot": "^0.37.0",
"vaul-vue": "^0.2.0",
"vue": "^3.4.36",
"vue-i18n": "^9.13.1",
"vue-i18n-routing": "^1.2.0",
Expand Down
41 changes: 33 additions & 8 deletions pages/search.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
<script lang="ts" setup>
import { SearchIcon } from "lucide-vue-next";
import * as v from "valibot";
import type { LocationQueryValue } from "vue-router";
import type { SearchFormData } from "@/components/search-form.vue";
import { Drawer, DrawerContent, DrawerTrigger } from "@/components/ui/drawer";
import {
Pagination,
PaginationEllipsis,
Expand Down Expand Up @@ -101,15 +103,38 @@ const facets = computed(() => {
</script>

<template>
<MainContent class="bg-frisch-marine pr-20">
<MainContent class="overflow-x-hidden bg-frisch-marine lg:overflow-x-auto lg:pr-20">
<h1 class="sr-only">{{ t("SearchPage.title") }}</h1>
<div v-if="!isLoading" class="grid h-full grid-cols-[minmax(650px,_1fr)_3fr]">
<SearchForm query="" @submit="onChange">
<SearchTextInput />
<SearchFilter :facets="facets" />
</SearchForm>
<div v-if="data != null" class="w-full bg-white p-8">
<div class="pt-9 font-semibold text-frisch-indigo">Suchergebnisse ({{ data.count }})</div>
<div v-if="!isLoading" class="grid h-full lg:grid-cols-[minmax(650px,_1fr)_auto_3fr]">
<div class="hidden content-start lg:block lg:content-stretch">
<SearchForm query="" @submit="onChange">
<SearchTextInput />
<SearchFilter :facets="facets" />
</SearchForm>
</div>
<div
class="hidden size-0 border-y-[85px] border-l-[85px] border-y-transparent border-l-frisch-orange lg:block"
/>
<div class="flex lg:hidden">
<Drawer>
<DrawerTrigger class="w-full">
<span class="flex w-full items-center bg-frisch-orange-searchform">
<SearchIcon :size="32" class="m-1.5 p-1 text-frisch-orange" />
<span class="font-semibold text-frisch-orange">Suche</span>
</span>
</DrawerTrigger>
<DrawerContent>
<SearchForm query="" @submit="onChange">
<SearchTextInput />
<SearchFilter :facets="facets" />
</SearchForm>
</DrawerContent>
</Drawer>
</div>
<div v-if="data != null" class="w-full bg-white px-3 pt-4 lg:p-8">
<div class="font-semibold text-frisch-indigo lg:pt-9">
Suchergebnisse ({{ data.count }})
</div>
<DataTable
class="flex align-top"
:data="data.results"
Expand Down
Loading

0 comments on commit 3100912

Please sign in to comment.