feat(phase-4-09): create new components — FolderRow, FolderBreadcrumb, FolderDeleteModal, ShareModal, DocumentPreviewModal, SearchBar, SortControls, AuditLogTab
- FolderRow: inline rename, three-dot menu, delete/rename callbacks, outside-click close - FolderBreadcrumb: truncation at depth > 4, nav aria-label, ol structure - FolderDeleteModal: role=dialog, warning icon, doc count in body, Keep/Delete buttons - ShareModal: handle input, recipients list with revoke, 404/409 error handling - DocumentPreviewModal: iframe with proxy URL only (never presigned), Escape/overlay close - SearchBar: role=search, aria-label, Escape clears - SortControls: aria-pressed, direction indicator, toggle vs switch logic - AuditLogTab: filters, paginated table, CSV export via window.location.href - api/client.js: add adminListAuditLog function
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<div class="flex items-center gap-1">
|
||||
<span class="sr-only">Sort by:</span>
|
||||
<button
|
||||
v-for="option in sortOptions"
|
||||
:key="option.value"
|
||||
@click="handleClick(option.value)"
|
||||
:aria-pressed="sort === option.value"
|
||||
:aria-label="sort === option.value ? `Sort by ${option.label}, ${order === 'asc' ? 'ascending' : 'descending'}` : `Sort by ${option.label}`"
|
||||
class="text-xs font-medium px-2 py-1 rounded transition-colors"
|
||||
:class="sort === option.value
|
||||
? 'text-indigo-600 font-semibold bg-indigo-50'
|
||||
: 'text-gray-500 hover:text-gray-900'"
|
||||
>
|
||||
{{ option.label }}{{ sort === option.value ? (order === 'asc' ? ' ↑' : ' ↓') : '' }}
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
const props = defineProps({
|
||||
sort: {
|
||||
type: String,
|
||||
default: 'date',
|
||||
},
|
||||
order: {
|
||||
type: String,
|
||||
default: 'desc',
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['change'])
|
||||
|
||||
const sortOptions = [
|
||||
{ value: 'name', label: 'Name' },
|
||||
{ value: 'date', label: 'Date' },
|
||||
{ value: 'size', label: 'Size' },
|
||||
]
|
||||
|
||||
function handleClick(value) {
|
||||
if (props.sort === value) {
|
||||
// Toggle order
|
||||
emit('change', { sort: value, order: props.order === 'asc' ? 'desc' : 'asc' })
|
||||
} else {
|
||||
// Switch to new sort, default desc
|
||||
emit('change', { sort: value, order: 'desc' })
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user