Skip to content

Commit e612537

Browse files
authored
New: Vertical item and custom icon support (fixes #154) (#155)
* Vertical item and custom icon support * Moved structural vertical styles to plugin * Readme, example updated * Updated _hasVerticalLayout to _isCenterAligned * Updated class name
1 parent 00bd8e4 commit e612537

File tree

6 files changed

+100
-14
lines changed

6 files changed

+100
-14
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,16 @@ guide the learner’s interaction with the component.
4646

4747
**\_setCompletionOn** (string): Determines when the component registers as complete. Acceptable values are `"allItems"` and `"inview"`. `"allItems"` (the default) requires the learner to view every single accordion item; `"inview"` requires only that the component has been viewed (i.e. passed completely through the browser viewport).
4848

49+
**\_isCenterAligned** (boolean): If enabled, the layout of the item button child elements will be stacked on top of one another centrally. Acceptable values are `true` and `false`. The default value is `false`.
50+
4951
**\_items** (array): Multiple items may be created. Each _item_ represents one element of the accordion and contains values for **title**, **body**, **\_graphic**, and **\_classes**.
5052

5153
>**title** (string): This text is displayed as the element's header. It is displayed at all times, even when the **body** has been collapsed.
5254
5355
>**body** (string): This content will be displayed when the learner opens this accordion element. It may contain HTML.
5456
57+
>**\_titleIcon** (string): CSS class name to be applied to the accordion title icon.
58+
5559
>**\_imageAlignment** (string): Defines the alignment of the item image. Full: Image spans the entire width of the container below the text area. Left: Image aligned to the left of the text area. Right: Image aligned to the right of the text area. The default alignment is `full`. For smaller screens the alignment defaults to `full`.
5660
5761
>**\_graphic** (object): An optional image which is displayed below the item body when the learner opens this accordion element. It contains values for **src**, **alt**, and **attribution**.

example.json

+5
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
"_shouldExpandFirstItem": false,
1414
"_comment": "setCompletionOn = inview | allItems",
1515
"_setCompletionOn": "allItems",
16+
"_isCenterAligned": false,
1617
"_items": [
1718
{
1819
"title": "Heading 1",
1920
"body": "This is display text 1 with a full width image.",
21+
"_titleIcon": "",
2022
"_imageAlignment": "full",
2123
"_graphic": {
2224
"src": "course/en/images/example.jpg",
@@ -28,6 +30,7 @@
2830
{
2931
"title": "Heading 2",
3032
"body": "This is display text 2 with a single width left aligned image.",
33+
"_titleIcon": "",
3134
"_imageAlignment": "left",
3235
"_graphic": {
3336
"src": "course/en/images/example.jpg",
@@ -39,6 +42,7 @@
3942
{
4043
"title": "Heading 3",
4144
"body": "This is display text 3 with a single width right aligned image.",
45+
"_titleIcon": "",
4246
"_imageAlignment": "right",
4347
"_graphic": {
4448
"src": "course/en/images/example.jpg",
@@ -50,6 +54,7 @@
5054
{
5155
"title": "Heading 4",
5256
"body": "This is display text 4 with no image.",
57+
"_titleIcon": "",
5358
"_imageAlignment": "",
5459
"_graphic": {
5560
"src": "",

less/accordion.less

+20-2
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,32 @@
1313

1414
// Item icon states
1515
// --------------------------------------------------
16-
&__btn.is-closed .icon {
16+
&__btn.is-closed &__icon .icon {
1717
.icon-plus;
1818
}
1919

20-
&__btn.is-visited .icon {
20+
&__btn.is-visited &__icon .icon {
2121
.icon-tick;
2222
}
2323

24+
// vertical items
25+
&.is-center-aligned &__btn {
26+
text-align: center;
27+
}
28+
29+
&.is-center-aligned &__title-icon,
30+
&.is-center-aligned &__title {
31+
display: block;
32+
}
33+
34+
&.is-center-aligned &__icon {
35+
display: block;
36+
}
37+
38+
&.is-center-aligned &__content {
39+
text-align: center;
40+
}
41+
2442
// Set up margin between body and image elements
2543
// Turn off margin when image is left / right aligned on desktop
2644
// --------------------------------------------------

properties.schema

+18
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,15 @@
7171
"help": "This is the item body text that is hidden until the item title is clicked on",
7272
"translatable": true
7373
},
74+
"_titleIcon": {
75+
"type": "string",
76+
"required": false,
77+
"default": "",
78+
"title": "Title icon",
79+
"inputType": "Text",
80+
"validators": [],
81+
"help": "CSS class name to be applied to the accordion title icon."
82+
},
7483
"_imageAlignment": {
7584
"type": "string",
7685
"required": false,
@@ -141,6 +150,15 @@
141150
"inputType": "Checkbox",
142151
"validators": [],
143152
"help": "If enabled, the first item will be expanded by default"
153+
},
154+
"_isCenterAligned": {
155+
"type": "boolean",
156+
"required": false,
157+
"default": false,
158+
"title": "Enable item button vertical layout",
159+
"inputType": "Checkbox",
160+
"validators": [],
161+
"help": "If enabled, the layout of the item button child elements will be stacked on top of one another centrally."
144162
}
145163
}
146164
}

schema/component.schema.json

+12
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,12 @@
6464
},
6565
"_backboneForms": "TextArea"
6666
},
67+
"_titleIcon": {
68+
"type": "string",
69+
"title": "Title icon",
70+
"description": "CSS class name to be applied to the accordion title icon.",
71+
"default": ""
72+
},
6773
"_imageAlignment": {
6874
"type": "string",
6975
"title": "Image alignment",
@@ -130,6 +136,12 @@
130136
"type": "boolean",
131137
"title": "Expand first item by default",
132138
"default": false
139+
},
140+
"_isCenterAligned": {
141+
"type": "boolean",
142+
"title": "Enable item button vertical layout",
143+
"description": "If enabled, the layout of the item button child elements will be stacked on top of one another centrally.",
144+
"default": false
133145
}
134146
}
135147
}

templates/accordion.jsx

+41-12
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ export default function Accordion (props) {
77
const visited = Adapt.course.get('_globals')?._accessibility?._ariaLabels.visited;
88
const {
99
_id,
10-
onClick
10+
onClick,
11+
_isCenterAligned
1112
} = props;
1213
return (
1314
<div className="component__inner accordion__inner">
@@ -16,7 +17,7 @@ export default function Accordion (props) {
1617

1718
<div className="component__widget accordion__widget">
1819

19-
{props._items.map(({ _graphic, _imageAlignment, _classes, title, body, _index, _isVisited, _isActive }, index) => {
20+
{props._items.map(({ _graphic, _imageAlignment, _classes, title, body, _titleIcon, _index, _isVisited, _isActive }, index) => {
2021

2122
const ariaLabel = `${_isVisited ? visited + '. ' : ''}${compile(title)}`;
2223

@@ -28,18 +29,23 @@ export default function Accordion (props) {
2829
'js-accordion-item',
2930
_graphic?.src && 'has-image',
3031
_graphic?.src && _imageAlignment && `align-image-${_imageAlignment}`,
32+
_isCenterAligned && 'is-center-aligned',
3133
_classes
3234
])}
3335
key={_index}
3436
data-index={_index}
3537
>
3638

37-
<div role="heading" aria-level={a11y.ariaLevel({ id: _id, level: 'componentItem' })} >
39+
<div
40+
role="heading"
41+
aria-level={a11y.ariaLevel({ id: _id, level: 'componentItem' })}
42+
>
3843
<button
3944
id={`${_id}-${index}-accordion-button`}
4045
className={classes([
4146
'accordion-item__btn',
4247
'js-toggle-item',
48+
_titleIcon && 'has-title-icon',
4349
_isVisited && 'is-visited',
4450
_isActive ? 'is-open is-selected' : 'is-closed'
4551
])}
@@ -50,14 +56,35 @@ export default function Accordion (props) {
5056

5157
<span className="accordion-item__btn-inner">
5258

53-
<span className="accordion-item__icon">
54-
<span className="icon" aria-hidden="true"></span>
55-
</span>
59+
{_titleIcon &&
60+
<span className="accordion-item__title-icon">
61+
<span
62+
className={classes([
63+
'icon',
64+
_titleIcon
65+
])}
66+
aria-hidden="true"
67+
/>
68+
</span>
69+
}
5670

5771
<span className="accordion-item__title">
58-
<span className="aria-label" dangerouslySetInnerHTML={{ __html: compile(ariaLabel) }}></span>
59-
<span className="accordion-item__title-inner" aria-hidden="true" dangerouslySetInnerHTML={{ __html: compile(title) }}>
60-
</span>
72+
<span
73+
className="aria-label"
74+
dangerouslySetInnerHTML={{ __html: compile(ariaLabel) }}
75+
/>
76+
<span
77+
className="accordion-item__title-inner"
78+
aria-hidden="true"
79+
dangerouslySetInnerHTML={{ __html: compile(title) }}
80+
/>
81+
</span>
82+
83+
<span className="accordion-item__icon">
84+
<span
85+
className="icon"
86+
aria-hidden="true"
87+
/>
6188
</span>
6289

6390
</span>
@@ -76,8 +103,10 @@ export default function Accordion (props) {
76103

77104
{body &&
78105
<div className="accordion-item__body">
79-
<div className="accordion-item__body-inner" dangerouslySetInnerHTML={{ __html: compile(body) }}>
80-
</div>
106+
<div
107+
className="accordion-item__body-inner"
108+
dangerouslySetInnerHTML={{ __html: compile(body) }}
109+
/>
81110
</div>
82111
}
83112

@@ -90,7 +119,7 @@ export default function Accordion (props) {
90119
</div>
91120

92121
</div>
93-
)
122+
);
94123
})}
95124

96125
</div>

0 commit comments

Comments
 (0)