Skip to content

Commit 307e35a

Browse files
committed
UI: improve form-rendering (WIP)
1 parent a71ec87 commit 307e35a

12 files changed

Lines changed: 384 additions & 274 deletions

File tree

components/ILIAS/UI/src/Implementation/Component/Input/Field/Renderer.php

Lines changed: 292 additions & 240 deletions
Large diffs are not rendered by default.
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# tpl.context_form.html
2+
3+
## Requirements
4+
5+
* For every input field there is a set of common parts that need to be represented. These
6+
should go into that template.
7+
* byline
8+
* error message
9+
* label (if possible, see below)
10+
* the actual input element from html
11+
* For every input that context should be as regular as possible:
12+
* to attach JS as easy as possible
13+
* to make styling via CSS as easy as possible
14+
* to make rendering code as simple as possible
15+
* to allow for easy maintenance of the template and all other code
16+
17+
## Usage of fieldset for the context (and beyond...)
18+
19+
* According to [0043886: missing legend element in fieldsets of KS forms](https://mantis.ilias.de/view.php?id=43886)
20+
`fieldset`s must have a `legend`. There is no specification that says so, but there
21+
[is a specification](https://www.w3.org/WAI/WCAG22/Understanding/labels-or-instructions)
22+
that says: "Labels or instructions are provided when content requires user input.". It is
23+
arguable, if a `fieldset` is targeted by that requirement (as we define labels for all
24+
actual inputs), but the current usage of the fieldset is flagged by accessibiliy tools,
25+
such as IBM Equal Access Accessibility Checker anyway. Most probably this is caused by
26+
our kind of unorthodox usage, since `fieldsets` are mostly used group radio options or
27+
multiselect options in other contexts.
28+
* If we use `fieldset`s, we can _only_ use `legend`s to label it. A `label`s [`for` attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/label#attributes)
29+
can only point to `labelable` elements, which `fieldset` sadly is not.
30+
* If we use `legend`s, we need to deal with specialized html-structures and hence CSS
31+
logic for any field that uses `fieldset`. Normally, we would put a `label` before the
32+
field that is labelled by it, for `fieldset`s the label (= `legend`) would be inside
33+
the field. We should avoid that.
34+
* We can use [aria roles for grouping](https://www.w3.org/WAI/WCAG22/Techniques/aria/ARIA17.html)
35+
instead and connect labels via [`aria-labelledby`](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-labelledby).
36+
But this does [not provide any other functionality that `for` does](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-labelledby#description),
37+
such as activating the input on click of the label. This has to be added via JavaScript.
38+
39+
## Implementation
40+
41+
* We should probably turn the renderer "inside out". By this we mean: normally we would
42+
switch on component type very early. But since we want to render a common context, we
43+
shall render that first and only switch for the inner parts.
44+
* We should probably use both, `for` and `aria-labelledby` for all inputs. `for` should
45+
override `aria-labelledby` if labelled element is `labelable`, else fallback to
46+
`aria-labelledby` will be used. Javascript then can be bound by looking into wether
47+
that `for` has bound or not.
48+
* "Disabled" need to be pushed down to the actual HTML-input all the time, especially
49+
for elements that could use `fieldsets` (but don't).
50+
* The error and the byline should be connected to the actual input inside the context
51+
container via `aria-describedby`. We can use more than one id for the label
52+
(https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Reference/Attributes/aria-describedby).
53+
if both thingies exist. We should probably start with the error then, just like in
54+
the HTML. Both, hence, need an id.
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<input id="{ID}" type="color"<!-- BEGIN name --> name="{NAME}"<!-- END name --> value="{VALUE}" class="c-field-color-picker"/>
1+
<input type="color" class="c-field-color" id="{ID}"<!-- BEGIN name --> name="{NAME}"<!-- END name --> aria-labelledby="{LABEL_ID}" <!-- BEGIN describedby -->aria-describedby="{DESCRIBED_BY}"<!-- END describedby --><!-- BEGIN disabled --> disabled="disabled"<!-- END disabled --><!-- BEGIN value --> value="{VALUE}"<!-- END value -->/>
Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,13 @@
1-
<fieldset class="c-input" data-il-ui-component="{UI_COMPONENT_NAME}" data-il-ui-input-name="{INPUT_NAME}"<!-- BEGIN disabled --> disabled="disabled"<!-- END disabled --><!-- BEGIN described --> aria-describedby="{ERROR_ID}"<!-- END described --><!-- BEGIN binding --> id="{BINDING_ID}"<!-- END binding --><!-- BEGIN tabindex --> tabindex="0"<!-- END tabindex -->>
1+
<div class="c-input<!-- BEGIN disabled --> c-input__disabled<!-- END disabled -->" data-il-ui-component="{UI_COMPONENT_NAME}" data-il-ui-input-name="{INPUT_NAME}" id="{BINDING_ID}">
2+
<label id="{LABEL_ID}" for="{INPUT_ID}">{LABEL}<!-- BEGIN required --><span class="asterisk" aria-label="{REQUIRED_ARIA}">*</span><!-- END required --></label>
23

3-
<label <!-- BEGIN for --> for="{ID}"<!-- END for -->>{LABEL}<!-- BEGIN required --><span class="asterisk" aria-label="{REQUIRED_ARIA}">*</span><!-- END required --></label>
4-
5-
<div class="c-input__field">
6-
{INPUT}
7-
</div>
4+
{INPUT}
85

96
<!-- BEGIN error -->
107
<div class="c-input__error-msg alert alert-danger" id="{ERROR_ID}"><span class="sr-only">{ERROR_LABEL}: </span>{ERROR}</div>
118
<!-- END error -->
129

1310
<!-- BEGIN byline -->
14-
<div class="c-input__help-byline">{BYLINE}</div>
11+
<div class="c-input__help-byline" id="{BYLINE_ID}">{BYLINE}</div>
1512
<!-- END byline -->
16-
17-
</fieldset>
13+
</div>
Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1 @@
1-
<div class="c-input-group">
2-
<input id="{ID}" <!-- BEGIN dttype -->type="{DTTYPE}"<!-- END dttype --><!-- BEGIN value --> value="{VALUE}"<!-- END value --><!-- BEGIN name --> name="{NAME}"<!-- END name -->
3-
<!-- BEGIN min_date -->min="{MIN_DATE}"<!-- END min_date --> <!-- BEGIN max_date -->max="{MAX_DATE}"<!-- END max_date -->
4-
<!-- BEGIN disabled --> {DISABLED}<!-- END disabled --> class="c-field-datetime" />
5-
</div>
1+
<input type="{DTTYPE}" class="c-field-datetime" id="{ID}"<!-- BEGIN name --> name="{NAME}"<!-- END name --> aria-labelledby="{LABEL_ID}" <!-- BEGIN describedby -->aria-describedby="{DESCRIBED_BY}"<!-- END describedby --><!-- BEGIN disabled --> disabled="disabled"<!-- END disabled --><!-- BEGIN min_date --> min="{MIN_DATE}"<!-- END min_date --> <!-- BEGIN max_date --> max="{MAX_DATE}"<!-- END max_date --><!-- BEGIN value --> value="{VALUE}"<!-- END value -->/>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<div class="c-input<!-- BEGIN disabled --> c-input__disabled<!-- END disabled -->" data-il-ui-component="{UI_COMPONENT_NAME}" data-il-ui-input-name="{INPUT_NAME}" id="{BINDING_ID}">
2+
3+
<div class="c-field-group" <!-- BEGIN name --> name="{NAME}"<!-- END name --><!-- BEGIN describedby --> aria-describedby="{DESCRIBED_BY}"<!-- END describedby -->>
4+
{INPUTS}
5+
</div>
6+
7+
<!-- BEGIN error -->
8+
<div class="c-input__error-msg alert alert-danger" id="{ERROR_ID}"><span class="sr-only">{ERROR_LABEL}: </span>{ERROR}</div>
9+
<!-- END error -->
10+
11+
<!-- BEGIN byline -->
12+
<div class="c-input__help-byline" id="{BYLINE_ID}">{BYLINE}</div>
13+
<!-- END byline -->
14+
</div>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<input id="{ID}" type="number"<!-- BEGIN value --> value="{VALUE}"<!-- END value --><!-- BEGIN name --> name="{NAME}"<!-- END name --><!-- BEGIN disabled --> {DISABLED}<!-- END disabled --> class="c-field-number" />
1+
<input type="number" class="c-field-numeric" id="{ID}"<!-- BEGIN name --> name="{NAME}"<!-- END name --> aria-labelledby="{LABEL_ID}" <!-- BEGIN describedby -->aria-describedby="{DESCRIBED_BY}"<!-- END describedby --><!-- BEGIN disabled --> disabled="disabled"<!-- END disabled --><!-- BEGIN value --> value="{VALUE}"<!-- END value -->/>
Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
<div class="c-field-password">
2-
<input id="{ID}" type="password"<!-- BEGIN name --> name="{NAME}"<!-- END name --><!-- BEGIN value --> value="{VALUE}"<!-- END value --><!-- BEGIN disabled --> {DISABLED}<!-- END disabled --> autocomplete="off" />
3-
<!-- BEGIN revelation -->
4-
<span class="c-field-password__revelation-glyph c-field-password__revelation-glyph--reveal">
5-
{PASSWORD_REVEAL}
6-
</span>
7-
<span class="c-field-password__revelation-glyph c-field-password__revelation-glyph--mask">
8-
{PASSWORD_MASK}
9-
</span>
10-
<!-- END revelation -->
2+
<input type="password" class="c-field-password" id="{ID}"<!-- BEGIN name --> name="{NAME}"<!-- END name --> aria-labelledby="{LABEL_ID}" <!-- BEGIN describedby -->aria-describedby="{DESCRIBED_BY}"<!-- END describedby --><!-- BEGIN disabled --> disabled="disabled"<!-- END disabled --> autocomplete="off"<!-- BEGIN value --> value="{VALUE}"<!-- END value -->/>
3+
<!-- BEGIN revelation -->
4+
<span class="c-field-password__revelation-glyph c-field-password__revelation-glyph--reveal">
5+
{PASSWORD_REVEAL}
6+
</span>
7+
<span class="c-field-password__revelation-glyph c-field-password__revelation-glyph--mask">
8+
{PASSWORD_MASK}
9+
</span>
10+
<!-- END revelation -->
1111
</div>
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<div role="group" class="c-field-section" id="{ID}"<!-- BEGIN name --> name="{NAME}"<!-- END name --> aria-labelledby="{LABEL_ID}" <!-- BEGIN describedby -->aria-describedby="{DESCRIBED_BY}"<!-- END describedby -->>
2+
{INPUTS}
3+
</div>
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
<input id="{ID}" type="text"<!-- BEGIN value --> value="{VALUE}"<!-- END value --><!-- BEGIN name --> name="{NAME}"<!-- END name --><!-- BEGIN disabled --> {DISABLED}<!-- END disabled --><!-- BEGIN max_length --> maxlength="{MAX_LENGTH}" <!-- END max_length --> class="c-field-text" />
1+
<input type="text" class="c-field-text" id="{ID}"<!-- BEGIN name --> name="{NAME}"<!-- END name --> aria-labelledby="{LABEL_ID}" <!-- BEGIN describedby -->aria-describedby="{DESCRIBED_BY}"<!-- END describedby --><!-- BEGIN disabled --> disabled="disabled"<!-- END disabled --><!-- BEGIN max_length --> maxlength="{MAX_LENGTH}"<!-- END max_length --><!-- BEGIN value --> value="{VALUE}"<!-- END value -->/>

0 commit comments

Comments
 (0)