Skip to content
Draft
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
13 changes: 13 additions & 0 deletions lib/rdoc/generator/template/aliki/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,19 @@ One search form and one result list serve both header layouts. CSS changes the p
| Type badge (`.search-type-*`) | inline-block, `space-0 space-2` pad, `xs`, weight 500, `radius-sm`, colors per §2 |
| Matched term (`li em`) | `search-highlight-bg`, `font-style: normal` |

The desktop field has a `/` keycap and an adjacent **Search shortcuts** button
with a keyboard icon. On compact screens, the keycap and adjacent button are
hidden. The same help is available below the search results, outside their
scroll area.

The help uses one native dialog: a 376 px panel below the desktop button and a
compact sheet aligned with the search surface. Pressing `?` outside an input,
text area, select, or editable content opens help. It lists this shortcut and
the existing `/`, arrow, `Enter`, and `Esc` actions, grouped by context. Close and Escape dismiss
help and restore the previous focus without clearing the search. Pressing `/`
in help closes the dialog and focuses the search field. Colors, keycaps,
borders, and focus indicators use the shared light and dark tokens.

### Right TOC (`#table-of-contents`)

| Property | Value |
Expand Down
18 changes: 17 additions & 1 deletion lib/rdoc/generator/template/aliki/_header.rhtml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@
<span class="search-icon" aria-hidden="true">🔍</span>
<input id="search-field" role="combobox" aria-label="Search"
aria-autocomplete="list" aria-controls="search-results"
type="text" name="search" placeholder="Search (/) for a class, method..."
type="text" name="search" placeholder="Search documentation…"
spellcheck="false" autocomplete="off"
title="Type to search, Up and Down to navigate, Enter to load">
<kbd class="search-shortcut-hint" aria-hidden="true">/</kbd>
<button type="button" class="search-close" aria-label="Close search" data-search-close>
<span aria-hidden="true">esc</span>
</button>
Expand All @@ -31,7 +32,22 @@
<p>No recent searches</p>
</div>
</div>
<div class="search-shortcuts-footer">
<button type="button" class="search-shortcuts-toggle" data-search-shortcuts
aria-haspopup="dialog" aria-controls="search-shortcuts" aria-expanded="false">
<svg aria-hidden="true"><use href="#icon-keyboard"></use></svg>
Search shortcuts
</button>
</div>
</div>

<button type="button" class="search-shortcuts-toggle search-shortcuts-desktop" data-search-shortcuts
aria-haspopup="dialog" aria-controls="search-shortcuts" aria-expanded="false">
<svg aria-hidden="true"><use href="#icon-keyboard"></use></svg>
Search shortcuts
</button>

<%= render '_search_shortcuts.rhtml' %>
</div>

<!-- Theme toggle button -->
Expand Down
6 changes: 6 additions & 0 deletions lib/rdoc/generator/template/aliki/_icons.rhtml
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="icon-keyboard" viewBox="0 0 20 14" fill="none" stroke="currentColor"
stroke-width="1.3" stroke-linecap="round">
<rect x="0.75" y="0.75" width="18.5" height="12.5" rx="2"></rect>
<path d="M4 4h1m3 0h1m3 0h1M4 7h1m3 0h1m3 0h1M6 10h8"></path>
</symbol>

<!-- Chevron (right arrow) - used for expand/collapse -->
<symbol
id="icon-chevron"
Expand Down
31 changes: 31 additions & 0 deletions lib/rdoc/generator/template/aliki/_search_shortcuts.rhtml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<dialog id="search-shortcuts" class="search-shortcuts" aria-labelledby="search-shortcuts-title">
<div class="search-shortcuts-heading">
<h2 id="search-shortcuts-title">Search shortcuts</h2>
<button type="button" class="search-shortcuts-close" autofocus>Close</button>
</div>
<p class="search-shortcuts-intro">A few keys to find your way around.</p>

<div class="search-shortcuts-group">
<h3>When you are not typing in an input</h3>
<dl>
<div><dt>Focus search</dt><dd><kbd>/</kbd></dd></div>
<div><dt>Open search shortcuts</dt><dd><kbd>?</kbd></dd></div>
</dl>
</div>
<div class="search-shortcuts-group">
<h3>When results are shown</h3>
<dl>
<div>
<dt>Move through results</dt>
<dd><kbd aria-label="Up arrow">↑</kbd> <kbd aria-label="Down arrow">↓</kbd></dd>
</div>
<div><dt>Open selected result</dt><dd><kbd>Enter</kbd></dd></div>
</dl>
</div>
<div class="search-shortcuts-group">
<h3>While search is open</h3>
<dl>
<div><dt>Close search</dt><dd><kbd>Esc</kbd></dd></div>
</dl>
</div>
</dialog>
200 changes: 199 additions & 1 deletion lib/rdoc/generator/template/aliki/css/rdoc.css
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,9 @@ header.top-navbar .navbar-brand:hover {
}

header.top-navbar .navbar-search {
display: flex;
align-items: center;
gap: var(--space-3);
grid-column: 2;
justify-self: center;
box-sizing: border-box;
Expand All @@ -485,6 +488,8 @@ header.top-navbar .navbar-search {

header.top-navbar .search-surface {
position: relative;
flex: 0 1 var(--layout-search-width);
min-width: 0;
width: min(100%, var(--layout-search-width));
margin: 0;
}
Expand Down Expand Up @@ -1991,7 +1996,8 @@ header.top-navbar #search-field {
display: block;
box-sizing: border-box;
width: 100%;
padding: var(--space-2) var(--space-4);
min-height: 2.625rem;
padding: var(--space-2) var(--space-12) var(--space-2) var(--space-4);
border: 1px solid var(--color-border-default);
border-radius: var(--radius-md);
font-size: var(--font-size-base);
Expand Down Expand Up @@ -2036,7 +2042,193 @@ header.top-navbar #search-results[aria-expanded="false"] {
display: none;
}

/* Search shortcut hint and help */
.search-shortcuts kbd,
.search-shortcut-hint {
display: inline-flex;
align-items: center;
justify-content: center;
box-sizing: border-box;
min-width: var(--space-6);
height: var(--space-6);
padding: 0 var(--space-1);
border: 1px solid var(--color-border-default);
border-bottom-width: 2px;
border-radius: var(--radius-sm);
background: var(--color-background-secondary);
color: var(--color-text-secondary);
font: var(--font-size-xs) / 1 var(--font-family-mono);
}

.search-shortcut-hint {
position: absolute;
top: 50%;
right: var(--space-3);
transform: translateY(-50%);
pointer-events: none;
}

.search-shortcuts-toggle,
.search-shortcuts-close {
display: inline-flex;
flex-shrink: 0;
align-items: center;
justify-content: center;
gap: var(--space-2);
padding: var(--space-2);
border: 1px solid var(--color-border-subtle);
border-radius: var(--radius-md);
background: var(--color-background-secondary);
color: var(--color-text-secondary);
font: inherit;
font-size: var(--font-size-sm);
cursor: pointer;
}

.search-shortcuts-toggle {
min-height: 2.625rem;
white-space: nowrap;
}

.search-shortcuts-toggle svg {
width: 1.125rem;
height: var(--space-4);
}

.search-shortcuts-toggle:hover,
.search-shortcuts-close:hover {
border-color: var(--color-border-default);
color: var(--color-text-primary);
}

.search-shortcuts-toggle:focus-visible,
.search-shortcuts-close:focus-visible {
outline: 2px solid var(--color-accent-primary);
outline-offset: 2px;
}

.search-shortcuts-toggle[aria-expanded="true"] {
border-color: var(--color-border-default);
color: var(--color-text-primary);
}

.search-shortcuts-footer {
display: none;
}

.search-shortcuts {
--search-shortcuts-right: var(--space-4);

position: fixed;
inset: calc(var(--layout-header-height) + var(--space-2)) var(--search-shortcuts-right) auto auto;
box-sizing: border-box;
width: 23.5rem;
max-width: calc(100% - var(--space-6));
max-height: calc(100dvh - var(--layout-header-height) - var(--space-6));
margin: 0;
padding: var(--space-5);
overflow: auto;
border: 1px solid var(--color-border-default);
border-radius: var(--radius-lg);
background: var(--color-background-primary);
color: var(--color-text-primary);
box-shadow: var(--shadow-lg);
}

.search-shortcuts::backdrop {
background: transparent;
}

.search-shortcuts-heading {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-3);
}

.search-shortcuts-heading h2 {
margin: 0;
color: var(--color-text-primary);
font-size: var(--font-size-lg);
font-weight: var(--font-weight-semibold);
}

.search-shortcuts-intro {
margin: var(--space-2) 0 var(--space-4);
color: var(--color-text-secondary);
font-size: var(--font-size-sm);
}

.search-shortcuts-group + .search-shortcuts-group {
margin-top: var(--space-3);
padding-top: var(--space-3);
border-top: 1px solid var(--color-border-subtle);
}

.search-shortcuts-group h3 {
margin: 0;
color: var(--color-text-secondary);
font-size: var(--font-size-xs);
font-weight: var(--font-weight-medium);
}

.search-shortcuts-group dl {
margin: 0;
font-size: var(--font-size-sm);
}

.search-shortcuts-group dl > div {
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-4);
min-height: 2.75rem;
}

.search-shortcuts-group dd {
display: flex;
flex-shrink: 0;
gap: var(--space-1);
margin: 0;
}

@media (width <= 1023px) {
.search-shortcut-hint,
.search-shortcuts-desktop {
display: none;
}

.search-shortcuts-footer {
display: block;
flex-shrink: 0;
padding: var(--space-1) var(--space-3);
border-top: 1px solid var(--color-border-subtle);
background: var(--color-background-secondary);
}

.search-shortcuts-footer .search-shortcuts-toggle {
min-height: 2.75rem;
border-color: transparent;
background: transparent;
}

.search-shortcuts {
inset: var(--space-16) auto auto 50%;
width: calc(100% - var(--space-8));
max-width: 600px;
max-height: 80dvh;
transform: translateX(-50%);
}

.search-shortcuts::backdrop {
background: var(--color-overlay);
}

.search-shortcuts-close {
min-height: 2.75rem;
min-width: 2.75rem;
}

body:has(header.top-navbar .navbar-search.is-open) {
overflow: hidden;
}
Expand Down Expand Up @@ -2175,6 +2367,12 @@ header.top-navbar #search-results[aria-expanded="false"] {
}

@media (width <= 420px) {
.search-shortcuts {
top: var(--space-4);
width: calc(100% - var(--space-6));
padding: var(--space-4);
}

header.top-navbar .navbar-search.is-open .search-surface {
top: var(--space-4);
width: calc(100% - var(--space-6));
Expand Down
Loading