Implemented phase 0 for the POC prototype in the Website service.
This commit is contained in:
1 parent
916df7e2f0
commit
717df5208c
31 files changed
+2351
-240
No files matched your search
@@ -0,0 +1,154 @@
|
||||
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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user