• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

jcubic / 10xDevs / 19946653658

04 Dec 2025 10:56PM UTC coverage: 62.673%. Remained the same
19946653658

push

github

jcubic
10xDev Project

303 of 501 branches covered (60.48%)

Branch coverage included in aggregate %.

555 of 864 new or added lines in 49 files covered. (64.24%)

4 existing lines in 1 file now uncovered.

555 of 868 relevant lines covered (63.94%)

214.35 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.57
/src/components/notes/RightPanel.tsx
1
/**
2
 * Right sidebar panel for markdown header navigation.
3
 *
4
 * @remarks
5
 * Dependencies: Chakra UI v3, React
6
 *
7
 * **Features:**
8
 * - Displays parsed markdown headers from current note
9
 * - Real-time header filtering
10
 * - Click-to-navigate to header line
11
 * - Current line highlighting
12
 * - Empty state handling
13
 * - Hover states for better UX
14
 *
15
 * **Performance:**
16
 * - Memoized header filtering
17
 * - useCallback for event handlers
18
 *
19
 * @example
20
 * ```tsx
21
 * <RightPanel
22
 *   headers={parsedHeaders}
23
 *   currentLine={42}
24
 *   onHeaderClick={(line) => editorRef.scrollToLine(line)}
25
 * />
26
 * ```
27
 *
28
 * @public
29
 */
30
'use client';
31

32
import { Box, Text, Input, Stack } from '@chakra-ui/react';
33
import { useState, useMemo, useCallback } from 'react';
34
import type { Header } from '@/types/notes';
35

36
/**
37
 * Props for the RightPanel component.
38
 *
39
 * @public
40
 */
41
interface RightPanelProps {
42
  /** Array of headers parsed from the current note */
43
  headers: Header[];
44
  /** Current line number in the editor */
45
  currentLine?: number;
46
  /** Callback invoked when a header is clicked */
47
  onHeaderClick: (line: number) => void;
48
}
49

50
/**
51
 * Renders the right sidebar panel with header navigation.
52
 *
53
 * @param props - Component props
54
 * @param props.headers - Array of parsed markdown headers
55
 * @param props.currentLine - Current line number in editor
56
 * @param props.onHeaderClick - Handler for header click navigation
57
 * @returns Right panel component
58
 *
59
 * @remarks
60
 * Filters headers by text content (case-insensitive).
61
 * Highlights header matching current editor line.
62
 * Shows empty state when no headers found or no matches.
63
 *
64
 * @public
65
 */
66
function RightPanel({ headers, currentLine, onHeaderClick }: RightPanelProps) {
72✔
67
  const [filter, setFilter] = useState('');
918✔
68

69
  const filteredHeaders = useMemo(() => {
918✔
NEW
70
    return headers.filter((header) =>
×
71
      header.text.toLowerCase().includes(filter.toLowerCase())
1,164✔
72
    );
73
  }, [headers, filter]);
74

75
  const handleFilterChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
918✔
NEW
76
    setFilter(e.target.value);
×
77
  }, []);
78

NEW
79
  return (
×
80
    <Box as="aside" h="100%" display="flex" flexDirection="column" bg="bg.subtle">
81
      <Stack gap={4} align="stretch" mx={6} mt={6} mb={0}>
82
        <Text fontSize="md" fontWeight="semibold">
83
          Headers
84
        </Text>
85

86
        <Input
87
          p={3}
88
          placeholder="Filter headers..."
89
          value={filter}
90
          onChange={handleFilterChange}
91
          size="sm"
92
        />
93
      </Stack>
94

95
      <Box
96
        flex={1}
97
        mt={4}
98
        overflow="auto"
99
        w="100%"
100
        borderTop="1px solid"
101
        borderColor="border"
102
      >
103
        {filteredHeaders.length === 0 ? (
×
104
          <Text textAlign="center" color="fg.muted" fontSize="sm" mt={4}>
280✔
105
            {headers.length === 0 ? 'No headers found' : 'No matching headers'}
280!
106
          </Text>
107
        ) : (
108
          <Stack gap={1} p={2}>
109
            {filteredHeaders.map((header) => (
NEW
110
              <Box
×
111
                key={header.id}
112
                cursor="pointer"
113
                bg={currentLine === header.line ? 'blue.solid' : 'transparent'}
1,248✔
114
                color={currentLine === header.line ? 'white' : 'fg'}
1,248✔
115
                _hover={{ bg: currentLine === header.line ? 'blue.solid' : 'bg.muted' }}
1,248✔
116
                borderRadius="md"
117
                px={2}
118
                py={2}
119
                onClick={() => onHeaderClick(header.line)}
5✔
120
                title={`Jump to line ${header.line}`}
121
                data-current={currentLine === header.line ? 'true' : undefined}
1,248✔
122
                data-line={header.line}
123
              >
124
                <Text
125
                  fontSize="sm"
126
                  fontWeight="medium"
127
                  color="currentColor"
128
                  lineClamp={2}
129
                >
130
                  {header.content}
131
                </Text>
132
              </Box>
133
            ))}
134
          </Stack>
135
        )}
136
      </Box>
137
    </Box>
138
  );
139
}
140

141
export default RightPanel;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc