Improve drag/swipe handling and Features page UX
- SwipeTabs: Delay pointer capture until drag starts for better tap detection - Features: Only allow drag via handle dots, not entire card - Features: Smart hasOrderChanges - hide buttons when order returns to initial - Features: Don't apply dragging style until movement exceeds threshold - ThemeSettings: Add role="button" for accessibility on all option cards - Sidebar: Light theme active menu item styling improvements - Layout: Tab bar translucency and blur effects 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -291,8 +291,16 @@ export default function ThemeSettings() {
|
||||
{colors.map((color) => (
|
||||
<div
|
||||
key={color.id}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={`color-card ${accentColor === color.id ? 'active' : ''}`}
|
||||
onClick={() => handleAccentColorChange(color.id)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleAccentColorChange(color.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="color-swatch-large" style={{ backgroundColor: color.value }}>
|
||||
{accentColor === color.id && (
|
||||
@@ -318,8 +326,16 @@ export default function ThemeSettings() {
|
||||
return (
|
||||
<div
|
||||
key={palette.id}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={`palette-card ${colorPalette === palette.id ? 'active' : ''}`}
|
||||
onClick={() => handleColorPaletteChange(palette.id)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleColorPaletteChange(palette.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="palette-preview">
|
||||
<div className="palette-swatch-row">
|
||||
@@ -363,8 +379,16 @@ export default function ThemeSettings() {
|
||||
{radii.map((radius) => (
|
||||
<div
|
||||
key={radius.id}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={`option-card ${borderRadius === radius.id ? 'active' : ''}`}
|
||||
onClick={() => handleBorderRadiusChange(radius.id)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleBorderRadiusChange(radius.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="option-preview">
|
||||
<div
|
||||
@@ -389,8 +413,16 @@ export default function ThemeSettings() {
|
||||
{sidebarStyles.map((style) => (
|
||||
<div
|
||||
key={style.id}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={`option-card ${sidebarStyle === style.id ? 'active' : ''}`}
|
||||
onClick={() => handleSidebarStyleChange(style.id)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleSidebarStyleChange(style.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="option-preview">
|
||||
<div className={`sidebar-preview sidebar-preview-${style.id}`}>
|
||||
@@ -415,8 +447,16 @@ export default function ThemeSettings() {
|
||||
{sidebarModes.map((mode) => (
|
||||
<div
|
||||
key={mode.id}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={`option-card ${sidebarMode === mode.id ? 'active' : ''}`}
|
||||
onClick={() => setSidebarMode(mode.id)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
setSidebarMode(mode.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="option-preview">
|
||||
<div className={`sidebar-mode-preview sidebar-mode-${mode.id}`}>
|
||||
@@ -441,8 +481,16 @@ export default function ThemeSettings() {
|
||||
{densities.map((d) => (
|
||||
<div
|
||||
key={d.id}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={`option-card ${density === d.id ? 'active' : ''}`}
|
||||
onClick={() => handleDensityChange(d.id)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleDensityChange(d.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="option-preview">
|
||||
<div className={`density-preview density-preview-${d.id}`}>
|
||||
@@ -468,8 +516,16 @@ export default function ThemeSettings() {
|
||||
{fonts.map((f) => (
|
||||
<div
|
||||
key={f.id}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className={`option-card ${fontFamily === f.id ? 'active' : ''}`}
|
||||
onClick={() => handleFontFamilyChange(f.id)}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Enter' || e.key === ' ') {
|
||||
e.preventDefault();
|
||||
handleFontFamilyChange(f.id);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="option-preview">
|
||||
<div className="font-preview" style={{ fontFamily: f.fontStyle }}>
|
||||
|
||||
Reference in New Issue
Block a user