Expand/collapse icon

This commit is contained in:
Jake Archibald
2018-10-27 16:55:37 +01:00
parent c8e0c56687
commit ce67f6c538
6 changed files with 57 additions and 15 deletions

View File

@@ -16,10 +16,15 @@ function getClosestHeading(el: Element): HTMLElement | undefined {
return undefined;
}
async function close(content: HTMLElement) {
async function close(heading: HTMLElement) {
const content = heading.nextElementSibling as HTMLElement;
// if there is no content, nothing to expand
if (!content) return;
const from = content.getBoundingClientRect().height;
content.removeAttribute('expanded');
heading.removeAttribute('content-expanded');
content.setAttribute('aria-expanded', 'false');
// Wait a microtask so other calls to open/close can get the final sizes.
@@ -34,10 +39,15 @@ async function close(content: HTMLElement) {
content.style.height = '';
}
async function open(content: HTMLElement) {
async function open(heading: HTMLElement) {
const content = heading.nextElementSibling as HTMLElement;
// if there is no content, nothing to expand
if (!content) return;
const from = content.getBoundingClientRect().height;
content.setAttribute('expanded', '');
heading.setAttribute('content-expanded', '');
content.setAttribute('aria-expanded', 'true');
const to = content.getBoundingClientRect().height;
@@ -148,23 +158,19 @@ export default class MultiPanel extends HTMLElement {
private _toggle(heading: HTMLElement) {
if (!heading) return;
const content = heading.nextElementSibling as HTMLElement;
// if there is no content, nothing to expand
if (!content) return;
// toggle expanded and aria-expanded attributes
if (content.hasAttribute('expanded')) {
close(content);
if (heading.hasAttribute('content-expanded')) {
close(heading);
} else {
if (this.openOneOnly) this._closeAll();
open(content);
open(heading);
}
}
private _closeAll(options: CloseAllOptions = {}): void {
const { exceptFirst = false } = options;
let els = [...this.children].filter(el => el.matches('[expanded]')) as HTMLElement[];
let els = [...this.children].filter(el => el.matches('[content-expanded]')) as HTMLElement[];
if (exceptFirst) {
els = els.slice(1);
@@ -194,8 +200,8 @@ export default class MultiPanel extends HTMLElement {
// Remove classes and attributes to prepare for this change.
heading.classList.remove(style.panelContent);
content.classList.remove(style.panelHeading);
heading.removeAttribute('expanded');
heading.removeAttribute('aria-expanded');
heading.removeAttribute('content-expanded');
// If appreciable, remove tabindex from content which used to be header.
content.removeAttribute('tabindex');
@@ -218,6 +224,13 @@ export default class MultiPanel extends HTMLElement {
heading.setAttribute('tabindex', '-1');
}
// It's possible that the heading & content expanded attributes are now out of sync. Resync
// them using the heading as the source of truth.
content.setAttribute(
'aria-expanded',
heading.hasAttribute('content-expanded') ? 'true' : 'false',
);
// next sibling of content = next heading
heading = content.nextElementSibling;
}

View File

@@ -5,6 +5,6 @@
height: 0px;
overflow: auto;
}
.panel-content[expanded] {
.panel-content[aria-expanded=true] {
height: auto;
}

View File

@@ -34,6 +34,7 @@ import Processor from '../../codecs/processor';
import { VectorResizeOptions, BitmapResizeOptions } from '../../codecs/resize/processor-meta';
import './custom-els/MultiPanel';
import Results from '../results';
import { ExpandIcon } from '../../lib/icons';
export interface SourceImage {
file: File | Fileish;
@@ -421,7 +422,10 @@ export default class Compress extends Component<Props, State> {
source={source}
loading={loading || image.loading}
>
{mobileView ? `${resultTitles[i]} (${encoderMap[image.encoderState.type].label})` : null}
{!mobileView ? null : [
<ExpandIcon class={style.expandIcon} key="expand-icon"/>,
`${resultTitles[i]} (${encoderMap[image.encoderState.type].label})`,
]}
</Results>
));

View File

@@ -59,3 +59,16 @@
order: 3;
}
}
.expand-icon {
transform: rotate(180deg);
margin-left: -12px;
}
[content-expanded] .expand-icon {
transform: none;
}
:focus .expand-icon {
fill: #34B9EB;
}

View File

@@ -19,6 +19,10 @@
grid-template-columns: 1fr auto;
background: rgba(0, 0, 0, 0.9);
font-size: 1.4rem;
&:focus {
outline: none;
}
}
.result-data {
@@ -30,6 +34,8 @@
}
.result-title {
display: flex;
align-items: center;
margin-right: 0.4em;
}

View File

@@ -41,3 +41,9 @@ export const CheckedIcon = (props: JSX.HTMLAttributes) => (
<path d="M21.3 0H2.7A2.7 2.7 0 0 0 0 2.7v18.6A2.7 2.7 0 0 0 2.7 24h18.6a2.7 2.7 0 0 0 2.7-2.7V2.7A2.7 2.7 0 0 0 21.3 0zm-12 18.7L2.7 12l1.8-1.9L9.3 15 19.5 4.8l1.8 1.9z"/>
</Icon>
);
export const ExpandIcon = (props: JSX.HTMLAttributes) => (
<Icon {...props}>
<path d="M16.6 8.6L12 13.2 7.4 8.6 6 10l6 6 6-6z"/>
</Icon>
);