1227 lines
39 KiB
HTML
1227 lines
39 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta content="width=device-width, initial-scale=1.0" name="viewport">
|
|
<title>Web Platform Fundamentals: Building with Native HTML</title>
|
|
<style>
|
|
:root {
|
|
--color-bg: #ffffff;
|
|
--color-card: #f8f9fa;
|
|
--color-primary: #0066cc;
|
|
--color-primary-hover: #0052a3;
|
|
--color-danger: #dc3545;
|
|
--color-warning: #856404;
|
|
--color-warning-bg: #fff3cd;
|
|
--color-content-bg: #f1f3f4;
|
|
--color-border: #dee2e6;
|
|
--color-text: #212529;
|
|
--color-text-muted: #6c757d;
|
|
--color-code-bg: #f8f9fa;
|
|
--color-code-text: #0066cc;
|
|
--shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
--radius: 8px;
|
|
--focus-outline: 2px solid #0066cc;
|
|
--focus-outline-danger: 2px solid #dc3545;
|
|
--focus-offset: 2px;
|
|
}
|
|
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
body {
|
|
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
line-height: 1.6;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
padding: 2rem;
|
|
background: var(--color-bg);
|
|
color: var(--color-text);
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.hero {
|
|
text-align: center;
|
|
margin-bottom: 4rem;
|
|
padding: 3rem;
|
|
background: var(--color-card);
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow);
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
.hero:focus-within {
|
|
outline: var(--focus-outline);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
.hero h1 {
|
|
font-size: clamp(2rem, 5vw, 3.5rem);
|
|
margin-bottom: 1.5rem;
|
|
color: var(--color-primary);
|
|
font-weight: 700;
|
|
letter-spacing: -0.02em;
|
|
}
|
|
|
|
.hero .subtitle {
|
|
font-size: 1.125rem;
|
|
color: var(--color-text-muted);
|
|
max-width: 700px;
|
|
margin: 0 auto;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.comparison-grid {
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: 2rem;
|
|
margin: 2rem 0;
|
|
}
|
|
|
|
.section {
|
|
margin: 4rem 0;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 2rem;
|
|
margin-bottom: 2rem;
|
|
padding: 1.5rem 0;
|
|
text-align: center;
|
|
color: var(--color-primary);
|
|
position: relative;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.section-title::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
width: 60px;
|
|
height: 2px;
|
|
background: var(--color-primary);
|
|
}
|
|
|
|
.column {
|
|
background: var(--color-card);
|
|
padding: 2rem;
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow);
|
|
border: 1px solid var(--color-border);
|
|
transition: box-shadow 0.2s ease;
|
|
position: relative;
|
|
}
|
|
|
|
.column:hover {
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
}
|
|
|
|
.column:focus-within {
|
|
outline: var(--focus-outline);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
.column.bad:focus-within {
|
|
outline: var(--focus-outline-danger);
|
|
}
|
|
|
|
.column h3 {
|
|
color: var(--color-text);
|
|
border-bottom: 1px solid var(--color-border);
|
|
padding-bottom: 1rem;
|
|
margin-bottom: 2rem;
|
|
font-size: 1.25rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.bad {
|
|
border-left: 3px solid var(--color-danger);
|
|
}
|
|
|
|
.bad h3::before {
|
|
content: '⚠️ ';
|
|
}
|
|
|
|
.bad button {
|
|
background: var(--color-danger);
|
|
}
|
|
|
|
.bad button:hover {
|
|
background: var(--color-danger);
|
|
}
|
|
|
|
.bad button:focus {
|
|
outline: var(--focus-outline-danger);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
.good {
|
|
border-left: 3px solid var(--color-primary);
|
|
}
|
|
|
|
.good h3::before {
|
|
content: '✅ ';
|
|
}
|
|
|
|
.accessibility-note {
|
|
background: var(--color-warning-bg);
|
|
border: 1px solid #ffc107;
|
|
color: var(--color-warning);
|
|
padding: 1rem;
|
|
border-radius: var(--radius);
|
|
margin: 1.5rem 0;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.code-block {
|
|
/*display: none;*/
|
|
background: var(--color-code-bg);
|
|
color: var(--color-code-text);
|
|
padding: 2rem 1.5rem 1rem;
|
|
border-radius: var(--radius);
|
|
overflow-x: auto;
|
|
font-family: 'SF Mono', Monaco, 'Cascadia Code', monospace;
|
|
font-size: 0.875rem;
|
|
margin: 1.5rem 0;
|
|
border: 1px solid var(--color-border);
|
|
position: relative;
|
|
}
|
|
|
|
.code-block:focus {
|
|
outline: var(--focus-outline);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
.code-block::before {
|
|
content: 'CODE';
|
|
position: absolute;
|
|
top: -6px;
|
|
right: 15px;
|
|
background: var(--color-primary);
|
|
color: white;
|
|
padding: 10px 8px 0;
|
|
font-size: 0.7rem;
|
|
border-radius: 4px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.pros-cons {
|
|
margin: 1.5rem 0;
|
|
}
|
|
|
|
.pros-cons h4 {
|
|
margin-bottom: 1rem;
|
|
color: var(--color-text);
|
|
font-size: 1rem;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.pros-cons ul {
|
|
list-style: none;
|
|
padding-left: 0;
|
|
}
|
|
|
|
.pros-cons li {
|
|
padding: 0.5rem 0;
|
|
padding-left: 1.5rem;
|
|
position: relative;
|
|
}
|
|
|
|
.pros li::before {
|
|
content: '✓';
|
|
position: absolute;
|
|
left: 0;
|
|
color: var(--color-primary);
|
|
font-weight: bold;
|
|
}
|
|
|
|
.cons li::before {
|
|
content: '✗';
|
|
position: absolute;
|
|
left: 0;
|
|
color: var(--color-danger);
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* Interactive Elements */
|
|
.js-collapsible {
|
|
color: white;
|
|
cursor: pointer;
|
|
padding: 12px 16px;
|
|
border: none;
|
|
text-align: left;
|
|
outline: none;
|
|
font-size: 1rem;
|
|
border-radius: var(--radius);
|
|
margin-bottom: 1rem;
|
|
width: 100%;
|
|
font-family: inherit;
|
|
font-weight: 500;
|
|
}
|
|
|
|
.js-wrapper {
|
|
display: flex;
|
|
flex-direction: column-reverse;
|
|
}
|
|
|
|
.js-content {
|
|
display: none;
|
|
background: var(--color-content-bg);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: 0 0 var(--radius) var(--radius);
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
.js-content.active {
|
|
display: block;
|
|
padding: 0.5rem;
|
|
}
|
|
|
|
.js-content.active + .js-collapsible {
|
|
border-radius: var(--radius) var(--radius) 0 0;
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
details {
|
|
background: var(--color-card);
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius);
|
|
margin-bottom: 1rem;
|
|
overflow: hidden;
|
|
}
|
|
|
|
details:focus-within {
|
|
outline: var(--focus-outline);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
summary {
|
|
background: var(--color-primary);
|
|
color: white;
|
|
padding: 12px 16px;
|
|
cursor: pointer;
|
|
font-size: 1rem;
|
|
list-style: none;
|
|
font-weight: 500;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
summary:hover {
|
|
background: var(--color-primary-hover);
|
|
}
|
|
|
|
summary:focus {
|
|
outline: var(--focus-outline);
|
|
outline-offset: -2px;
|
|
}
|
|
|
|
summary::-webkit-details-marker {
|
|
display: none;
|
|
}
|
|
|
|
summary::before {
|
|
content: '▶';
|
|
margin-right: 8px;
|
|
transition: transform 0.2s ease;
|
|
display: inline-block;
|
|
}
|
|
|
|
details[open] summary::before {
|
|
transform: rotate(90deg);
|
|
}
|
|
|
|
details > div {
|
|
padding: 16px;
|
|
background: var(--color-content-bg);
|
|
}
|
|
|
|
/* Modal Styles */
|
|
.js-modal-overlay {
|
|
display: none;
|
|
position: fixed;
|
|
top: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(0, 0, 0, 0.6);
|
|
z-index: 1000;
|
|
}
|
|
|
|
.js-modal-overlay.active {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.js-modal-content {
|
|
margin: auto;
|
|
background: var(--color-bg);
|
|
padding: 2rem;
|
|
border-radius: var(--radius);
|
|
max-width: 500px;
|
|
width: 90%;
|
|
border: 1px solid var(--color-border);
|
|
box-shadow: var(--shadow);
|
|
}
|
|
|
|
.js-modal-content:focus {
|
|
outline: var(--focus-outline-danger);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
dialog {
|
|
margin: auto;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius);
|
|
padding: 2rem;
|
|
background: var(--color-bg);
|
|
color: var(--color-text);
|
|
box-shadow: var(--shadow);
|
|
max-width: 500px;
|
|
width: 90vw;
|
|
}
|
|
|
|
dialog:focus {
|
|
outline: var(--focus-outline);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
dialog::backdrop {
|
|
background: rgba(0, 0, 0, 0.6);
|
|
}
|
|
|
|
/* Form Styles */
|
|
.form-group {
|
|
margin-bottom: 1.5rem;
|
|
}
|
|
|
|
.form-group label {
|
|
display: block;
|
|
margin-bottom: 0.5rem;
|
|
font-weight: 500;
|
|
color: var(--color-text);
|
|
}
|
|
|
|
.form-group input, .form-group textarea, .form-group select {
|
|
width: 100%;
|
|
padding: 10px 12px;
|
|
border: 2px solid var(--color-border);
|
|
border-radius: var(--radius);
|
|
font-size: 1rem;
|
|
background: var(--color-bg);
|
|
color: var(--color-text);
|
|
transition: all 0.2s ease;
|
|
font-family: inherit;
|
|
}
|
|
|
|
.form-group input:focus, .form-group textarea:focus, .form-group select:focus {
|
|
outline: var(--focus-outline);
|
|
outline-offset: 2px;
|
|
border-color: var(--color-border);
|
|
}
|
|
|
|
.form-group input:invalid {
|
|
border-color: var(--color-danger);
|
|
}
|
|
|
|
.form-group input:valid {
|
|
border-color: var(--color-primary);
|
|
}
|
|
|
|
.js-error {
|
|
color: var(--color-danger);
|
|
font-size: 0.875rem;
|
|
margin-top: 0.5rem;
|
|
display: none;
|
|
}
|
|
|
|
.js-error.active {
|
|
display: block;
|
|
}
|
|
|
|
/* Progress Styles */
|
|
.js-progress-container {
|
|
width: 100%;
|
|
background: var(--color-border);
|
|
border-radius: 4px;
|
|
height: 20px;
|
|
margin: 1.5rem 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.js-progress-bar {
|
|
height: 100%;
|
|
background: var(--color-danger);
|
|
width: 0;
|
|
transition: width 0.3s ease;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
progress {
|
|
width: 100%;
|
|
height: 20px;
|
|
margin: 1.5rem 0;
|
|
border-radius: 4px;
|
|
border: none;
|
|
background: var(--color-border);
|
|
}
|
|
|
|
progress:focus {
|
|
outline: var(--focus-outline);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
progress::-webkit-progress-bar {
|
|
background-color: var(--color-border);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
progress::-webkit-progress-value {
|
|
background: var(--color-primary);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
progress::-moz-progress-bar {
|
|
background: var(--color-primary);
|
|
border-radius: 4px;
|
|
}
|
|
|
|
/* Button Styles */
|
|
button {
|
|
background: var(--color-primary);
|
|
color: white;
|
|
border: none;
|
|
padding: 10px 16px;
|
|
border-radius: var(--radius);
|
|
cursor: pointer;
|
|
font-size: 1rem;
|
|
margin: 0.5rem 0.5rem 0.5rem 0;
|
|
font-weight: 500;
|
|
transition: all 0.2s ease;
|
|
font-family: inherit;
|
|
}
|
|
|
|
button:hover {
|
|
background: var(--color-primary-hover);
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
button:focus {
|
|
outline: var(--focus-outline);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
button:disabled {
|
|
background: var(--color-text-muted);
|
|
cursor: not-allowed;
|
|
transform: none;
|
|
}
|
|
|
|
/* Component Styles */
|
|
.datalist-container {
|
|
position: relative;
|
|
}
|
|
|
|
input[list] {
|
|
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%23666' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='m6 8 4 4 4-4'/%3e%3c/svg%3e");
|
|
background-position: right 12px center;
|
|
background-repeat: no-repeat;
|
|
background-size: 16px;
|
|
padding-right: 36px;
|
|
}
|
|
|
|
.slider-container {
|
|
margin: 2rem 0;
|
|
}
|
|
|
|
input[type="range"] {
|
|
width: 100%;
|
|
height: 6px;
|
|
border-radius: 3px;
|
|
background: var(--color-border);
|
|
outline: none;
|
|
-webkit-appearance: none;
|
|
}
|
|
|
|
input[type="range"]:focus {
|
|
outline: var(--focus-outline);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
input[type="range"]::-webkit-slider-thumb {
|
|
appearance: none;
|
|
width: 18px;
|
|
height: 18px;
|
|
border-radius: 50%;
|
|
background: var(--color-primary);
|
|
cursor: pointer;
|
|
}
|
|
|
|
input[type="range"]::-moz-range-thumb {
|
|
width: 18px;
|
|
height: 18px;
|
|
border-radius: 50%;
|
|
background: var(--color-primary);
|
|
cursor: pointer;
|
|
border: none;
|
|
}
|
|
|
|
.color-input {
|
|
width: 50px;
|
|
height: 32px;
|
|
border: 1px solid var(--color-border);
|
|
border-radius: var(--radius);
|
|
cursor: pointer;
|
|
}
|
|
|
|
.color-input:focus {
|
|
outline: var(--focus-outline);
|
|
outline-offset: var(--focus-offset);
|
|
}
|
|
|
|
.summary-box {
|
|
margin-top: 4rem;
|
|
padding: 2rem;
|
|
background: var(--color-card);
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow);
|
|
border: 1px solid var(--color-border);
|
|
text-align: center;
|
|
}
|
|
|
|
.summary-box h3 {
|
|
font-size: 1.5rem;
|
|
margin-bottom: 1rem;
|
|
color: var(--color-primary);
|
|
font-weight: 600;
|
|
}
|
|
|
|
.zen-quote {
|
|
font-style: italic;
|
|
color: var(--color-text-muted);
|
|
font-size: 1rem;
|
|
margin-top: 1.5rem;
|
|
border-left: 3px solid var(--color-primary);
|
|
padding-left: 1rem;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.comparison-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
body {
|
|
padding: 1rem;
|
|
}
|
|
|
|
.hero {
|
|
padding: 2rem;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 1.75rem;
|
|
}
|
|
}
|
|
|
|
/* Performance indicators */
|
|
.perf-indicator {
|
|
display: inline-block;
|
|
padding: 2px 6px;
|
|
border-radius: 4px;
|
|
font-size: 0.75rem;
|
|
font-weight: 600;
|
|
margin-left: 8px;
|
|
}
|
|
|
|
.perf-fast {
|
|
background: rgba(0, 102, 204, 0.1);
|
|
color: var(--color-primary);
|
|
}
|
|
|
|
.perf-slow {
|
|
background: rgba(220, 53, 69, 0.1);
|
|
color: var(--color-danger);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body class="search_plugin_added">
|
|
|
|
<div class="hero">
|
|
<h1>🚀 Web Platform Fundamentals</h1>
|
|
<p class="subtitle">Master native HTML capabilities and progressive enhancement patterns. This guide demonstrates how
|
|
leveraging built-in browser features reduces complexity, improves performance, and creates more maintainable
|
|
codebases.</p>
|
|
</div>
|
|
|
|
<!-- COLLAPSIBLES -->
|
|
<div class="section">
|
|
<h2 class="section-title">🎯 Progressive Disclosure Patterns</h2>
|
|
<div class="comparison-grid">
|
|
<div class="column bad">
|
|
<h3>JavaScript-Dependent Implementation <span class="perf-indicator perf-slow">COMPLEX</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>⚠️ Implementation Overhead:</strong> Manual ARIA state management, keyboard event handling, focus
|
|
management, and screen reader compatibility.
|
|
</div>
|
|
|
|
<div class="js-wrapper">
|
|
<div class="js-content" id="content1">
|
|
Custom collapsible implementations require comprehensive event handling, state synchronization across
|
|
components, and careful attention to accessibility requirements including proper ARIA attributes and keyboard
|
|
navigation patterns.
|
|
</div>
|
|
<button class="js-collapsible" onclick="toggleContent('content1')">
|
|
Custom Collapsible Architecture
|
|
</button>
|
|
</div>
|
|
|
|
<div class="js-wrapper">
|
|
<div class="js-content" id="content2">
|
|
Managing state across multiple collapsible sections introduces complexity in event coordination, memory
|
|
management, and performance optimization, particularly when dealing with dynamic content loading.
|
|
</div>
|
|
<button class="js-collapsible" onclick="toggleContent('content2')">
|
|
State Management Challenges
|
|
</button>
|
|
</div>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="cons">❌ Architecture Complexity:</h4>
|
|
<ul>
|
|
<li>Event delegation and memory leak prevention</li>
|
|
<li>ARIA state synchronization and keyboard trap management</li>
|
|
<li>Cross-browser compatibility and polyfill requirements</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column good">
|
|
<h3>Native Details/Summary Elements <span class="perf-indicator perf-fast">ZERO-JS</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>🎯 Platform Integration:</strong> Built-in ARIA semantics, keyboard navigation, screen reader support,
|
|
and browser-optimized animations.
|
|
</div>
|
|
|
|
<details name="architecture">
|
|
<summary>Semantic HTML Architecture</summary>
|
|
<div>
|
|
The HTML5 details/summary pattern provides declarative progressive disclosure without JavaScript dependencies.
|
|
Browser engines handle state management, accessibility, and user interaction patterns according to platform
|
|
conventions.
|
|
</div>
|
|
</details>
|
|
|
|
<details name="architecture">
|
|
<summary>Progressive Enhancement Benefits</summary>
|
|
<div>
|
|
Starting with functional HTML ensures graceful degradation across all environments. CSS and JavaScript become
|
|
enhancement layers rather than functional requirements, improving reliability and reducing technical debt.
|
|
</div>
|
|
</details>
|
|
|
|
<details name="architecture">
|
|
<summary>Performance Characteristics</summary>
|
|
<div>
|
|
Native elements eliminate bundle size overhead, reduce runtime memory consumption, and leverage browser
|
|
optimizations unavailable to custom implementations. Hardware acceleration and efficient event handling come
|
|
built-in.
|
|
</div>
|
|
</details>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="pros">✅ Platform Advantages:</h4>
|
|
<ul>
|
|
<li>Zero JavaScript footprint with full accessibility compliance</li>
|
|
<li>Browser-native performance optimizations and hardware acceleration</li>
|
|
<li>Consistent cross-platform behavior with no maintenance overhead</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- MODALS -->
|
|
<div class="section">
|
|
<h2 class="section-title">🪟 Modal Dialog Patterns</h2>
|
|
<div class="comparison-grid">
|
|
<div class="column bad">
|
|
<h3>Custom Modal Implementation <span class="perf-indicator perf-slow">BRITTLE</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>⚠️ Critical Requirements:</strong> Focus trapping, inert background content, ESC key handling, backdrop
|
|
click management, and ARIA modal semantics.
|
|
</div>
|
|
|
|
<button onclick="openJSModal()">Launch Custom Modal</button>
|
|
|
|
<div class="js-modal-overlay" id="jsModal">
|
|
<div class="js-modal-content">
|
|
<h4>Custom Modal Architecture</h4>
|
|
<p>This approach requires managing the modal stack, preventing background interaction, coordinating focus
|
|
management, and ensuring proper cleanup to avoid memory leaks and accessibility violations.</p>
|
|
<p><strong>Critical Issue:</strong> Background content remains accessible to screen readers and keyboard
|
|
navigation without explicit inert management.</p>
|
|
<button onclick="closeJSModal()">Close Modal</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="cons">❌ Implementation Challenges:</h4>
|
|
<ul>
|
|
<li>Focus trap implementation and restoration complexity</li>
|
|
<li>Modal stack management and z-index coordination</li>
|
|
<li>Event cleanup and memory leak prevention</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column good">
|
|
<h3>Native Dialog Element <span class="perf-indicator perf-fast">ROBUST</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>🎯 Built-in Capabilities:</strong> Automatic focus trapping, inert background management, ESC key
|
|
support, and proper modal semantics.
|
|
</div>
|
|
|
|
<button onclick="document.getElementById('nativeDialog').showModal()">
|
|
Launch Native Dialog
|
|
</button>
|
|
|
|
<dialog id="nativeDialog">
|
|
<h4>Native Dialog Element</h4>
|
|
<p>The HTML5 dialog element provides robust modal functionality with automatic focus management, backdrop
|
|
interaction handling, and proper accessibility semantics built into the browser engine.</p>
|
|
<p><strong>Key Advantage:</strong> Background content becomes automatically inert, preventing interaction and
|
|
screen reader access without additional implementation.</p>
|
|
<button onclick="document.getElementById('nativeDialog').close()">
|
|
Close Dialog
|
|
</button>
|
|
</dialog>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="pros">✅ Engine-Level Features:</h4>
|
|
<ul>
|
|
<li>Automatic focus trapping with proper restoration</li>
|
|
<li>Built-in ESC key handling and backdrop click support</li>
|
|
<li>Modal semantics and inert background management</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- FORM VALIDATION -->
|
|
<div class="section">
|
|
<h2 class="section-title">📝 Constraint Validation Patterns</h2>
|
|
<div class="comparison-grid">
|
|
<div class="column bad">
|
|
<h3>Custom Validation Logic <span class="perf-indicator perf-slow">FRAGILE</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>⚠️ Validation Complexity:</strong> Custom error messaging, timing coordination, accessibility
|
|
announcements, and server-client synchronization.
|
|
</div>
|
|
|
|
<form onsubmit="return validateJSForm(event)">
|
|
<div class="form-group">
|
|
<label for="js-email">Email Validation</label>
|
|
<input id="js-email" name="email" type="text">
|
|
<div class="js-error" id="email-error">Invalid email format detected</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="js-regex">Pattern Matching (UUID)</label>
|
|
<input id="js-regex" name="uuid" type="text">
|
|
<div class="js-error" id="regex-error">UUID format required: 8-4-4-4-12 hex digits</div>
|
|
</div>
|
|
|
|
<button type="submit">Validate Form</button>
|
|
</form>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="cons">❌ Validation Brittleness:</h4>
|
|
<ul>
|
|
<li>Regex patterns miss edge cases and internationalization</li>
|
|
<li>Error timing and accessibility announcement coordination</li>
|
|
<li>Client-server validation drift and synchronization issues</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column good">
|
|
<h3>Constraint Validation API <span class="perf-indicator perf-fast">SPEC-COMPLIANT</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>🎯 Standards-Based:</strong> Automatic error announcements, internationalized messages, and CSS
|
|
pseudo-class integration.
|
|
</div>
|
|
|
|
<form>
|
|
<div class="form-group">
|
|
<label for="native-email">Email Validation</label>
|
|
<input id="native-email" name="email" placeholder="developer@example.org" required type="email">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="native-uuid">UUID Pattern</label>
|
|
<input id="native-uuid" name="uuid"
|
|
pattern="[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
|
|
placeholder="550e8400-e29b-41d4-a716-446655440000" required
|
|
title="Enter a valid UUID format (e.g., 550e8400-e29b-41d4-a716-446655440000)" type="text">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="native-api">API Endpoint URL</label>
|
|
<input id="native-api" name="api" placeholder="https://api.example.org/v1" type="url">
|
|
</div>
|
|
|
|
<button type="submit">Submit Form</button>
|
|
</form>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="pros">✅ Specification Compliance:</h4>
|
|
<ul>
|
|
<li>RFC-compliant validation patterns with internationalization</li>
|
|
<li>Automatic error messaging in user's preferred language</li>
|
|
<li>CSS pseudo-classes (:valid, :invalid) for styling integration</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- PROGRESS INDICATORS -->
|
|
<div class="section">
|
|
<h2 class="section-title">📊 Progress Indication Patterns</h2>
|
|
<div class="comparison-grid">
|
|
<div class="column bad">
|
|
<h3>Custom Progress Implementation <span class="perf-indicator perf-slow">SEMANTIC-VOID</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>⚠️ Accessibility Gap:</strong> No semantic meaning without explicit ARIA implementation and screen
|
|
reader progress announcements.
|
|
</div>
|
|
|
|
<div class="js-progress-container">
|
|
<div class="js-progress-bar" id="jsProgress"></div>
|
|
</div>
|
|
|
|
<p>Build Progress: <span id="jsProgressText">0%</span></p>
|
|
<button onclick="startJSProgress()">Start Build Process</button>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="cons">❌ Semantic Limitations:</h4>
|
|
<ul>
|
|
<li>No inherent semantic meaning for assistive technologies</li>
|
|
<li>Manual ARIA live region management for progress updates</li>
|
|
<li>Custom animation performance and value interpolation</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column good">
|
|
<h3>Native Progress Element <span class="perf-indicator perf-fast">SEMANTIC</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>🎯 Semantic Integration:</strong> Built-in progress role, automatic ARIA value announcements, and
|
|
indeterminate state support.
|
|
</div>
|
|
|
|
<p>Compilation Progress</p>
|
|
<progress max="100" value="75">75% complete</progress>
|
|
|
|
<p>Indeterminate Operation (processing)</p>
|
|
<progress>Processing dependencies...</progress>
|
|
|
|
<p>Dynamic Progress: <span id="nativeProgressText">0%</span></p>
|
|
<progress id="nativeProgress" max="100" value="0">0%</progress>
|
|
<button onclick="startNativeProgress()">Start Process</button>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="pros">✅ Semantic Advantages:</h4>
|
|
<ul>
|
|
<li>Built-in progress role with automatic value announcements</li>
|
|
<li>Indeterminate state support for unknown duration operations</li>
|
|
<li>Platform-optimized rendering and animation performance</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- DATE/TIME INPUTS -->
|
|
<div class="section">
|
|
<h2 class="section-title">📅 Temporal Input Patterns</h2>
|
|
<div class="comparison-grid">
|
|
<div class="column bad">
|
|
<h3>Custom Date Picker <span class="perf-indicator perf-slow">HEAVYWEIGHT</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>⚠️ Implementation Scope:</strong> Calendar widget architecture, keyboard navigation,
|
|
internationalization, timezone handling, and mobile touch optimization.
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="js-date">Deployment Date (Custom)</label>
|
|
<input id="js-date" onclick="openDatePicker()" placeholder="YYYY-MM-DD" readonly type="text">
|
|
<div id="datePicker"
|
|
style="display:none; position:absolute; background:white; border:1px solid #ccc; z-index:1000;">
|
|
<p style="padding:20px; color:#666;">
|
|
[Calendar widget implementation]<br>
|
|
Requires: Date manipulation library, internationalization,<br>
|
|
keyboard navigation, mobile gesture handling,<br>
|
|
timezone calculations, accessibility compliance.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="cons">❌ Implementation Overhead:</h4>
|
|
<ul>
|
|
<li>Large JavaScript libraries and complex calendar logic</li>
|
|
<li>Mobile UX inconsistency with platform date pickers</li>
|
|
<li>Internationalization complexity and timezone edge cases</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column good">
|
|
<h3>Native Temporal Inputs <span class="perf-indicator perf-fast">PLATFORM-NATIVE</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>🎯 OS Integration:</strong> Platform-consistent UI, automatic keyboard navigation, built-in validation,
|
|
and internationalization support.
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="native-date">Release Date</label>
|
|
<input id="native-date" max="2025-12-31" min="2024-01-01" name="date" type="date" value="2024-12-15">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="native-datetime">Build Timestamp</label>
|
|
<input id="native-datetime" name="datetime" step="1" type="datetime-local">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="native-time">Deployment Window</label>
|
|
<input id="native-time" max="18:00" min="02:00" name="time" step="900" type="time">
|
|
</div>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="pros">✅ Platform Integration:</h4>
|
|
<ul>
|
|
<li>Zero-bundle impact with native OS picker integration</li>
|
|
<li>Automatic validation and internationalization support</li>
|
|
<li>Consistent UX aligned with platform conventions</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- SEARCH & AUTOCOMPLETE -->
|
|
<div class="section">
|
|
<h2 class="section-title">🔍 Autocomplete Patterns</h2>
|
|
<div class="comparison-grid">
|
|
<div class="column bad">
|
|
<h3>Custom Autocomplete <span class="perf-indicator perf-slow">INTERACTION-HEAVY</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>⚠️ Interaction Complexity:</strong> Dropdown positioning, keyboard navigation, ARIA combobox
|
|
implementation, and mobile touch handling.
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="js-search">Framework Search (Custom)</label>
|
|
<input autocomplete="off" id="js-search" onkeyup="filterFrameworks(this.value)"
|
|
placeholder="Type framework name..." type="text">
|
|
<div id="js-results"
|
|
style="display:none; position:absolute; background:var(--color-card); border:1px solid var(--color-border); max-height:200px; overflow-y:auto; z-index:100;"></div>
|
|
</div>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="cons">❌ Interaction Management:</h4>
|
|
<ul>
|
|
<li>Complex ARIA combobox implementation and state management</li>
|
|
<li>Dropdown positioning and viewport collision detection</li>
|
|
<li>Mobile keyboard optimization and touch event handling</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="column good">
|
|
<h3>Native Datalist Element <span class="perf-indicator perf-fast">ZERO-CONFIG</span></h3>
|
|
|
|
<div class="accessibility-note">
|
|
<strong>🎯 Native Combobox:</strong> Built-in ARIA combobox semantics, keyboard navigation, and
|
|
platform-consistent interaction patterns.
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="native-framework">JavaScript Framework</label>
|
|
<input id="native-framework" list="frameworks" placeholder="Select or type framework..." type="text">
|
|
<datalist id="frameworks">
|
|
<option value="React">React - Component-based library</option>
|
|
<option value="Vue.js">Vue.js - Progressive framework</option>
|
|
<option value="Angular">Angular - Full platform</option>
|
|
<option value="Svelte">Svelte - Compile-time framework</option>
|
|
<option value="Solid">Solid - Fine-grained reactivity</option>
|
|
<option value="Alpine.js">Alpine.js - Minimal framework</option>
|
|
<option value="Lit">Lit - Web Components library</option>
|
|
<option value="Preact">Preact - Lightweight React alternative</option>
|
|
</datalist>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label for="native-language">Programming Language</label>
|
|
<input id="native-language" list="languages" placeholder="Choose language..." type="text">
|
|
<datalist id="languages">
|
|
<option label="JavaScript - Dynamic scripting" value="JavaScript"></option>
|
|
<option label="TypeScript - Typed JavaScript" value="TypeScript"></option>
|
|
<option label="Python - General purpose" value="Python"></option>
|
|
<option label="Rust - Systems programming" value="Rust"></option>
|
|
<option label="Go - Concurrent systems" value="Go"></option>
|
|
<option label="WebAssembly - High-performance web" value="WebAssembly"></option>
|
|
|
|
<option label="C - Low-level systems" value="C"></option>
|
|
<option label="C++ - High-performance systems" value="C++"></option>
|
|
<option label="C# - .NET ecosystem" value="C#"></option>
|
|
<option label="Java - Cross-platform enterprise" value="Java"></option>
|
|
<option label="Kotlin - Modern JVM language" value="Kotlin"></option>
|
|
<option label="Swift - iOS and macOS" value="Swift"></option>
|
|
|
|
<option label="Ruby - Web development (Rails)" value="Ruby"></option>
|
|
<option label="PHP - Server-side scripting" value="PHP"></option>
|
|
<option label="Perl - Text processing" value="Perl"></option>
|
|
<option label="Haskell - Functional programming" value="Haskell"></option>
|
|
<option label="Elixir - Scalable applications" value="Elixir"></option>
|
|
<option label="Dart - Web and mobile apps" value="Dart"></option>
|
|
|
|
<option label="Scala - Functional JVM language" value="Scala"></option>
|
|
<option label="Lua - Lightweight scripting" value="Lua"></option>
|
|
<option label="R - Statistical computing" value="R"></option>
|
|
<option label="Julia - High-performance computing" value="Julia"></option>
|
|
<option label="Shell - Command-line scripting" value="Shell"></option>
|
|
<option label="MATLAB - Engineering and science" value="MATLAB"></option>
|
|
</datalist>
|
|
</div>
|
|
|
|
<div class="pros-cons">
|
|
<h4 class="pros">✅ Zero-Configuration Benefits:</h4>
|
|
<ul>
|
|
<li>Native combobox semantics with automatic ARIA support</li>
|
|
<li>Platform-consistent keyboard and interaction patterns</li>
|
|
<li>Form validation integration and graceful degradation</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="summary-box">
|
|
<h3>Platform-First Development</h3>
|
|
<p>Native HTML elements represent years of browser engineering, accessibility research, and web standards evolution.
|
|
They provide robust functionality with minimal implementation overhead and maximum compatibility.</p>
|
|
|
|
<p><strong>The Progressive Enhancement Approach:</strong></p>
|
|
<ul style="text-align: left; max-width: 600px; margin: 2rem auto;">
|
|
<li>Build with semantic HTML that functions universally</li>
|
|
<li>Enhance visual design through CSS without breaking functionality</li>
|
|
<li>Layer JavaScript for complex interactions where native capabilities are insufficient</li>
|
|
</ul>
|
|
|
|
<p>Leverage browser engines rather than reimplementing their functionality. <strong>Your codebase will be more
|
|
maintainable, your users will have better experiences.</strong></p>
|
|
|
|
<div class="zen-quote">
|
|
"The most sophisticated architecture is often the one that uses existing, well-tested components. Native HTML
|
|
elements provide decades of optimization and accessibility engineering—build upon this foundation rather than around
|
|
it."
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
// JavaScript functions remain unchanged except for filterFrameworks addition
|
|
const frameworks = ['React', 'Vue.js', 'Angular', 'Svelte', 'Solid', 'Alpine.js', 'Lit', 'Preact', 'Qwik', 'SvelteKit', 'Next.js', 'Nuxt.js'];
|
|
|
|
function filterFrameworks(value) {
|
|
const results = document.getElementById('js-results');
|
|
if (!value) {
|
|
results.style.display = 'none';
|
|
return;
|
|
}
|
|
const filtered = frameworks.filter(fw => fw.toLowerCase().includes(value.toLowerCase()));
|
|
results.innerHTML = filtered.map(fw => `<div style="padding:8px; cursor:pointer;" onclick="selectFramework('${fw}')">${fw}</div>`).join('');
|
|
results.style.display = filtered.length ? 'block' : 'none';
|
|
}
|
|
|
|
function selectFramework(fw) {
|
|
document.getElementById('js-search').value = fw;
|
|
document.getElementById('js-results').style.display = 'none';
|
|
}
|
|
|
|
// All other functions remain unchanged
|
|
function startNativeProgress() {
|
|
const progress = document.getElementById('nativeProgress');
|
|
const text = document.getElementById('nativeProgressText');
|
|
let value = 0;
|
|
const interval = setInterval(() => {
|
|
value += Math.random() * 15;
|
|
if (value >= 100) {
|
|
value = 100;
|
|
clearInterval(interval);
|
|
}
|
|
progress.value = value;
|
|
text.textContent = Math.round(value) + '%';
|
|
}, 200);
|
|
}
|
|
|
|
function toggleContent(id) {
|
|
document.getElementById(id).classList.toggle("active");
|
|
}
|
|
|
|
function openJSModal() {
|
|
document.getElementById('jsModal').style.display = 'flex';
|
|
}
|
|
|
|
function closeJSModal() {
|
|
document.getElementById('jsModal').style.display = 'none';
|
|
}
|
|
|
|
function validateJSForm(event) {
|
|
event.preventDefault();
|
|
alert('Custom validation would run here');
|
|
return false;
|
|
}
|
|
|
|
function startJSProgress() {
|
|
const bar = document.getElementById('jsProgress');
|
|
const text = document.getElementById('jsProgressText');
|
|
let width = 0;
|
|
const interval = setInterval(() => {
|
|
width += Math.random() * 15;
|
|
if (width >= 100) {
|
|
width = 100;
|
|
clearInterval(interval);
|
|
}
|
|
bar.style.width = width + '%';
|
|
text.textContent = Math.round(width) + '%';
|
|
}, 200);
|
|
}
|
|
|
|
function openDatePicker() {
|
|
const picker = document.getElementById('datePicker');
|
|
picker.style.display = picker.style.display === 'none' ? 'block' : 'none';
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
</html>
|