Files
ccn/Services/Website/Sources/Library/Internal/Components/SiteFooter.swift
T

155 lines
5.0 KiB
Swift

import Elementary
/// The site footer: the about blurb, the link columns, the language toggle, and the legal line.
struct SiteFooter: HTML {
// MARK: Computed
var body: some HTML {
footer(.class("site-footer")) {
div(.class("site-footer__inner")) {
div(.class("site-footer__columns")) {
div(.class("site-footer__about")) {
span(.class("site-footer__wordmark")) {
"CCN"
}
p {
"A marketplace for single-issue comics, manga, trade paperbacks and hardcovers, sold by independent shops in the Netherlands and across the EU."
}
}
for column in Self.columns {
nav(
.class("site-footer__column"),
.custom(
name: "aria-label",
value: column.title
)
) {
h2(.class("site-footer__heading")) {
column.title
}
ul(.class("site-footer__links")) {
for link in column.links {
li {
a(.href(link.path)) {
link.label
}
}
}
}
}
}
language
}
div(.class("site-footer__legal")) {
span {
"CCN B.V. · Amsterdam · KvK [NUMBER] · BTW-id [NUMBER] · Business sellers show their KvK number on their shop page; consumers have a 14-day right of withdrawal on purchases from business sellers."
}
span(.class("site-footer__legal-links")) {
a(.href(.Route.terms)) {
"Terms"
}
a(.href(.Route.privacy)) {
"Privacy"
}
a(.href(.Route.sellerRules)) {
"Seller rules"
}
}
}
}
}
}
}
// MARK: - Helpers
private extension SiteFooter {
// MARK: Type aliases
/// A titled column of links.
typealias Column = (title: String, links: [(label: String, path: String)])
// MARK: Constants
/// The link columns, in reading order.
static let columns: [Column] = [
(
title: "Browse",
links: Format.allCases.map { ($0.label, $0.path) } + [
("By series", .Route.series)
]
),
(
title: "Sell",
links: [
("Open a shop", .Route.openShop),
("Seller dashboard", .Route.sellerDashboard),
("Grading guide", .Route.gradingGuide),
("Trade at events", .Route.events),
]
),
(
title: "Account",
links: [
("Sign in or join", .Route.signIn),
("Want list & alerts", .Route.wants),
("My collection", .Route.collection),
("Messages", .Route.messages),
("Passkeys & settings", .Route.account),
("Lost your passkey?", .Route.recover),
]
),
]
// MARK: Computed
/// The language toggle; display-only while the prototype serves English alone.
var language: some HTML {
div(.class("site-footer__column site-footer__language")) {
h2(.class("site-footer__heading")) {
"Language"
}
div(
.class("language-toggle"),
.custom(
name: "role",
value: "group"
),
.custom(
name: "aria-label",
value: "Language"
)
) {
button(
.class("language-toggle__option"),
.type(.button),
.custom(
name: "aria-pressed",
value: "false"
),
.disabled
) {
"NL"
}
button(
.class("language-toggle__option"),
.type(.button),
.custom(
name: "aria-pressed",
value: "true"
)
) {
"EN"
}
}
span(.class("site-footer__note")) {
"Prices in € · ships to NL"
}
}
}
}