# Mobile Touch Patterns

## Text Selection Prevention for Touch Interactions

When building components with drag-and-drop, touch gestures, or interactive elements on mobile, text selection can interfere with the user experience. Users attempting to drag items may accidentally select text instead.

### The Problem

On mobile devices:
- Touch-and-hold triggers text selection
- Dragging while text is selected feels broken
- iOS shows callout menus on long press
- Double-tap zoom can interfere with interactions

### The Solution

Apply a combination of CSS rules and Tailwind classes to prevent text selection on interactive elements.

## CSS Pattern

Add this to your component's `<style scoped>` section:

```css
/* Prevent text selection on all draggable/interactive elements AND their children */
:deep([draggable="true"]),
:deep([draggable="true"] *),
:deep(.sortable-item),
:deep(.sortable-item *),
.interactive-item,
.interactive-item * {
  -webkit-user-select: none !important;
  -moz-user-select: none !important;
  -ms-user-select: none !important;
  user-select: none !important;
  -webkit-touch-callout: none !important; /* Prevent iOS callout menu */
}

/* Touch action on containers only (not children) */
:deep([draggable="true"]),
:deep(.sortable-item) {
  touch-action: manipulation; /* Allow pan/zoom but optimize for touch */
}

/* Apply to chosen/active drag states */
:deep(.sortable-chosen),
:deep(.sortable-chosen *) {
  -webkit-user-select: none !important;
  user-select: none !important;
}
```

## Tailwind Classes

Add these classes to interactive container elements:

```html
<div class="select-none touch-manipulation">
  <!-- Interactive content -->
</div>
```

- `select-none` - Prevents text selection (`user-select: none`)
- `touch-manipulation` - Optimizes touch handling (`touch-action: manipulation`)

## When to Apply

Apply this pattern to:

1. **Draggable elements** - Any element using vuedraggable, SortableJS, or native drag-and-drop
2. **Interactive cards/list items** - Items users tap frequently
3. **Custom sliders/controls** - Touch-based UI controls
4. **Bottom sheets/modals** - Draggable overlays
5. **Swipeable elements** - Carousels, dismissible items

## When NOT to Apply

Do NOT apply to:

1. **Form inputs** - Text fields, textareas need selection
2. **Read-only content** - Articles, documentation, static text
3. **Copyable content** - Code blocks, IDs, URLs users might copy

## Vuedraggable Configuration

When using vuedraggable, also configure touch-friendly options:

```typescript
const dragOptions = {
  animation: 200,
  ghostClass: 'drag-ghost',
  chosenClass: 'drag-chosen',
  dragClass: 'drag-dragging',
  // Touch settings for mobile
  delay: 50,                    // Small delay before drag starts
  delayOnTouchOnly: true,       // Only apply delay on touch devices
  touchStartThreshold: 3,       // Pixels of movement before drag starts
}
```

## Example Implementation

```vue
<template>
  <div class="select-none">
    <draggable
      :list="items"
      item-key="id"
      v-bind="dragOptions"
      class="space-y-2"
    >
      <template #item="{ element }">
        <div class="item-card select-none touch-manipulation cursor-grab active:cursor-grabbing">
          <span class="font-medium">{{ element.name }}</span>
        </div>
      </template>
    </draggable>
  </div>
</template>

<style scoped>
/* Full pattern from above */
:deep([draggable="true"]),
:deep([draggable="true"] *) {
  -webkit-user-select: none !important;
  user-select: none !important;
  -webkit-touch-callout: none !important;
}

:deep([draggable="true"]) {
  touch-action: manipulation;
}
</style>
```

## Testing Checklist

When testing on mobile:

- [ ] Can drag items without text selection appearing
- [ ] No iOS callout menu on long press
- [ ] Drag feels responsive (not delayed)
- [ ] Can still scroll the page normally
- [ ] Form inputs still allow text selection
- [ ] No double-tap zoom interference

## References

- [MDN: user-select](https://developer.mozilla.org/en-US/docs/Web/CSS/user-select)
- [MDN: touch-action](https://developer.mozilla.org/en-US/docs/Web/CSS/touch-action)
- [SortableJS Options](https://github.com/SortableJS/Sortable#options)
- [Vuedraggable Documentation](https://github.com/SortableJS/vue.draggable.next)

---

**Created**: 2025-01-17
**Pattern Source**: LineupBuilder.vue mobile drag-and-drop implementation