From cee157fc19f19bf253de03168b0ed44446363474 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 5 May 2018 17:11:48 +0200 Subject: Improve accessibility of toot dropdown menu * Prevent Enter keypresses from triggering dropdown display toggle twice * Give focus to first/selected item of dropdown menus * Implement keyboard navigation in generic dropdown menus Partial port from ef7d64c80109074b39983b50cc8cf701c337cdcc to glitch-soc --- .../flavours/glitch/components/dropdown_menu.js | 46 ++++++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/dropdown_menu.js b/app/javascript/flavours/glitch/components/dropdown_menu.js index 245bebef3..27b2586e5 100644 --- a/app/javascript/flavours/glitch/components/dropdown_menu.js +++ b/app/javascript/flavours/glitch/components/dropdown_menu.js @@ -43,6 +43,7 @@ class DropdownMenu extends React.PureComponent { componentDidMount () { document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); + if (this.focusedItem) this.focusedItem.focus(); this.setState({ mounted: true }); } @@ -55,6 +56,46 @@ class DropdownMenu extends React.PureComponent { this.node = c; } + setFocusRef = c => { + this.focusedItem = c; + } + + handleKeyDown = e => { + const items = Array.from(this.node.getElementsByTagName('a')); + const index = items.indexOf(e.currentTarget); + let element; + + switch(e.key) { + case 'Enter': + this.handleClick(e); + break; + case 'ArrowDown': + element = items[index+1]; + if (element) { + element.focus(); + } + break; + case 'ArrowUp': + element = items[index-1]; + if (element) { + element.focus(); + } + break; + case 'Home': + element = items[0]; + if (element) { + element.focus(); + } + break; + case 'End': + element = items[items.length-1]; + if (element) { + element.focus(); + } + break; + } + } + handleClick = e => { const i = Number(e.currentTarget.getAttribute('data-index')); const { action, to } = this.props.items[i]; @@ -79,7 +120,7 @@ class DropdownMenu extends React.PureComponent { return (
  • - + {text}
  • @@ -156,9 +197,6 @@ export default class Dropdown extends React.PureComponent { handleKeyDown = e => { switch(e.key) { - case 'Enter': - this.handleClick(e); - break; case 'Escape': this.handleClose(); break; -- cgit From 553cc2824040ba0b745644eb4633840129ffc13b Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 5 May 2018 17:18:25 +0200 Subject: [Glitch] Prevent timeline from moving when cursor is hovering over it Port 58852695c8ec490239ed3812f82971f8c1e6c172 to glitch-soc --- .../flavours/glitch/components/scrollable_list.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index df3ace4c1..56e91f864 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -35,6 +35,7 @@ export default class ScrollableList extends PureComponent { state = { fullscreen: null, + mouseOver: false, }; intersectionObserverWrapper = new IntersectionObserverWrapper(); @@ -85,7 +86,7 @@ export default class ScrollableList extends PureComponent { const someItemInserted = React.Children.count(prevProps.children) > 0 && React.Children.count(prevProps.children) < React.Children.count(this.props.children) && this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props); - if (someItemInserted && this.node.scrollTop > 0) { + if (someItemInserted && this.node.scrollTop > 0 || this.state.mouseOver) { return this.node.scrollHeight - this.node.scrollTop; } else { return null; @@ -147,6 +148,14 @@ export default class ScrollableList extends PureComponent { this.props.onScrollToBottom(); } + handleMouseEnter = () => { + this.setState({ mouseOver: true }); + } + + handleMouseLeave = () => { + this.setState({ mouseOver: false }); + } + render () { const { children, scrollKey, trackScroll, shouldUpdateScroll, isLoading, hasMore, prepend, emptyMessage } = this.props; const { fullscreen } = this.state; @@ -157,7 +166,7 @@ export default class ScrollableList extends PureComponent { if (isLoading || childrenCount > 0 || !emptyMessage) { scrollableArea = ( -
    +
    {prepend} -- cgit From 32974a58dcf5a8db39a9c0378f923a40d787cad3 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sat, 5 May 2018 17:18:55 +0200 Subject: [Glitch] Do not re-position scroll when loading more (inserting items from below) Port 8c601b54ccf530bd193b4500fee439aa4e9162d0 to glitch-soc --- app/javascript/flavours/glitch/components/scrollable_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index 56e91f864..b8281b1ee 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -86,7 +86,7 @@ export default class ScrollableList extends PureComponent { const someItemInserted = React.Children.count(prevProps.children) > 0 && React.Children.count(prevProps.children) < React.Children.count(this.props.children) && this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props); - if (someItemInserted && this.node.scrollTop > 0 || this.state.mouseOver) { + if (someItemInserted && this.node.scrollTop > 0 || (this.state.mouseOver && !prevProps.isLoading)) { return this.node.scrollHeight - this.node.scrollTop; } else { return null; -- cgit From 4133f70902c0c88f511ef8f09b665b2ea4b8dc3a Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sun, 6 May 2018 21:50:26 +0200 Subject: Revert "[Glitch] Do not re-position scroll when loading more (inserting items from below)" This reverts commit 32974a58dcf5a8db39a9c0378f923a40d787cad3. --- app/javascript/flavours/glitch/components/scrollable_list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index b8281b1ee..56e91f864 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -86,7 +86,7 @@ export default class ScrollableList extends PureComponent { const someItemInserted = React.Children.count(prevProps.children) > 0 && React.Children.count(prevProps.children) < React.Children.count(this.props.children) && this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props); - if (someItemInserted && this.node.scrollTop > 0 || (this.state.mouseOver && !prevProps.isLoading)) { + if (someItemInserted && this.node.scrollTop > 0 || this.state.mouseOver) { return this.node.scrollHeight - this.node.scrollTop; } else { return null; -- cgit From de7feea30ea4ed3a514740706f1d2023e3103429 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Sun, 6 May 2018 21:50:33 +0200 Subject: Revert "[Glitch] Prevent timeline from moving when cursor is hovering over it" This reverts commit 553cc2824040ba0b745644eb4633840129ffc13b. --- .../flavours/glitch/components/scrollable_list.js | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.js index 56e91f864..df3ace4c1 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.js @@ -35,7 +35,6 @@ export default class ScrollableList extends PureComponent { state = { fullscreen: null, - mouseOver: false, }; intersectionObserverWrapper = new IntersectionObserverWrapper(); @@ -86,7 +85,7 @@ export default class ScrollableList extends PureComponent { const someItemInserted = React.Children.count(prevProps.children) > 0 && React.Children.count(prevProps.children) < React.Children.count(this.props.children) && this.getFirstChildKey(prevProps) !== this.getFirstChildKey(this.props); - if (someItemInserted && this.node.scrollTop > 0 || this.state.mouseOver) { + if (someItemInserted && this.node.scrollTop > 0) { return this.node.scrollHeight - this.node.scrollTop; } else { return null; @@ -148,14 +147,6 @@ export default class ScrollableList extends PureComponent { this.props.onScrollToBottom(); } - handleMouseEnter = () => { - this.setState({ mouseOver: true }); - } - - handleMouseLeave = () => { - this.setState({ mouseOver: false }); - } - render () { const { children, scrollKey, trackScroll, shouldUpdateScroll, isLoading, hasMore, prepend, emptyMessage } = this.props; const { fullscreen } = this.state; @@ -166,7 +157,7 @@ export default class ScrollableList extends PureComponent { if (isLoading || childrenCount > 0 || !emptyMessage) { scrollableArea = ( -
    +
    {prepend} -- cgit From 658ac4396cf1b7cab034701082645747c39f7af2 Mon Sep 17 00:00:00 2001 From: Thibaut Girka Date: Mon, 7 May 2018 15:00:55 +0200 Subject: Hide media in report modal regardless of whether they are marked sensitive MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rationale behind this is that if the user wants to report violent media, they might not want to see it repeatedly. The “sensitive” property is still kept, displaying different messages for hidden media depending on whether they are marked as sensitive. --- app/javascript/flavours/glitch/components/media_gallery.js | 3 ++- .../glitch/features/report/components/status_check_box.js | 3 ++- app/javascript/flavours/glitch/features/video/index.js | 14 +++++++++++--- 3 files changed, 15 insertions(+), 5 deletions(-) (limited to 'app/javascript/flavours/glitch/components') diff --git a/app/javascript/flavours/glitch/components/media_gallery.js b/app/javascript/flavours/glitch/components/media_gallery.js index 925132b07..7f5150f7b 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.js +++ b/app/javascript/flavours/glitch/components/media_gallery.js @@ -202,6 +202,7 @@ export default class MediaGallery extends React.PureComponent { static propTypes = { sensitive: PropTypes.bool, + revealed: PropTypes.bool, standalone: PropTypes.bool, letterbox: PropTypes.bool, fullwidth: PropTypes.bool, @@ -216,7 +217,7 @@ export default class MediaGallery extends React.PureComponent { }; state = { - visible: !this.props.sensitive || displaySensitiveMedia, + visible: this.props.revealed === undefined ? (!this.props.sensitive || displaySensitiveMedia) : this.props.revealed, }; componentWillReceiveProps (nextProps) { diff --git a/app/javascript/flavours/glitch/features/report/components/status_check_box.js b/app/javascript/flavours/glitch/features/report/components/status_check_box.js index d72a0fd07..a685132b0 100644 --- a/app/javascript/flavours/glitch/features/report/components/status_check_box.js +++ b/app/javascript/flavours/glitch/features/report/components/status_check_box.js @@ -40,6 +40,7 @@ export default class StatusCheckBox extends React.PureComponent { height={110} inline sensitive={status.get('sensitive')} + revealed={false} onOpenVideo={noop} /> )} @@ -48,7 +49,7 @@ export default class StatusCheckBox extends React.PureComponent { } else { media = ( - {Component => } + {Component => } ); } diff --git a/app/javascript/flavours/glitch/features/video/index.js b/app/javascript/flavours/glitch/features/video/index.js index 8c6d68dc4..3be6e19f7 100644 --- a/app/javascript/flavours/glitch/features/video/index.js +++ b/app/javascript/flavours/glitch/features/video/index.js @@ -92,6 +92,7 @@ export default class Video extends React.PureComponent { width: PropTypes.number, height: PropTypes.number, sensitive: PropTypes.bool, + revealed: PropTypes.bool, startTime: PropTypes.number, onOpenVideo: PropTypes.func, onCloseVideo: PropTypes.func, @@ -111,7 +112,7 @@ export default class Video extends React.PureComponent { fullscreen: false, hovered: false, muted: false, - revealed: !this.props.sensitive || displaySensitiveMedia, + revealed: this.props.revealed === undefined ? (!this.props.sensitive || displaySensitiveMedia) : this.props.revealed, }; setPlayerRef = c => { @@ -255,7 +256,7 @@ export default class Video extends React.PureComponent { } render () { - const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, letterbox, fullwidth, detailed } = this.props; + const { preview, src, inline, startTime, onOpenVideo, onCloseVideo, intl, alt, letterbox, fullwidth, detailed, sensitive } = this.props; const { containerWidth, currentTime, duration, buffer, dragging, paused, fullscreen, hovered, muted, revealed } = this.state; const progress = (currentTime / duration) * 100; const playerStyle = {}; @@ -270,6 +271,13 @@ export default class Video extends React.PureComponent { playerStyle.height = height; } + let warning; + if (sensitive) { + warning = ; + } else { + warning = ; + } + return (