Skip to content

Commit fb2bdd4

Browse files
committed
Add step by step instructions for new event submission
1 parent 48e1193 commit fb2bdd4

4 files changed

Lines changed: 317 additions & 5 deletions

File tree

pcd-website/src/components/MapView.vue

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import NodePanel from './NodePanel.vue';
77
import NodeList from './NodeList.vue';
88
import LanguageSwitcher from './LanguageSwitcher.vue';
99
import InfoModal from './InfoModal.vue';
10-
import { SUBMIT_EVENT_URL } from '../config';
10+
import SubmitModal from './SubmitModal.vue';
1111
import { currentLocale } from '../i18n/localeState';
1212
import { i18n } from '../i18n/index';
1313
@@ -25,6 +25,7 @@ const listOpen = ref(false);
2525
const INFO_MODAL_SUPPRESS_KEY = 'pcd-info-modal-suppressed';
2626
const infoModalOpen = ref(false);
2727
const infoModalAutoOpened = ref(false);
28+
const submitModalOpen = ref(false);
2829
2930
function shouldAutoOpenInfoModal(): boolean {
3031
return localStorage.getItem(INFO_MODAL_SUPPRESS_KEY) !== 'true';
@@ -231,6 +232,8 @@ function onNodeSelect(node: Node) {
231232
}
232233
233234
function handleKeydown(e: KeyboardEvent) {
235+
if (infoModalOpen.value || submitModalOpen.value) return;
236+
234237
const tag = (document.activeElement as HTMLElement)?.tagName?.toLowerCase();
235238
const isTextInput = tag === 'input' || tag === 'textarea' ||
236239
(document.activeElement as HTMLElement)?.isContentEditable;
@@ -693,10 +696,10 @@ onUnmounted(() => {
693696
<LanguageSwitcher />
694697
</div>
695698
<div class="host-btn-group">
696-
<a
699+
<button
697700
id="host-btn"
698-
:href="SUBMIT_EVENT_URL"
699-
>{{ t('nav.submit_event') }}</a>
701+
@click="submitModalOpen = true"
702+
>{{ t('nav.submit_event') }}</button>
700703
<button
701704
id="info-btn"
702705
:aria-label="t('nav.info_button_label')"
@@ -705,6 +708,7 @@ onUnmounted(() => {
705708
>i</button>
706709
</div>
707710
<InfoModal :open="infoModalOpen" :bannerImageUrl="props.bannerImageUrl" :autoOpened="infoModalAutoOpened" @close="infoModalOpen = false" @suppress="suppressInfoModal" />
711+
<SubmitModal :open="submitModalOpen" @close="submitModalOpen = false" />
708712
<div class="banner-controls-right">
709713
<button
710714
id="theme-toggle"
Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
<script setup lang="ts">
2+
import { ref, watch, nextTick, onUnmounted } from 'vue';
3+
import { useI18n } from 'vue-i18n';
4+
import { createFocusTrap, type FocusTrap } from 'focus-trap';
5+
import { SUBMIT_EVENT_URL, PCD_FORUM_THREAD_URL, PCD_FORUM_NEW_TOPIC_URL } from '../config';
6+
7+
const props = defineProps<{ open: boolean }>();
8+
const emit = defineEmits<{ close: [] }>();
9+
10+
const { t } = useI18n();
11+
const modalRef = ref<HTMLElement | null>(null);
12+
let trap: FocusTrap | null = null;
13+
let closing = false;
14+
15+
function handleClose() {
16+
if (closing) return;
17+
closing = true;
18+
emit('close');
19+
setTimeout(() => {
20+
document.getElementById('host-btn')?.focus();
21+
closing = false;
22+
}, 0);
23+
}
24+
25+
watch(
26+
() => props.open,
27+
async (isOpen) => {
28+
if (isOpen) {
29+
closing = false;
30+
await nextTick();
31+
if (modalRef.value) {
32+
trap = createFocusTrap(modalRef.value, {
33+
onDeactivate: () => handleClose(),
34+
escapeDeactivates: true,
35+
allowOutsideClick: true,
36+
fallbackFocus: () => modalRef.value!,
37+
});
38+
trap.activate();
39+
}
40+
} else {
41+
trap?.deactivate();
42+
trap = null;
43+
}
44+
},
45+
);
46+
47+
onUnmounted(() => {
48+
trap?.deactivate();
49+
});
50+
</script>
51+
52+
<template>
53+
<Teleport to="body">
54+
<div
55+
v-if="open"
56+
class="submit-modal-backdrop"
57+
@click.self="handleClose()"
58+
>
59+
<div
60+
ref="modalRef"
61+
role="dialog"
62+
aria-modal="true"
63+
aria-labelledby="submit-modal-title"
64+
class="submit-modal"
65+
>
66+
<button
67+
class="submit-modal-close"
68+
:aria-label="t('nav.submit_modal_close')"
69+
@click="handleClose()"
70+
>×</button>
71+
<div class="submit-modal-body">
72+
<h2 id="submit-modal-title" class="submit-modal-title">{{ t('nav.submit_modal_title') }}</h2>
73+
<ol class="submit-steps">
74+
<li class="submit-step">
75+
<span class="step-num" aria-hidden="true">1</span>
76+
<a
77+
class="step-btn"
78+
:href="PCD_FORUM_THREAD_URL"
79+
target="_blank"
80+
rel="noopener"
81+
:aria-label="`${t('nav.submit_modal_step1_heading')} — ${t('nav.submit_modal_step1_body')} (${t('nav.opens_in_new_tab')})`"
82+
>
83+
<span class="step-btn-text">
84+
<strong>{{ t('nav.submit_modal_step1_heading') }}</strong>
85+
<span class="step-btn-body">{{ t('nav.submit_modal_step1_body') }}</span>
86+
</span>
87+
<span class="step-btn-arrow" aria-hidden="true">→</span>
88+
</a>
89+
</li>
90+
<li class="submit-step">
91+
<span class="step-num" aria-hidden="true">2</span>
92+
<a
93+
class="step-btn"
94+
:href="PCD_FORUM_NEW_TOPIC_URL"
95+
target="_blank"
96+
rel="noopener"
97+
:aria-label="`${t('nav.submit_modal_step2_heading')} — ${t('nav.submit_modal_step2_body')} (${t('nav.opens_in_new_tab')})`"
98+
>
99+
<span class="step-btn-text">
100+
<strong>{{ t('nav.submit_modal_step2_heading') }}</strong>
101+
<span class="step-btn-body">{{ t('nav.submit_modal_step2_body') }}</span>
102+
</span>
103+
<span class="step-btn-arrow" aria-hidden="true">→</span>
104+
</a>
105+
</li>
106+
<li class="submit-step">
107+
<span class="step-num" aria-hidden="true">3</span>
108+
<a
109+
class="step-btn"
110+
:href="SUBMIT_EVENT_URL"
111+
target="_blank"
112+
rel="noopener"
113+
:aria-label="`${t('nav.submit_modal_step3_heading')} — ${t('nav.submit_modal_step3_body')} (${t('nav.opens_in_new_tab')})`"
114+
>
115+
<span class="step-btn-text">
116+
<strong>{{ t('nav.submit_modal_step3_heading') }}</strong>
117+
<span class="step-btn-body">{{ t('nav.submit_modal_step3_body') }}</span>
118+
</span>
119+
<span class="step-btn-arrow" aria-hidden="true">→</span>
120+
</a>
121+
</li>
122+
</ol>
123+
<p class="submit-modal-note">{{ t('nav.submit_modal_note') }}</p>
124+
</div>
125+
</div>
126+
</div>
127+
</Teleport>
128+
</template>
129+
130+
<style scoped>
131+
.submit-modal-backdrop {
132+
position: fixed;
133+
inset: 0;
134+
background: rgba(0, 0, 0, 0.5);
135+
z-index: var(--z-overlay);
136+
display: flex;
137+
align-items: center;
138+
justify-content: center;
139+
padding: var(--spacing-md);
140+
}
141+
142+
.submit-modal {
143+
position: relative;
144+
background: var(--color-bg-panel);
145+
border-radius: 12px;
146+
max-width: 480px;
147+
width: 100%;
148+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.18);
149+
overflow: hidden;
150+
}
151+
152+
.submit-modal-close {
153+
position: absolute;
154+
top: var(--spacing-sm);
155+
right: var(--spacing-sm);
156+
z-index: 1;
157+
width: 32px;
158+
height: 32px;
159+
display: flex;
160+
align-items: center;
161+
justify-content: center;
162+
background: transparent;
163+
color: var(--color-text-muted);
164+
border: none;
165+
border-radius: 50%;
166+
cursor: pointer;
167+
font-size: 1.25rem;
168+
line-height: 1;
169+
transition: background-color 0.15s ease, color 0.15s ease;
170+
}
171+
172+
.submit-modal-close:hover {
173+
background: var(--color-border);
174+
color: var(--color-text);
175+
}
176+
177+
.submit-modal-close:focus-visible {
178+
outline: 2px solid var(--color-focus);
179+
outline-offset: 2px;
180+
}
181+
182+
.submit-modal-body {
183+
padding: var(--spacing-lg);
184+
padding-top: calc(var(--spacing-lg) + 8px);
185+
}
186+
187+
.submit-modal-title {
188+
font-size: 1.125rem;
189+
font-weight: 700;
190+
margin: 0 0 var(--spacing-lg);
191+
color: var(--color-text);
192+
padding-right: 2rem;
193+
}
194+
195+
.submit-steps {
196+
list-style: none;
197+
padding: 0;
198+
margin: 0 0 var(--spacing-lg);
199+
display: flex;
200+
flex-direction: column;
201+
gap: var(--spacing-sm);
202+
}
203+
204+
.submit-step {
205+
display: flex;
206+
gap: var(--spacing-sm);
207+
align-items: stretch;
208+
}
209+
210+
.step-num {
211+
flex-shrink: 0;
212+
width: 2rem;
213+
height: 2rem;
214+
border-radius: 50%;
215+
background: var(--color-primary);
216+
color: #fff;
217+
font-size: 0.9375rem;
218+
font-weight: 700;
219+
display: flex;
220+
align-items: center;
221+
justify-content: center;
222+
margin-top: 0.5rem;
223+
}
224+
225+
.step-btn {
226+
flex: 1;
227+
display: flex;
228+
align-items: center;
229+
gap: var(--spacing-sm);
230+
padding: 0.625rem 0.75rem;
231+
background: var(--color-bg-secondary, color-mix(in srgb, var(--color-bg-panel) 94%, var(--color-text) 6%));
232+
border: 1px solid var(--color-border);
233+
border-radius: 8px;
234+
text-decoration: none;
235+
color: var(--color-text);
236+
transition: background-color 0.15s ease, border-color 0.15s ease;
237+
min-width: 0;
238+
}
239+
240+
.step-btn:hover {
241+
background: color-mix(in srgb, var(--color-bg-panel) 88%, var(--color-primary) 12%);
242+
border-color: var(--color-primary);
243+
}
244+
245+
.step-btn:focus-visible {
246+
outline: 2px solid var(--color-focus);
247+
outline-offset: 2px;
248+
}
249+
250+
.step-btn-text {
251+
flex: 1;
252+
min-width: 0;
253+
display: flex;
254+
flex-direction: column;
255+
gap: 0.125rem;
256+
}
257+
258+
.step-btn-text strong {
259+
font-size: 0.9375rem;
260+
font-weight: 600;
261+
line-height: 1.3;
262+
}
263+
264+
.step-btn-body {
265+
font-size: 0.8125rem;
266+
color: var(--color-text-muted);
267+
line-height: 1.4;
268+
}
269+
270+
.step-btn-arrow {
271+
flex-shrink: 0;
272+
font-size: 1rem;
273+
color: var(--color-text-muted);
274+
transition: transform 0.15s ease, color 0.15s ease;
275+
}
276+
277+
.step-btn:hover .step-btn-arrow {
278+
transform: translateX(3px);
279+
color: var(--color-primary);
280+
}
281+
282+
.submit-modal-note {
283+
margin: 0;
284+
font-size: 0.8125rem;
285+
line-height: 1.5;
286+
color: var(--color-text-muted);
287+
border-top: 1px solid var(--color-border);
288+
padding-top: var(--spacing-md);
289+
}
290+
</style>

pcd-website/src/config.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,11 @@ export const GITHUB_CONTENT_ISSUE_URL =
77
"https://github.com/processing/processing-community-day/issues/new?template=03-content-issue.yml";
88
export const PCD_FORUM_THREAD_URL =
99
"https://discourse.processing.org/t/pcd-worldwide-2026-call-for-organizers/48081";
10+
export const PCD_FORUM_NEW_TOPIC_URL =
11+
"https://discourse.processing.org/new-topic?" +
12+
new URLSearchParams({
13+
title: "PCD @ [Your City] 2026",
14+
body: "Hi! I'm organizing a Processing Community Day 2026 event in [City, Country].\n\nI'll update this thread with more details as planning progresses.",
15+
category: "community",
16+
tags: "pcd",
17+
}).toString();

pcd-website/src/i18n/locales/en.json

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,17 @@
1616
"info_modal_forum_btn_new_tab": "Visit the forum thread (opens in new tab)",
1717
"info_modal_go_to_map": "Go to the map",
1818
"info_modal_back_to_map": "Back to the map",
19-
"info_modal_dont_show_again": "Don't show this again"
19+
"info_modal_dont_show_again": "Don't show this again",
20+
"opens_in_new_tab": "opens in new tab",
21+
"submit_modal_title": "How to submit your event",
22+
"submit_modal_step1_heading": "Say hi in the thread",
23+
"submit_modal_step1_body": "Let us know you're interested in the organizer thread.",
24+
"submit_modal_step2_heading": "Open a forum thread for your event",
25+
"submit_modal_step2_body": "Start a thread for your city — a stub is fine.",
26+
"submit_modal_step3_heading": "Submit via GitHub",
27+
"submit_modal_step3_body": "Fill in the event form. A pull request opens automatically.",
28+
"submit_modal_note": "No GitHub account? Just say hi in the forum thread and we'll help you from there.",
29+
"submit_modal_close": "Close"
2030
},
2131
"node_list": {
2232
"dialog_label": "Node list",

0 commit comments

Comments
 (0)