mirror of
https://github.com/danny-avila/LibreChat.git
synced 2026-10-20 17:13:44 +00:00
🗺️ refactor: Light Up In-Viewport Ribs at Rest in Message Nav (#14041)
At rest (no hover/focus) the rail now reads like a minimap: only the in-viewport message ribs are at full opacity while the rest fade to 40%, updating live as you scroll. Replaces the blanket nav opacity-30 with per-rib opacity driven by the existing viewport-visibility highlight, so hover/focus still brings every rib to full opacity for the fisheye.
This commit is contained in:
parent
dd8a4558f1
commit
6523a5add6
2 changed files with 28 additions and 6 deletions
|
|
@ -130,10 +130,13 @@ export function magnifyFalloff(distance: number, influence: number): number {
|
|||
}
|
||||
|
||||
const indicatorButtonClasses = cn(
|
||||
'flex h-1.5 w-full items-center justify-end rounded-sm',
|
||||
'flex h-1.5 w-full items-center justify-end rounded-sm transition-opacity duration-300',
|
||||
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-xheavy',
|
||||
);
|
||||
|
||||
const dimIndicatorClasses =
|
||||
'opacity-40 group-hover/nav:opacity-100 group-focus-within/nav:opacity-100';
|
||||
|
||||
const MessageIndicator = memo(function MessageIndicator({
|
||||
entry,
|
||||
isHighlighted,
|
||||
|
|
@ -155,7 +158,7 @@ const MessageIndicator = memo(function MessageIndicator({
|
|||
e.stopPropagation();
|
||||
onSelect(entry.id);
|
||||
}}
|
||||
className={indicatorButtonClasses}
|
||||
className={cn(indicatorButtonClasses, isHighlighted ? 'opacity-100' : dimIndicatorClasses)}
|
||||
aria-label={label}
|
||||
aria-current={isCurrent ? 'true' : undefined}
|
||||
data-msg-id={entry.id}
|
||||
|
|
@ -172,8 +175,9 @@ const MessageIndicator = memo(function MessageIndicator({
|
|||
});
|
||||
|
||||
const chevronButtonClasses = cn(
|
||||
'rounded-md p-0.5 text-text-tertiary transition-colors',
|
||||
'group-hover/nav:text-text-secondary group-focus-within/nav:text-text-secondary',
|
||||
'rounded-md p-0.5 text-text-tertiary opacity-40 transition-[color,opacity] duration-300',
|
||||
'group-hover/nav:text-text-secondary group-hover/nav:opacity-100',
|
||||
'group-focus-within/nav:text-text-secondary group-focus-within/nav:opacity-100',
|
||||
'group-hover/nav:hover:text-text-primary',
|
||||
'group-hover/nav:disabled:opacity-30 group-focus-within/nav:disabled:opacity-30',
|
||||
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-xheavy',
|
||||
|
|
@ -1113,8 +1117,6 @@ function MessageNav({ scrollableRef }: { scrollableRef: React.RefObject<HTMLDivE
|
|||
className={cn(
|
||||
'group/nav absolute right-2 top-1/2 z-40 hidden max-h-[min(24rem,calc(100%-2rem))]',
|
||||
'-translate-y-1/2 flex-col items-end gap-1.5 px-1.5 py-2 md:flex',
|
||||
'opacity-30 transition-opacity duration-300',
|
||||
'focus-within:opacity-100 hover:opacity-100',
|
||||
)}
|
||||
>
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -303,6 +303,26 @@ describe('MessageNav', () => {
|
|||
expect(userLine?.className).toContain('w-4');
|
||||
expect(assistantLine?.className).toContain('w-4');
|
||||
});
|
||||
|
||||
it('lights up only the in-viewport ribs at rest (no hover)', () => {
|
||||
const messages = [
|
||||
buildMessage({ messageId: 'a', text: 'alpha', isCreatedByUser: true }),
|
||||
buildMessage({ messageId: 'b', text: 'bravo' }),
|
||||
buildMessage({ messageId: 'c', text: 'charlie', isCreatedByUser: true }),
|
||||
];
|
||||
const { container } = renderNav(messages);
|
||||
const io = MockIntersectionObserver.last();
|
||||
act(() => {
|
||||
io!.trigger([{ target: document.getElementById('a')!, isIntersecting: true }]);
|
||||
jest.advanceTimersByTime(32);
|
||||
});
|
||||
|
||||
const ribA = container.querySelector('[data-msg-id="a"]') as HTMLElement;
|
||||
const ribB = container.querySelector('[data-msg-id="b"]') as HTMLElement;
|
||||
expect(ribA.className).toContain('opacity-100');
|
||||
expect(ribA.className).not.toContain('opacity-40');
|
||||
expect(ribB.className).toContain('opacity-40');
|
||||
});
|
||||
});
|
||||
|
||||
describe('preview text', () => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue