Add living styleguide endpoint and vanilla JS utilities
- New /styleguide endpoint with CSS Grid layout system, design tokens, and component library (buttons, forms, alerts, cards, tables, etc.) - custom.js replaces jQuery patterns with native DOM APIs - Pure CSS with custom properties, no preprocessors, no flexbox - Capability-driven presentation with progressive enhancement - Wire styleguide app into middleware includes - Update CLAUDE.md with UI modernization goals
This commit is contained in:
parent
4f73837822
commit
340e25aa71
7 changed files with 1979 additions and 0 deletions
772
rhodecode/templates/styleguide/index.mako
Normal file
772
rhodecode/templates/styleguide/index.mako
Normal file
|
|
@ -0,0 +1,772 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en" class="no-js">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Style Guide — RhodeCode</title>
|
||||
<link rel="stylesheet" href="${h.asset('css/styleguide.css')}">
|
||||
<noscript>
|
||||
<style>.js-only { display: none !important; }</style>
|
||||
</noscript>
|
||||
</head>
|
||||
<body class="sg-body">
|
||||
|
||||
<div class="sg-layout">
|
||||
|
||||
<!-- Header -->
|
||||
<header class="sg-header">
|
||||
<h1>RhodeCode Style Guide</h1>
|
||||
<span></span>
|
||||
<span class="sg-version">v${c.rhodecode_version}</span>
|
||||
</header>
|
||||
|
||||
<!-- Sidebar Navigation -->
|
||||
<aside class="sg-sidebar">
|
||||
<nav>
|
||||
<h3>Foundation</h3>
|
||||
<a href="#colors">Colors</a>
|
||||
<a href="#typography">Typography</a>
|
||||
<a href="#spacing">Spacing</a>
|
||||
<a href="#grid">CSS Grid Layout</a>
|
||||
|
||||
<h3>Components</h3>
|
||||
<a href="#buttons">Buttons</a>
|
||||
<a href="#forms">Forms</a>
|
||||
<a href="#alerts">Alerts</a>
|
||||
<a href="#cards">Cards</a>
|
||||
<a href="#tables">Tables</a>
|
||||
<a href="#badges">Badges</a>
|
||||
<a href="#details">Details / Accordion</a>
|
||||
<a href="#dialog">Dialog</a>
|
||||
|
||||
<h3>Patterns</h3>
|
||||
<a href="#navigation">Navigation Bar</a>
|
||||
<a href="#repo-list">Repository List</a>
|
||||
<a href="#diff">Diff View</a>
|
||||
<a href="#code">Code Blocks</a>
|
||||
|
||||
<h3>Principles</h3>
|
||||
<a href="#capability">Capability-Driven</a>
|
||||
</nav>
|
||||
</aside>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="sg-main">
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- COLORS -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="colors">
|
||||
<h2>Colors</h2>
|
||||
<p class="sg-desc">
|
||||
All colors are CSS custom properties defined on <code>:root</code>.
|
||||
No preprocessor variables. Change the token, change the world.
|
||||
</p>
|
||||
|
||||
<div class="sg-subsection">
|
||||
<h3>Core</h3>
|
||||
<div class="sg-colors">
|
||||
<div class="sg-swatch">
|
||||
<div class="sg-swatch-color" style="background: var(--bg)"></div>
|
||||
<div class="sg-swatch-info">
|
||||
<div class="sg-swatch-name">--bg</div>
|
||||
<div class="sg-swatch-value">#fafafa</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sg-swatch">
|
||||
<div class="sg-swatch-color" style="background: var(--surface)"></div>
|
||||
<div class="sg-swatch-info">
|
||||
<div class="sg-swatch-name">--surface</div>
|
||||
<div class="sg-swatch-value">#ffffff</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sg-swatch">
|
||||
<div class="sg-swatch-color" style="background: var(--text)"></div>
|
||||
<div class="sg-swatch-info">
|
||||
<div class="sg-swatch-name">--text</div>
|
||||
<div class="sg-swatch-value">#1a1a1a</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sg-swatch">
|
||||
<div class="sg-swatch-color" style="background: var(--text-muted)"></div>
|
||||
<div class="sg-swatch-info">
|
||||
<div class="sg-swatch-name">--text-muted</div>
|
||||
<div class="sg-swatch-value">#6b7280</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sg-swatch">
|
||||
<div class="sg-swatch-color" style="background: var(--border)"></div>
|
||||
<div class="sg-swatch-info">
|
||||
<div class="sg-swatch-name">--border</div>
|
||||
<div class="sg-swatch-value">#e0e0e0</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sg-swatch">
|
||||
<div class="sg-swatch-color" style="background: var(--accent)"></div>
|
||||
<div class="sg-swatch-info">
|
||||
<div class="sg-swatch-name">--accent</div>
|
||||
<div class="sg-swatch-value">#2563eb</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sg-subsection">
|
||||
<h3>Semantic</h3>
|
||||
<div class="sg-colors">
|
||||
<div class="sg-swatch">
|
||||
<div class="sg-swatch-color" style="background: var(--success)"></div>
|
||||
<div class="sg-swatch-info">
|
||||
<div class="sg-swatch-name">--success</div>
|
||||
<div class="sg-swatch-value">#059669</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sg-swatch">
|
||||
<div class="sg-swatch-color" style="background: var(--warning)"></div>
|
||||
<div class="sg-swatch-info">
|
||||
<div class="sg-swatch-name">--warning</div>
|
||||
<div class="sg-swatch-value">#d97706</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sg-swatch">
|
||||
<div class="sg-swatch-color" style="background: var(--danger)"></div>
|
||||
<div class="sg-swatch-info">
|
||||
<div class="sg-swatch-name">--danger</div>
|
||||
<div class="sg-swatch-value">#dc2626</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sg-swatch">
|
||||
<div class="sg-swatch-color" style="background: var(--info)"></div>
|
||||
<div class="sg-swatch-info">
|
||||
<div class="sg-swatch-name">--info</div>
|
||||
<div class="sg-swatch-value">#2563eb</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- TYPOGRAPHY -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="typography">
|
||||
<h2>Typography</h2>
|
||||
<p class="sg-desc">
|
||||
System font stack for sans-serif. Modern monospace stack for code.
|
||||
16px base. 1.6 line height. Maximum 65ch measure for body text.
|
||||
</p>
|
||||
|
||||
<div class="sg-showcase">
|
||||
<div class="sg-type-scale">
|
||||
<div class="sg-type-specimen">
|
||||
<span class="sg-type-label">2rem</span>
|
||||
<span style="font-size: 2rem; font-weight: 700; letter-spacing: -0.02em">Page Title</span>
|
||||
</div>
|
||||
<div class="sg-type-specimen">
|
||||
<span class="sg-type-label">1.5rem</span>
|
||||
<span style="font-size: 1.5rem; font-weight: 700; letter-spacing: -0.02em">Section Title</span>
|
||||
</div>
|
||||
<div class="sg-type-specimen">
|
||||
<span class="sg-type-label">1.125rem</span>
|
||||
<span style="font-size: 1.125rem; font-weight: 600">Subsection Title</span>
|
||||
</div>
|
||||
<div class="sg-type-specimen">
|
||||
<span class="sg-type-label">1rem</span>
|
||||
<span style="font-size: 1rem">Body text — the quick brown fox jumps over the lazy dog.</span>
|
||||
</div>
|
||||
<div class="sg-type-specimen">
|
||||
<span class="sg-type-label">0.875rem</span>
|
||||
<span style="font-size: 0.875rem">Secondary text, form labels, table cells.</span>
|
||||
</div>
|
||||
<div class="sg-type-specimen">
|
||||
<span class="sg-type-label">0.75rem</span>
|
||||
<span style="font-size: 0.75rem; color: var(--text-muted)">Caption, metadata, timestamps.</span>
|
||||
</div>
|
||||
<div class="sg-type-specimen">
|
||||
<span class="sg-type-label">mono</span>
|
||||
<span style="font-family: var(--font-mono); font-size: 0.875rem">git commit -m "code outlasts authors"</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- SPACING -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="spacing">
|
||||
<h2>Spacing</h2>
|
||||
<p class="sg-desc">
|
||||
4px base unit. 8-step scale. Use CSS custom properties for consistency.
|
||||
</p>
|
||||
|
||||
<div class="sg-showcase">
|
||||
<div style="display: grid; gap: var(--space-3);">
|
||||
% for i, size in enumerate(['4px', '8px', '12px', '16px', '24px', '32px', '48px', '64px'], 1):
|
||||
<div style="display: grid; grid-template-columns: 80px 1fr; align-items: center; gap: var(--space-4);">
|
||||
<code style="font-size: 0.75rem;">--space-${i}</code>
|
||||
<div style="height: 16px; width: var(--space-${i}); background: var(--accent); border-radius: 2px;"></div>
|
||||
</div>
|
||||
% endfor
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- CSS GRID LAYOUT -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="grid">
|
||||
<h2>CSS Grid Layout</h2>
|
||||
<p class="sg-desc">
|
||||
All layout uses CSS Grid. No flexbox. No floats. Grid handles both
|
||||
macro layout (page structure) and micro layout (component internals).
|
||||
</p>
|
||||
|
||||
<div class="sg-subsection">
|
||||
<h3>12-column grid</h3>
|
||||
<div class="sg-showcase">
|
||||
<div style="display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--space-2);">
|
||||
% for i in range(12):
|
||||
<div style="background: var(--accent-light); padding: var(--space-2); text-align: center; font-size: 0.75rem; border-radius: var(--radius-sm); color: var(--accent);">${i+1}</div>
|
||||
% endfor
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--space-2); margin-top: var(--space-3);">
|
||||
<div style="grid-column: span 8; background: var(--accent); color: var(--text-inverse); padding: var(--space-3); border-radius: var(--radius-sm); font-size: 0.8125rem;">span 8 — main content</div>
|
||||
<div style="grid-column: span 4; background: var(--surface-alt); padding: var(--space-3); border-radius: var(--radius-sm); font-size: 0.8125rem; border: 1px solid var(--border);">span 4 — sidebar</div>
|
||||
</div>
|
||||
<div style="display: grid; grid-template-columns: repeat(12, 1fr); gap: var(--space-2); margin-top: var(--space-3);">
|
||||
<div style="grid-column: span 4; background: var(--surface-alt); padding: var(--space-3); border-radius: var(--radius-sm); font-size: 0.8125rem; border: 1px solid var(--border);">span 4</div>
|
||||
<div style="grid-column: span 4; background: var(--surface-alt); padding: var(--space-3); border-radius: var(--radius-sm); font-size: 0.8125rem; border: 1px solid var(--border);">span 4</div>
|
||||
<div style="grid-column: span 4; background: var(--surface-alt); padding: var(--space-3); border-radius: var(--radius-sm); font-size: 0.8125rem; border: 1px solid var(--border);">span 4</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sg-code"><div style="display: grid; grid-template-columns: repeat(12, 1fr); gap: 8px;">
|
||||
<div style="grid-column: span 8;">Main content</div>
|
||||
<div style="grid-column: span 4;">Sidebar</div>
|
||||
</div></div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- BUTTONS -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="buttons">
|
||||
<h2>Buttons</h2>
|
||||
<p class="sg-desc">
|
||||
Simple, accessible buttons. Keyboard-focusable with visible focus rings.
|
||||
Use <code><button></code> for actions, <code><a></code> for navigation.
|
||||
</p>
|
||||
|
||||
<div class="sg-showcase">
|
||||
<div class="sg-button-grid">
|
||||
<button class="btn btn-primary">Primary</button>
|
||||
<button class="btn btn-secondary">Secondary</button>
|
||||
<button class="btn btn-danger">Danger</button>
|
||||
<button class="btn btn-ghost">Ghost</button>
|
||||
<button class="btn btn-primary" disabled>Disabled</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sg-subsection">
|
||||
<h3>Sizes</h3>
|
||||
<div class="sg-showcase">
|
||||
<div class="sg-button-grid">
|
||||
<button class="btn btn-primary btn-sm">Small</button>
|
||||
<button class="btn btn-primary">Default</button>
|
||||
<button class="btn btn-primary btn-lg">Large</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sg-code"><button class="btn btn-primary">Primary</button>
|
||||
<button class="btn btn-secondary">Secondary</button>
|
||||
<button class="btn btn-danger">Danger</button>
|
||||
<button class="btn btn-ghost">Ghost</button></div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- FORMS -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="forms">
|
||||
<h2>Forms</h2>
|
||||
<p class="sg-desc">
|
||||
Native HTML5 form elements. No custom dropdowns unless absolutely necessary.
|
||||
Use <code><datalist></code> for autocomplete. Use <code>required</code>,
|
||||
<code>pattern</code>, and <code>type</code> for validation.
|
||||
</p>
|
||||
|
||||
<div class="sg-showcase">
|
||||
<div class="form-row">
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="sg-repo-name">Repository name</label>
|
||||
<input class="form-input" type="text" id="sg-repo-name" placeholder="my-project" required>
|
||||
<span class="form-hint">Letters, numbers, hyphens, and underscores only.</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="sg-repo-type">Type</label>
|
||||
<select class="form-select" id="sg-repo-type">
|
||||
<option>Git</option>
|
||||
<option>Mercurial</option>
|
||||
<option>Subversion</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label" for="sg-desc">Description</label>
|
||||
<textarea class="form-textarea" id="sg-desc" placeholder="A short description of the repository..."></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">
|
||||
<input type="checkbox"> Make this repository private
|
||||
</label>
|
||||
</div>
|
||||
<button class="btn btn-primary">Create Repository</button>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- ALERTS -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="alerts">
|
||||
<h2>Alerts</h2>
|
||||
<p class="sg-desc">
|
||||
Capability-driven: dismiss buttons are <code>js-only</code>. Without JavaScript,
|
||||
users see the message but not a broken dismiss button.
|
||||
</p>
|
||||
|
||||
<div class="sg-showcase" style="display: grid; gap: var(--space-3);">
|
||||
<div class="alert alert-success">
|
||||
<span>✓</span>
|
||||
<span>Repository <strong>my-project</strong> created successfully.</span>
|
||||
<button class="alert-dismiss js-only" onclick="dismissAlert(this.parentElement)">×</button>
|
||||
</div>
|
||||
<div class="alert alert-warning">
|
||||
<span>⚠</span>
|
||||
<span>Your session will expire in 5 minutes.</span>
|
||||
<button class="alert-dismiss js-only" onclick="dismissAlert(this.parentElement)">×</button>
|
||||
</div>
|
||||
<div class="alert alert-danger">
|
||||
<span>✗</span>
|
||||
<span>Failed to merge pull request: conflicts detected.</span>
|
||||
<button class="alert-dismiss js-only" onclick="dismissAlert(this.parentElement)">×</button>
|
||||
</div>
|
||||
<div class="alert alert-info">
|
||||
<span>ℹ</span>
|
||||
<span>A new version of RhodeCode is available.</span>
|
||||
<button class="alert-dismiss js-only" onclick="dismissAlert(this.parentElement)">×</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- CARDS -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="cards">
|
||||
<h2>Cards</h2>
|
||||
<p class="sg-desc">
|
||||
Content containers with optional header and footer. Use CSS Grid for card layouts.
|
||||
</p>
|
||||
|
||||
<div class="card-grid">
|
||||
<div class="card">
|
||||
<div class="card-header">Pull Request #142</div>
|
||||
<div class="card-body">
|
||||
<p style="font-size: 0.875rem;">Fix session handling for cookie-based authentication. Remove beaker dependency entirely.</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<span class="badge badge-success">Approved</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">Pull Request #143</div>
|
||||
<div class="card-body">
|
||||
<p style="font-size: 0.875rem;">Modernize UI: remove jQuery, switch to CSS Grid, add living style guide endpoint.</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<span class="badge badge-warning">Review Required</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card">
|
||||
<div class="card-header">Pull Request #144</div>
|
||||
<div class="card-body">
|
||||
<p style="font-size: 0.875rem;">Add SQLite3 support for single-instance deployments on permacomputer hardware.</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<span class="badge badge-accent">Draft</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- TABLES -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="tables">
|
||||
<h2>Tables</h2>
|
||||
<p class="sg-desc">
|
||||
Native HTML tables with minimal styling. Wrapped for horizontal scroll on narrow screens.
|
||||
</p>
|
||||
|
||||
<div class="table-wrap">
|
||||
<table class="sg-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Commit</th>
|
||||
<th>Message</th>
|
||||
<th>Author</th>
|
||||
<th>Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>4f73837</code></td>
|
||||
<td>Remove beaker dependency, switch to SignedCookieSessionFactory</td>
|
||||
<td>fox</td>
|
||||
<td>2 hours ago</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>ceb23e4</code></td>
|
||||
<td>release(version-bump): 5.11.3 → 5.11.4</td>
|
||||
<td>andverb</td>
|
||||
<td>1 day ago</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>93d4bc5</code></td>
|
||||
<td>Cleanup, better handling for multiline comments</td>
|
||||
<td>andverb</td>
|
||||
<td>3 days ago</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- BADGES -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="badges">
|
||||
<h2>Badges</h2>
|
||||
|
||||
<div class="sg-showcase">
|
||||
<div style="display: grid; grid-auto-flow: column; gap: var(--space-3); justify-content: start;">
|
||||
<span class="badge badge-accent">Feature</span>
|
||||
<span class="badge badge-success">Merged</span>
|
||||
<span class="badge badge-warning">Pending</span>
|
||||
<span class="badge badge-danger">Rejected</span>
|
||||
<span class="badge badge-neutral">Draft</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- DETAILS / ACCORDION -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="details">
|
||||
<h2>Details / Accordion</h2>
|
||||
<p class="sg-desc">
|
||||
Native <code><details></code> element. Works without JavaScript.
|
||||
Progressive enhancement at its finest.
|
||||
</p>
|
||||
|
||||
<details class="sg-details">
|
||||
<summary>Repository Settings</summary>
|
||||
<div class="sg-details-body">
|
||||
<p style="font-size: 0.875rem;">Configure repository name, description, landing page, and permissions. All changes take effect immediately.</p>
|
||||
</div>
|
||||
</details>
|
||||
<details class="sg-details">
|
||||
<summary>VCS Configuration</summary>
|
||||
<div class="sg-details-body">
|
||||
<p style="font-size: 0.875rem;">Configure hooks, large file storage, and protocol settings for this repository.</p>
|
||||
</div>
|
||||
</details>
|
||||
<details class="sg-details" open>
|
||||
<summary>Danger Zone</summary>
|
||||
<div class="sg-details-body">
|
||||
<p style="font-size: 0.875rem; margin-bottom: var(--space-4);">Destructive actions that cannot be undone. Proceed with caution.</p>
|
||||
<button class="btn btn-danger btn-sm">Delete Repository</button>
|
||||
</div>
|
||||
</details>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- DIALOG -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="dialog">
|
||||
<h2>Dialog</h2>
|
||||
<p class="sg-desc">
|
||||
Native <code><dialog></code> element with <code>showModal()</code>.
|
||||
Accessible by default. Backdrop handled by CSS.
|
||||
The trigger button is <code>js-only</code> — no broken button without JS.
|
||||
</p>
|
||||
|
||||
<div class="sg-showcase">
|
||||
<button class="btn btn-primary js-only" onclick="openDialog('#sg-demo-dialog')">Open Dialog</button>
|
||||
<noscript><p style="font-size: 0.875rem; color: var(--text-muted);">Dialog requires JavaScript.</p></noscript>
|
||||
</div>
|
||||
|
||||
<dialog id="sg-demo-dialog" class="sg-dialog">
|
||||
<div class="sg-dialog-header">
|
||||
<h3>Confirm Merge</h3>
|
||||
<button class="btn btn-ghost btn-sm" onclick="closeDialog('#sg-demo-dialog')">×</button>
|
||||
</div>
|
||||
<div class="sg-dialog-body">
|
||||
<p style="font-size: 0.875rem;">
|
||||
You are about to merge pull request <strong>#142</strong> into <code>main</code>.
|
||||
This action cannot be undone.
|
||||
</p>
|
||||
</div>
|
||||
<div class="sg-dialog-footer">
|
||||
<span></span>
|
||||
<button class="btn btn-secondary" onclick="closeDialog('#sg-demo-dialog')">Cancel</button>
|
||||
<button class="btn btn-primary" onclick="closeDialog('#sg-demo-dialog')">Merge</button>
|
||||
</div>
|
||||
</dialog>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- NAVIGATION BAR -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="navigation">
|
||||
<h2>Navigation Bar</h2>
|
||||
<p class="sg-desc">
|
||||
Top navigation using CSS Grid. Three-column layout: logo, links, actions.
|
||||
</p>
|
||||
|
||||
<div class="sg-showcase" style="padding: 0;">
|
||||
<nav class="nav-bar">
|
||||
<a class="nav-logo" href="#">RhodeCode</a>
|
||||
<div class="nav-links">
|
||||
<a href="#">Repositories</a>
|
||||
<a href="#">Groups</a>
|
||||
<a href="#">Admin</a>
|
||||
</div>
|
||||
<div class="nav-actions">
|
||||
<button class="btn btn-primary btn-sm">New Repo</button>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- REPOSITORY LIST -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="repo-list">
|
||||
<h2>Repository List</h2>
|
||||
<p class="sg-desc">
|
||||
Repository listing with icon, info, and metadata. CSS Grid three-column layout.
|
||||
</p>
|
||||
|
||||
<div class="sg-showcase" style="padding: 0;">
|
||||
<div class="card">
|
||||
<div class="repo-item">
|
||||
<div class="repo-icon">G</div>
|
||||
<div class="repo-info">
|
||||
<h4><a href="#">rhodecode-enterprise-ce</a></h4>
|
||||
<p>Enterprise Source Code Management Platform</p>
|
||||
</div>
|
||||
<div class="repo-meta">
|
||||
<span>★ 42</span>
|
||||
<span>⋔ 7</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="repo-item">
|
||||
<div class="repo-icon" style="background: var(--success-light); color: var(--success);">M</div>
|
||||
<div class="repo-info">
|
||||
<h4><a href="#">make_post_sell</a></h4>
|
||||
<p>Commission-free digital and physical sales</p>
|
||||
</div>
|
||||
<div class="repo-meta">
|
||||
<span>★ 18</span>
|
||||
<span>⋔ 3</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="repo-item">
|
||||
<div class="repo-icon" style="background: var(--warning-light); color: var(--warning);">H</div>
|
||||
<div class="repo-info">
|
||||
<h4><a href="#">remarkbox</a></h4>
|
||||
<p>Hosted comment system, embeds in pages</p>
|
||||
</div>
|
||||
<div class="repo-meta">
|
||||
<span>★ 31</span>
|
||||
<span>⋔ 5</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- DIFF VIEW -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="diff">
|
||||
<h2>Diff View</h2>
|
||||
<p class="sg-desc">
|
||||
Side-by-side line numbers with CSS Grid. Monospace font. Addition and deletion colors.
|
||||
</p>
|
||||
|
||||
<div class="diff-block">
|
||||
<div class="diff-header">rhodecode/lib/rc_beaker.py</div>
|
||||
<div class="diff-line diff-del">
|
||||
<span class="diff-line-num">8</span>
|
||||
<span class="diff-line-num"></span>
|
||||
<span class="diff-line-content">-from beaker import cache</span>
|
||||
</div>
|
||||
<div class="diff-line diff-del">
|
||||
<span class="diff-line-num">9</span>
|
||||
<span class="diff-line-num"></span>
|
||||
<span class="diff-line-content">-from beaker.session import SessionObject, Session</span>
|
||||
</div>
|
||||
<div class="diff-line diff-add">
|
||||
<span class="diff-line-num"></span>
|
||||
<span class="diff-line-num">8</span>
|
||||
<span class="diff-line-content">+from pyramid.session import SignedCookieSessionFactory</span>
|
||||
</div>
|
||||
<div class="diff-line diff-add">
|
||||
<span class="diff-line-num"></span>
|
||||
<span class="diff-line-num">9</span>
|
||||
<span class="diff-line-content">+from pyramid.settings import asbool</span>
|
||||
</div>
|
||||
<div class="diff-line">
|
||||
<span class="diff-line-num">10</span>
|
||||
<span class="diff-line-num">10</span>
|
||||
<span class="diff-line-content"> </span>
|
||||
</div>
|
||||
<div class="diff-line">
|
||||
<span class="diff-line-num">11</span>
|
||||
<span class="diff-line-num">11</span>
|
||||
<span class="diff-line-content"> </span>
|
||||
</div>
|
||||
<div class="diff-line diff-del">
|
||||
<span class="diff-line-num">12</span>
|
||||
<span class="diff-line-num"></span>
|
||||
<span class="diff-line-content">-class CustomSession(Session):</span>
|
||||
</div>
|
||||
<div class="diff-line diff-del">
|
||||
<span class="diff-line-num">13</span>
|
||||
<span class="diff-line-num"></span>
|
||||
<span class="diff-line-content">- pass</span>
|
||||
</div>
|
||||
<div class="diff-line diff-add">
|
||||
<span class="diff-line-num"></span>
|
||||
<span class="diff-line-num">12</span>
|
||||
<span class="diff-line-content">+def session_factory_from_settings(settings):</span>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- CODE BLOCKS -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="code">
|
||||
<h2>Code Blocks</h2>
|
||||
<p class="sg-desc">
|
||||
Inline <code>code</code> and block-level pre/code. Monospace font stack.
|
||||
</p>
|
||||
|
||||
<div class="sg-code">def session_factory_from_settings(settings):
|
||||
"""Return a Pyramid session factory using signed cookie session settings."""
|
||||
prefixes = ("session.", "beaker.session.")
|
||||
options = {}
|
||||
for k, v in settings.items():
|
||||
for prefix in prefixes:
|
||||
if k.startswith(prefix):
|
||||
options[k[len(prefix):]] = v
|
||||
return SignedCookieSessionFactory(**factory_kwargs)</div>
|
||||
</section>
|
||||
|
||||
<!-- ============================================================ -->
|
||||
<!-- CAPABILITY-DRIVEN PRESENTATION -->
|
||||
<!-- ============================================================ -->
|
||||
<section class="sg-section" id="capability">
|
||||
<h2>Capability-Driven Presentation</h2>
|
||||
<p class="sg-desc">
|
||||
A web page does not need to look the same on every browser or device.
|
||||
Capability drives presentation. Deliver identical content regardless of
|
||||
viewer capabilities. Use the viewer's capabilities to gracefully enhance
|
||||
the presentation.
|
||||
</p>
|
||||
|
||||
<div class="sg-subsection">
|
||||
<h3>The <code>js-only</code> Pattern</h3>
|
||||
<p style="font-size: 0.875rem; color: var(--text-muted); margin-bottom: var(--space-4); max-width: 65ch;">
|
||||
Elements with <code>class="js-only"</code> are hidden when JavaScript is
|
||||
unavailable. This prevents presenting broken interactive elements to users
|
||||
whose browser cannot execute them.
|
||||
</p>
|
||||
|
||||
<div class="sg-code"><noscript>
|
||||
<style>.js-only { display: none !important; }</style>
|
||||
</noscript>
|
||||
|
||||
<!-- The dismiss button only shows when JS can handle it -->
|
||||
<div class="alert alert-success">
|
||||
<span>Repository created.</span>
|
||||
<button class="alert-dismiss js-only">&times;</button>
|
||||
</div></div>
|
||||
</div>
|
||||
|
||||
<div class="sg-subsection">
|
||||
<h3>The Rules</h3>
|
||||
<div class="sg-showcase">
|
||||
<ol style="font-size: 0.875rem; padding-left: var(--space-5); display: grid; gap: var(--space-3);">
|
||||
<li>Maintain a single canonical URI for all users.</li>
|
||||
<li>Deliver identical content regardless of viewer capabilities.</li>
|
||||
<li>Use the viewer's capabilities to gracefully enhance the presentation.</li>
|
||||
<li>Never present a broken button to the user.</li>
|
||||
<li>CSS Grid only. No flexbox. No floats.</li>
|
||||
<li>No jQuery. No CSS preprocessors. No framework bloat.</li>
|
||||
<li>Native HTML5 elements first: <code><details></code>, <code><dialog></code>, <code><datalist></code>.</li>
|
||||
<li>Code outlasts authors. Infrastructure outlasts builders.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
|
||||
<script src="${h.asset('js/custom.js')}"></script>
|
||||
|
||||
<script>
|
||||
// Sidebar active state on scroll
|
||||
onReady(function() {
|
||||
var links = $$('.sg-sidebar nav a');
|
||||
var sections = $$('.sg-section[id]');
|
||||
|
||||
// Smooth scroll for sidebar links
|
||||
links.forEach(function(link) {
|
||||
link.addEventListener('click', function(e) {
|
||||
var href = this.getAttribute('href');
|
||||
if (href && href.startsWith('#')) {
|
||||
e.preventDefault();
|
||||
scrollToElement(href);
|
||||
history.replaceState(null, '', href);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Highlight active section on scroll
|
||||
var main = $('.sg-main');
|
||||
if (main) {
|
||||
main.addEventListener('scroll', function() {
|
||||
var scrollTop = main.scrollTop;
|
||||
var current = '';
|
||||
sections.forEach(function(section) {
|
||||
if (section.offsetTop - 100 <= scrollTop) {
|
||||
current = section.id;
|
||||
}
|
||||
});
|
||||
links.forEach(function(link) {
|
||||
link.classList.remove('active');
|
||||
if (link.getAttribute('href') === '#' + current) {
|
||||
link.classList.add('active');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Add a link
Reference in a new issue