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 } } } }