kit

Form group

Built revision v17.10.0

React
Topics

Human support

Bring a missing role, layout, or state, or a rendering against the standard, to the session working on kit. Name the package and the entry.

On Shell, Home, List, Record, Form, Stepped flow, Settings, Find, Reports, Calendar

Form group

Oakmere Village Hall
12
aisha@oakmereprimary.org
01632 960 123
Garden room

Room selection while bookings cannot be changed.

Garden room
Accepts CSV and TSV files.
  • bookings-2025.csvUploaded
  • hirers.xlsxRefusedExcel files cannot be added.
Accepts CSV and TSV files.
At least twelve characters.
No reference given
On the hirer’s confirmation, above the date.
No reference given

Camera not available. Type the reference.

On the hirer’s confirmation, above the date.
Side gate open from half past five.35 of 160 charactersThe caretaker reads this note when the booking starts.
Your booking on 14 February is confirmed. The side gate is open from half past five and the caretaker will meet you at the hall door.Sends as 1 message
Add a note for the caretaker.
40
50

A field that may be left empty, empty and filled, beside a required field.

A field that takes a paste of several lines.

The form owns the submit action.

A password that cannot be changed, with Show disabled.

Password cannot be changed.

A booking reference that cannot be changed, with Scan disabled.

No reference given
Booking reference cannot be changed.

A file that cannot be changed, with its selector disabled.

Files cannot be changed. Accepts CSV and TSV files.

Files that cannot be changed, with their selector and Remove disabled.

  • bookings-2025.csvUploaded
Files cannot be changed. Accepts CSV and TSV files.
Search cannot be changed.

A note that can mention people and jobs.

Ask @Daniel Okafor about the boiler.

  • Dana Reyesdana@oakmerebuilders.co.uk
  • Adam Priceadam@oakmerebuilders.co.uk
  • Daniel Okafordaniel@okaforplumbing.co.ukNo access
  • Davies kitchen refitJOB-2214

    Daniel Okafor will not be told.

    A note that cannot be changed.

    Ask @Dana Reyes for the gate code.

        Notes cannot be changed.

        A description that takes headings, lists, checklists, quotes, code, mentions, dates and files.

        Kitchen refit

        Start on once @Dana Reyes has the keys. Keep the boiler off, ventilate the room and read the survey. The lockbox code is 4471.

        Floor plan: kitchen-plan.pdf

        • Strip the units

        • Move the sink

        1. Isolate the water

        2. Cap the pipes

        • Done

          Order the worktop

        • Not done

          Book the electrician

        Leave the side gate unlocked.

        Gate code: 4471

            Source
            let reader = Specimen_Reader.reader
            let on = (year, month, day) => KitReact.Time.day(reader, {year, month, day})
            
            let characterCount: KitReact.Roles.FormGroup.count = {
              limit: 160,
              read: value => {
                let amount = String.length(value)
                {amount, words: Int.toString(amount) ++ " of 160 characters"}
              },
            }
            
            let messageCount: KitReact.Roles.FormGroup.count = {
              limit: 2,
              read: value => {
                let length = String.length(value)
                let amount = length == 0 ? 1 : (length + 159) / 160
                {amount, words: "Sends as " ++ Int.toString(amount) ++ (amount == 1 ? " message" : " messages")}
              },
            }
            
            module Description = {
              @get external fileName: KitReact.EditorContext.chosenFile => string = "name"
            
              let onFile = (file: KitReact.EditorContext.chosenFile): promise<KitReact.EditorContext.upload> =>
                Promise.make((resolve, reject) =>
                  setTimeout(() =>
                    switch fileName(file) {
                    | name if name->String.endsWith(".zip") => reject(JsError.make("The upload stopped."))
                    | name if name->String.endsWith(".xlsx") => resolve(KitReact.EditorContext.Refused("Excel files cannot be added."))
                    | name => resolve(KitReact.EditorContext.Uploaded({id: name, name}))
                    }, 4000)->ignore
                )
            }
            
            module Note = {
              let suggestions: KitReact.FormGroupEditor.suggestions = {
                canOpen: [
                  {id: "p-dana", name: [Matched("Da"), Plain("na Reyes")], email: "dana@oakmerebuilders.co.uk", avatar: Person({name: "Dana Reyes", initials: "DR"})},
                  {id: "p-adam", name: [Plain("A"), Matched("da"), Plain("m Price")], email: "adam@oakmerebuilders.co.uk", avatar: Person({name: "Adam Price", initials: "AP"})},
                ],
                others: [
                  {id: "p-daniel", name: [Matched("Da"), Plain("niel Okafor")], email: "daniel@okaforplumbing.co.uk", avatar: Person({name: "Daniel Okafor", initials: "DO"}), noAccess: true},
                ],
                subjects: [{id: "j-2214", identifier: "JOB-2214", name: [Matched("Da"), Plain("vies kitchen refit")], icon: KitReact.Icons.iconWrench}],
              }
            
              @react.component
              let make = () => {
                let (notTold, setNotTold) = React.useState(() => ["Daniel Okafor"])
                <KitReact.Roles.FormGroup id="react-form-note"
                  label={React.string("Note")}
                  kind={KitReact.FormGroupEditor.control({
                    name: "note",
                    place: {blocks: [], insertions: [#mention]},
                    value: [Paragraph([Text("Ask ", []), Mention({kind: Person, id: "p-daniel", label: "Daniel Okafor"}), Text(" about the boiler.", [])])],
                    suggestions,
                    onChange: value => setNotTold(_ => KitReact.AuthoredText.mentions(value)->Array.filterMap(({kind, id, label}) => kind == Person && id == "p-daniel" ? Some(label) : None)),
                    notTold,
                    onPaste: address =>
                      Promise.resolve(address == "https://app.example.test/people/p-daniel" ? Some({KitReact.AuthoredText.kind: Person, id: "p-daniel", label: "Daniel Okafor"}) : None),
                  })}
                />
              }
            }
            
            @react.component
            let make = () => {
              <>
              <KitReact.Roles.FormGroup id="react-form-text"
                label={React.string("Text")}
                controlProps={{name: "text"}} controlValue="Oakmere Village Hall" printedValue={React.string("Oakmere Village Hall")}
                kind=Text(Medium)
              />
              <KitReact.Roles.FormGroup id="react-form-number-group"
                label={React.string("Number")}
                controlProps={{id: "react-form-number", name: "number", inputMode: "numeric"}} controlValue="12" printedValue={React.string("12")}
                kind=Text(Narrow)
              />
              <KitReact.Roles.FormGroup id="react-form-email-form-group"
                kind=Email
                label={React.string("Email")}
                controlProps={{id: "react-form-email", name: "email"}} controlValue="aisha@oakmereprimary.org" printedValue={React.string("aisha@oakmereprimary.org")}
              />
              <KitReact.Roles.FormGroup id="react-form-telephone-form-group"
                kind=Telephone
                label={React.string("Telephone")}
                controlProps={{id: "react-form-telephone", name: "telephone"}} controlValue="01632 960 123" printedValue={React.string("01632 960 123")}
              />
              <KitReact.Roles.FormGroup id="react-form-date" printedValue={<time dateTime="2025-02-15"> {React.string("Saturday, 15 February 2025")} </time>}
                label={React.string("Date")}
                kind={KitReact.Roles.DateField.control({
                  name: "date",
                  reader,
                  value: Day(on(2025, 2, 15)),
                  today: on(2025, 2, 10),
                  direction: Either,
                  onCommit: _ => (),
                })}
              />
              <KitReact.Roles.FormGroup id="react-form-time" printedValue={<time dateTime="10:00"> {React.string("10:00")} </time>}
                label={React.string("Time")}
                kind={KitReact.Roles.TimeField.control({
                  name: "time",
                  reader,
                  value: Clock(KitReact.Time.clock(reader, {hour: 10, minute: 0})),
                  onCommit: _ => (),
                })}
              />
              <KitReact.Roles.FormGroup id="react-form-select-form-group"
                kind=Select
                label={React.string("Select")}
                controlProps={{id: "react-form-select", name: "select"}}
                controlValue="garden"
                printedValue={React.string("Garden room")}
                options=[
                  {label: React.string("All rooms"), value: "all", props: {}},
                  {label: React.string("Garden room"), value: "garden", props: {}},
                ]
              />
              <p className="specimen-case-line"> {React.string("Room selection while bookings cannot be changed.")} </p>
              <KitReact.Roles.FormGroup id="react-form-select-disabled-form-group"
                kind=Select
                label={React.string("Select")}
                controlProps={{id: "react-form-select-disabled", name: "select-disabled", disabled: true}}
                controlValue="garden"
                printedValue={React.string("Garden room")}
                options=[
                  {label: React.string("All rooms"), value: "all", props: {}},
                  {label: React.string("Garden room"), value: "garden", props: {}},
                ]
              />
              <KitReact.Roles.FormGroup id="react-form-file-form-group"
                kind=File
                label={React.string("File")}
                help={React.string("Accepts CSV and TSV files.")}
                controlProps={{id: "react-form-file", name: "file", accept: ".csv,.tsv"}}
              />
              <KitReact.Roles.FormGroup id="react-form-files-form-group"
                kind=File
                label={React.string("Files")}
                help={React.string("Accepts CSV and TSV files.")}
                controlProps={{id: "react-form-files", name: "files", multiple: true, accept: ".csv,.tsv"}}
                files=[
                  {name: "bookings-2025.csv", nameId: "react-form-files-bookings", state: Uploaded, stateWords: "Uploaded", props: {}, nameProps: {}, stateProps: {}, reasonProps: {}, removeProps: {}},
                  {name: "hirers.xlsx", nameId: "react-form-files-hirers", state: Refused([KitReact.Words.Text("Excel files cannot be added.")]), stateWords: "Refused", props: {}, nameProps: {}, stateProps: {}, reasonProps: {}, removeProps: {}},
                ]
              />
              <KitReact.Roles.FormGroup id="react-form-password-form-group"
                kind=Password
                label={React.string("Password")}
                autocomplete=Actor("current-password")
                controlProps={{id: "react-form-password", name: "password"}}
                controlValue="oakmere-hall-2025"
              />
              <KitReact.Roles.FormGroup id="react-form-new-password-form-group"
                kind=Password
                label={React.string("New password")}
                help={React.string("At least twelve characters.")}
                autocomplete=Actor("new-password")
                controlProps={{id: "react-form-new-password", name: "new-password"}}
                controlValue="garden-room-keys"
              />
              <KitReact.Roles.FormGroup id="react-form-reference-form-group"
                kind=Scan(KitReact.FormGroupScanner.scan, Medium)
                stream=Camera
                label={React.string("Booking reference")}
                help={React.string("On the hirer’s confirmation, above the date.")}
                controlProps={{id: "react-form-reference", name: "reference"}}
                controlValue=""
                printedValue={React.string("No reference given")}
              />
              <KitReact.Roles.FormGroup id="react-form-reference-refused-form-group"
                kind=Scan(KitReact.FormGroupScanner.scan, Medium)
                stream=Unavailable
                label={React.string("Booking reference")}
                help={React.string("On the hirer’s confirmation, above the date.")}
                controlProps={{
                  id: "react-form-reference-refused", name: "reference-refused",
                }}
                controlValue=""
                printedValue={React.string("No reference given")}
              />
              <KitReact.Roles.FormGroup id="react-form-limited-form-group"
                kind=Textarea
                count=characterCount
                label={React.string("Note for the caretaker")}
                countLine={React.string("35 of 160 characters")}
                countLineProps={{id: "react-form-limited-count"}}
                help={React.string("The caretaker reads this note when the booking starts.")}
                controlProps={{
                  id: "react-form-limited", name: "limited", maxLength: 160,
                  ariaDescribedby: "react-form-limited-count",
                }}
                controlValue="Side gate open from half past five."
                printedValue={React.string("Side gate open from half past five.")}
              />
              <KitReact.Roles.FormGroup id="react-form-parts-form-group"
                kind=Textarea
                count=messageCount
                label={React.string("Text message to the hirer")}
                countLine={React.string("Sends as 1 message")}
                countLineProps={{id: "react-form-parts-count"}}
                controlProps={{id: "react-form-parts", name: "parts", ariaDescribedby: "react-form-parts-count"}}
                controlValue="Your booking on 14 February is confirmed. The side gate is open from half past five and the caretaker will meet you at the hall door."
                printedValue={React.string("Your booking on 14 February is confirmed. The side gate is open from half past five and the caretaker will meet you at the hall door.")}
              />
              <KitReact.Roles.FormGroup id="react-form-textarea-form-group"
                kind=Textarea
                label={React.string("Text area")}
                controlProps={{id: "react-form-textarea", name: "textarea"}} controlValue="Add a note for the caretaker." printedValue={React.string("Add a note for the caretaker.")}
              />
              <fieldset>
                <KitReact.Roles.FormGroup id="react-form-range-first" printedValue={<time dateTime="2025-02-10"> {React.string("Monday, 10 February 2025")} </time>}
                  label={React.string("First")}
                  kind={KitReact.Roles.DateField.control({
                    name: "range-first",
                    reader,
                    value: Day(on(2025, 2, 10)),
                    today: on(2025, 2, 10),
                    direction: Either,
                    onCommit: _ => (),
                  })}
                />
                <KitReact.Roles.FormGroup id="react-form-range-last" printedValue={<time dateTime="2025-02-16"> {React.string("Sunday, 16 February 2025")} </time>}
                  label={React.string("Last")}
                  kind={KitReact.Roles.DateField.control({
                    name: "range-last",
                    reader,
                    value: Day(on(2025, 2, 16)),
                    today: on(2025, 2, 10),
                    direction: Either,
                    onCommit: _ => (),
                  })}
                />
              </fieldset>
              <fieldset>
                <div>
                  <KitReact.Roles.FormGroup id="react-form-chairs-out-form-group"
                    label={React.string("Chairs out")}
                    controlProps={{id: "react-form-chairs-out", name: "chairs-out", inputMode: "numeric"}} controlValue="40" printedValue={React.string("40")}
                    kind=Text(Narrow)
                  />
                  <KitReact.Roles.FormGroup id="react-form-deposit-held-form-group"
                    label={React.string("Deposit held")}
                    controlProps={{id: "react-form-deposit-held", name: "deposit-held", inputMode: "decimal"}} controlValue="50" printedValue={React.string("50")}
                    kind=Text(Narrow)
                  />
                </div>
              </fieldset>
              <p className="specimen-case-line" id="role-form-group-marks">{React.string("A field that may be left empty, empty and filled, beside a required field.")}</p>
              <KitReact.Roles.FormGroup id="react-form-reference-empty"
                optional=true
                label={React.string("Purchase order")}
                controlProps={{name: "purchase_order"}}
                kind=Text(Medium)
              />
              <KitReact.Roles.FormGroup id="react-form-reference-filled"
                optional=true
                label={React.string("Purchase order")}
                controlProps={{name: "purchase_order_filled"}} controlValue="PO-4471"
                kind=Text(Medium)
              />
              <KitReact.Roles.FormGroup id="react-form-hirer-required"
                required=true
                label={React.string("Hirer name")}
                autocomplete=Other("hirer-name")
                controlProps={{name: "hirer_name"}}
                kind=Text(Medium)
              />
              <p className="specimen-case-line" id="role-form-group-search">{React.string("A search holding text, with Clear.")}</p>
              <KitReact.Roles.FormGroup id="react-form-search"
                kind=Search
                label={React.string("Search bookings")}
                controlProps={{name: "q", placeholder: "Find bookings by hirer name"}} controlValue="Oakmere"
              />
              <p className="specimen-case-line" id="role-form-group-scan-search">{React.string("A search for booking references, with Clear and Scan.")}</p>
              <KitReact.Roles.FormGroup id="react-form-scan-search"
                kind=Search
                scannable=KitReact.FormGroupScanner.scan
                label={React.string("Search booking references")}
                controlProps={{name: "q", placeholder: "Find bookings by reference"}}
              />
              <p className="specimen-case-line" id="role-form-group-paste">{React.string("A field that takes a paste of several lines.")}</p>
              <form>
                <KitReact.Roles.FormGroup id="react-form-paste"
                  label={React.string("Hirer")}
                  paste={{name: "hirers", kind: "invoices", reader: Specimen_Reader.reader}}
                  autocomplete=Other("hirer-name")
                  controlProps={{name: "hirer"}}
                  kind=Text(Medium)
                />
              </form>
              <p>{React.string("The form owns the submit action.")}</p>
              <p className="specimen-case-line" id="role-form-group-disabled-password"> {React.string("A password that cannot be changed, with Show disabled.")} </p>
              <KitReact.Roles.FormGroup id="react-form-password-disabled-form-group"
                kind=Password  label={React.string("Password")}
                autocomplete=Actor("current-password")
                controlProps={{id: "react-form-password-disabled", name: "password", disabled: true}}
                controlValue="oakmere-hall-2025" help={React.string("Password cannot be changed.")}
              />
              <p className="specimen-case-line" id="role-form-group-disabled-scan"> {React.string("A booking reference that cannot be changed, with Scan disabled.")} </p>
              <KitReact.Roles.FormGroup id="react-form-reference-disabled-form-group"
                kind=Scan(KitReact.FormGroupScanner.scan, Medium) stream=Camera
                label={React.string("Booking reference")}
                controlProps={{id: "react-form-reference-disabled", name: "reference", disabled: true}}
                controlValue="" printedValue={React.string("No reference given")}
                help={React.string("Booking reference cannot be changed.")}
              />
              <p className="specimen-case-line" id="role-form-group-disabled-file"> {React.string("A file that cannot be changed, with its selector disabled.")} </p>
              <KitReact.Roles.FormGroup id="react-form-file-disabled-form-group"
                kind=File label={React.string("File")}
                controlProps={{id: "react-form-file-disabled", name: "file", accept: ".csv,.tsv", disabled: true}}
                help={React.string("Files cannot be changed. Accepts CSV and TSV files.")}
              />
              <p className="specimen-case-line" id="role-form-group-disabled-files"> {React.string("Files that cannot be changed, with their selector and Remove disabled.")} </p>
              <KitReact.Roles.FormGroup id="react-form-files-disabled-form-group"
                kind=File label={React.string("Files")}
                controlProps={{id: "react-form-files-disabled", name: "files", multiple: true, accept: ".csv,.tsv", disabled: true}}
                files=[{name: "bookings-2025.csv", nameId: "react-form-files-disabled-bookings", state: Uploaded, stateWords: "Uploaded"}]
                help={React.string("Files cannot be changed. Accepts CSV and TSV files.")}
              />
              <p className="specimen-case-line" id="role-form-group-disabled-search"> {React.string("A search that cannot be changed, with Clear disabled.")} </p>
              <KitReact.Roles.FormGroup id="react-form-search-disabled"
                kind=Search  label={React.string("Search bookings")}
                controlProps={{name: "q", placeholder: "Find bookings by hirer name", disabled: true}}
                controlValue="Oakmere" help={React.string("Search cannot be changed.")}
              />
              <p className="specimen-case-line" id="role-form-group-mentions"> {React.string("A note that can mention people and jobs.")} </p>
              <Note />
              <p className="specimen-case-line" id="role-form-group-disabled-note"> {React.string("A note that cannot be changed.")} </p>
              <KitReact.Roles.FormGroup id="react-form-note-disabled"
                label={React.string("Note")}
                help={React.string("Notes cannot be changed.")}
                kind={KitReact.FormGroupEditor.control({
                  name: "note",
                  place: {blocks: [], insertions: [#mention]},
                  value: [Paragraph([Text("Ask ", []), Mention({kind: Person, id: "p-dana", label: "Dana Reyes"}), Text(" for the gate code.", [])])],
                  disabled: true,
                })}
              />
              <p className="specimen-case-line" id="role-form-group-every-block"> {React.string("A description that takes headings, lists, checklists, quotes, code, mentions, dates and files.")} </p>
              <KitReact.Roles.FormGroup id="react-form-description"
                label={React.string("Description")}
                kind={KitReact.FormGroupEditor.control({
                  name: "description",
                  place: {blocks: [#heading, #bulletList, #orderedList, #taskList, #blockquote, #codeBlock], insertions: [#mention, #date, #file]},
                  value: [
                    Heading([Text("Kitchen refit", [])]),
                    Paragraph([
                      Text("Start on ", []),
                      Date({year: 2025, month: 2, day: 17}),
                      Text(" once ", []),
                      Mention({kind: Person, id: "p-dana", label: "Dana Reyes"}),
                      Text(" has the keys. Keep the ", []),
                      Text("boiler", [Bold]),
                      Text(" off, ", []),
                      Text("ventilate", [Italic]),
                      Text(" the room and read ", []),
                      Text("the survey", [Link("https://oakmerebuilders.co.uk/survey")]),
                      Text(". The lockbox code is ", []),
                      Text("4471", [Code]),
                      Text(".", []),
                    ]),
                    Paragraph([Text("Floor plan: ", []), File({id: "floor-plan", name: "kitchen-plan.pdf"})]),
                    BulletList([[[Text("Strip the units", [])]], [[Text("Move the sink", [])]]]),
                    OrderedList([[[Text("Isolate the water", [])]], [[Text("Cap the pipes", [])]]]),
                    TaskList([{checked: true, content: [[Text("Order the worktop", [])]]}, {checked: false, content: [[Text("Book the electrician", [])]]}]),
                    Blockquote([[Text("Leave the side gate unlocked.", [])]]),
                    CodeBlock("Gate code: 4471"),
                  ],
                  today: on(2025, 2, 10),
                  onFile: Description.onFile,
                  fileWords: {uploading: "Uploading", uploaded: "Uploaded", refused: "Refused"},
                })}
              />
              </>
            }
            

            Form group, error

            The email control is described by its help, then its error, and is invalid.

            accounts@Use the address that receives the hirer’s invoices.Enter a complete billing email, such as aisha@oakmereprimary.org.
            Oakmere Village Hall
            Source
            @react.component
            let make = () =>
              <>
                <p className="specimen-case-line">{React.string("The email control is described by its help, then its error, and is invalid.")}</p>
              <fieldset>
                <KitReact.Roles.FormGroup id="billing-email-error-form-group"
                  kind=Email
                  label={React.string("Billing email")}
                  labelProps={{htmlFor: "billing-email-error"}}
                  autocomplete=Other("hirer-billing-email")
                  controlProps={{
                    id: "billing-email-error", name: "email",
                  }}
                  controlValue="accounts@"
                  printedValue={React.string("accounts@")}
                  help={React.string("Use the address that receives the hirer’s invoices.")}
                  error={React.string("Enter a complete billing email, such as aisha@oakmereprimary.org.")}
                />
                <KitReact.Roles.FormGroup id="form-error-neighbour-form-group"
                  label={React.string("Text")}
                  labelProps={{htmlFor: "form-error-neighbour"}}
                  controlProps={{id: "form-error-neighbour", name: "text"}}
                  controlValue="Oakmere Village Hall"
                  printedValue={React.string("Oakmere Village Hall")}
                  kind=Text(Medium)
                />
              </fieldset>
              </>
            

            Form group, shown

            At least twelve characters.

            A shown password that cannot be changed, with Hide disabled.

            Password cannot be changed.
            Source
            @react.component
            let make = () =>
              <>
                <KitReact.Roles.FormGroup id="react-form-password-shown-form-group"
                  kind=Password
                  label={React.string("Password")}
                  labelProps={{htmlFor: "react-form-password-shown"}}
                  autocomplete=Actor("current-password")
                  controlProps={{
                    id: "react-form-password-shown",
                    name: "password",
                    type_: "text",
                  }}
                  controlValue="oakmere-hall-2025"
                />
                <KitReact.Roles.FormGroup id="react-form-new-password-shown-form-group"
                  kind=Password
                  label={React.string("New password")}
                  labelProps={{htmlFor: "react-form-new-password-shown"}}
                  help={React.string("At least twelve characters.")}
                  autocomplete=Actor("new-password")
                  controlProps={{
                    id: "react-form-new-password-shown",
                    name: "new-password",
                    type_: "text",
                  }}
                  controlValue="garden-room-keys"
                />
                <p className="specimen-case-line" id="role-form-group-disabled-hide"> {React.string("A shown password that cannot be changed, with Hide disabled.")} </p>
                <KitReact.Roles.FormGroup id="react-form-password-shown-disabled-form-group"
                  kind=Password  label={React.string("Password")}
                  autocomplete=Actor("current-password")
                  controlProps={{id: "react-form-password-shown-disabled", name: "password", type_: "text", disabled: true}}
                  controlValue="oakmere-hall-2025" help={React.string("Password cannot be changed.")}
                />
              </>
            

            Form group, chosen

            • bookings-2025.csvChosen
            • hirers.csvChosen
            Accepts CSV and TSV files.
            Source
            @react.component
            let make = () =>
              <KitReact.Roles.FormGroup id="react-form-files-chosen-form-group"
                kind=File
                label={React.string("Hirer records")}
                labelProps={{htmlFor: "react-form-files-chosen"}}
                help={React.string("Accepts CSV and TSV files.")}
                controlProps={{
                  id: "react-form-files-chosen",
                  name: "files",
                  multiple: true,
                  accept: ".csv,.tsv",
                }}
                files=[
                  {
                    name: "bookings-2025.csv",
                    nameId: "react-form-files-chosen-bookings",
                    state: Chosen,
                    stateWords: "Chosen",
                    props: {},
                    nameProps: {},
                    stateProps: {},
                    reasonProps: {},
                    removeProps: {},
                  },
                  {
                    name: "hirers.csv",
                    nameId: "react-form-files-chosen-hirers",
                    state: Chosen,
                    stateWords: "Chosen",
                    props: {},
                    nameProps: {},
                    stateProps: {},
                    reasonProps: {},
                    removeProps: {},
                  },
                ]
              />
            

            Form group, uploading

            • oakmere-primary-school-bookings-and-collections-2025.csvUploading
            • hirers.csvUploading
            Accepts CSV and TSV files.
            Source
            @react.component
            let make = () =>
              <KitReact.Roles.FormGroup id="react-form-files-uploading-form-group"
                kind=File
                label={React.string("Hirer records")}
                labelProps={{htmlFor: "react-form-files-uploading"}}
                help={React.string("Accepts CSV and TSV files.")}
                controlProps={{
                  id: "react-form-files-uploading",
                  name: "files",
                  multiple: true,
                  accept: ".csv,.tsv",
                }}
                files=[
                  {
                    name: "oakmere-primary-school-bookings-and-collections-2025.csv",
                    nameId: "react-form-files-uploading-bookings",
                    state: Uploading,
                    stateWords: "Uploading",
                    props: {},
                    nameProps: {},
                    stateProps: {},
                    reasonProps: {},
                    removeProps: {},
                  },
                  {
                    name: "hirers.csv",
                    nameId: "react-form-files-uploading-hirers",
                    state: Uploading,
                    stateWords: "Uploading",
                    props: {},
                    nameProps: {},
                    stateProps: {},
                    reasonProps: {},
                    removeProps: {},
                  },
                ]
              />
            

            Form group, uploaded

            • oakmere-primary-school-bookings-and-collections-2025.csvUploaded
            • hirers.csvUploaded
            Accepts CSV and TSV files.

            An uploaded file whose name opens it.

            Accepts MP3 files.
            Source
            @react.component
            let make = () =>
              <>
              <KitReact.Roles.FormGroup id="react-form-files-uploaded-form-group"
                kind=File
                label={React.string("Hirer records")}
                labelProps={{htmlFor: "react-form-files-uploaded"}}
                help={React.string("Accepts CSV and TSV files.")}
                controlProps={{
                  id: "react-form-files-uploaded",
                  name: "files",
                  multiple: true,
                  accept: ".csv,.tsv",
                }}
                files=[
                  {
                    name: "oakmere-primary-school-bookings-and-collections-2025.csv",
                    nameId: "react-form-files-uploaded-bookings",
                    state: Uploaded,
                    stateWords: "Uploaded",
                    props: {},
                    nameProps: {},
                    stateProps: {},
                    reasonProps: {},
                    removeProps: {},
                  },
                  {
                    name: "hirers.csv",
                    nameId: "react-form-files-uploaded-hirers",
                    state: Uploaded,
                    stateWords: "Uploaded",
                    props: {},
                    nameProps: {},
                    stateProps: {},
                    reasonProps: {},
                    removeProps: {},
                  },
                ]
              />
              <p className="specimen-case-line" id="role-form-group-linked-file">{React.string("An uploaded file whose name opens it.")}</p>
              <KitReact.Roles.FormGroup id="react-form-file-linked-form-group"
                kind=File
                label={React.string("Audio file")}
                controlProps={{id: "react-form-file-linked", name: "audio", accept: ".mp3"}}
                files=[{name: "media-audio.mp3", nameId: "react-form-file-linked-name", href: "../../media/media-audio.mp3", state: Uploaded, stateWords: "Uploaded"}]
                help={React.string("Accepts MP3 files.")}
              />
              </>
            

            Form group, refused

            • hirers.xlsxRefusedExcel files cannot be added.
            • bookings-2025.csvUploaded
            Accepts CSV and TSV files.
            Accepts PDF files.
            • main-hall.heicRefusedHEIC images cannot be added.
            Accepts JPEG and PNG images.
            Source
            @react.component
            let make = () =>
              <>
              <KitReact.Roles.FormGroup id="react-form-files-refused-form-group"
                kind=File
                label={React.string("Hirer records")}
                labelProps={{htmlFor: "react-form-files-refused"}}
                help={React.string("Accepts CSV and TSV files.")}
                controlProps={{
                  id: "react-form-files-refused",
                  name: "files",
                  multiple: true,
                  accept: ".csv,.tsv",
                }}
                files=[
                  {
                    name: "hirers.xlsx",
                    nameId: "react-form-files-refused-hirers",
                    state: Refused([KitReact.Words.Text("Excel files cannot be added.")]), stateWords: "Refused",
                    props: {},
                    nameProps: {},
                    stateProps: {},
                    reasonProps: {},
                    removeProps: {},
                  },
                  {
                    name: "bookings-2025.csv",
                    nameId: "react-form-files-refused-bookings",
                    state: Uploaded,
                    stateWords: "Uploaded",
                    props: {},
                    nameProps: {},
                    stateProps: {},
                    reasonProps: {},
                    removeProps: {},
                  },
                ]
              />
              <fieldset>
                <KitReact.Roles.FormGroup id="react-form-floor-plan-form-group"
                  kind=File
                  label={React.string("Floor plan")}
                  labelProps={{htmlFor: "react-form-floor-plan"}}
                  help={React.string("Accepts PDF files.")}
                  controlProps={{id: "react-form-floor-plan", name: "floor-plan", accept: ".pdf"}}
                />
                <KitReact.Roles.FormGroup id="react-form-hall-photo-form-group"
                  kind=File
                  label={React.string("Hall photo")}
                  labelProps={{htmlFor: "react-form-hall-photo"}}
                  help={React.string("Accepts JPEG and PNG images.")}
                  controlProps={{id: "react-form-hall-photo", name: "hall-photo", accept: ".jpg,.jpeg,.png"}}
                  files=[
                    {
                      name: "main-hall.heic",
                      nameId: "react-form-hall-photo-main-hall",
                      state: Refused([KitReact.Words.Text("HEIC images cannot be added.")]), stateWords: "Refused",
                      props: {},
                      nameProps: {},
                      stateProps: {},
                      reasonProps: {},
                      removeProps: {},
                    },
                  ]
                />
              </fieldset>
              </>