feat(11-04): mobile-safe modals and form baseline verification

- Add max-h-[90vh] overflow-y-auto to ShareModal, CloudCredentialModal,
  FolderDeleteModal, and DocumentView cloud-delete modal panels
- Add responsive px-4 sm:px-6 to DocumentPreviewModal header for narrow viewports
- Add data-test attributes to all modal panels for testability
- Confirm @tailwindcss/forms active in tailwind.config.js (no drift found)
- Audit forms: focus:outline-none focus:ring-2 pattern is consistent throughout
- Add 4 test files covering mobile-safe modal classes and form baseline:
  ShareModal.mobile.test.js, CloudCredentialModal.mobile.test.js,
  FolderDeleteModal.mobile.test.js, DocumentPreviewModal.mobile.test.js

VISUAL-02, RESP-04
This commit is contained in:
curo1305
2026-06-16 21:33:57 +02:00
parent 83cdf28231
commit df53cef3b7
9 changed files with 257 additions and 5 deletions
@@ -5,7 +5,7 @@
@click.self="handleOverlayClick"
@keydown.escape.window="handleEscape"
>
<div class="bg-white rounded-xl shadow-xl w-full max-w-md p-6">
<div data-test="cloud-credential-modal-panel" class="bg-white rounded-xl shadow-xl w-full max-w-md p-6 max-h-[90vh] overflow-y-auto">
<!-- Header -->
<div class="flex items-center justify-between mb-5">
<h3 class="text-xl font-semibold text-gray-900">
@@ -0,0 +1,52 @@
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { mount } from '@vue/test-utils'
import { createPinia, setActivePinia } from 'pinia'
vi.mock('../../../api/client.js', () => ({
getConnectionConfig: vi.fn().mockResolvedValue({ connection_username: '', server_url: '' }),
connectWebDav: vi.fn(),
}))
import CloudCredentialModal from '../CloudCredentialModal.vue'
const globalStubs = {
AppIcon: true,
}
const testProvider = { key: 'webdav', label: 'WebDAV' }
beforeEach(() => {
setActivePinia(createPinia())
vi.clearAllMocks()
})
describe('RESP-04: CloudCredentialModal mobile-safe panel', () => {
it('panel has max-h-[90vh] class for mobile scroll safety', () => {
const wrapper = mount(CloudCredentialModal, {
props: { show: true, provider: testProvider, existing: null },
global: { stubs: globalStubs },
})
const panel = wrapper.find('[data-test="cloud-credential-modal-panel"]')
expect(panel.exists()).toBe(true)
expect(panel.classes()).toContain('max-h-[90vh]')
})
it('panel has overflow-y-auto class for mobile scroll', () => {
const wrapper = mount(CloudCredentialModal, {
props: { show: true, provider: testProvider, existing: null },
global: { stubs: globalStubs },
})
const panel = wrapper.find('[data-test="cloud-credential-modal-panel"]')
expect(panel.classes()).toContain('overflow-y-auto')
})
it('panel not rendered when show=false', () => {
const wrapper = mount(CloudCredentialModal, {
props: { show: false, provider: testProvider, existing: null },
global: { stubs: globalStubs },
})
// When show=false the v-if hides the entire overlay
const panel = wrapper.find('[data-test="cloud-credential-modal-panel"]')
expect(panel.exists()).toBe(false)
})
})