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

113 lines
2.7 KiB
Swift

import Elementary
/// A labelled text field, with its hint or — tied to it for assistive technology — what is wrong with it.
struct TextField: HTML {
// MARK: Properties
let name: String
let title: String
var value: String = ""
var placeholder: String = ""
var hint: String?
var problem: String?
var isWide = false
var maxLength: Int?
// MARK: Computed
var body: some HTML {
div(.class(isWide ? "field field--wide" : "field")) {
label(
.class("field__label"),
.for(name)
) {
title
}
input(
.class("input"),
.id(name),
.type(.text),
.name(name),
.value(value),
.placeholder(placeholder)
)
.attributes(.custom(name: "maxlength", value: "\(maxLength ?? 0)"), when: maxLength != nil)
.attributes(
.custom(name: "aria-invalid", value: "true"),
.custom(name: "aria-describedby", value: "\(name)-error"),
when: problem != nil
)
FieldNote(name: name, hint: hint, problem: problem)
}
}
}
/// A labelled select, showing the chosen option.
struct SelectField: HTML {
// MARK: Properties
let name: String
let title: String
let options: [(value: String, label: String)]
var selected: String?
var problem: String?
// MARK: Computed
var body: some HTML {
div(.class("field")) {
label(
.class("field__label"),
.for(name)
) {
title
}
select(
.class("select select--block"),
.id(name),
.name(name)
) {
ForEach(options) { option in
Elementary.option(.value(option.value)) {
option.label
}
.attributes(.selected, when: option.value == selected)
}
}
FieldNote(name: name, hint: nil, problem: problem)
}
}
}
/// What is wrong with a field, under it; or, when nothing is, its hint.
struct FieldNote: HTML {
// MARK: Properties
let name: String
let hint: String?
let problem: String?
// MARK: Computed
var body: some HTML {
if let problem {
p(
.class("field__error"),
.id("\(name)-error")
) {
problem
}
} else if let hint {
p(.class("field__hint")) {
hint
}
}
}
}