UI improvements

pull/570/merge
Thibaut Courouble 8 years ago
parent fd03ac1133
commit 0f238609da

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

@ -10,7 +10,7 @@ app.templates.aboutPage = -> """
</ul>
</nav>
<h1 class="_lined-heading">API Documentation Browser</h1>
<h1 class="_lined-heading">DevDocs: API Documentation Browser</h1>
<p>DevDocs combines multiple API documentations in a fast, organized, and searchable interface.
<ul>
<li>Created and maintained by <a href="http://thibaut.me">Thibaut Courouble</a>
@ -26,7 +26,7 @@ app.templates.aboutPage = -> """
<p class="_note _note-green">If you like DevDocs, please consider supporting my work on
<a href="https://gratipay.com/devdocs/">Gratipay</a>. Thanks!<br>
<h2 class="_lined-heading" id="credits">Credits</h2>
<h2 class="_block-heading" id="credits">Credits</h2>
<p><strong>Special thanks to:</strong>
<ul>
@ -45,7 +45,7 @@ app.templates.aboutPage = -> """
#{("<tr><td>#{c[0]}<td>&copy; #{c[1]}<td><a href=\"#{c[3]}\">#{c[2]}</a>" for c in credits).join('')}
</table>
<h2 class="_lined-heading" id="faq">Questions & Answers</h2>
<h2 class="_block-heading" id="faq">Questions & Answers</h2>
<dl>
<dt>Where can I suggest new docs and features?
<dd>You can suggest and vote for new docs on the <a href="https://trello.com/b/6BmTulfx/devdocs-documentation">Trello board</a>.<br>
@ -56,7 +56,7 @@ app.templates.aboutPage = -> """
</dl>
<p>For anything else, feel free to email me at <a href="mailto:thibaut@devdocs.io">thibaut@devdocs.io</a>.
<h2 class="_lined-heading" id="copyright">Copyright and License</h2>
<h2 class="_block-heading" id="copyright">Copyright and License</h2>
<p class="_note">
<strong>Copyright 2013&ndash;2017 Thibaut Courouble and <a href="https://github.com/Thibaut/devdocs/graphs/contributors">other contributors</a></strong><br>
This software is licensed under the terms of the Mozilla Public License v2.0.<br>
@ -64,7 +64,7 @@ app.templates.aboutPage = -> """
For more information, see the <a href="https://github.com/Thibaut/devdocs/blob/master/COPYRIGHT">COPYRIGHT</a>
and <a href="https://github.com/Thibaut/devdocs/blob/master/LICENSE">LICENSE</a> files.
<h2 class="_lined-heading" id="plugins">Plugins and Extensions</h2>
<h2 class="_block-heading" id="plugins">Plugins and Extensions</h2>
<ul>
<li><a href="https://chrome.google.com/webstore/detail/devdocs/mnfehgbmkapmjnhcnbodoamcioleeooe">Chrome web app</a>
<li><a href="https://sublime.wbond.net/packages/DevDocs">Sublime Text plugin</a>
@ -73,7 +73,7 @@ app.templates.aboutPage = -> """
<li><a href="https://github.com/xuchunyang/DevDocs.el">Emacs Package</a>
</ul>
<h2 class="_lined-heading" id="privacy">Privacy Policy</h2>
<h2 class="_block-heading" id="privacy">Privacy Policy</h2>
<ul>
<li><a href="http://devdocs.io">devdocs.io</a> ("App") is operated by Thibaut Courouble ("We").
<li>We do not collect personal information.

@ -11,7 +11,9 @@ app.templates.helpPage = """
</ul>
</nav>
<h2 class="_lined-heading" id="search">Search</h2>
<h1 class="_lined-heading" id="search">Help</h2>
<h2 class="_block-heading" id="search">Search</h2>
<p>
The search is case-insensitive and supports fuzzy matching (for queries longer than two characters).
For example, searching <code class="_label">bgcp</code> brings up <code class="_label">background-clip</code>.<br>
@ -42,7 +44,7 @@ app.templates.helpPage = """
<a href="https://support.mozilla.org/en-US/kb/how-search-from-address-bar">these instructions</a>.
</dl>
<h2 class="_lined-heading" id="shortcuts">Keyboard Shortcuts</h2>
<h2 class="_block-heading" id="shortcuts">Keyboard Shortcuts</h2>
<h3 class="_shortcuts-title">Selection</h3>
<dl class="_shortcuts-dl">
<dt class="_shortcuts-dt">
@ -110,7 +112,7 @@ app.templates.helpPage = """
<strong>Tip:</strong> If the cursor is no longer in the search field, press <code class="_label">/</code> or
continue to type and it will refocus the search field and start showing new results.
<h2 class="_lined-heading" id="abbreviations">Abbreviations</h2>
<h2 class="_block-heading" id="abbreviations">Abbreviations</h2>
<p>Feel free to suggest new abbreviations on <a href="https://github.com/Thibaut/devdocs/issues/new">GitHub</a>.
<table class="_abbreviations">
<tr>

@ -15,7 +15,7 @@ app.templates.newsList = (news, options = {}) ->
date = new Date(value[0])
if options.years isnt false and year isnt date.getUTCFullYear()
year = date.getUTCFullYear()
result += "<h4>#{year}</h4>"
result += """<h2 class="_block-heading">#{year}</h2>"""
result += newsItem(date, value[1..])
result

@ -21,7 +21,7 @@ app.templates.offlinePage = (docs) -> """
#{docs}
</table>
<p class="_note"><strong>Note:</strong> your browser may delete DevDocs's offline data if your computer is running low on disk space and you haven't used the app in a while. Load this page before going offline to make sure the data is still there.
<h1 class="_lined-heading">Questions & Answers</h1>
<h2 class="_block-heading">Questions & Answers</h2>
<dl>
<dt>How does this work?
<dd>Each page is cached as a key-value pair in <a href="https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API">IndexedDB</a> (downloaded from a single file).<br>

@ -48,15 +48,6 @@ app.templates.intro = """
"""
<% end %>
app.templates.mobileNav = """
<nav class="_mobile-nav">
<a href="/offline" class="_mobile-nav-link">Offline</a>
<a href="/about" class="_mobile-nav-link">About</a>
<a href="/news" class="_mobile-nav-link">News</a>
<a href="/help" class="_mobile-nav-link">Help</a>
</nav>
"""
app.templates.mobileIntro = """
<div class="_mobile-intro">
<h2 class="_intro-title">Welcome!</h2>

@ -9,7 +9,6 @@ class app.views.RootPage extends app.View
render: ->
@empty()
@append @tmpl('mobileNav') if app.isMobile()
if app.isAndroidWebview()
@append @tmpl('androidWarning')
else

@ -1,6 +1,6 @@
class app.views.Document extends app.View
MAX_WIDTH_CLASS = '_max-width'
HIDE_SIDEBAR_CLASS = '_sidebar-hidden'
MAX_WIDTH_LAYOUT = '_max-width'
SIDEBAR_HIDDEN_LAYOUT = '_sidebar-hidden'
@el: document
@ -14,16 +14,12 @@ class app.views.Document extends app.View
superRight: 'onForward'
init: ->
@addSubview @nav = new app.views.Nav,
@addSubview @menu = new app.views.Menu,
@addSubview @sidebar = new app.views.Sidebar
@addSubview @resizer = new app.views.Resizer if app.views.Resizer.isSupported()
@addSubview @content = new app.views.Content
@addSubview @path = new app.views.Path unless app.isSingleDoc() or app.isMobile()
@sidebar.search
.on 'searching', @onSearching
.on 'clear', @onSearchClear
$.on document.body, 'click', @onClick
@activate()
@ -39,41 +35,19 @@ class app.views.Document extends app.View
return
toggleLayout: ->
wantsMaxWidth = !app.el.classList.contains(MAX_WIDTH_CLASS)
app.el.classList[if wantsMaxWidth then 'add' else 'remove'](MAX_WIDTH_CLASS)
app.settings.setLayout(MAX_WIDTH_CLASS, wantsMaxWidth)
wantsMaxWidth = !app.el.classList.contains(MAX_WIDTH_LAYOUT)
app.el.classList[if wantsMaxWidth then 'add' else 'remove'](MAX_WIDTH_LAYOUT)
app.settings.setLayout(MAX_WIDTH_LAYOUT, wantsMaxWidth)
app.appCache?.updateInBackground()
return
showSidebar: (options = {}) ->
@toggleSidebar(options, true)
return
hideSidebar: (options = {}) ->
@toggleSidebar(options, false)
return
toggleSidebar: (options = {}, shouldShow) ->
shouldShow ?= if options.save then !@hasSidebar() else app.el.classList.contains(HIDE_SIDEBAR_CLASS)
app.el.classList[if shouldShow then 'remove' else 'add'](HIDE_SIDEBAR_CLASS)
if options.save
app.settings.setLayout(HIDE_SIDEBAR_CLASS, !shouldShow)
toggleSidebarLayout: ->
shouldHide = !app.settings.hasLayout(SIDEBAR_HIDDEN_LAYOUT)
app.el.classList[if shouldHide then 'add' else 'remove'](SIDEBAR_HIDDEN_LAYOUT)
app.settings.setLayout(SIDEBAR_HIDDEN_LAYOUT, shouldHide)
app.appCache?.updateInBackground()
return
hasSidebar: ->
!app.settings.hasLayout(HIDE_SIDEBAR_CLASS)
onSearching: =>
unless @hasSidebar()
@showSidebar()
return
onSearchClear: =>
unless @hasSidebar()
@hideSidebar()
return
setTitle: (title) ->
@el.title = if title then "DevDocs — #{title}" else 'DevDocs API Documentation'

@ -0,0 +1,24 @@
class app.views.Menu extends app.View
@el: '._menu'
@activeClass: 'active'
@events:
click: 'onClick'
init: ->
$.on document.body, 'click', @onGlobalClick
return
onClick: =>
prev = @el.previousElementSibling
$.remove @el
$.requestAnimationFrame => $.after(prev, @el)
return
onGlobalClick: (event) =>
return if event.which isnt 1
if event.target.hasAttribute?('data-toggle-menu')
@toggleClass @constructor.activeClass
else if @hasClass @constructor.activeClass
@removeClass @constructor.activeClass
return

@ -35,44 +35,48 @@ class app.views.Mobile extends app.View
FastClick.attach @body
$.on @body, 'click', @onClick
$.on $('._home-btn'), 'click', @onClickHome
$.on $('._menu-btn'), 'click', @onClickMenu
$.on $('._search'), 'touchend', @onTapSearch
@back = $('._back-btn')
@toggleSidebar = $('button[data-toggle-sidebar]')
@toggleSidebar.removeAttribute('hidden')
$.on @toggleSidebar, 'click', @onClickToggleSidebar
@back = $('button[data-back]')
@back.removeAttribute('hidden')
$.on @back, 'click', @onClickBack
@forward = $('._forward-btn')
@forward = $('button[data-forward]')
@forward.removeAttribute('hidden')
$.on @forward, 'click', @onClickForward
app.document.sidebar.search
.on 'searching', @showSidebar
.on 'clear', @hideSidebar
@activate()
return
showSidebar: =>
if @isSidebarShown()
@body.scrollTop = 0
window.scrollTo 0, 0
return
@contentTop = @body.scrollTop
@contentTop = window.scrollY
@content.style.display = 'none'
@sidebar.style.display = 'block'
if selection = @findByClass app.views.ListSelect.activeClass
$.scrollTo selection, @body, 'center'
scrollContainer = if window.scrollY is @body.scrollTop then @body else document.documentElement
$.scrollTo selection, scrollContainer, 'center'
else
@body.scrollTop = @findByClass(app.views.ListFold.activeClass) and @sidebarTop or 0
window.scrollTo 0, @findByClass(app.views.ListFold.activeClass) and @sidebarTop or 0
return
hideSidebar: =>
return unless @isSidebarShown()
@sidebarTop = @body.scrollTop
@sidebarTop = window.scrollY
@sidebar.style.display = 'none'
@content.style.display = 'block'
@body.scrollTop = @contentTop or 0
window.scrollTo 0, @contentTop or 0
return
isSidebarShown: ->
@ -89,17 +93,12 @@ class app.views.Mobile extends app.View
onClickForward: =>
history.forward()
onClickHome: =>
app.shortcuts.trigger 'escape'
@hideSidebar()
return
onClickMenu: =>
onClickToggleSidebar: =>
if @isSidebarShown() then @hideSidebar() else @showSidebar()
return
onTapSearch: =>
@body.scrollTop = 0
window.scrollTo 0, 0
afterRoute: =>
@hideSidebar()

@ -1,26 +0,0 @@
class app.views.Nav extends app.View
@el: '._nav'
@activeClass: '_nav-current'
@routes:
after: 'afterRoute'
select: (href) ->
@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
afterRoute: (route, context) =>
if route in ['page', 'offline']
@select context.pathname
else
@deselect()

@ -35,7 +35,7 @@ class app.views.Resizer extends app.View
return
onClick: ->
app.document.toggleSidebar(save: true)
app.document.toggleSidebarLayout()
return
onDragStart: (event) =>

@ -14,7 +14,7 @@ class app.views.ListFocus extends app.View
constructor: (@el) ->
super
@focus = $.framify(@focus, @)
@focusOnNextFrame = $.framify(@focus, @)
focus: (el) ->
if el and not el.classList.contains @constructor.activeClass
@ -87,22 +87,22 @@ class app.views.ListFocus extends app.View
onDown: =>
if cursor = @getCursor()
@focus @findNext(cursor)
@focusOnNextFrame @findNext(cursor)
else
@focus @findByTag('a')
@focusOnNextFrame @findByTag('a')
return
onUp: =>
if cursor = @getCursor()
@focus @findPrev(cursor)
@focusOnNextFrame @findPrev(cursor)
else
@focus @findLastByTag('a')
@focusOnNextFrame @findLastByTag('a')
return
onLeft: =>
cursor = @getCursor()
if cursor and not cursor.classList.contains(app.views.ListFold.activeClass) and cursor.parentElement isnt @el
@focus cursor.parentElement.previousSibling
@focusOnNextFrame cursor.parentElement.previousSibling
return
onEnter: =>

@ -18,7 +18,6 @@ class app.views.Notice extends app.View
return
show: ->
@addClass '_top' if @type is 'disabledDoc'
@html @tmpl("#{@type}Notice", @args...)
@prependTo $('._app')
return

@ -130,7 +130,7 @@ class app.views.Search extends app.View
if event.target is @resetLink
$.stopEvent(event)
@reset()
@focus()
app.document.onEscape()
return
onSubmit: (event) ->

@ -148,7 +148,7 @@ class app.views.DocList extends app.View
return
scrollTo: (model) ->
$.scrollTo @find("a[href='#{model.fullPath()}']"), null, 'top', margin: 0
$.scrollTo @find("a[href='#{model.fullPath()}']"), null, 'top', margin: if app.isMobile() then 48 else 0
return
toggleDisabled: ->

@ -15,8 +15,8 @@ class app.views.Results extends app.View
return
init: ->
@addSubview @listSelect = new app.views.ListSelect @el
@addSubview @listFocus = new app.views.ListFocus @el unless app.isMobile()
@addSubview @listSelect = new app.views.ListSelect @el
@search
.on 'results', @onResults
@ -42,7 +42,7 @@ class app.views.Results extends app.View
return
focusFirst: ->
@listFocus?.focus @el.firstElementChild
@listFocus?.focusOnNextFrame @el.firstElementChild
return
openFirst: ->

@ -3,6 +3,7 @@ class app.views.Sidebar extends app.View
@events:
focus: 'onFocus'
select: 'onSelect'
click: 'onClick'
@shortcuts:
@ -14,8 +15,8 @@ class app.views.Sidebar extends app.View
@addSubview @search = new app.views.Search
@search
.on 'searching', @showResults
.on 'clear', @showDocList
.on 'searching', @onSearching
.on 'clear', @onSearchClear
.scope
.on 'change', @onScopeChange
@ -27,7 +28,15 @@ class app.views.Sidebar extends app.View
$.on document, 'click', @onGlobalClick if @docPicker
return
show: (view) ->
display: ->
@el.style.display = 'block'
return
resetDisplay: ->
@el.style.display = '' unless @el.style.display is 'none'
return
showView: (view) ->
unless @view is view
@hover?.hide()
@saveScrollPosition()
@ -44,28 +53,29 @@ class app.views.Sidebar extends app.View
@append @tmpl('sidebarSettings') if @view is @docList and @docPicker
return
showDocList: (reset) =>
@show @docList
if reset is true
@docList.reset(revealCurrent: true)
@search.reset()
showDocList: ->
@showView @docList
return
showDocPicker: =>
@show @docPicker
@showView @docPicker
return
showResults: =>
@show @results
@showView @results
return
reset: ->
@display()
@showDocList()
@docList.reset()
@search.reset()
return
onReady: =>
@view = @docList
@render()
@view.activate()
reset: ->
@showDocList true
return
onScopeChange: (newDoc, previousDoc) =>
@ -90,15 +100,30 @@ class app.views.Sidebar extends app.View
@el.scrollTop = 0
return
onSearching: =>
@display()
@showResults()
return
onSearchClear: =>
@resetDisplay()
@showDocList()
return
onFocus: (event) =>
@display()
$.scrollTo event.target, @el, 'continuous', bottomGap: 2 unless event.target is @el
return
onSelect: =>
@resetDisplay()
return
onClick: (event) =>
return if event.which isnt 1
if event.target.hasAttribute? 'data-reset-list'
$.stopEvent(event)
@reset()
@onAltR()
else if event.target.hasAttribute? 'data-light'
$.stopEvent(event)
document.activeElement?.blur()
@ -120,6 +145,8 @@ class app.views.Sidebar extends app.View
onAltR: =>
@reset()
@docList.reset(revealCurrent: true)
@display()
return
onEscape: =>

@ -35,6 +35,13 @@ class app.View
@el.classList.remove(name)
return
toggleClass: (name) ->
@el.classList.toggle(name)
return
hasClass: (name) ->
@el.classList.contains(name)
resetClass: ->
@el.className = @originalClassName or ''
if @constructor.className

@ -2,7 +2,6 @@
position: relative;
z-index: 1;
height: 100%;
padding-top: $headerHeight;
overflow: hidden;
background: $contentBackground;
-webkit-transition: opacity .2s;
@ -31,7 +30,7 @@
left: 0;
right: 0;
line-height: 1;
margin-top: -.75em;
margin-top: -.6em;
font-size: 4rem;
font-weight: 300;
letter-spacing: -.125rem;

@ -20,18 +20,24 @@
height: 100%;
overflow-y: scroll;
margin-left: .875rem;
padding: 1.25rem 1.5rem 0;
padding: 1.125rem 1.5rem 0;
font-size: .875rem;
pointer-events: auto;
-webkit-overflow-scrolling: touch;
@extend %border-box;
-webkit-padding-start: .75rem;
-webkit-padding-end: 1rem;
-webkit-padding-start: .625rem;
-webkit-padding-end: .75rem;
@media (-moz-overlay-scrollbars) { padding-left: .75rem; }
@media (-moz-overlay-scrollbars) { padding-left: .625rem; }
@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) { margin-left: 0; }
._sidebar-hidden &:before {
content: '';
display: block;
margin-top: $headerHeight;
}
&:after { // padding bottom
content: '';
display: block;
@ -77,15 +83,22 @@
// Intro
//
._intro { text-align: center; }
._intro {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
min-height: calc(100vh - 2.375rem);
._sidebar-hidden & {
min-height: calc(100vh - 2.375rem - #{$headerHeight});
}
}
._intro-message {
position: relative;
display: inline-block;
vertical-align: top;
max-width: 37rem;
margin: .5rem 0;
padding: 1rem 1.25rem;
text-align: left;
@extend %note, %note-green;
}
@ -146,23 +159,25 @@
._lined-heading,
%lined-heading {
white-space: nowrap;
overflow: hidden;
word-wrap: normal;
overflow-wrap: normal;
display: flex;
justify-content: center;
align-items: center;
&:after {
content: '';
display: inline-block;
vertical-align: middle;
width: 100%;
flex-grow: 1;
height: 1px;
line-height: 0;
margin-top: .25rem;
margin-left: 1rem;
background: $boxBorderLight;
}
}
._block-heading { @extend %block-heading; }
._heading-links {
float: right;
font-weight: normal;

@ -7,79 +7,131 @@
z-index: $headerZ;
top: 0;
left: 0;
right: 0;
display: flex;
width: $sidebarWidth;
height: $headerHeight;
line-height: $headerHeight;
background: $headerBackground;
border-bottom: 1px solid $headerBorder;
@extend %user-select-none;
@media #{$mediumScreen} { width: $sidebarMediumWidth; }
}
//
// Navigation menu
//
._header-left {
float: left;
height: 100%;
}
._nav {
._header-right {
float: right;
margin-right: .5rem;
font-size: .875rem;
color: $textColor;
height: 100%;
}
._nav-link,
._nav-link:hover {
._header-btn {
position: relative;
float: left;
padding: 0 1.25rem;
color: inherit;
text-decoration: none;
width: 2.25rem;
height: 100%;
color: $textColorLight;
text-align: center;
@media #{$mediumScreen} { padding: 0 .75rem; }
}
&[hidden] { display: none; }
._nav-link {
&:before, &:after {
position: absolute;
left: 50%;
bottom: 0;
width: 0;
height: 0;
margin-left: -.375rem;
border: .375rem solid transparent;
border-bottom-color: darken($headerBorder, 2%);
&[disabled] {
opacity: .3;
cursor: not-allowed;
}
&:after {
bottom: -1px;
border-bottom-color: $contentBackground;
> svg {
display: inline-block;
vertical-align: top;
width: 1.5rem;
height: 1.5rem;
fill: currentColor;
pointer-events: none;
}
}
._nav-current {
outline: 0;
//
// Menu
//
&:before, &:after { content: ''; }
._menu-btn {
border-right: 1px solid $headerBorder;
}
//
// Logo
//
._menu {
position: absolute;
z-index: 1;
top: .25rem;
right: .25rem;
width: 8rem;
height: calc(11.5rem + 1px);
font-size: .875rem;
background: $contentBackground;
border: 1px solid $headerBorder;
border-radius: 3px;
box-shadow: -1px 1px 1px rgba(black, .05);
transition: all 250ms cubic-bezier(0.23, 1, 0.32, 1);
opacity: 0;
-webkit-transform: scale(0, 0);
transform: scale(0, 0);
-webkit-transform-origin: 100% 0;
transform-origin: 100% 0;
._logo {
position: relative;
float: left;
height: $headerHeight;
&:hover,
._menu-btn:hover + & {
transition-delay: 100ms;
}
&:hover,
&.active,
._menu-btn:hover + &,
._menu-btn:focus + & {
opacity: 1;
-webkit-transform: scale(1, 1);
transform: scale(1, 1);
}
&:focus-within {
opacity: 1;
-webkit-transform: scale(1, 1);
transform: scale(1, 1);
}
}
._menu-title {
margin: 0;
line-height: inherit;
font-size: inherit;
line-height: 1.5rem;
font-size: 1rem;
font-weight: $boldFontWeight;
cursor: default;
letter-spacing: -.5px;
background: $sidebarBackground;
border-bottom: 1px solid $sidebarBorder;
border-radius: 2px 2px 0 0;
}
> ._nav-link {
float: none;
margin-left: .75rem;
padding: 0 .25rem;
._menu-title-link,
._menu-title-link:hover {
display: block;
padding: .5rem 1rem;
color: $focusText;
text-decoration: none;
}
._menu-link {
display: block;
padding: 0 1rem;
line-height: 2.25rem;
color: inherit;
text-decoration: none;
&:hover {
color: $focusText;
text-decoration: none;
background: $sidebarBackground;
}
&:last-child { border-radius: 0 0 2px 2px; }
}
//
@ -87,20 +139,19 @@
//
._search {
flex-grow: 1;
position: relative;
float: left;
width: $sidebarWidth;
height: 100%;
padding: .5rem 0 .5rem .5rem;
@extend %border-box;
@media #{$mediumScreen} { width: $sidebarMediumWidth; }
&:before {
position: absolute;
z-index: 1;
top: 1rem;
left: 1rem;
opacity: .4;
pointer-events: none;
@if $style == 'dark' {
@extend %icon, %icon-search-white;
} @else {
@ -110,6 +161,7 @@
}
._search-input {
position: relative;
display: block;
width: 100%;
height: 100%;
@ -164,6 +216,7 @@
._search-tag {
display: none;
position: absolute;
z-index: 2;
top: .875rem;
left: .875rem;
padding: 0 .5rem;

@ -10,18 +10,17 @@
body { -ms-overflow-style: -ms-autohiding-scrollbar; }
._app, ._container, ._content { overflow: visible; }
._container {
margin: 0;
border: 0;
}
._app, ._content { overflow: visible; }
._app { padding-top: $headerHeight; }
._container { margin: 0; }
._content {
position: static;
height: auto;
margin: 0;
padding: .75rem 1rem 2.5rem;
&:before { content: none; }
}
._booting:before, ._content-loading:before { font-size: 3rem; }
@ -33,16 +32,13 @@
max-width: 100vw;
}
._logo, ._nav { display: none; }
._mobile-btn { display: block; }
._header-btn { width: 2.5rem; }
._header-btn[hidden] { display: block; }
._menu-btn { border-right: 0; }
._search {
float: none;
width: auto;
overflow: hidden;
padding-left: 2px;
padding-right: 2px;
border-right: 0;
padding-right: .125rem;
padding-left: .125rem;
&:before { left: .5rem; }
}
@ -57,7 +53,7 @@
overflow: visible;
}
._list, ._sidebar-footer { width: 100%; }
._header, ._list, ._sidebar-footer { width: 100%; }
._list-item {
white-space: normal;
@ -85,33 +81,12 @@
box-shadow: 0 1px $noteGreenBorder, 0 -1px $noteGreenBorder;
}
// Splash
._splash-sponsors { margin-top: 1rem; }
._splash-sponsor {
position: static;
._logo-info {
left: 1rem;
right: 1rem;
width: auto;
max-width: none;
margin: 0;
}
}
// Notice
._notice {
position: fixed;
left: 0;
padding: 0 .5rem;
~ ._sidebar {
margin-top: 2.5rem;
padding-bottom: 4rem;
}
}
._notice-text { font-size: .75em; }
@ -143,76 +118,10 @@
// Header buttons
//
._mobile-btn {
display: none;
position: relative;
float: left;
width: 2.5rem;
height: 100%;
@extend %hide-text;
&[disabled] {
opacity: .3;
cursor: not-allowed;
}
&:before {
position: absolute;
top: 50%;
left: 50%;
margin: -.5rem 0 0 -.5rem;
@extend %icon;
}
}
._back-btn {
&:before { @extend %icon-back; }
}
._forward-btn {
width: 2.25rem;
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
&:before {
margin-left: -.375rem;
@extend %icon-back;
}
}
._home-btn {
float: right;
width: 2rem;
&:before {
margin-left: -.375rem;
@extend %icon-home;
}
}
._menu-btn {
float: right;
margin-right: -.5rem;
&:before { @extend %icon-menu; }
}
//
// Navigation menu
//
._mobile-nav {
margin: .25rem 0 1.25rem;
padding: 0;
line-height: 2.8;
overflow: hidden;
@extend %box;
}
._mobile-nav-link {
float: left;
width: 25%;
text-align: center;
font-weight: $boldFontWeight;
> svg { margin-left: -.375rem; }
}
//
@ -222,14 +131,11 @@
._mobile-intro {
> ._intro-list { padding-left: 1.5rem; }
> ._intro-hide,
> ._intro-sponsors {
._intro-hide {
position: static;
float: none;
display: block;
margin-top: .75rem;
text-align: center;
}
._intro-sponsor { margin: .5em .75em; }
}

@ -12,17 +12,7 @@
@media #{$mediumScreen} { left: $sidebarMediumWidth; }
._sidebar-hidden & { left: $sidebarHiddenWidth; }
&:not(._top) ~ ._container { padding-bottom: 2.5rem; }
&._top {
bottom: auto;
top: $headerHeight;
margin-top: 1px;
box-shadow: inset 0 -1px $noticeBorder;
~ ._container { padding-top: 2.5rem; }
}
~ ._container { padding-bottom: 2.5rem; }
}
._notice-text {

@ -40,7 +40,7 @@
._resizer {
position: absolute;
z-index: $sidebarZ + 1;
z-index: $sidebarZ;
top: $headerHeight;
bottom: 0;
left: $sidebarWidth;

@ -37,8 +37,6 @@
%icon-clear { background-position: -3rem 0; }
%icon-settings { background-position: 0 -1rem; }
%icon-check { background-position: -1rem -1rem; }
%icon-menu { background-position: -2rem -1rem; @extend %darkIconFix !optional; }
%icon-home { background-position: -3rem -1rem; @extend %darkIconFix !optional; }
%icon-path { background-position: 0 -2rem; }
%icon-search-white { background-position: -1rem -2rem; }
%icon-dir-white { background-position: -2rem -2rem; }
@ -54,7 +52,6 @@
%icon-clipboard { background-position: 0 -5rem; }
%icon-clipboard-white { background-position: -1rem -5rem; }
%icon-close-white { background-position: -2rem -5rem; }
%icon-back { background-position: -3rem -5rem; @extend %darkIconFix !optional; }
._icon-codeceptjs:before { background-position: -3rem 0; }
._icon-codeception:before { background-position: -4rem 0; }

@ -7,7 +7,7 @@ $style: 'dark';
$maxWidth: 80rem;
$headerHeight: 3rem;
$sidebarWidth: 18rem;
$sidebarWidth: 20rem;
$sidebarMediumWidth: 16rem;
$sidebarHiddenWidth: 9px;
@ -37,7 +37,7 @@ $linkColor: $textColor;
$linkColorHover: white;
$linkTextDecoration: underline;
$headerBackground: #1e1e1e;
$headerBackground: #1c1c1c;
$headerBorder: #000;
$sidebarBackground: #24282a;

@ -7,7 +7,7 @@ $style: 'light';
$maxWidth: 80rem;
$headerHeight: 3rem;
$sidebarWidth: 18rem;
$sidebarWidth: 20rem;
$sidebarMediumWidth: 16rem;
$sidebarHiddenWidth: 9px;
@ -37,11 +37,11 @@ $linkColor: #3377c0;
$linkColorHover: #2f6cb6;
$linkTextDecoration: none;
$headerBackground: #f0f0f0;
$headerBorder: #d9d9d9;
$headerBackground: #eee;
$headerBorder: #d7d7d7;
$sidebarBackground: #f9f9f9;
$sidebarBorder: #e3e3e3;
$sidebarBorder: #e1e1e1;
$scrollbarColor: #d2d2d2;
$scrollbarColorHover: #aaa;

@ -184,7 +184,7 @@ class App < Sinatra::Application
end
def app_size
@app_size ||= cookies[:size].nil? ? '18rem' : "#{cookies[:size]}px"
@app_size ||= cookies[:size].nil? ? '20rem' : "#{cookies[:size]}px"
end
def app_layout

Binary file not shown.

Before

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 267 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 343 B

@ -1 +0,0 @@
http://www.entypo.com/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 B

@ -31,7 +31,7 @@ class AppTest < MiniTest::Spec
it "sets default size" do
get '/'
assert_includes last_response.body, 'data-size="18rem"'
assert_includes last_response.body, 'data-size="20rem"'
end
it "sets size from cookie" do
@ -115,7 +115,7 @@ class AppTest < MiniTest::Spec
it "sets default size" do
get '/manifest.appcache'
assert_includes last_response.body, '18rem'
assert_includes last_response.body, '20rem'
end
it "sets size from cookie" do

@ -1,22 +1,28 @@
<div class="_app<%= " #{app_layout}" if app_layout %>" role="application">
<header class="_header" role="banner">
<button type="button" class="_mobile-btn _back-btn">Back</button>
<button type="button" class="_mobile-btn _forward-btn">Forward</button>
<button type="button" class="_mobile-btn _menu-btn">Menu</button>
<button type="button" class="_mobile-btn _home-btn">Home</button>
<button type="button" aria-label="Toggle navigation" class="_header-btn" data-toggle-sidebar hidden>
<svg viewBox="0 0 24 24"><path d="M3 18h18v-2H3v2zm0-5h18v-2H3v2zm0-7v2h18V6H3z"></path></svg>
</button>
<form class="_search" role="search">
<input type="search" name="q" class="_search-input" placeholder="Search&hellip;" autocomplete="off" autocapitalize="off" autocorrect="off" spellcheck="false" maxlength="30" aria-label="Search">
<button type="reset" class="_search-clear" title="Clear search">Clear search</button>
<div class="_search-tag"></div>
</form>
<h1 class="_logo">
<a href="/" class="_nav-link" title="Offline API Documentation Browser">DevDocs</a><%= "/ #{@doc['full_name']}" if @doc %>
</h1>
<nav class="_nav" role="navigation">
<a href="/offline" class="_nav-link">Offline</a>
<a href="/about" class="_nav-link">About</a>
<a href="/news" class="_nav-link">News</a>
<a href="/help" class="_nav-link">Tips</a>
<button type="button" aria-label="Back" class="_header-btn" data-back hidden>
<svg viewBox="0 0 24 24"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></svg>
</button>
<button type="button" aria-label="Forward" class="_header-btn _forward-btn" data-forward hidden>
<svg viewBox="0 0 24 24"><path d="M12 4l-1.41 1.41L16.17 11H4v2h12.17l-5.58 5.59L12 20l8-8z"></svg>
</button>
<button type="button" aria-label="Toggle menu" title="Toggle menu" class="_header-btn _menu-btn" data-toggle-menu>
<svg viewBox="0 0 24 24"><path d="M12 8c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm0 2c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"></path></svg>
</button>
<nav class="_menu" role="navigation">
<h1 class="_menu-title"><a href="/" class="_menu-title-link">DevDocs</a></h1>
<a href="/offline" class="_menu-link">Offline</a>
<a href="/news" class="_menu-link">Changelog</a>
<a href="/help" class="_menu-link">Help</a>
<a href="/about" class="_menu-link">About</a>
</nav>
</header>
<section class="_sidebar" tabindex="-1">
@ -34,7 +40,7 @@
</div>
<style data-size="<%= app_size %>" data-resizer>
._container { margin-left: <%= app_size %>; }
._search, ._list, ._sidebar-footer { width: <%= app_size %>; }
._header, ._list, ._sidebar-footer { width: <%= app_size %>; }
._list-hover.clone { min-width: <%= app_size %>; }
._notice, ._path, ._resizer { left: <%= app_size %>; }
</style>

Loading…
Cancel
Save