@markout-lang/bootstrap-kit 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/parts/breadcrumb.htm +7 -3
- package/parts/dropdown.htm +27 -4
- package/parts/list-group.htm +48 -24
- package/parts/nav.htm +14 -2
- package/parts/navbar.htm +16 -1
- package/parts/pagination.htm +48 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@markout-lang/bootstrap-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Bootstrap 5.3 as Markout components: one part per component, with the id wiring, the ARIA attributes and the repetition written once",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
package/parts/breadcrumb.htm
CHANGED
|
@@ -7,8 +7,11 @@
|
|
|
7
7
|
describes the entries, the component owns the markup.
|
|
8
8
|
|
|
9
9
|
An entry is `{ name, link }`. The one without a `link` is the current
|
|
10
|
-
page, and gets `active` plus `aria-current
|
|
11
|
-
|
|
10
|
+
page, and gets `active` plus `aria-current`. It is also the one entry
|
|
11
|
+
with no `<a>` around it: an anchor with no `href` renders as plain text,
|
|
12
|
+
which is why it used to be left in place, but it is still an anchor to
|
|
13
|
+
everything that reads the document rather than looks at it. Bootstrap's
|
|
14
|
+
own markup for the current crumb is the text on its own, and so is this.
|
|
12
15
|
-->
|
|
13
16
|
<:define tag="bs-breadcrumb:nav"
|
|
14
17
|
aria-label="breadcrumb"
|
|
@@ -34,7 +37,8 @@
|
|
|
34
37
|
:for-as="item"
|
|
35
38
|
:class-active=${!item.link}
|
|
36
39
|
aria-current=${item.link ? null : 'page'}>
|
|
37
|
-
<a href=${item.link
|
|
40
|
+
<a :if=${item.link} href=${item.link}>${item.name}</a>
|
|
41
|
+
<:group :else>${item.name}</:group>
|
|
38
42
|
</li>
|
|
39
43
|
</ol>
|
|
40
44
|
</:define>
|
package/parts/dropdown.htm
CHANGED
|
@@ -3,8 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
<!---
|
|
5
5
|
A dropdown. Entries are `{ name, link, active, disabled, header, divider,
|
|
6
|
-
select }`; the
|
|
7
|
-
|
|
6
|
+
select }`; the shapes Bootstrap draws differently — a divider, a header,
|
|
7
|
+
an item — are optional regions over the same list.
|
|
8
|
+
|
|
9
|
+
An item comes out as an `<a>` when it has a `link` and a `<button>` when
|
|
10
|
+
it does not, which is the rule the whole kit follows: what navigates is a
|
|
11
|
+
link, what acts is a button, and what does neither is not an interactive
|
|
12
|
+
element at all. The alternative -- one `<a>` with the `href` dropped when
|
|
13
|
+
there is nowhere to go -- looks identical and is reachable only by mouse:
|
|
14
|
+
an anchor without an `href` takes no focus and reaches the accessibility
|
|
15
|
+
tree with no role, so `select` could be triggered by a click and by
|
|
16
|
+
nothing else. Bootstrap styles `.dropdown-item` on both elements.
|
|
8
17
|
|
|
9
18
|
The menu is tied to its toggle by `aria-labelledby`, and the id for that
|
|
10
19
|
comes from `$id`, which is unique per instance. That is the general
|
|
@@ -72,12 +81,26 @@
|
|
|
72
81
|
:else-if=${item.header}>${item.header}</h6>
|
|
73
82
|
|
|
74
83
|
<a class="dropdown-item"
|
|
75
|
-
:else
|
|
84
|
+
:else-if=${item.link}
|
|
76
85
|
:class-active=${item.active}
|
|
77
86
|
:class-disabled=${item.disabled}
|
|
78
|
-
href=${item.link
|
|
87
|
+
href=${item.link}
|
|
79
88
|
aria-current=${item.active ? 'true' : null}
|
|
89
|
+
aria-disabled=${item.disabled ? 'true' : null}
|
|
80
90
|
:on-click=${() => item.select?.(item)}>${item.name}</a>
|
|
91
|
+
|
|
92
|
+
<!---
|
|
93
|
+
`disabled` rather than `.disabled`: on a button the attribute is
|
|
94
|
+
the real thing, and it takes the entry out of the tab order as
|
|
95
|
+
well as greying it. Bootstrap's CSS matches both.
|
|
96
|
+
-->
|
|
97
|
+
<button class="dropdown-item"
|
|
98
|
+
type="button"
|
|
99
|
+
:else
|
|
100
|
+
:class-active=${item.active}
|
|
101
|
+
:attr-disabled=${item.disabled}
|
|
102
|
+
aria-current=${item.active ? 'true' : null}
|
|
103
|
+
:on-click=${() => item.select?.(item)}>${item.name}</button>
|
|
81
104
|
</li>
|
|
82
105
|
</ul>
|
|
83
106
|
</:define>
|
package/parts/list-group.htm
CHANGED
|
@@ -6,10 +6,17 @@
|
|
|
6
6
|
A list group, from `{ name, link, active, disabled, variant, badge, text }`
|
|
7
7
|
entries.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
An entry with a `link` is an `<a>`; one without is a `<div>`. Both were
|
|
10
|
+
an `<a>` once, the second with its `href` dropped, which is inert and
|
|
11
|
+
looks right and is still a link as far as anything reading the document
|
|
12
|
+
is concerned. `.list-group-item-action` — Bootstrap's hover and focus
|
|
13
|
+
treatment — goes on the first alone, as it always did, and now it goes on
|
|
14
|
+
the element that can take focus.
|
|
15
|
+
|
|
16
|
+
The body is written twice because the element is what differs and markout
|
|
17
|
+
has no way to choose a tag name from an expression. Two branches of six
|
|
18
|
+
lines is the smaller cost: the alternative is a wrapper inside every
|
|
19
|
+
entry, on every page, to save repeating them here.
|
|
13
20
|
-->
|
|
14
21
|
<:define tag="bs-list-group:div"
|
|
15
22
|
|
|
@@ -31,26 +38,43 @@
|
|
|
31
38
|
|
|
32
39
|
class=${_class}
|
|
33
40
|
>
|
|
34
|
-
|
|
35
|
-
:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
41
|
+
<:group :for-each=${items} :for-as="item">
|
|
42
|
+
<a :if=${item.link}
|
|
43
|
+
class="list-group-item list-group-item-action d-flex justify-content-between align-items-center"
|
|
44
|
+
:class-active=${item.active}
|
|
45
|
+
:class-disabled=${item.disabled}
|
|
46
|
+
href=${item.link}
|
|
47
|
+
aria-current=${item.active ? 'true' : null}
|
|
48
|
+
aria-disabled=${item.disabled ? 'true' : null}>
|
|
49
|
+
|
|
50
|
+
<span>
|
|
51
|
+
<span :class-fw-bold=${!!item.text}>${item.name}</span>
|
|
52
|
+
<span class="d-block small opacity-75"
|
|
53
|
+
:if=${item.text}>${item.text}</span>
|
|
54
|
+
</span>
|
|
55
|
+
|
|
56
|
+
<bs-badge ::variant=${item.badge?.variant ?? 'secondary'}
|
|
57
|
+
::pill
|
|
58
|
+
:if=${item.badge}>${item.badge?.name ?? item.badge}</bs-badge>
|
|
59
|
+
</a>
|
|
60
|
+
|
|
61
|
+
<div :else
|
|
62
|
+
class="list-group-item d-flex justify-content-between align-items-center"
|
|
63
|
+
:class-active=${item.active}
|
|
64
|
+
:class-disabled=${item.disabled}
|
|
65
|
+
aria-current=${item.active ? 'true' : null}>
|
|
66
|
+
|
|
67
|
+
<span>
|
|
68
|
+
<span :class-fw-bold=${!!item.text}>${item.name}</span>
|
|
69
|
+
<span class="d-block small opacity-75"
|
|
70
|
+
:if=${item.text}>${item.text}</span>
|
|
71
|
+
</span>
|
|
72
|
+
|
|
73
|
+
<bs-badge ::variant=${item.badge?.variant ?? 'secondary'}
|
|
74
|
+
::pill
|
|
75
|
+
:if=${item.badge}>${item.badge?.name ?? item.badge}</bs-badge>
|
|
76
|
+
</div>
|
|
77
|
+
</:group>
|
|
54
78
|
</:define>
|
|
55
79
|
|
|
56
80
|
</lib>
|
package/parts/nav.htm
CHANGED
|
@@ -8,6 +8,12 @@
|
|
|
8
8
|
Entries are `{ name, link, active, disabled, target }`. For a tabbed
|
|
9
9
|
interface set `:toggle="tab"` (or `"pill"`) and give each entry the
|
|
10
10
|
`target` of its pane; `bs-tab-pane` below is the other half.
|
|
11
|
+
|
|
12
|
+
Three elements come out of that, one per kind of entry: a `<button>` when
|
|
13
|
+
the nav switches panes, an `<a>` when the entry has a `link`, and a
|
|
14
|
+
`<span>` when it has neither and is a label sitting among the links. The
|
|
15
|
+
third used to be an `<a>` with no `href`, which reads as a link to
|
|
16
|
+
anything that is not looking at the screen.
|
|
11
17
|
-->
|
|
12
18
|
<:define tag="bs-nav:ul"
|
|
13
19
|
|
|
@@ -53,12 +59,18 @@
|
|
|
53
59
|
aria-selected=${item.active ? 'true' : 'false'}>${item.name}</button>
|
|
54
60
|
|
|
55
61
|
<a class="nav-link"
|
|
56
|
-
:else
|
|
62
|
+
:else-if=${item.link}
|
|
57
63
|
:class-active=${item.active}
|
|
58
64
|
:class-disabled=${item.disabled}
|
|
59
|
-
href=${item.link
|
|
65
|
+
href=${item.link}
|
|
60
66
|
aria-current=${item.active ? 'page' : null}
|
|
61
67
|
aria-disabled=${item.disabled ? 'true' : null}>${item.name}</a>
|
|
68
|
+
|
|
69
|
+
<span class="nav-link"
|
|
70
|
+
:else
|
|
71
|
+
:class-active=${item.active}
|
|
72
|
+
:class-disabled=${item.disabled}
|
|
73
|
+
aria-current=${item.active ? 'page' : null}>${item.name}</span>
|
|
62
74
|
</li>
|
|
63
75
|
</:define>
|
|
64
76
|
|
package/parts/navbar.htm
CHANGED
|
@@ -70,14 +70,29 @@
|
|
|
70
70
|
<div class="collapse navbar-collapse" id=${_id}>
|
|
71
71
|
<ul class=${_navClass}>
|
|
72
72
|
<li class="nav-item" :for-each=${items} :for-as="item">
|
|
73
|
+
<!---
|
|
74
|
+
An entry with no `link` is a label among the links rather than
|
|
75
|
+
a link that goes nowhere, and comes out as a `<span>`. See
|
|
76
|
+
`nav.htm`, which makes the same distinction for the same
|
|
77
|
+
reason.
|
|
78
|
+
-->
|
|
73
79
|
<a class="nav-link"
|
|
80
|
+
:if=${item.link}
|
|
74
81
|
:class-active=${item.active}
|
|
75
82
|
:class-disabled=${item.disabled}
|
|
76
83
|
:class-btn=${item.button}
|
|
77
84
|
:class-btn-primary=${item.button}
|
|
78
|
-
href=${item.link
|
|
85
|
+
href=${item.link}
|
|
79
86
|
aria-current=${item.active ? 'page' : null}
|
|
80
87
|
aria-disabled=${item.disabled ? 'true' : null}>${item.name}</a>
|
|
88
|
+
|
|
89
|
+
<span class="nav-link"
|
|
90
|
+
:else
|
|
91
|
+
:class-active=${item.active}
|
|
92
|
+
:class-disabled=${item.disabled}
|
|
93
|
+
:class-btn=${item.button}
|
|
94
|
+
:class-btn-primary=${item.button}
|
|
95
|
+
aria-current=${item.active ? 'page' : null}>${item.name}</span>
|
|
81
96
|
</li>
|
|
82
97
|
</ul>
|
|
83
98
|
|
package/parts/pagination.htm
CHANGED
|
@@ -15,6 +15,14 @@
|
|
|
15
15
|
called with the page number for one that stays on the page. Both are
|
|
16
16
|
ordinary function parameters — a callback the component calls, not a DOM
|
|
17
17
|
event, so it is a value and not an `:on-` handler.
|
|
18
|
+
|
|
19
|
+
They also decide the element. `::link` yields an href, so those entries
|
|
20
|
+
are `<a>`; with `::select` alone — the default, and the mode a page that
|
|
21
|
+
never reloads uses — there is nowhere to go, and each entry is a
|
|
22
|
+
`<button>`. Written as an `<a>` with no `href` it looks right and pages
|
|
23
|
+
for a mouse alone: an anchor without an `href` takes no focus and carries
|
|
24
|
+
no role, so the whole control is unreachable from the keyboard. Bootstrap
|
|
25
|
+
styles `.page-link` on both.
|
|
18
26
|
-->
|
|
19
27
|
<:define tag="bs-pagination:nav"
|
|
20
28
|
|
|
@@ -41,11 +49,27 @@
|
|
|
41
49
|
aria-label=${label}
|
|
42
50
|
>
|
|
43
51
|
<ul class=${_class}>
|
|
44
|
-
|
|
52
|
+
<!---
|
|
53
|
+
`_href` is declared on the `<li>` so the two branches inside read one
|
|
54
|
+
value rather than calling `link()` twice each. The `<li>` is a scope
|
|
55
|
+
like any element, which is what makes that the obvious place for it.
|
|
56
|
+
-->
|
|
57
|
+
<li class="page-item"
|
|
58
|
+
:class-disabled=${current <= 1}
|
|
59
|
+
:_href=${link(current - 1)}>
|
|
45
60
|
<a class="page-link"
|
|
46
|
-
|
|
61
|
+
:if=${_href != null}
|
|
62
|
+
href=${_href}
|
|
47
63
|
aria-label="Previous"
|
|
64
|
+
aria-disabled=${current <= 1 ? 'true' : null}
|
|
48
65
|
:on-click=${() => current > 1 && select(current - 1)}>${prev}</a>
|
|
66
|
+
|
|
67
|
+
<button class="page-link"
|
|
68
|
+
type="button"
|
|
69
|
+
:else
|
|
70
|
+
:attr-disabled=${current <= 1}
|
|
71
|
+
aria-label="Previous"
|
|
72
|
+
:on-click=${() => select(current - 1)}>${prev}</button>
|
|
49
73
|
</li>
|
|
50
74
|
|
|
51
75
|
<li class="page-item"
|
|
@@ -53,17 +77,35 @@
|
|
|
53
77
|
:for-as="n"
|
|
54
78
|
:for-key=${n}
|
|
55
79
|
:class-active=${n === current}
|
|
56
|
-
aria-current=${n === current ? 'page' : null}
|
|
80
|
+
aria-current=${n === current ? 'page' : null}
|
|
81
|
+
:_href=${link(n)}>
|
|
57
82
|
<a class="page-link"
|
|
58
|
-
|
|
83
|
+
:if=${_href != null}
|
|
84
|
+
href=${_href}
|
|
59
85
|
:on-click=${() => select(n)}>${n}</a>
|
|
86
|
+
|
|
87
|
+
<button class="page-link"
|
|
88
|
+
type="button"
|
|
89
|
+
:else
|
|
90
|
+
:on-click=${() => select(n)}>${n}</button>
|
|
60
91
|
</li>
|
|
61
92
|
|
|
62
|
-
<li class="page-item"
|
|
93
|
+
<li class="page-item"
|
|
94
|
+
:class-disabled=${current >= pages}
|
|
95
|
+
:_href=${link(current + 1)}>
|
|
63
96
|
<a class="page-link"
|
|
64
|
-
|
|
97
|
+
:if=${_href != null}
|
|
98
|
+
href=${_href}
|
|
65
99
|
aria-label="Next"
|
|
100
|
+
aria-disabled=${current >= pages ? 'true' : null}
|
|
66
101
|
:on-click=${() => current < pages && select(current + 1)}>${next}</a>
|
|
102
|
+
|
|
103
|
+
<button class="page-link"
|
|
104
|
+
type="button"
|
|
105
|
+
:else
|
|
106
|
+
:attr-disabled=${current >= pages}
|
|
107
|
+
aria-label="Next"
|
|
108
|
+
:on-click=${() => select(current + 1)}>${next}</button>
|
|
67
109
|
</li>
|
|
68
110
|
</ul>
|
|
69
111
|
</:define>
|