Skip to content

Commit

Permalink
New: Vertical item and custom icon support (fixes #154) (#155)
Browse files Browse the repository at this point in the history
* Vertical item and custom icon support

* Moved structural vertical styles to plugin

* Readme, example updated

* Updated _hasVerticalLayout to _isCenterAligned

* Updated class name
  • Loading branch information
guywillis authored Oct 1, 2024
1 parent 00bd8e4 commit e612537
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 14 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,16 @@ guide the learner’s interaction with the component.

**\_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).

**\_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`.

**\_items** (array): Multiple items may be created. Each _item_ represents one element of the accordion and contains values for **title**, **body**, **\_graphic**, and **\_classes**.

>**title** (string): This text is displayed as the element's header. It is displayed at all times, even when the **body** has been collapsed.
>**body** (string): This content will be displayed when the learner opens this accordion element. It may contain HTML.
>**\_titleIcon** (string): CSS class name to be applied to the accordion title icon.
>**\_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`.
>**\_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**.
Expand Down
5 changes: 5 additions & 0 deletions example.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@
"_shouldExpandFirstItem": false,
"_comment": "setCompletionOn = inview | allItems",
"_setCompletionOn": "allItems",
"_isCenterAligned": false,
"_items": [
{
"title": "Heading 1",
"body": "This is display text 1 with a full width image.",
"_titleIcon": "",
"_imageAlignment": "full",
"_graphic": {
"src": "course/en/images/example.jpg",
Expand All @@ -28,6 +30,7 @@
{
"title": "Heading 2",
"body": "This is display text 2 with a single width left aligned image.",
"_titleIcon": "",
"_imageAlignment": "left",
"_graphic": {
"src": "course/en/images/example.jpg",
Expand All @@ -39,6 +42,7 @@
{
"title": "Heading 3",
"body": "This is display text 3 with a single width right aligned image.",
"_titleIcon": "",
"_imageAlignment": "right",
"_graphic": {
"src": "course/en/images/example.jpg",
Expand All @@ -50,6 +54,7 @@
{
"title": "Heading 4",
"body": "This is display text 4 with no image.",
"_titleIcon": "",
"_imageAlignment": "",
"_graphic": {
"src": "",
Expand Down
22 changes: 20 additions & 2 deletions less/accordion.less
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,32 @@

// Item icon states
// --------------------------------------------------
&__btn.is-closed .icon {
&__btn.is-closed &__icon .icon {
.icon-plus;
}

&__btn.is-visited .icon {
&__btn.is-visited &__icon .icon {
.icon-tick;
}

// vertical items
&.is-center-aligned &__btn {
text-align: center;
}

&.is-center-aligned &__title-icon,
&.is-center-aligned &__title {
display: block;
}

&.is-center-aligned &__icon {
display: block;
}

&.is-center-aligned &__content {
text-align: center;
}

// Set up margin between body and image elements
// Turn off margin when image is left / right aligned on desktop
// --------------------------------------------------
Expand Down
18 changes: 18 additions & 0 deletions properties.schema
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@
"help": "This is the item body text that is hidden until the item title is clicked on",
"translatable": true
},
"_titleIcon": {
"type": "string",
"required": false,
"default": "",
"title": "Title icon",
"inputType": "Text",
"validators": [],
"help": "CSS class name to be applied to the accordion title icon."
},
"_imageAlignment": {
"type": "string",
"required": false,
Expand Down Expand Up @@ -141,6 +150,15 @@
"inputType": "Checkbox",
"validators": [],
"help": "If enabled, the first item will be expanded by default"
},
"_isCenterAligned": {
"type": "boolean",
"required": false,
"default": false,
"title": "Enable item button vertical layout",
"inputType": "Checkbox",
"validators": [],
"help": "If enabled, the layout of the item button child elements will be stacked on top of one another centrally."
}
}
}
12 changes: 12 additions & 0 deletions schema/component.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@
},
"_backboneForms": "TextArea"
},
"_titleIcon": {
"type": "string",
"title": "Title icon",
"description": "CSS class name to be applied to the accordion title icon.",
"default": ""
},
"_imageAlignment": {
"type": "string",
"title": "Image alignment",
Expand Down Expand Up @@ -130,6 +136,12 @@
"type": "boolean",
"title": "Expand first item by default",
"default": false
},
"_isCenterAligned": {
"type": "boolean",
"title": "Enable item button vertical layout",
"description": "If enabled, the layout of the item button child elements will be stacked on top of one another centrally.",
"default": false
}
}
}
Expand Down
53 changes: 41 additions & 12 deletions templates/accordion.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ export default function Accordion (props) {
const visited = Adapt.course.get('_globals')?._accessibility?._ariaLabels.visited;
const {
_id,
onClick
onClick,
_isCenterAligned
} = props;
return (
<div className="component__inner accordion__inner">
Expand All @@ -16,7 +17,7 @@ export default function Accordion (props) {

<div className="component__widget accordion__widget">

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

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

Expand All @@ -28,18 +29,23 @@ export default function Accordion (props) {
'js-accordion-item',
_graphic?.src && 'has-image',
_graphic?.src && _imageAlignment && `align-image-${_imageAlignment}`,
_isCenterAligned && 'is-center-aligned',
_classes
])}
key={_index}
data-index={_index}
>

<div role="heading" aria-level={a11y.ariaLevel({ id: _id, level: 'componentItem' })} >
<div
role="heading"
aria-level={a11y.ariaLevel({ id: _id, level: 'componentItem' })}
>
<button
id={`${_id}-${index}-accordion-button`}
className={classes([
'accordion-item__btn',
'js-toggle-item',
_titleIcon && 'has-title-icon',
_isVisited && 'is-visited',
_isActive ? 'is-open is-selected' : 'is-closed'
])}
Expand All @@ -50,14 +56,35 @@ export default function Accordion (props) {

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

<span className="accordion-item__icon">
<span className="icon" aria-hidden="true"></span>
</span>
{_titleIcon &&
<span className="accordion-item__title-icon">
<span
className={classes([
'icon',
_titleIcon
])}
aria-hidden="true"
/>
</span>
}

<span className="accordion-item__title">
<span className="aria-label" dangerouslySetInnerHTML={{ __html: compile(ariaLabel) }}></span>
<span className="accordion-item__title-inner" aria-hidden="true" dangerouslySetInnerHTML={{ __html: compile(title) }}>
</span>
<span
className="aria-label"
dangerouslySetInnerHTML={{ __html: compile(ariaLabel) }}
/>
<span
className="accordion-item__title-inner"
aria-hidden="true"
dangerouslySetInnerHTML={{ __html: compile(title) }}
/>
</span>

<span className="accordion-item__icon">
<span
className="icon"
aria-hidden="true"
/>
</span>

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

{body &&
<div className="accordion-item__body">
<div className="accordion-item__body-inner" dangerouslySetInnerHTML={{ __html: compile(body) }}>
</div>
<div
className="accordion-item__body-inner"
dangerouslySetInnerHTML={{ __html: compile(body) }}
/>
</div>
}

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

</div>
)
);
})}

</div>
Expand Down

0 comments on commit e612537

Please sign in to comment.