From 6add377db4713ef4743239404c877fd989b5a918 Mon Sep 17 00:00:00 2001 From: Ben Floyd Date: Tue, 16 Dec 2025 15:32:14 -0700 Subject: [PATCH] collapse button --- src/features/backlinks/BlockComponent.ts | 12 ++++++++-- src/features/backlinks/HeaderComponent.ts | 11 +-------- src/features/backlinks/HeaderUI.ts | 9 +++++--- src/features/backlinks/SettingsControls.ts | 23 +++++++------------ .../backlinks/ui/BacklinksViewController.ts | 8 ++++++- src/features/shared-utilities/IconProvider.ts | 1 + styles/components/blocks.css | 13 ++++++++--- styles/components/header.css | 9 +------- 8 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/features/backlinks/BlockComponent.ts b/src/features/backlinks/BlockComponent.ts index 5cb8bcf..fd80246 100644 --- a/src/features/backlinks/BlockComponent.ts +++ b/src/features/backlinks/BlockComponent.ts @@ -79,9 +79,11 @@ export class BlockComponent { private createToggleButton(): void { this.toggleButton = this.headerContainer.createEl('span', { cls: 'coalesce-toggle-arrow', - text: '▼', }); + // Use chevron icon instead of text characters for consistency with header + IconProvider.setIcon(this.toggleButton, 'chevronDown', { size: 'sm' }); + this.toggleButton.addEventListener('click', (event) => { this.logger.debug('Toggle button clicked'); event.stopPropagation(); // Prevent header click from also triggering @@ -328,7 +330,13 @@ export class BlockComponent { } else { this.mainContainer.classList.remove('is-collapsed'); } - this.toggleButton.textContent = collapsed ? '▶' : '▼'; + + // Update icon based on state: chevron-right when collapsed, chevron-down when expanded + IconProvider.setIcon( + this.toggleButton, + collapsed ? 'chevronRight' : 'chevronDown', + { size: 'sm' } + ); } public updateTitleDisplay(headerStyle: string): void { diff --git a/src/features/backlinks/HeaderComponent.ts b/src/features/backlinks/HeaderComponent.ts index 7b3f14a..86ccc1b 100644 --- a/src/features/backlinks/HeaderComponent.ts +++ b/src/features/backlinks/HeaderComponent.ts @@ -306,22 +306,13 @@ export class HeaderComponent { const collapseButton = createIconButton({ parent: tempContainer, - icon: 'chevronDown', + icon: isCollapsed ? 'chevronRight' : 'chevronDown', size: 'sm', ariaLabel: isCollapsed ? 'Expand all' : 'Collapse all', classes: ['coalesce-collapse-button'], onClick: onCollapseToggle }); - const svg = collapseButton.querySelector('svg') as SVGElement | null; - if (svg) { - if (isCollapsed) { - svg.classList.add('is-collapsed'); - } else { - svg.classList.remove('is-collapsed'); - } - } - return collapseButton; } diff --git a/src/features/backlinks/HeaderUI.ts b/src/features/backlinks/HeaderUI.ts index b68acb5..fe468ae 100644 --- a/src/features/backlinks/HeaderUI.ts +++ b/src/features/backlinks/HeaderUI.ts @@ -230,9 +230,12 @@ export class HeaderUI implements IHeaderUI { try { const collapseButton = header.querySelector('.coalesce-collapse-button') as HTMLElement; if (collapseButton) { - const classesToAdd = isCollapsed ? ['is-collapsed'] : []; - const classesToRemove = isCollapsed ? [] : ['is-collapsed']; - IconProvider.updateIconClasses(collapseButton, classesToAdd, classesToRemove); + // Update icon based on state: chevron-right when collapsed, chevron-down when expanded + IconProvider.setIcon( + collapseButton, + isCollapsed ? 'chevronRight' : 'chevronDown', + { size: 'sm' } + ); } } catch (error) { this.logger.error('Failed to update collapse button state', { header, isCollapsed, error }); diff --git a/src/features/backlinks/SettingsControls.ts b/src/features/backlinks/SettingsControls.ts index e95cc0b..dab034e 100644 --- a/src/features/backlinks/SettingsControls.ts +++ b/src/features/backlinks/SettingsControls.ts @@ -1,4 +1,5 @@ import { Logger } from '../shared-utilities/Logger'; +import { IconProvider } from '../shared-utilities/IconProvider'; import { ISettingsControls, SortButtonOptions, @@ -78,19 +79,13 @@ export class SettingsControls implements ISettingsControls { const button = createIconButton({ parent: buttonContainer, - icon: 'chevronDown', + icon: options.isCollapsed ? 'chevronRight' : 'chevronDown', size: 'sm', ariaLabel: options.isCollapsed ? 'Expand all' : 'Collapse all', classes: ['coalesce-collapse-button'], onClick: options.onToggle }); - // Set initial state - const svg = button.querySelector('svg') as SVGElement | null; - if (svg && options.isCollapsed) { - svg.classList.add('is-collapsed'); - } - this.logger.debug('Collapse button created successfully', { buttonContainer }); return buttonContainer; } catch (error) { @@ -244,14 +239,12 @@ export class SettingsControls implements ISettingsControls { this.logger.debug('Updating collapse button state', { isCollapsed }); try { - const svg = button.querySelector('svg') as SVGElement; - if (svg) { - if (isCollapsed) { - svg.classList.add('is-collapsed'); - } else { - svg.classList.remove('is-collapsed'); - } - } + // Update icon based on state: chevron-right when collapsed, chevron-down when expanded + IconProvider.setIcon( + button, + isCollapsed ? 'chevronRight' : 'chevronDown', + { size: 'sm' } + ); } catch (error) { this.logger.error('Failed to update collapse button state', { button, isCollapsed, error }); } diff --git a/src/features/backlinks/ui/BacklinksViewController.ts b/src/features/backlinks/ui/BacklinksViewController.ts index 6ee8d34..3aa7199 100644 --- a/src/features/backlinks/ui/BacklinksViewController.ts +++ b/src/features/backlinks/ui/BacklinksViewController.ts @@ -1,6 +1,7 @@ import { App, TFile, MarkdownView } from 'obsidian'; import { Logger } from '../../shared-utilities/Logger'; import { PerformanceMonitor } from '../../shared-utilities/PerformanceMonitor'; +import { IconProvider } from '../../shared-utilities/IconProvider'; import { BlockData, BlockRenderOptions, @@ -760,7 +761,12 @@ export class BacklinksViewController { '.coalesce-toggle-arrow' ) as HTMLElement; if (toggleArrow) { - toggleArrow.textContent = collapsed ? '▶' : '▼'; + // Update icon based on state: chevron-right when collapsed, chevron-down when expanded + IconProvider.setIcon( + toggleArrow, + collapsed ? 'chevronRight' : 'chevronDown', + { size: 'sm' } + ); } }); } diff --git a/src/features/shared-utilities/IconProvider.ts b/src/features/shared-utilities/IconProvider.ts index 481e609..433b04c 100644 --- a/src/features/shared-utilities/IconProvider.ts +++ b/src/features/shared-utilities/IconProvider.ts @@ -29,6 +29,7 @@ export class IconProvider { sortToggle: 'arrow-up-down', // For toggle buttons chevronDown: 'chevron-down', chevronUp: 'chevron-up', + chevronRight: 'chevron-right', // UI controls settings: 'more-horizontal', diff --git a/styles/components/blocks.css b/styles/components/blocks.css index 0d019f3..fa9851f 100644 --- a/styles/components/blocks.css +++ b/styles/components/blocks.css @@ -20,9 +20,16 @@ .coalesce-toggle-arrow { cursor: pointer; margin-right: 5px; - transition: transform 0.2s ease; - font-size: 11px; - line-height: 1; + display: flex; + align-items: center; + justify-content: center; +} + +/* Toggle arrow icon styling */ +.coalesce-toggle-arrow svg { + width: var(--coalesce-icon-size-sm); + height: var(--coalesce-icon-size-sm); + transition: opacity 0.2s ease; } /* Block title link */ diff --git a/styles/components/header.css b/styles/components/header.css index 67151a7..e1d32cb 100644 --- a/styles/components/header.css +++ b/styles/components/header.css @@ -38,14 +38,7 @@ flex-wrap: nowrap; } -/* Button group and icon transforms */ -.coalesce-button-group svg:not(.is-collapsed) { - transform: none; -} - -.coalesce-button-group svg.is-collapsed { - transform: rotate(-90deg); -} +/* Button group - icon transforms removed since we use different icons for collapsed/expanded states */ .coalesce-button-group svg.sort-ascending { transform: rotate(180deg);