Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New: Vertical item and custom icon support (fixes #154) #155

Merged
merged 5 commits into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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