refactor: Implement mobile-friendly control panel toggle and remove keyboard shortcuts hint.
This commit is contained in:
@@ -6,226 +6,336 @@ import TuiButton from "./TuiButton.astro";
|
||||
---
|
||||
|
||||
<footer id="tui-controls" class="control-panel">
|
||||
<div class="control-panel-content">
|
||||
<!-- Sliders Section -->
|
||||
<div class="panel-section sliders-section">
|
||||
<div class="section-header">ADJUSTMENTS</div>
|
||||
<div class="sliders-grid">
|
||||
<TuiSlider
|
||||
id="exposure"
|
||||
label="EXP"
|
||||
min={0}
|
||||
max={3}
|
||||
step={0.01}
|
||||
value={1.0}
|
||||
title="Exposure / Brightness"
|
||||
description="Adjusts the overall brightness level of the input image before processing."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="contrast"
|
||||
label="CON"
|
||||
min={0}
|
||||
max={3}
|
||||
step={0.01}
|
||||
value={1.0}
|
||||
title="Contrast"
|
||||
description="Increases or decreases the difference between light and dark areas."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="saturation"
|
||||
label="SAT"
|
||||
min={0}
|
||||
max={3}
|
||||
step={0.01}
|
||||
value={1.2}
|
||||
title="Saturation"
|
||||
description="Controls color intensity. Higher values make colors more vibrant in Color Mode."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="gamma"
|
||||
label="GAM"
|
||||
min={0}
|
||||
max={3}
|
||||
step={0.01}
|
||||
value={1.0}
|
||||
title="Gamma Correction"
|
||||
description="Non-linear brightness adjustment. useful for correcting washed-out or too dark images."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="overlayStrength"
|
||||
label="OVL"
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
value={0.3}
|
||||
title="Overlay Blend Strength"
|
||||
description="Blends the original image over the ASCII output. 0 is pure ASCII, 1 is original image."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="resolution"
|
||||
label="RES"
|
||||
min={0.1}
|
||||
max={2}
|
||||
step={0.01}
|
||||
value={1.0}
|
||||
title="Resolution Scale"
|
||||
description="Adjusts the density of characters. Higher values give more detail but may reduce performance."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="dither"
|
||||
label="DTH"
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
value={0}
|
||||
title="Dither Strength"
|
||||
description="Applies ordered dithering to simulate shading. Useful for low-contrast areas."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mobile-controls-header">
|
||||
<span class="mobile-controls-title">CONTROLS</span>
|
||||
<svg
|
||||
class="mobile-toggle-icon"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
<div class="panel-divider-v"></div>
|
||||
|
||||
<!-- Toggles & Segments Section -->
|
||||
<div class="panel-section effects-section">
|
||||
<div class="sub-section">
|
||||
<div class="section-header">EFFECTS</div>
|
||||
<div class="toggles-row">
|
||||
<TuiToggle
|
||||
id="toggle-color"
|
||||
label="CLR"
|
||||
title="Color Output (HTML)"
|
||||
description="Toggles between monochrome text and colored HTML spans."
|
||||
<div class="control-panel-inner">
|
||||
<div class="control-panel-content">
|
||||
<!-- Sliders Section -->
|
||||
<div class="panel-section sliders-section">
|
||||
<div class="section-header">ADJUSTMENTS</div>
|
||||
<div class="sliders-grid">
|
||||
<TuiSlider
|
||||
id="exposure"
|
||||
label="EXP"
|
||||
min={0}
|
||||
max={3}
|
||||
step={0.01}
|
||||
value={1.0}
|
||||
title="Exposure / Brightness"
|
||||
description="Adjusts the overall brightness level of the input image before processing."
|
||||
/>
|
||||
|
||||
<TuiToggle
|
||||
id="toggle-denoise"
|
||||
label="DNZ"
|
||||
title="Denoise Pre-processing"
|
||||
description="Applies a bilateral filter to reduce image noise while preserving edges."
|
||||
<TuiSlider
|
||||
id="contrast"
|
||||
label="CON"
|
||||
min={0}
|
||||
max={3}
|
||||
step={0.01}
|
||||
value={1.0}
|
||||
title="Contrast"
|
||||
description="Increases or decreases the difference between light and dark areas."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="shadows"
|
||||
label="SHD"
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
value={0.0}
|
||||
title="Shadow Lift"
|
||||
description="Brightens dark areas to recover details in shadows."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="highlights"
|
||||
label="HLT"
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
value={0.0}
|
||||
title="Highlight Dim"
|
||||
description="Darkens bright areas to recover details in highlights."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="saturation"
|
||||
label="SAT"
|
||||
min={0}
|
||||
max={3}
|
||||
step={0.01}
|
||||
value={1.2}
|
||||
title="Saturation"
|
||||
description="Controls color intensity. Higher values make colors more vibrant in Color Mode."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="gamma"
|
||||
label="GAM"
|
||||
min={0}
|
||||
max={3}
|
||||
step={0.01}
|
||||
value={1.0}
|
||||
title="Gamma Correction"
|
||||
description="Non-linear brightness adjustment. useful for correcting washed-out or too dark images."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="sharpen"
|
||||
label="SHP"
|
||||
min={0}
|
||||
max={2}
|
||||
step={0.01}
|
||||
value={0.0}
|
||||
title="Sharpen"
|
||||
description="Enhances edges and fine details using an unsharp mask filter."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="overlayStrength"
|
||||
label="OVL"
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
value={0.3}
|
||||
title="Overlay Blend Strength"
|
||||
description="Blends the original image over the ASCII output. 0 is pure ASCII, 1 is original image."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="resolution"
|
||||
label="RES"
|
||||
min={0.1}
|
||||
max={2}
|
||||
step={0.01}
|
||||
value={1.0}
|
||||
title="Resolution Scale"
|
||||
description="Adjusts the density of characters. Higher values give more detail but may reduce performance."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="dither"
|
||||
label="DTH"
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
value={0}
|
||||
title="Dither Strength"
|
||||
description="Applies ordered dithering to simulate shading. Useful for low-contrast areas."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="edgeThreshold"
|
||||
label="THR"
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
value={0.5}
|
||||
title="Edge Threshold"
|
||||
description="Sets the sensitivity for edge detection. Higher values detect only strong edges."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="scanlines"
|
||||
label="SCN"
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
value={0.0}
|
||||
title="Scanlines"
|
||||
description="Adds CRT-style scanline effect."
|
||||
/>
|
||||
<TuiSlider
|
||||
id="vignette"
|
||||
label="VIG"
|
||||
min={0}
|
||||
max={1}
|
||||
step={0.01}
|
||||
value={0.0}
|
||||
title="Vignette"
|
||||
description="Darkens the corners of the image."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sub-section">
|
||||
<div class="section-header">OUTPUT</div>
|
||||
<div class="segments-col">
|
||||
<TuiSegment
|
||||
id="segment-invert"
|
||||
label="INV"
|
||||
options={["AUTO", "ON", "OFF"]}
|
||||
value="AUTO"
|
||||
title="Invert Colors"
|
||||
description="Inverts brightness mapping. AUTO detects dark/light mode."
|
||||
/>
|
||||
<TuiSegment
|
||||
id="segment-edge"
|
||||
label="EDG"
|
||||
options={["OFF", "SPL", "SOB", "CNY"]}
|
||||
value="OFF"
|
||||
title="Edge Detection Mode"
|
||||
description="Algorithm used to detect edges. SPL: Simple, SOB: Sobel, CNY: Canny."
|
||||
/>
|
||||
<TuiSegment
|
||||
id="segment-charset"
|
||||
label="SET"
|
||||
options={["STD", "EXT", "BLK", "MIN", "DOT", "SHP"]}
|
||||
value="STD"
|
||||
title="Character Set"
|
||||
description="The set of characters used for mapping brightness levels."
|
||||
/>
|
||||
<div class="panel-divider-v"></div>
|
||||
|
||||
<!-- Toggles & Segments Section -->
|
||||
<div class="panel-section effects-section">
|
||||
<div class="sub-section">
|
||||
<div class="section-header">EFFECTS</div>
|
||||
<div class="toggles-row">
|
||||
<TuiToggle
|
||||
id="toggle-color"
|
||||
label="CLR"
|
||||
title="Color Output (HTML)"
|
||||
description="Toggles between monochrome text and colored HTML spans."
|
||||
/>
|
||||
|
||||
<!-- Color Picker for Monochrome -->
|
||||
<div
|
||||
class="tui-color-btn"
|
||||
title="Monochrome Tint Color"
|
||||
>
|
||||
<input
|
||||
type="color"
|
||||
id="input-mono-color"
|
||||
value="#ffffff"
|
||||
/>
|
||||
<span id="color-swatch-display" class="color-swatch"
|
||||
></span>
|
||||
<span class="label">TINT</span>
|
||||
</div>
|
||||
|
||||
<TuiToggle
|
||||
id="toggle-denoise"
|
||||
label="DNZ"
|
||||
title="Denoise Pre-processing"
|
||||
description="Applies a bilateral filter to reduce image noise while preserving edges."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-divider-v"></div>
|
||||
|
||||
<!-- Right Column: Actions & Export -->
|
||||
<div class="panel-section actions-section">
|
||||
<div class="sub-section">
|
||||
<div class="section-header">ACTIONS</div>
|
||||
<div class="actions-grid">
|
||||
<TuiButton
|
||||
id="btn-reset"
|
||||
label="RESET"
|
||||
shortcut="R"
|
||||
title="Reset to Auto-detected Settings"
|
||||
description="Resets all sliders and toggles to their default values."
|
||||
/>
|
||||
|
||||
<TuiButton
|
||||
id="btn-next"
|
||||
label="NEXT"
|
||||
shortcut="N"
|
||||
variant="primary"
|
||||
title="Load Next Image"
|
||||
description="Discards current image and loads a new one from the queue."
|
||||
/>
|
||||
|
||||
<div
|
||||
class="queue-display"
|
||||
data-tooltip-title="Buffered Images"
|
||||
data-tooltip-desc="Number of images pre-loaded in background queue."
|
||||
>
|
||||
<span class="queue-label">Q:</span>
|
||||
<span id="val-queue" class="queue-value">0</span>
|
||||
<div class="sub-section">
|
||||
<div class="section-header">OUTPUT</div>
|
||||
<div class="segments-col">
|
||||
<TuiSegment
|
||||
id="segment-invert"
|
||||
label="INV"
|
||||
options={["AUTO", "ON", "OFF"]}
|
||||
value="AUTO"
|
||||
title="Invert Colors"
|
||||
description="Inverts brightness mapping. AUTO detects dark/light mode."
|
||||
/>
|
||||
<TuiSegment
|
||||
id="segment-edge"
|
||||
label="EDG"
|
||||
options={["OFF", "SPL", "SOB", "CNY"]}
|
||||
value="OFF"
|
||||
title="Edge Detection Mode"
|
||||
description="Algorithm used to detect edges. SPL: Simple, SOB: Sobel, CNY: Canny."
|
||||
/>
|
||||
<TuiSegment
|
||||
id="segment-charset"
|
||||
label="SET"
|
||||
options={["STD", "EXT", "BLK", "MIN", "DOT", "SHP"]}
|
||||
value="STD"
|
||||
title="Character Set"
|
||||
description="The set of characters used for mapping brightness levels."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-divider-h"></div>
|
||||
<div class="panel-divider-v"></div>
|
||||
|
||||
<div class="sub-section">
|
||||
<div class="section-header">IMPORT / EXPORT</div>
|
||||
<div class="actions-grid">
|
||||
<!-- Hidden File Input -->
|
||||
<input
|
||||
type="file"
|
||||
id="file-upload"
|
||||
accept="image/*"
|
||||
style="display: none;"
|
||||
/>
|
||||
<TuiButton
|
||||
id="btn-import"
|
||||
label="IMP"
|
||||
title="Import Image"
|
||||
description="Upload your own image from your device."
|
||||
/>
|
||||
<TuiButton
|
||||
id="btn-save-png"
|
||||
label="PNG"
|
||||
title="Save as Image"
|
||||
description="Download high-res PNG capture of the current view."
|
||||
/>
|
||||
<TuiButton
|
||||
id="btn-copy-text"
|
||||
label="TXT"
|
||||
title="Save as Text"
|
||||
description="Download raw ASCII text file."
|
||||
/>
|
||||
<TuiButton
|
||||
id="btn-copy-html"
|
||||
label="HTML"
|
||||
title="Save as HTML"
|
||||
description="Download colored HTML file."
|
||||
/>
|
||||
<!-- Right Column: Actions & Export -->
|
||||
<div class="panel-section actions-section">
|
||||
<div class="sub-section">
|
||||
<div class="section-header">ACTIONS</div>
|
||||
<div class="actions-grid">
|
||||
<TuiButton
|
||||
id="btn-reset"
|
||||
label="RESET"
|
||||
shortcut="R"
|
||||
title="Reset to Auto-detected Settings"
|
||||
description="Resets all sliders and toggles to their default values."
|
||||
/>
|
||||
|
||||
<TuiButton
|
||||
id="btn-next"
|
||||
label="NEXT"
|
||||
shortcut="N"
|
||||
variant="primary"
|
||||
title="Load Next Image"
|
||||
description="Discards current image and loads a new one from the queue."
|
||||
/>
|
||||
|
||||
<div
|
||||
class="queue-display"
|
||||
data-tooltip-title="Buffered Images"
|
||||
data-tooltip-desc="Number of images pre-loaded in background queue."
|
||||
>
|
||||
<span class="queue-label">Q:</span>
|
||||
<span id="val-queue" class="queue-value">0</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel-divider-h"></div>
|
||||
|
||||
<div class="sub-section">
|
||||
<div class="section-header">IMPORT / EXPORT</div>
|
||||
<div class="actions-grid">
|
||||
<!-- Hidden File Input -->
|
||||
<input
|
||||
type="file"
|
||||
id="file-upload"
|
||||
accept="image/*"
|
||||
style="display: none;"
|
||||
/>
|
||||
<TuiButton
|
||||
id="btn-import"
|
||||
label="IMP"
|
||||
title="Import Image"
|
||||
description="Upload your own image from your device."
|
||||
/>
|
||||
<TuiButton
|
||||
id="btn-save-png"
|
||||
label="PNG"
|
||||
title="Save as Image"
|
||||
description="Download high-res PNG capture of the current view."
|
||||
/>
|
||||
<TuiButton
|
||||
id="btn-copy-text"
|
||||
label="TXT"
|
||||
title="Save as Text"
|
||||
description="Download raw ASCII text file."
|
||||
/>
|
||||
<TuiButton
|
||||
id="btn-copy-html"
|
||||
label="HTML"
|
||||
title="Save as HTML"
|
||||
description="Download colored HTML file."
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Keyboard shortcuts hint -->
|
||||
<div class="shortcuts-hint">
|
||||
<span><kbd>N</kbd> Next</span>
|
||||
<span><kbd>R</kbd> Reset</span>
|
||||
<span><kbd>I</kbd> Invert</span>
|
||||
<span><kbd>C</kbd> Color</span>
|
||||
<span><kbd>D</kbd> Dither</span>
|
||||
<span><kbd>E</kbd> Edges</span>
|
||||
<span><kbd>S</kbd> Charset</span>
|
||||
<!-- Keyboard shortcuts hint -->
|
||||
<div class="shortcuts-hint">
|
||||
<span><kbd>N</kbd> Next</span>
|
||||
<span><kbd>R</kbd> Reset</span>
|
||||
<span><kbd>I</kbd> Invert</span>
|
||||
<span><kbd>C</kbd> Color</span>
|
||||
<span><kbd>D</kbd> Dither</span>
|
||||
<span><kbd>E</kbd> Edges</span>
|
||||
<span><kbd>S</kbd> Charset</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
const controlPanel = document.getElementById("tui-controls");
|
||||
const toggleBtn = controlPanel?.querySelector(".mobile-controls-header");
|
||||
|
||||
if (controlPanel && toggleBtn) {
|
||||
// Default to collapsed on mobile
|
||||
if (window.innerWidth <= 1200) {
|
||||
controlPanel.classList.add("collapsed");
|
||||
}
|
||||
|
||||
toggleBtn.addEventListener("click", () => {
|
||||
controlPanel.classList.toggle("collapsed");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* Main Container matching Sidebar visual style */
|
||||
.control-panel {
|
||||
@@ -384,10 +494,62 @@ import TuiButton from "./TuiButton.astro";
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.mobile-controls-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 1200px) {
|
||||
.control-panel {
|
||||
padding: 0; /* Let inner content handle padding or just reset */
|
||||
}
|
||||
|
||||
.mobile-controls-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1rem 1.5rem;
|
||||
cursor: pointer;
|
||||
background: #000;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.mobile-controls-title {
|
||||
font-family: var(--font-mono);
|
||||
font-weight: 700;
|
||||
font-size: 0.9rem;
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.mobile-toggle-icon {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.control-panel.collapsed .mobile-toggle-icon {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.control-panel-inner {
|
||||
padding: 1.5rem;
|
||||
overflow: hidden;
|
||||
transition:
|
||||
max-height 0.4s ease,
|
||||
opacity 0.4s ease,
|
||||
padding 0.4s ease;
|
||||
max-height: 2000px;
|
||||
opacity: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.control-panel.collapsed .control-panel-inner {
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
padding: 0 1.5rem;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.control-panel-content {
|
||||
@@ -408,4 +570,55 @@ import TuiButton from "./TuiButton.astro";
|
||||
grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
|
||||
}
|
||||
}
|
||||
|
||||
.tui-color-btn {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
font-family: var(--font-mono);
|
||||
font-size: 11px;
|
||||
padding: 4px 10px;
|
||||
cursor: pointer;
|
||||
border-radius: 2px;
|
||||
transition: all 0.2s;
|
||||
height: 29px; /* Match toggle/button height approx */
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.tui-color-btn:hover {
|
||||
color: #fff;
|
||||
border-color: rgba(255, 255, 255, 0.3);
|
||||
background: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
|
||||
.tui-color-btn input[type="color"] {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
opacity: 0;
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
border: none;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.color-swatch {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
background-color: #ffffff;
|
||||
border-radius: 2px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.3);
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.tui-color-btn .label {
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -3,6 +3,22 @@
|
||||
---
|
||||
|
||||
<aside class="sidebar">
|
||||
<div class="mobile-header">
|
||||
<span class="mobile-brand">SYNTAXBULLET</span>
|
||||
<svg
|
||||
class="mobile-toggle-icon"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="2"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<polyline points="6 9 12 15 18 9"></polyline>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-content">
|
||||
<div class="brand-group">
|
||||
<a href="/" class="brand-link">
|
||||
@@ -10,24 +26,24 @@
|
||||
</a>
|
||||
<div class="brand-subtitle">
|
||||
FULL STACK ENGINEER
|
||||
<span class="muted">//</span>
|
||||
<span class="muted">|</span>
|
||||
CREATIVE TECHNOLOGIST
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p class="brand-bio">
|
||||
Crafting high-performance digital experiences at the intersection of
|
||||
code, art, and artificial intelligence.
|
||||
engineering, design, and artificial intelligence.
|
||||
</p>
|
||||
|
||||
<div class="sidebar-actions">
|
||||
<a href="/projects" class="sidebar-link">
|
||||
<span class="icon">⚡</span> PROJECTS
|
||||
<a href="/" class="sidebar-link">
|
||||
<span class="icon">⚡</span> GENERATE
|
||||
</a>
|
||||
<a href="/blog" class="sidebar-link">
|
||||
<span class="icon">📝</span> BLOG
|
||||
</a>
|
||||
<a href="mailto:contact@syntaxbullet.me" class="sidebar-link">
|
||||
<a href="mailto:me@syntaxbullet.com" class="sidebar-link">
|
||||
<span class="icon">✉️</span> CONTACT
|
||||
</a>
|
||||
</div>
|
||||
@@ -116,6 +132,10 @@
|
||||
box-shadow: 4px 0 20px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.mobile-header {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-content {
|
||||
padding: 4rem 3rem;
|
||||
display: flex;
|
||||
@@ -224,13 +244,52 @@
|
||||
min-width: 0;
|
||||
border-right: none;
|
||||
border-bottom: 1px solid rgba(255, 255, 255, 0.1);
|
||||
padding: 3rem 0; /* Increased padding */
|
||||
padding: 0; /* Remove padding from container, move to toggle */
|
||||
}
|
||||
|
||||
.mobile-header {
|
||||
display: flex; /* Show on mobile */
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 1.5rem;
|
||||
cursor: pointer;
|
||||
background: #000;
|
||||
}
|
||||
|
||||
.mobile-brand {
|
||||
font-size: 1.25rem;
|
||||
font-weight: 900;
|
||||
color: #fff;
|
||||
letter-spacing: -0.5px;
|
||||
}
|
||||
|
||||
.mobile-toggle-icon {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.sidebar.collapsed .mobile-toggle-icon {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
|
||||
.sidebar-content {
|
||||
padding: 1rem 3rem; /* Increased horizontal padding */
|
||||
padding: 0 3rem 3rem 3rem; /* Adjust padding */
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
transition:
|
||||
max-height 0.4s ease,
|
||||
opacity 0.4s ease,
|
||||
padding 0.4s ease;
|
||||
max-height: 1000px; /* Arbitrary large height */
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.sidebar.collapsed .sidebar-content {
|
||||
max-height: 0;
|
||||
opacity: 0;
|
||||
padding: 0 3rem; /* Collapse padding */
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.brand-subtitle,
|
||||
@@ -238,5 +297,29 @@
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Hide the large title in the content on mobile since we have the header,
|
||||
or keep it? The user might want the full bio etc.
|
||||
Let's keep the content as is, but maybe hide the "SYNTAXBULLET" big text in content if it's redundant?
|
||||
Actually, the design seems to desire the big brand text. I'll leave it. */
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
const sidebar = document.querySelector(".sidebar");
|
||||
const toggleBtn = document.querySelector(".mobile-header");
|
||||
|
||||
if (sidebar && toggleBtn) {
|
||||
// Default to collapsed on mobile initially?
|
||||
// User didn't specify, but usually "collapsible" implies starting collapsed or having the ability.
|
||||
// Let's start expanded or collapsed? "Make... collapsible".
|
||||
// I'll default to collapsed to save space as requested "mobile friendly".
|
||||
if (window.innerWidth <= 1024) {
|
||||
sidebar.classList.add("collapsed");
|
||||
}
|
||||
|
||||
toggleBtn.addEventListener("click", () => {
|
||||
sidebar.classList.toggle("collapsed");
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
Reference in New Issue
Block a user