emergency: 911 demoted to very last resort — page now leads with event-help share card; emergency-services number moved to collapsed 'If none of the above is working' disclosure at the very bottom, no alert styling
Some checks failed
ci / check (push) Has been cancelled
Some checks failed
ci / check (push) Has been cancelled
This commit is contained in:
parent
5b5d1857c3
commit
1c49b8a4a8
3 changed files with 85 additions and 17 deletions
|
|
@ -661,16 +661,35 @@ html.dark .app-main__icon {
|
|||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
.emergency-fallback {
|
||||
background: var(--emergency);
|
||||
border: 1px solid var(--emergency);
|
||||
.emergency-share-card {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: var(--radius);
|
||||
color: var(--emergency-contrast);
|
||||
padding: 1rem;
|
||||
}
|
||||
.emergency-fallback h2 {
|
||||
.emergency-share-card h2 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.emergency-last-resort {
|
||||
border-top: 1px solid var(--border);
|
||||
margin-top: 1.5rem;
|
||||
padding-top: 0.75rem;
|
||||
}
|
||||
.emergency-last-resort summary {
|
||||
color: var(--muted);
|
||||
cursor: pointer;
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
.emergency-last-resort p {
|
||||
color: var(--muted);
|
||||
}
|
||||
.emergency-call-last {
|
||||
border: 1px solid var(--border);
|
||||
border-radius: 999px;
|
||||
color: var(--foreground);
|
||||
display: inline-block;
|
||||
padding: 0.4rem 1rem;
|
||||
text-decoration: none;
|
||||
}
|
||||
.emergency-service p {
|
||||
margin: 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,13 +129,18 @@ export function createEmergencyView(
|
|||
const address = detail?.address ?? resolved.floor.address;
|
||||
const procedures = detail?.procedures?.length ? detail.procedures : resolved.floor.procedures;
|
||||
|
||||
const urgent = document.createElement("div");
|
||||
urgent.className = "emergency-fallback";
|
||||
urgent.append(heading("emergency-call-heading", "Can't reach event help?"));
|
||||
|
||||
// Share first: the practical action (send your location + numbers to your
|
||||
// group) belongs above the emergency-services number, which the procedures
|
||||
// now frame as the fallback.
|
||||
// Share card at top: the primary self-help action. The emergency-services
|
||||
// number is deliberately NOT here — per product rule it is the very last
|
||||
// resort and lives behind an explicit disclosure at the page bottom.
|
||||
const shareCard = document.createElement("div");
|
||||
shareCard.className = "emergency-share-card";
|
||||
shareCard.append(heading("emergency-share-heading", "Start with event help"));
|
||||
shareCard.append(
|
||||
text(
|
||||
"p",
|
||||
"Event staff, security, and first aid are your first responders here. Share your situation and location with them or your group.",
|
||||
),
|
||||
);
|
||||
const shareBtn = document.createElement("button");
|
||||
shareBtn.className = "emergency-share-btn";
|
||||
shareBtn.textContent = "Share emergency info";
|
||||
|
|
@ -153,11 +158,8 @@ export function createEmergencyView(
|
|||
alert("Copied to clipboard: " + textToShare.slice(0, 80) + "...");
|
||||
}
|
||||
};
|
||||
urgent.append(shareBtn);
|
||||
|
||||
addService(urgent, "Emergency services", services.emergencyNumber, true);
|
||||
urgent.append(text("p", "Call only when event staff and first aid can't respond. Tap to call."));
|
||||
section.append(urgent);
|
||||
shareCard.append(shareBtn);
|
||||
section.append(shareCard);
|
||||
|
||||
const contacts = document.createElement("section");
|
||||
contacts.setAttribute("aria-labelledby", "emergency-services-heading");
|
||||
|
|
@ -241,5 +243,31 @@ export function createEmergencyView(
|
|||
section.append(notices);
|
||||
}
|
||||
|
||||
// Very last resort: the emergency-services number sits at the BOTTOM of
|
||||
// the page behind an explicit disclosure, deliberately not styled as an
|
||||
// alert. The dial link stays in the DOM for accessibility; it just is not
|
||||
// presented until asked for.
|
||||
const lastResort = document.createElement("details");
|
||||
lastResort.className = "emergency-last-resort";
|
||||
const summary = document.createElement("summary");
|
||||
summary.textContent = "If none of the above is working";
|
||||
lastResort.append(summary);
|
||||
lastResort.append(
|
||||
text(
|
||||
"p",
|
||||
`Only when event staff, security, and first aid are unreachable and someone is in immediate danger: call ${services.emergencyNumber}.`,
|
||||
),
|
||||
);
|
||||
const dialLink = document.createElement("a");
|
||||
dialLink.className = "emergency-call-last";
|
||||
dialLink.href = `tel:${services.emergencyNumber}`;
|
||||
dialLink.textContent = `Call ${services.emergencyNumber}`;
|
||||
dialLink.setAttribute(
|
||||
"aria-label",
|
||||
`As a last resort, call emergency services at ${services.emergencyNumber}`,
|
||||
);
|
||||
lastResort.append(dialLink);
|
||||
section.append(lastResort);
|
||||
|
||||
return section;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -189,6 +189,27 @@ describe("emergency view", () => {
|
|||
expect(view.textContent).toContain("isn't on this device yet");
|
||||
});
|
||||
|
||||
it("emergency number is last-resort: bottom of page, collapsed, after procedures", () => {
|
||||
const view = createEmergencyView(undefined, NOW);
|
||||
const last = view.querySelector(".emergency-last-resort");
|
||||
expect(last).toBeTruthy();
|
||||
// collapsed by default — the number is not presented until asked
|
||||
expect(last?.hasAttribute("open")).toBe(false);
|
||||
// it is the very last element of the view
|
||||
expect(view.lastElementChild).toBe(last);
|
||||
// ...it comes after the procedures section...
|
||||
const idx = (selector: string): number => {
|
||||
const el = view.querySelector(selector);
|
||||
return el ? [...view.children].indexOf(el) : -1;
|
||||
};
|
||||
expect(idx(".emergency-last-resort")).toBeGreaterThan(
|
||||
idx('[aria-labelledby="emergency-procedures-heading"]'),
|
||||
);
|
||||
// ...and the page leads with event help, not the dial number
|
||||
expect(idx(".emergency-share-card")).toBeGreaterThanOrEqual(1);
|
||||
expect(view.querySelector(".emergency-share-card")?.textContent).toContain("event help");
|
||||
});
|
||||
|
||||
it("dataset tier renders locations with map handoffs and notices", () => {
|
||||
const view = createEmergencyView(dataset(), NOW);
|
||||
expect(view.textContent).toContain("FESTIVAL DATA v3");
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue