1<template>
2 <div class="flex flex-col gap-3">
3 <div class="flex flex-col">
4 <h3 class="text-base-medium text-ink-gray-8">
5 {{ __("Quick links") }}
6 </h3>
7 <span class="mt-1 text-base leading-5 text-ink-gray-6">
8 {{
9 __(
10 "Add links to your website, docs or social pages. They will appear at the top right of every knowledge base page."
11 )
12 }}
13 </span>
14 </div>
15 <div class="rounded-5 border border-outline-gray-2 px-1 text-sm">
16 <List
17 v-if="rows.length"
18 :columns="columns"
19 :row-height="44"
20 class="[--list-gap:1rem] [--list-row-padding-x:0.5rem]"
21 >
22 <ListHeader>
23 <ListHeaderCell class="ms-2">{{ __("Label") }}</ListHeaderCell>
24 <ListHeaderCell class="ms-2">{{ __("URL") }}</ListHeaderCell>
25 <ListHeaderCell class="justify-center">
26 {{ __("Open in new tab") }}
27 </ListHeaderCell>
28 <ListHeaderCell />
29 </ListHeader>
30 <ListRows :items="rows" v-slot="{ item: row, index }">
31 <ListRow>
32 <ListCell>
33 <TextInput
34 v-model="row.label"
35 class="w-full"
36 variant="ghost"
37 :placeholder="__('Contact sales')"
38 />
39 </ListCell>
40 <ListCell>
41 <TextInput
42 v-model="row.url"
43 class="w-full"
44 variant="ghost"
45 :placeholder="__('https://example.com/contact')"
46 />
47 </ListCell>
48 <ListCell class="justify-center">
49 <Checkbox v-model="row.open_in_new_tab" />
50 </ListCell>
51 <ListCell>
52 <Dropdown
53 align="end"
54 :options="rowOptions(index)"
55 @update:open="(open) => open && (isConfirmingDelete = false)"
56 >
57 <Button
58 variant="ghost"
59 icon="lucide-more-horizontal"
60 :label="__('Row actions')"
61 />
62 </Dropdown>
63 </ListCell>
64 </ListRow>
65 </ListRows>
66 </List>
67 <div v-else class="p-4 text-center text-ink-gray-5">
68 {{ __("No links added yet.") }}
69 </div>
70 </div>
71 <Button
72 class="self-start"
73 variant="subtle"
74 icon-left="lucide-plus"
75 :label="__('Add link')"
76 :disabled="rows.some((row) => !row.label?.trim() || !row.url?.trim())"
77 @click="rows.push({ label: '', url: '', open_in_new_tab: false })"
78 />
79 </div>
80</template>
81
82<script setup lang="ts">
83import { __ } from "../translation";
84import { ConfirmDelete } from "../utils";
85import { Button, Checkbox, Dropdown, TextInput } from "frappe-ui";
86import {
87 List,
88 ListCell,
89 ListHeader,
90 ListHeaderCell,
91 ListRow,
92 ListRows,
93} from "frappe-ui/list";
94import { ref } from "vue";
95
96type HeaderLink = { label: string; url: string; open_in_new_tab: boolean };
97
98const rows = defineModel<HeaderLink[]>({ required: true });
99
100const columns = ["minmax(0,1fr)", "minmax(0,2fr)", "112px", "32px"];
101
102const isConfirmingDelete = ref(false);
103
104function rowOptions(index: number) {
105 return ConfirmDelete({
106 isConfirmingDelete,
107 onConfirmDelete: () => rows.value.splice(index, 1),
108 });
109}
110</script>
111