Skip to content

Commit b5d1ed3

Browse files
André DietrichAndré Dietrich
authored andcommitted
improve menu modal in preview
1 parent a10a1be commit b5d1ed3

31 files changed

Lines changed: 743 additions & 438 deletions

src/components/ImportModal.vue

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,10 @@ export default defineComponent({
6565
<button
6666
type="button"
6767
class="import-card"
68-
:class="{ 'import-card--disabled': isDisabled(source) }"
68+
:class="{
69+
'import-card--disabled': isDisabled(source),
70+
'import-card--featured': source.featured,
71+
}"
6972
:disabled="isDisabled(source)"
7073
@click="pick(source)"
7174
>
@@ -111,6 +114,13 @@ export default defineComponent({
111114
outline: none;
112115
}
113116
117+
/* the primary "blank document" card stands out even without hover */
118+
.import-card--featured {
119+
border-color: var(--bs-primary, #0d6efd);
120+
border-width: 2px;
121+
background: rgba(13, 110, 253, 0.06);
122+
}
123+
114124
.import-card--disabled {
115125
cursor: not-allowed;
116126
opacity: 0.55;

src/components/ShareModal.vue

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
<script lang="ts">
2+
import { defineComponent, PropType } from "vue";
3+
import Modal from "bootstrap/js/dist/modal";
4+
5+
// A share/action item rendered as a card. `href` items open an external link
6+
// (e.g. a previous export); the others emit their `id` so the parent (the editor)
7+
// runs the matching method. `disabled` items render greyed-out and inert.
8+
export interface ShareItem {
9+
id: string;
10+
icon: string;
11+
/** i18n key for the card title; ignored when `label` is given. */
12+
labelKey?: string;
13+
/** pre-translated title (use when the label needs interpolation). */
14+
label?: string;
15+
descriptionKey?: string;
16+
disabled?: boolean;
17+
href?: string;
18+
}
19+
20+
export interface ShareSection {
21+
headingKey?: string;
22+
items: ShareItem[];
23+
}
24+
25+
export interface ShareTab {
26+
id: string;
27+
labelKey: string;
28+
sections: ShareSection[];
29+
}
30+
31+
// Tabbed card chooser that replaces the editor's old "menu" dropdown. It groups
32+
// every share / publish / GitHub / local-folder action into tabs of cards. The
33+
// component is purely presentational: the parent passes the tabs (built from its
34+
// reactive state) and handles the emitted action ids.
35+
export default defineComponent({
36+
name: "ShareModal",
37+
38+
props: {
39+
tabs: {
40+
type: Array as PropType<ShareTab[]>,
41+
required: true,
42+
},
43+
},
44+
45+
emits: ["action"],
46+
47+
data() {
48+
return {
49+
active: "" as string,
50+
modal: null as Modal | null,
51+
};
52+
},
53+
54+
methods: {
55+
open() {
56+
if (!this.active && this.tabs.length) this.active = this.tabs[0].id;
57+
if (!this.modal) {
58+
this.modal = new Modal(this.$refs.el as Element);
59+
}
60+
this.modal.show();
61+
},
62+
63+
cardTag(item: ShareItem): string {
64+
return !item.disabled && item.href ? "a" : "button";
65+
},
66+
67+
onCardClick(item: ShareItem) {
68+
if (item.disabled) return;
69+
// href cards keep their default behaviour (open in a new tab); just close
70+
// the modal. Action cards emit their id for the parent to handle.
71+
this.modal?.hide();
72+
if (!item.href) this.$emit("action", item.id);
73+
},
74+
},
75+
});
76+
</script>
77+
78+
<template>
79+
<div ref="el" class="modal fade" tabindex="-1" aria-hidden="true">
80+
<div class="modal-dialog modal-lg modal-dialog-centered">
81+
<div class="modal-content">
82+
<div class="modal-header">
83+
<h5 class="modal-title">{{ $t("share.modalTitle") }}</h5>
84+
<button
85+
type="button"
86+
class="btn-close"
87+
data-bs-dismiss="modal"
88+
:aria-label="$t('card.close')"
89+
></button>
90+
</div>
91+
<div class="modal-body">
92+
<ul class="nav nav-tabs mb-3">
93+
<li v-for="tab in tabs" :key="tab.id" class="nav-item">
94+
<button
95+
type="button"
96+
class="nav-link"
97+
:class="{ active: active === tab.id }"
98+
@click="active = tab.id"
99+
>
100+
{{ $t(tab.labelKey) }}
101+
</button>
102+
</li>
103+
</ul>
104+
105+
<template v-for="tab in tabs" :key="tab.id">
106+
<div v-if="active === tab.id">
107+
<template v-for="(section, i) in tab.sections" :key="i">
108+
<h6
109+
v-if="section.headingKey"
110+
class="share-section-heading text-uppercase text-muted"
111+
>
112+
{{ $t(section.headingKey) }}
113+
</h6>
114+
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3 mb-2">
115+
<div v-for="item in section.items" :key="item.id" class="col">
116+
<component
117+
:is="cardTag(item)"
118+
class="share-card"
119+
:class="{ 'share-card--disabled': item.disabled }"
120+
:href="!item.disabled && item.href ? item.href : null"
121+
:target="item.href ? '_blank' : null"
122+
:disabled="item.disabled || null"
123+
@click="onCardClick(item)"
124+
>
125+
<i class="bi share-card-icon" :class="item.icon"></i>
126+
<span class="share-card-title">
127+
{{ item.label || (item.labelKey ? $t(item.labelKey) : "") }}
128+
</span>
129+
<small
130+
v-if="item.descriptionKey"
131+
class="share-card-desc text-muted"
132+
>
133+
{{ $t(item.descriptionKey) }}
134+
</small>
135+
</component>
136+
</div>
137+
</div>
138+
</template>
139+
</div>
140+
</template>
141+
</div>
142+
</div>
143+
</div>
144+
</div>
145+
</template>
146+
147+
<style scoped>
148+
.share-section-heading {
149+
font-size: 0.75rem;
150+
letter-spacing: 0.04em;
151+
margin: 0.75rem 0 0.4rem;
152+
}
153+
154+
.share-card {
155+
display: flex;
156+
flex-direction: column;
157+
align-items: center;
158+
text-align: center;
159+
width: 100%;
160+
height: 100%;
161+
gap: 0.4rem;
162+
padding: 1.1rem 0.9rem;
163+
background: var(--bs-body-bg, #fff);
164+
border: 1px solid var(--bs-border-color, #dee2e6);
165+
border-radius: 0.75rem;
166+
cursor: pointer;
167+
text-decoration: none;
168+
color: inherit;
169+
transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
170+
}
171+
172+
.share-card:hover,
173+
.share-card:focus-visible {
174+
transform: translateY(-3px);
175+
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
176+
border-color: var(--bs-primary, #0d6efd);
177+
outline: none;
178+
color: inherit;
179+
}
180+
181+
.share-card--disabled {
182+
cursor: not-allowed;
183+
opacity: 0.55;
184+
}
185+
186+
.share-card--disabled:hover,
187+
.share-card--disabled:focus-visible {
188+
transform: none;
189+
box-shadow: none;
190+
border-color: var(--bs-border-color, #dee2e6);
191+
}
192+
193+
.share-card--disabled .share-card-icon {
194+
color: var(--bs-secondary, #6c757d);
195+
}
196+
197+
.share-card-icon {
198+
font-size: 2rem;
199+
line-height: 1;
200+
color: var(--bs-primary, #0d6efd);
201+
}
202+
203+
.share-card-title {
204+
font-weight: 600;
205+
}
206+
207+
.share-card-desc {
208+
font-size: 0.8125rem;
209+
line-height: 1.3;
210+
}
211+
</style>

src/i18n/am.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@
3333
},
3434
"share": {
3535
"header": "አርታዒውን አጋራ ...",
36+
"modalTitle": "Share & actions",
37+
"publishedHeading": "Open existing publication",
38+
"nostr": "Nostr",
39+
"downloadZipLabel": "ZIP archive",
40+
"downloadReadmeLabel": "Readme file",
41+
"downloadActiveFileInfo": "Downloads only the currently open file",
42+
"tabs": {
43+
"collaborate": "Editor",
44+
"publish": "Publish",
45+
"published": "Published links",
46+
"export": "Export",
47+
"github": "GitHub",
48+
"localFolder": "Local folder"
49+
},
3650
"collaborationLink": "የትብብር አገናኝ",
3751
"collaborationLinkTitle": "ይህን ሰነድ ከሌሎች ጋር አጋራ",
3852
"collaborationLinkTooltip": "ይህን ተግባር ከመጠቀምህ/ሽ በፊት ይህን ሰነድ fork አድርግ/ጊ",

src/i18n/ar.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@
3333
},
3434
"share": {
3535
"header": "مشاركة المحرر ...",
36+
"modalTitle": "المشاركة والإجراءات",
37+
"publishedHeading": "فتح منشور موجود",
38+
"nostr": "Nostr",
39+
"downloadZipLabel": "أرشيف ZIP",
40+
"downloadReadmeLabel": "ملف Readme",
41+
"downloadActiveFileInfo": "ينزّل الملف المفتوح حاليًا فقط",
42+
"tabs": {
43+
"collaborate": "Editor",
44+
"publish": "نشر",
45+
"published": "الروابط المنشورة",
46+
"export": "تصدير",
47+
"github": "GitHub",
48+
"localFolder": "مجلد محلي"
49+
},
3650
"collaborationLink": "رابط التعاون",
3751
"collaborationLinkTitle": "مشاركة هذا المستند مع الآخرين",
3852
"collaborationLinkTooltip": "أنشئ Fork لهذا المستند قبل استخدام هذه الوظيفة",

src/i18n/bg.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@
3333
},
3434
"share": {
3535
"header": "Споделяне на редактора ...",
36+
"modalTitle": "Споделяне и действия",
37+
"publishedHeading": "Отваряне на съществуваща публикация",
38+
"nostr": "Nostr",
39+
"downloadZipLabel": "ZIP архив",
40+
"downloadReadmeLabel": "Файл Readme",
41+
"downloadActiveFileInfo": "Изтегля само текущо отворения файл",
42+
"tabs": {
43+
"collaborate": "Editor",
44+
"publish": "Публикуване",
45+
"published": "Публикувани връзки",
46+
"export": "Експортиране",
47+
"github": "GitHub",
48+
"localFolder": "Локална папка"
49+
},
3650
"collaborationLink": "връзка за съвместна работа",
3751
"collaborationLinkTitle": "Споделяне на този документ с други",
3852
"collaborationLinkTooltip": "Направете fork на този документ, преди да използвате тази функция",

src/i18n/cs.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@
3333
},
3434
"share": {
3535
"header": "Sdílet editor ...",
36+
"modalTitle": "Sdílení a akce",
37+
"publishedHeading": "Otevřít existující publikaci",
38+
"nostr": "Nostr",
39+
"downloadZipLabel": "Archiv ZIP",
40+
"downloadReadmeLabel": "Soubor Readme",
41+
"downloadActiveFileInfo": "Stáhne pouze aktuálně otevřený soubor",
42+
"tabs": {
43+
"collaborate": "Editor",
44+
"publish": "Publikovat",
45+
"published": "Publikované odkazy",
46+
"export": "Exportovat",
47+
"github": "GitHub",
48+
"localFolder": "Místní složka"
49+
},
3650
"collaborationLink": "odkaz pro spolupráci",
3751
"collaborationLinkTitle": "Sdílet tento dokument s ostatními",
3852
"collaborationLinkTooltip": "Před použitím této funkce vytvořte fork tohoto dokumentu",

src/i18n/da.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@
3333
},
3434
"share": {
3535
"header": "Del editor ...",
36+
"modalTitle": "Deling og handlinger",
37+
"publishedHeading": "Åbn eksisterende udgivelse",
38+
"nostr": "Nostr",
39+
"downloadZipLabel": "ZIP-arkiv",
40+
"downloadReadmeLabel": "Readme-fil",
41+
"downloadActiveFileInfo": "Downloader kun den aktuelt åbne fil",
42+
"tabs": {
43+
"collaborate": "Editor",
44+
"publish": "Udgiv",
45+
"published": "Udgivne links",
46+
"export": "Eksportér",
47+
"github": "GitHub",
48+
"localFolder": "Lokal mappe"
49+
},
3650
"collaborationLink": "samarbejdslink",
3751
"collaborationLinkTitle": "Del dette dokument med andre",
3852
"collaborationLinkTooltip": "Fork dette dokument, før du kan bruge denne funktion",

src/i18n/de.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@
3333
},
3434
"share": {
3535
"header": "Editor teilen ...",
36+
"modalTitle": "Teilen & Aktionen",
37+
"publishedHeading": "Vorhandene Veröffentlichung öffnen",
38+
"nostr": "Nostr",
39+
"downloadZipLabel": "ZIP-Archiv",
40+
"downloadReadmeLabel": "Readme-Datei",
41+
"downloadActiveFileInfo": "Lädt nur die aktuell geöffnete Datei herunter",
42+
"tabs": {
43+
"collaborate": "Editor",
44+
"publish": "Publizieren",
45+
"published": "Veröffentlichte Links",
46+
"export": "Export",
47+
"github": "GitHub",
48+
"localFolder": "Lokaler Ordner"
49+
},
3650
"collaborationLink": "Kollaborationslink",
3751
"collaborationLinkTitle": "Dieses Dokument mit anderen teilen",
3852
"collaborationLinkTooltip": "Forke das Dokument, bevor du diese Funktion nutzt",

src/i18n/el.json

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@
3333
},
3434
"share": {
3535
"header": "Κοινή χρήση επεξεργαστή ...",
36+
"modalTitle": "Κοινή χρήση και ενέργειες",
37+
"publishedHeading": "Άνοιγμα υπάρχουσας δημοσίευσης",
38+
"nostr": "Nostr",
39+
"downloadZipLabel": "Αρχείο ZIP",
40+
"downloadReadmeLabel": "Αρχείο Readme",
41+
"downloadActiveFileInfo": "Λήψη μόνο του τρέχοντος ανοικτού αρχείου",
42+
"tabs": {
43+
"collaborate": "Editor",
44+
"publish": "Δημοσίευση",
45+
"published": "Δημοσιευμένοι σύνδεσμοι",
46+
"export": "Εξαγωγή",
47+
"github": "GitHub",
48+
"localFolder": "Τοπικός φάκελος"
49+
},
3650
"collaborationLink": "σύνδεσμος συνεργασίας",
3751
"collaborationLinkTitle": "Κοινή χρήση αυτού του εγγράφου με άλλους",
3852
"collaborationLinkTooltip": "Κάντε fork αυτού του εγγράφου πριν χρησιμοποιήσετε αυτή τη λειτουργία",

0 commit comments

Comments
 (0)