Skip to content

Commit 930667e

Browse files
committed
feat: file search, use octicons
1 parent f4f1ce9 commit 930667e

File tree

7 files changed

+72
-30
lines changed

7 files changed

+72
-30
lines changed

app/components/diff/FileTree.vue

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
<script setup lang="ts">
22
import type { FileChange } from '#shared/types'
3-
import { getFileIcon } from '~/utils/file-icons'
43
54
interface DiffTreeNode {
65
name: string
@@ -113,11 +112,11 @@ function isExpanded(path: string): boolean {
113112
function getChangeIcon(type: 'added' | 'removed' | 'modified') {
114113
switch (type) {
115114
case 'added':
116-
return 'i-carbon-add-alt text-green-500'
115+
return 'i-octicon-diff-added-16 text-green-500'
117116
case 'removed':
118-
return 'i-carbon-subtract-alt text-red-500'
117+
return 'i-octicon-diff-removed-16 text-red-500'
119118
case 'modified':
120-
return 'i-carbon-edit text-yellow-500'
119+
return 'i-octicon-diff-modified-16 text-yellow-500'
121120
}
122121
}
123122
@@ -172,8 +171,7 @@ function handleFileClick(node: DiffTreeNode) {
172171
:style="{ paddingLeft: `${depth * 12 + 32}px` }"
173172
@click="handleFileClick(node)"
174173
>
175-
<span class="w-4 h-4 shrink-0" :class="getFileIcon(node.name)" />
176-
<span class="w-3 h-3 shrink-0" :class="getChangeIcon(node.changeType!)" />
174+
<span class="w-4 h-4 shrink-0" :class="getChangeIcon(node.changeType!)" />
177175
<span class="truncate">{{ node.name }}</span>
178176
</button>
179177
</template>

app/components/diff/SidebarPanel.vue

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,18 @@ const sectionList = computed(() => {
3939
.sort((a, b) => a.order - b.order)
4040
})
4141
42+
const fileSearch = ref('')
43+
4244
const filteredChanges = computed(() => {
43-
if (fileFilter.value === 'all') return props.allChanges
44-
return props.allChanges.filter(f => f.type === fileFilter.value)
45+
let files = props.allChanges
46+
if (fileFilter.value !== 'all') {
47+
files = files.filter(f => f.type === fileFilter.value)
48+
}
49+
if (fileSearch.value.trim()) {
50+
const query = fileSearch.value.trim().toLowerCase()
51+
files = files.filter(f => f.path.toLowerCase().includes(query))
52+
}
53+
return files
4554
})
4655
4756
function getSemverBadgeClass(semverDiff: string | null | undefined): string {
@@ -185,33 +194,51 @@ function handleFileSelect(file: FileChange) {
185194
/>
186195
</summary>
187196

188-
<div class="border-b border-border px-3 py-2 shrink-0 flex items-center justify-end">
189-
<select
190-
v-model="fileFilter"
191-
:aria-label="$t('compare.filter_files_label')"
192-
class="text-[10px] px-2 py-1 bg-bg-subtle border border-border rounded font-mono cursor-pointer hover:border-border-hover transition-colors"
193-
>
194-
<option value="all">
195-
{{ $t('compare.file_filter_option.all', { count: allChanges.length }) }}
196-
</option>
197-
<option value="added">
198-
{{ $t('compare.file_filter_option.added', { count: compare.stats.filesAdded }) }}
199-
</option>
200-
<option value="removed">
201-
{{ $t('compare.file_filter_option.removed', { count: compare.stats.filesRemoved }) }}
202-
</option>
203-
<option value="modified">
204-
{{ $t('compare.file_filter_option.modified', { count: compare.stats.filesModified }) }}
205-
</option>
206-
</select>
197+
<div class="border-b border-border px-3 py-2 shrink-0 space-y-2">
198+
<div class="relative">
199+
<span
200+
class="absolute left-2 top-1/2 -translate-y-1/2 i-carbon-search w-3 h-3 text-fg-subtle pointer-events-none"
201+
/>
202+
<input
203+
v-model="fileSearch"
204+
type="search"
205+
:placeholder="$t('compare.search_files_placeholder')"
206+
:aria-label="$t('compare.search_files_placeholder')"
207+
class="w-full text-[11px] pl-6.5 pr-2 py-1 bg-bg-subtle border border-border rounded font-mono placeholder:text-fg-subtle transition-colors hover:border-border-hover focus:border-accent focus:outline-none"
208+
/>
209+
</div>
210+
<div class="flex items-center justify-end">
211+
<select
212+
v-model="fileFilter"
213+
:aria-label="$t('compare.filter_files_label')"
214+
class="text-[10px] px-2 py-1 bg-bg-subtle border border-border rounded font-mono cursor-pointer hover:border-border-hover transition-colors"
215+
>
216+
<option value="all">
217+
{{ $t('compare.file_filter_option.all', { count: allChanges.length }) }}
218+
</option>
219+
<option value="added">
220+
{{ $t('compare.file_filter_option.added', { count: compare.stats.filesAdded }) }}
221+
</option>
222+
<option value="removed">
223+
{{ $t('compare.file_filter_option.removed', { count: compare.stats.filesRemoved }) }}
224+
</option>
225+
<option value="modified">
226+
{{
227+
$t('compare.file_filter_option.modified', { count: compare.stats.filesModified })
228+
}}
229+
</option>
230+
</select>
231+
</div>
207232
</div>
208233

209234
<div class="flex-1 overflow-y-auto min-h-0">
210235
<div v-if="filteredChanges.length === 0" class="p-8 text-center text-xs text-fg-muted">
211236
{{
212-
fileFilter === 'all'
213-
? $t('compare.no_files_all')
214-
: $t('compare.no_files_filtered', { filter: $t(`compare.filter.${fileFilter}`) })
237+
fileSearch.trim()
238+
? $t('compare.no_files_search', { query: fileSearch.trim() })
239+
: fileFilter === 'all'
240+
? $t('compare.no_files_all')
241+
: $t('compare.no_files_filtered', { filter: $t(`compare.filter.${fileFilter}`) })
215242
}}
216243
</div>
217244

i18n/locales/en.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,9 @@
10111011
"removed": "Removed ({count})",
10121012
"modified": "Modified ({count})"
10131013
},
1014+
"search_files_placeholder": "Search files...",
10141015
"no_files_all": "No files",
1016+
"no_files_search": "No files matching \"{query}\"",
10151017
"no_files_filtered": "No {filter} files",
10161018
"filter": {
10171019
"added": "added",

lunaria/files/en-GB.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,9 @@
10111011
"removed": "Removed ({count})",
10121012
"modified": "Modified ({count})"
10131013
},
1014+
"search_files_placeholder": "Search files...",
10141015
"no_files_all": "No files",
1016+
"no_files_search": "No files matching \"{query}\"",
10151017
"no_files_filtered": "No {filter} files",
10161018
"filter": {
10171019
"added": "added",

lunaria/files/en-US.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,7 +1011,9 @@
10111011
"removed": "Removed ({count})",
10121012
"modified": "Modified ({count})"
10131013
},
1014+
"search_files_placeholder": "Search files...",
10141015
"no_files_all": "No files",
1016+
"no_files_search": "No files matching \"{query}\"",
10151017
"no_files_filtered": "No {filter} files",
10161018
"filter": {
10171019
"added": "added",

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"@floating-ui/vue": "1.1.10",
5151
"@iconify-json/carbon": "1.2.18",
5252
"@iconify-json/lucide": "1.2.87",
53+
"@iconify-json/octicon": "1.2.20",
5354
"@iconify-json/simple-icons": "1.2.68",
5455
"@iconify-json/svg-spinners": "1.2.4",
5556
"@iconify-json/vscode-icons": "1.2.40",

pnpm-lock.yaml

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)