justin.deal/src/components/common/StyleControls.astro

227 lines
7.9 KiB
Plaintext
Raw Normal View History

---
interface Props {
showSizeSelector?: boolean;
showViewSelector?: boolean;
className?: string;
}
const {
showSizeSelector = true,
showViewSelector = true,
className = "",
} = Astro.props;
---
<div class={`flex items-center gap-4 ${className}`}>
{showSizeSelector && (
<div class="flex items-center gap-2">
<span class="text-sm zag-text-muted hidden sm:inline">Size:</span>
2025-05-03 19:05:21 -07:00
<div class="size-selector flex flex-col items-center border-2 border-solid zag-border-b rounded-lg p-2 zag-bg zag-transition">
<input
type="range"
min="1"
max="3"
step="1"
x-model="iconSizeValue"
@input="updateIconSizeFromSlider()"
class="size-slider w-full"
aria-label="Icon size slider"
title="Adjust icon size (Alt+1: Small, Alt+2: Medium, Alt+3: Large)"
/>
</div>
</div>
)}
2025-05-03 13:35:55 -07:00
{/* Display options selector */}
<div class="flex items-center gap-2">
<span class="text-sm zag-text-muted hidden sm:inline">Display:</span>
<div class="display-selector flex items-center gap-1 border-2 border-solid zag-border-b rounded-lg p-1 zag-bg zag-transition">
<button
@click="setDisplayMode('both')"
:class="displayMode === 'both' ? 'active-display' : 'inactive-display'"
class="p-1.5 transition-all rounded-md focus:outline-none focus:ring-2 focus:ring-current"
aria-label="Show both image and name"
title="Show both image and name (Alt+B)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="12" rx="2" ry="2"></rect>
<line x1="3" y1="19" x2="21" y2="19"></line>
<line x1="3" y1="23" x2="21" y2="23"></line>
</svg>
</button>
<button
@click="setDisplayMode('image')"
:class="displayMode === 'image' ? 'active-display' : 'inactive-display'"
class="p-1.5 transition-all rounded-md focus:outline-none focus:ring-2 focus:ring-current"
aria-label="Show image only"
title="Show image only (Alt+I)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
2025-05-03 19:08:16 -07:00
<circle cx="8.5" cy="8.5" r="1.5"></circle>
<polyline points="21 15 16 10 5 21"></polyline>
2025-05-03 13:35:55 -07:00
</svg>
</button>
<button
@click="setDisplayMode('name')"
:class="displayMode === 'name' ? 'active-display' : 'inactive-display'"
class="p-1.5 transition-all rounded-md focus:outline-none focus:ring-2 focus:ring-current"
aria-label="Show name only"
title="Show name only (Alt+N)"
>
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="3" y1="12" x2="21" y2="12"></line>
<line x1="3" y1="6" x2="21" y2="6"></line>
<line x1="3" y1="18" x2="21" y2="18"></line>
</svg>
</button>
</div>
</div>
{showViewSelector && (
<div class="flex items-center gap-2">
<span class="text-sm zag-text-muted hidden sm:inline">View:</span>
<div class="view-selector border-2 border-solid zag-border-b rounded-lg p-1 zag-bg zag-transition">
<button
@click="toggleViewMode"
:class="viewMode === 'grid' ? 'active-view' : 'inactive-view'"
class="p-1.5 transition-all rounded-md focus:outline-none focus:ring-2 focus:ring-current"
aria-label="Toggle view mode"
:title="viewMode === 'grid' ? 'Switch to list view (Alt+G)' : 'Switch to grid view (Alt+G)'"
>
<svg x-show="viewMode === 'grid'" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="7" height="7"></rect>
<rect x="14" y="3" width="7" height="7"></rect>
<rect x="14" y="14" width="7" height="7"></rect>
<rect x="3" y="14" width="7" height="7"></rect>
</svg>
<svg x-show="viewMode === 'list'" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<line x1="8" y1="6" x2="21" y2="6"></line>
<line x1="8" y1="12" x2="21" y2="12"></line>
<line x1="8" y1="18" x2="21" y2="18"></line>
<line x1="3" y1="6" x2="3.01" y2="6"></line>
<line x1="3" y1="12" x2="3.01" y2="12"></line>
<line x1="3" y1="18" x2="3.01" y2="18"></line>
</svg>
</button>
</div>
</div>
)}
</div>
<style>
2025-05-03 13:35:55 -07:00
.size-selector, .view-selector, .display-selector {
box-shadow: 2px 2px 0 var(--color-zag-dark);
:where(.dark, .dark *) & {
box-shadow: 2px 2px 0 var(--color-zag-light);
}
}
2025-05-03 13:35:55 -07:00
.active-size, .active-view, .active-display {
color: var(--color-zag-dark);
background-color: var(--color-zag-light);
transform: translateY(-1px);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
:where(.dark, .dark *) & {
color: var(--color-zag-dark);
}
}
2025-05-03 13:35:55 -07:00
.inactive-size, .inactive-view, .inactive-display {
color: var(--color-zag-dark-muted);
:where(.dark, .dark *) & {
color: var(--color-zag-light-muted);
}
}
2025-05-03 13:35:55 -07:00
.inactive-size:hover, .inactive-view:hover, .inactive-display:hover {
background-color: var(--color-zag-light-muted);
color: var(--color-zag-dark);
:where(.dark, .dark *) & {
background-color: var(--color-zag-dark-muted);
color: var(--color-zag-light);
}
}
2025-05-03 19:05:21 -07:00
/* Slider styles */
.size-slider {
-webkit-appearance: none;
appearance: none;
height: 6px;
border-radius: 3px;
background: var(--color-zag-light-muted);
outline: none;
cursor: pointer;
transition: all 0.2s;
:where(.dark, .dark *) & {
background: var(--color-zag-dark-muted);
}
}
/* Slider thumb */
.size-slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--color-zag-dark);
cursor: pointer;
border: 2px solid var(--color-zag-light);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
transition: all 0.2s;
:where(.dark, .dark *) & {
background: var(--color-zag-light);
border: 2px solid var(--color-zag-dark);
}
}
.size-slider::-moz-range-thumb {
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--color-zag-dark);
cursor: pointer;
border: 2px solid var(--color-zag-light);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
transition: all 0.2s;
:where(.dark, .dark *) & {
background: var(--color-zag-light);
border: 2px solid var(--color-zag-dark);
}
}
/* Hover state */
.size-slider:hover::-webkit-slider-thumb {
transform: scale(1.1);
}
.size-slider:hover::-moz-range-thumb {
transform: scale(1.1);
}
/* Focus state */
.size-slider:focus {
outline: none;
}
.size-slider:focus::-webkit-slider-thumb {
box-shadow: 0 0 0 3px var(--color-zag-light), 0 0 0 5px var(--color-zag-dark-muted);
:where(.dark, .dark *) & {
box-shadow: 0 0 0 3px var(--color-zag-dark), 0 0 0 5px var(--color-zag-light-muted);
}
}
.size-slider:focus::-moz-range-thumb {
box-shadow: 0 0 0 3px var(--color-zag-light), 0 0 0 5px var(--color-zag-dark-muted);
:where(.dark, .dark *) & {
box-shadow: 0 0 0 3px var(--color-zag-dark), 0 0 0 5px var(--color-zag-light-muted);
}
}
</style>