+17
index.html
+17
index.html
···
131
131
margin-bottom: 1rem;
132
132
}
133
133
.poll-header h2 { margin: 0; flex: 1; }
134
+
.toast {
135
+
position: fixed;
136
+
top: 1rem;
137
+
left: 50%;
138
+
transform: translateX(-50%);
139
+
background: #1a1a1a;
140
+
border: 1px solid #444;
141
+
padding: 0.75rem 1.5rem;
142
+
z-index: 1001;
143
+
animation: toast-fade 3s ease-in-out forwards;
144
+
}
145
+
@keyframes toast-fade {
146
+
0% { opacity: 0; transform: translateX(-50%) translateY(-10px); }
147
+
10% { opacity: 1; transform: translateX(-50%) translateY(0); }
148
+
80% { opacity: 1; }
149
+
100% { opacity: 0; }
150
+
}
134
151
</style>
135
152
</head>
136
153
<body>
+13
-1
src/main.ts
+13
-1
src/main.ts
···
26
26
27
27
const setStatus = (msg: string) => (status.textContent = msg);
28
28
29
+
const showToast = (msg: string) => {
30
+
const existing = document.querySelector(".toast");
31
+
if (existing) existing.remove();
32
+
33
+
const toast = document.createElement("div");
34
+
toast.className = "toast";
35
+
toast.textContent = msg;
36
+
document.body.appendChild(toast);
37
+
38
+
setTimeout(() => toast.remove(), 3000);
39
+
};
40
+
29
41
// track if a vote is in progress to prevent double-clicks
30
42
let votingInProgress = false;
31
43
···
217
229
218
230
const handleVote = async (pollUri: string, option: number) => {
219
231
if (!agent || !currentDid) {
220
-
setStatus("login to vote");
232
+
showToast("login to vote");
221
233
return;
222
234
}
223
235