Improve tab navigation

Closes #396.
pull/427/merge
Thibaut Courouble 9 years ago
parent 87ede1f4a0
commit 39b9846d78

@ -15,7 +15,7 @@ app.templates.aboutPage = -> """
<ul>
<li>Created and maintained by <a href="http://thibaut.me">Thibaut Courouble</a>
<li>Free and <a href="https://github.com/Thibaut/devdocs">open source</a>
<iframe class="_github-btn" src="https://ghbtns.com/github-btn.html?user=Thibaut&repo=devdocs&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20"></iframe>
<iframe class="_github-btn" src="https://ghbtns.com/github-btn.html?user=Thibaut&repo=devdocs&type=watch&count=true" allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20" tabindex="-1"></iframe>
</ul>
<p>To keep up-to-date with the latest news:
<ul>

@ -3,7 +3,7 @@ app.templates.splash = """<div class="_splash-title">DevDocs</div>"""
<% if App.development? %>
app.templates.intro = """
<div class="_intro"><div class="_intro-message">
<a class="_intro-hide" data-hide-intro>Stop showing this message</a>
<a href="#" class="_intro-hide" data-hide-intro>Stop showing this message</a>
<h2 class="_intro-title">Hi there!</h2>
<p>Thanks for downloading DevDocs. Here are a few things you should know:
<ol class="_intro-list">
@ -27,7 +27,7 @@ app.templates.intro = """
<% else %>
app.templates.intro = """
<div class="_intro"><div class="_intro-message">
<a class="_intro-hide" data-hide-intro>Stop showing this message</a>
<a href="#" class="_intro-hide" data-hide-intro>Stop showing this message</a>
<h2 class="_intro-title">Welcome!</h2>
<p>DevDocs combines multiple API documentations in a fast, organized, and searchable interface.
Here's what you should know before you start:

@ -3,7 +3,7 @@ templates = app.templates
templates.sidebarDoc = (doc, options = {}) ->
link = """<a href="#{doc.fullPath()}" class="_list-item _icon-#{doc.icon} """
link += if options.disabled then '_list-disabled' else '_list-dir'
link += """" data-slug="#{doc.slug}" title="#{doc.fullName}">"""
link += """" data-slug="#{doc.slug}" title="#{doc.fullName}" tabindex="-1">"""
if options.disabled
link += """<span class="_list-enable" data-enable="#{doc.slug}">Enable</span>"""
else
@ -14,10 +14,10 @@ templates.sidebarDoc = (doc, options = {}) ->
link + "</span></a>"
templates.sidebarType = (type) ->
"""<a href="#{type.fullPath()}" class="_list-item _list-dir" data-slug="#{type.slug}"><span class="_list-arrow"></span><span class="_list-count">#{type.count}</span><span class="_list-text">#{type.name}</span></a>"""
"""<a href="#{type.fullPath()}" class="_list-item _list-dir" data-slug="#{type.slug}" tabindex="-1"><span class="_list-arrow"></span><span class="_list-count">#{type.count}</span><span class="_list-text">#{type.name}</span></a>"""
templates.sidebarEntry = (entry) ->
"""<a href="#{entry.fullPath()}" class="_list-item _list-hover">#{$.escape entry.name}</a>"""
"""<a href="#{entry.fullPath()}" class="_list-item _list-hover" tabindex="-1">#{$.escape entry.name}</a>"""
templates.sidebarResult = (entry) ->
addons = if entry.isIndex() and app.disabledDocs.contains(entry.doc)
@ -25,17 +25,17 @@ templates.sidebarResult = (entry) ->
else
"""<span class="_list-reveal" data-reset-list title="Reveal in list"></span>"""
addons += """<span class="_list-count">#{entry.doc.short_version}</span>""" if entry.doc.version and not entry.isIndex()
"""<a href="#{entry.fullPath()}" class="_list-item _list-hover _list-result _icon-#{entry.doc.icon}">#{addons}<span class="_list-text">#{$.escape entry.name}</span></a>"""
"""<a href="#{entry.fullPath()}" class="_list-item _list-hover _list-result _icon-#{entry.doc.icon}" tabindex="-1">#{addons}<span class="_list-text">#{$.escape entry.name}</span></a>"""
templates.sidebarNoResults = ->
html = """ <div class="_list-note">No results.</div> """
html += """
<div class="_list-note">Note: documentations must be <a class="_list-note-link" data-pick-docs>enabled</a> to appear in the search.</div>
<div class="_list-note">Note: documentations must be <a href="#" class="_list-note-link" data-pick-docs>enabled</a> to appear in the search.</div>
""" unless app.isSingleDoc() or app.disabledDocs.isEmpty()
html
templates.sidebarPageLink = (count) ->
"""<span class="_list-item _list-pagelink">Show more\u2026 (#{count})</span>"""
"""<span role="link" class="_list-item _list-pagelink">Show more\u2026 (#{count})</span>"""
templates.sidebarLabel = (doc, options = {}) ->
label = """<label class="_list-item"""
@ -47,7 +47,7 @@ templates.sidebarLabel = (doc, options = {}) ->
templates.sidebarVersionedDoc = (doc, versions, options = {}) ->
html = """<div class="_list-item _list-dir _list-rdir _icon-#{doc.icon}"""
html += " open" if options.open
html + """"><span class="_list-arrow"></span>#{doc.name}</div><div class="_list _list-sub">#{versions}</div>"""
html + """" tabindex="0"><span class="_list-arrow"></span>#{doc.name}</div><div class="_list _list-sub">#{versions}</div>"""
templates.sidebarDisabled = (options) ->
"""<h6 class="_list-title"><span class="_list-arrow"></span>Disabled (#{options.count})</h6>"""
@ -56,7 +56,7 @@ templates.sidebarDisabledList = (html) ->
"""<div class="_disabled-list">#{html}</div>"""
templates.sidebarDisabledVersionedDoc = (doc, versions) ->
"""<a class="_list-item _list-dir _icon-#{doc.icon} _list-disabled" data-slug="#{doc.slug_without_version}"><span class="_list-arrow"></span>#{doc.name}</a><div class="_list _list-sub">#{versions}</div>"""
"""<a class="_list-item _list-dir _icon-#{doc.icon} _list-disabled" data-slug="#{doc.slug_without_version}" tabindex="-1"><span class="_list-arrow"></span>#{doc.name}</a><div class="_list _list-sub">#{versions}</div>"""
templates.sidebarPickerNote = """
<div class="_list-note">Tip: for faster and better search results, select only the docs you need.</div>
@ -67,9 +67,9 @@ sidebarFooter = (html) -> """<div class="_sidebar-footer">#{html}</div>"""
templates.sidebarSettings = ->
sidebarFooter """
<button type="button" class="_sidebar-footer-link _sidebar-footer-edit" data-pick-docs>Select documentation</button>
<button type="button" class="_sidebar-footer-link _sidebar-footer-light" title="Toggle light" data-light>Toggle light</button>
<button type="button" class="_sidebar-footer-link _sidebar-footer-layout" title="Toggle layout" data-layout>Toggle layout</button>
<a href="#" class="_sidebar-footer-link _sidebar-footer-edit" data-pick-docs>Select documentation</a>
"""
templates.sidebarSave = ->

@ -9,11 +9,13 @@ class app.views.Nav extends app.View
@deselect()
if @current = @find "a[href='#{href}']"
@current.classList.add @constructor.activeClass
@current.setAttribute 'tabindex', '-1'
return
deselect: ->
if @current
@current.classList.remove @constructor.activeClass
@current.removeAttribute 'tabindex'
@current = null
return

@ -84,10 +84,11 @@ class app.views.SearchScope extends app.View
if @doc and not @input.value
$.stopEvent(event)
@reset()
else if event.which is 9 or # tab
event.which is 32 and (app.isMobile() or $.isTouchScreen()) # space
$.stopEvent(event)
@search @input.value[0...@input.selectionStart]
else if not @doc and @input.value
if event.which is 9 or # tab
event.which is 32 and (app.isMobile() or $.isTouchScreen()) # space
@search @input.value[0...@input.selectionStart]
$.stopEvent(event) if @doc
return
extractHashValue: ->

@ -21,14 +21,14 @@ class app.views.DocPicker extends app.View
@render()
@findByTag('input')?.focus()
app.appCache?.on 'progress', @onAppCacheProgress
$.on @el, 'focus', @onFocus, true
$.on @el, 'focus', @onDOMFocus, true
return
deactivate: ->
if super
@empty()
app.appCache?.off 'progress', @onAppCacheProgress
$.off @el, 'focus', @onFocus, true
$.off @el, 'focus', @onDOMFocus, true
return
render: ->
@ -84,14 +84,27 @@ class app.views.DocPicker extends app.View
input.name
onClick: (event) =>
if @focusTimeout
clearTimeout @focusTimeout
@focusTimeout = null
return if event.which isnt 1
if event.target is @saveLink
$.stopEvent(event)
@save()
return
onFocus: (event) ->
$.scrollTo event.target.parentNode, null, 'continuous', bottomGap: 2
onDOMFocus: (event) =>
target = event.target
if target.tagName is 'INPUT'
$.scrollTo target.parentNode, null, 'continuous', bottomGap: 2
else if target.classList.contains(app.views.ListFold.targetClass)
target.blur()
@focusTimeout = setTimeout =>
@listFold.open(target) unless target.classList.contains(app.views.ListFold.activeClass)
$('input', target.nextElementSibling).focus()
@focusTimeout = null
, 10
return
onEnter: =>
@save()

@ -101,9 +101,11 @@ class app.views.Sidebar extends app.View
@reset()
else if event.target.hasAttribute? 'data-light'
$.stopEvent(event)
document.activeElement?.blur()
app.document.toggleLight()
else if event.target.hasAttribute? 'data-layout'
$.stopEvent(event)
document.activeElement?.blur()
app.document.toggleLayout()
return

@ -13,8 +13,6 @@
background: $headerBackground;
border-bottom: 1px solid $headerBorder;
@extend %user-select-none;
a:focus { outline: 0; }
}
//
@ -58,6 +56,8 @@
}
._nav-current {
outline: 0;
&:before, &:after { content: ''; }
}

@ -32,8 +32,6 @@
}
}
a:focus { outline: 0; }
._sidebar-hidden & {
display: none;
}
@ -88,6 +86,8 @@
min-height: 100%;
padding-bottom: 3.5rem;
}
a:focus { outline: 0; }
}
._list-title {
@ -422,6 +422,8 @@
}
._sidebar-footer-edit {
display: inline-block;
@if $style == 'dark' {
&:before { @extend %icon-settings-white; }
} @else {

@ -159,6 +159,8 @@ td {
> pre:last-child, > p:last-child, > ul:last-child, > ol:last-child { margin-bottom: 0; }
}
section, main { outline: 0; }
input, button {
margin: 0;
font-family: inherit;
@ -179,6 +181,11 @@ button, input[type="search"] {
-moz-appearance: none;
}
button:focus {
outline: 1px dotted;
outline: -webkit-focus-ring-color auto 5px;
}
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;

@ -22,7 +22,7 @@
%hide-text {
white-space: nowrap;
overflow: hidden;
color: transparent !important;
text-indent: -1000px;
@extend %user-select-none;
}

@ -19,7 +19,7 @@
<a href="/help" class="_nav-link">Tips</a>
</nav>
</header>
<section class="_sidebar">
<section class="_sidebar" tabindex="-1">
<div class="_list" role="navigation">
<% unless @doc %>
<% App.docs.each do |slug, doc| %>
@ -29,7 +29,7 @@
</div>
</section>
<div class="_container" role="document">
<main class="_content _content-loading" role="main"></main>
<main class="_content _content-loading" role="main" tabindex="1"></main>
</div>
</div>
<style data-size="<%= app_size %>" data-resizer>

Loading…
Cancel
Save