Skip to content

Search in files

Results of a search across files, grouped by file with a count, each hit with its line number and the match marked. Put them in a TreeView; Expand all and Collapse all control expandedKeys.

  • SearchFileRow
  • SearchHitRow

PreviewLink to the section Preview

Live in all three themes. Everything here is interactive.

Light theme, Search in files

4 matches in 3 files
QuickOpen.tsxsrc/search2 matches
Line 14import { useFilter } from 'react-aria-components'
Line 58const { contains } = useFilter({ sensitivity: "base" })
CommandPalette.tsxsrc/search1 match
Line 7import { Autocomplete, useFilter } from 'react-aria-components'
filters.tspackages/desktop/src/renderer/views/settings/a-very-long-folder-name1 match
Line 203… right so the lead is cut with an ellipsis: useFilter(options)

Dark theme, Search in files

4 matches in 3 files
QuickOpen.tsxsrc/search2 matches
Line 14import { useFilter } from 'react-aria-components'
Line 58const { contains } = useFilter({ sensitivity: "base" })
CommandPalette.tsxsrc/search1 match
Line 7import { Autocomplete, useFilter } from 'react-aria-components'
filters.tspackages/desktop/src/renderer/views/settings/a-very-long-folder-name1 match
Line 203… right so the lead is cut with an ellipsis: useFilter(options)

High contrast theme, Search in files

4 matches in 3 files
QuickOpen.tsxsrc/search2 matches
Line 14import { useFilter } from 'react-aria-components'
Line 58const { contains } = useFilter({ sensitivity: "base" })
CommandPalette.tsxsrc/search1 match
Line 7import { Autocomplete, useFilter } from 'react-aria-components'
filters.tspackages/desktop/src/renderer/views/settings/a-very-long-folder-name1 match
Line 203… right so the lead is cut with an ellipsis: useFilter(options)

UsageLink to the section Usage

tsx
import { SearchFileRow, SearchHitRow } from '@skribly/ui/code'
tsx
<TreeView aria-label={t('search.results')} expandedKeys={expanded} onExpandedChange={setExpanded}>
  {files.map((file) => (
    <SearchFileRow key={file.path} id={file.path} path={file.path} count={file.hits.length}
      countLabel={t('search.matches', { count: file.hits.length })}>
      {file.hits.map((hit) => (
        <SearchHitRow key={hit.id} id={hit.id} line={hit.line} lineLabel={t('search.line')}
          text={hit.text} matchStart={hit.at} matchLength={hit.length} onAction={() => open(hit)} />
      ))}
    </SearchFileRow>
  ))}
</TreeView>

Every label is a prop, so the app passes its own words in its own language. See no built-in text.

AccessibilityLink to the section Accessibility

  • A tree: Up and Down move, Right opens a file and Left closes it or goes to the file, Enter opens a hit and typing jumps to a file.
  • The count is read in words.
  • The match is tinted, bold and underlined, so it shows without colour; a long lead is cut from the start so the hit stays in view at 400% zoom.

This demo runs through axe in all three themes on every test run. See what the tests check.

Search this site

Arrows move through the results, Enter opens one, Esc closes. Ctrl K /