Commit graph

68 commits

Author SHA1 Message Date
callumalpass
d60ceace4b Tighten CSS linting and selector scopes 2026-05-14 23:06:37 +10:00
callumalpass
9d0665e82f Clean up CSS lint issues 2026-05-14 21:06:30 +10:00
callumalpass
490faab1bc Use official Obsidian Bases value rendering 2026-04-26 18:57:21 +10:00
callumalpass
26712c4f7d fix: polish manual ordering drag reorder 2026-03-29 07:35:51 +11:00
ac8318740
99494510f1 fix(drag-reorder): replace line indicator with gap/slot UX and fix drag bugs
- Fix column expand/contract glitch: replace `transition: all` with specific
  properties and remove scale(1.02) transform on dragover columns
- Fix wrong drop position when dragging upward: collapse dragged card's
  layout space after browser captures drag image, removing the phantom
  element that distorted sibling getBoundingClientRect values
- Replace thin 3px accent line with animated gap/slot pattern where sibling
  cards shift apart via translateY to show the drop position
- Lock source column min-height during drag so collapsing the dragged card
  doesn't shrink the priority bucket
- Clip overflow on cards container during drag so translateY shifts don't
  cause scrollbars
- Suppress hover background-color, transform, and box-shadow on all task
  cards during active drag via body-level .tn-drag-active class
- Add rAF throttling to dragover handlers (preventDefault stays synchronous)
- Support cross-column drag: detect container change, clean old, set up new
- Respect prefers-reduced-motion: reduce for shift animations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-29 07:32:29 +11:00
ac8318740
a18f58d3e4 feat(task-list): add drag-to-reorder with shared sort_order algorithm
Extract sort_order computation from KanbanView into sortOrderUtils.ts
as free functions (computeSortOrder, getGroupTasks, renumberAndInsert,
isSortOrderInSortConfig, stripPropertyPrefix) so both views share the
same midpoint insertion algorithm without code duplication.

Add drag-to-reorder to TaskListView:
- Container-level drag event delegation (dragenter/dragover/drop) with
  unconditional e.preventDefault() as required by the HTML5 DnD spec
- Within-group reordering: cards get draggable="true" when sort_order
  is in the view's sort config
- Cross-group dragging: detects group changes via a taskGroupKeys map
  (populated at render time) and updates the group property via
  TaskService.updateProperty alongside the sort_order write
- Deferred re-render during drag to prevent DOM destruction mid-drop
- Works in both flat and grouped modes; gracefully skipped in virtual
  scrolling paths

Simplify .task-card--dragging CSS: remove rotate/scale transforms and
pointer-events:none that caused adjacent cards to steal hit-test events
during drag. Add drop indicator pseudo-elements (::before/::after) for
visual feedback in task-list-view.css.
2026-03-29 07:32:29 +11:00
callumalpass
69b8ae2506 feat: add checklist progress task-card property with Bases support 2026-02-17 20:02:45 +11:00
callumalpass
4c29a1e806 feat(#1205): Add Google Calendar export for tasks
Push TaskNotes tasks to Google Calendar as calendar events with:
- New TaskCalendarSyncService for managing task-to-event sync
- Settings UI in integrations tab for configuration
- Support for custom title templates ({{title}}, {{status}}, {{priority}})
- Automatic sync on task create/update/complete/delete
- Frontmatter-based event ID storage for stable linkage across renames
- Non-blocking sync calls to prevent modal hang
- Sync indicator pill on task cards
- Command palette actions for manual sync
2026-01-04 15:49:25 +11:00
callumalpass
01ac9ee003 fix(#1301): remove blank space from inline task wikilinks when metadata is empty
Only apply margin and min-width to metadata container when it has content,
preventing blank space when all inline task properties are disabled.
2025-12-07 12:09:53 +11:00
callumalpass
887487448a fix: respect Kanban column width setting on mobile (#1279, #1282)
- Remove mobile media query constraints that overrode user's column width setting
- Add spacing between task title and metadata in inline task widgets
2025-12-01 07:22:45 +11:00
callumalpass
2af2bcdad1 feat: add custom icon support for task statuses (#1245, #793)
Add optional Lucide icon configuration for task statuses, allowing
shape-based status differentiation alongside color coding.

- Add icon field to StatusConfig type
- Render Lucide icons via setIcon() when icon is configured
- Add CSS for icon-based status indicators with theme color support
- Add icon input field to status settings UI
- Add translations for all 8 locales (en, de, es, fr, ja, pt, ru, zh)

Users can configure icons per status in Settings → Task Properties by
entering a Lucide icon name (e.g., check, circle, clock). Icons inherit
the status color and improve accessibility for colorblind users.
2025-11-30 17:43:16 +11:00
callumalpass
4ef3fc482c fix: multiple bug fixes and UI enhancements
- (#904) Add visual highlighting for overdue/past dates on task cards
- (#1128) Allow slashes in NLP context names for hierarchical contexts
- (#1151) Increase mini calendar heatmap color intensity for better visibility
- (#1164) Add priorityWeight formula to default Bases templates
- (#1170) Fix dateCreated/dateModified using custom property names in ICS notes
- (#1171) Fix calendar event toggles not responding to changes after initial load
- (#1198) Fix project links resolving relative to wrong file in Bases views
2025-11-30 17:16:16 +11:00
callumalpass
3535b8170a fix: improve inline task embed layout for indented bullets (#1157)
Rework inline task card CSS to properly handle indented bullet lists:
- Switch from inline-flex to inline display for natural text flow
- Allow title text to wrap naturally within line boundaries
- Add scrollable metadata that stays on same line when space permits
- Use em-based sizing for icons to scale with editor font
- Add proper spacing between metadata categories
2025-11-30 11:32:47 +11:00
callumalpass
1bcdb38088 feat: only show border on first selected task
Secondary selected tasks now only show accent background, while the
primary (first) selected task shows both background and border.
2025-11-30 11:32:47 +11:00
callumalpass
acd5ed2975 fix: remove crosshair cursor in selection mode 2025-11-30 11:32:47 +11:00
callumalpass
2f979ad692 feat: click selection indicator to clear selection 2025-11-30 11:32:47 +11:00
callumalpass
3a0cfab8e6 feat: add batch task editing with multi-select support
- Add TaskSelectionService for managing selection state across views
- Add BatchContextMenu for batch operations (status, priority, dates, archive, delete)
- Implement shift-to-select mode with keyboard shortcuts:
  - Shift+click to enter selection mode and toggle selection
  - Ctrl/Cmd+click to toggle individual selection
  - Escape to exit selection mode and clear selection
- Add visual selection feedback (highlighted border on selected cards)
- Add floating selection count indicator
- Integrate selection handling into clickHandlers.ts for all task cards
- Add batch drag-and-drop support in Kanban view
- Handle batch operations on list properties with additive approach
2025-11-30 11:32:47 +11:00
callumalpass
d0dd3ad37c style: polish task card styling with native Obsidian colors
- Simplify hover/focus states to use --background-modifier-hover
- Remove backdrop-filter blur and shadows from metadata pills
- Fix subtask chevron vertical alignment with status dot
- Reduce swimlane label column width in Kanban view
2025-11-30 11:32:47 +11:00
callumalpass
f014949bc7 fix: disable drag cursor for inline task cards
Inline tasks shouldn't show grab cursor or drag effects since they're
embedded in editor content and not meant to be dragged.

- Remove drag handler registration from TaskLinkWidget
- Add CSS overrides for inline draggable cards (fallback)
2025-11-30 11:32:47 +11:00
callumalpass
6588f18c64 feat: preview next status color on status dot hover
- Add --next-status-color CSS custom property to task cards
- Show faded next status color in dot center on hover
- Provides visual feedback for what clicking will do
2025-11-30 11:32:47 +11:00
callumalpass
bfe5fb35fc style: polish task card styling with consistent CSS variables
- Remove dot separators from metadata (use spacing instead)
- Standardize border-radius using CSS variables (xs, sm, md)
- Standardize transitions to use --tn-transition-fast
- Hide badges container when empty via :empty pseudo-selector
- Enhance compact mode with reduced padding and smaller elements
- Rename addMetadataSeparators to updateMetadataVisibility
2025-11-30 11:32:47 +11:00
callumalpass
7d0c831d90 refactor: simplify TaskCard code and improve UI consistency
Code improvements:
- Extract click handlers into reusable factory functions
- Add createStatusCycleHandler, createPriorityClickHandler, etc.
- Add updateCardCompletionState helper for status updates
- Remove ~200 lines of duplicate inline handler code

CSS improvements:
- Remove all cursor: var(--cursor) declarations (keep grab/grabbing for drag)
- Make hover states consistent (no scale transforms, just color/opacity)
- Status dot: border color change only on hover
- Priority dot: opacity change only on hover
- Badges/dates: background color change only on hover
2025-11-30 11:32:47 +11:00
callumalpass
3681903c09 Refactor: Consolidate color patterns and improve consistency
- Replace duplicate color-mix patterns with var(--tn-interactive-hover)
- Normalize rgba() spacing for consistency
- Investigated !important usage: most are necessary for FullCalendar overrides

No line reduction, but improved maintainability and consistency.
2025-11-20 22:22:27 +11:00
callumalpass
830b659a6b Refactor: Remove deprecated legacy classes
Remove unused deprecated classes from task-card-bem.css:
- .tasknotes-card
- .task-content
- .task-title
- .task-metadata-line
- .status-dot
- .recurring-indicator

These classes are no longer used in the codebase and were marked
for removal. Reduces CSS from 18,326 to 18,252 lines (74 lines).
2025-11-20 21:06:34 +11:00
callumalpass
669da8e0b2 Refactor: Further simplify CSS styling
- Remove unused action-button and content-type-buttons style blocks
- Remove unnecessary will-change properties (performance optimization)
- Simplify box-shadow: 0 0 0 0 transparent to box-shadow: none
- Remove empty style blocks with placeholder comments

Reduces CSS from 18,370 to 18,326 lines.
2025-11-20 21:01:37 +11:00
callumalpass
0f9ce902fd Refactor: Pare back unnecessary custom styling
Based on feedback from kepano to reduce custom styling and use
Obsidian's native styles where possible:

- Replace all `cursor: pointer` with `cursor: var(--cursor)` across
  all CSS files (100+ instances). Following Obsidian's convention where
  `cursor: pointer` is only for links.

- Remove forced `border: none; box-shadow: none` rules that were
  fighting against Obsidian's native button styling.

- Scope custom `.tn-btn` button system to `.mod-settings` only,
  allowing Obsidian's native button styles to work elsewhere.

- Add `background: transparent` to mini-calendar buttons to match
  Obsidian's native `.text-icon-button` styling.

This makes the plugin more cohesive with Obsidian's UI and reduces
unnecessary style overrides.
2025-11-20 20:59:30 +11:00
callumalpass
e26c7bd7cb Fix: Task embeds appearing on new line instead of inline with bullets (#1157)
Task embeds (inline task link widgets) were wrapping to a new line instead
of appearing inline with bullet points in lists, particularly when the task
card was wider than the editor screen.

Changes:
- Changed inline task cards to use <span> elements instead of <div> for
  proper inline flow in CodeMirror's rendering context
- Added max-width: calc(100% - 40px) to prevent wrapping to new line
- Added explicit inline display styles to wrapper and child containers
- Strengthened CSS with !important and vertical-align: baseline

The fix ensures task embeds display correctly inline with bullets during
live preview/editing mode, even when they contain multiple metadata properties.

Fixes #1157
2025-11-20 08:09:07 +11:00
callumalpass
b40900d76c Fix: Custom priority colors not being respected in task cards (#1127)
Medium priority was incorrectly sharing the same CSS variable as normal
priority, causing custom colors to be ignored. Each priority now uses its
own correctly-named CSS variable, ensuring custom priority colors
configured in settings are properly displayed.
2025-11-18 12:51:23 +11:00
callumalpass
c456216bf1 Fix: Increase max-width for inline task titles to prevent truncation (#1122)
Inline task titles were being truncated too aggressively at 250-300px,
cutting off normal-length task descriptions. This fix:

- Increases max-width from 250-300px to responsive min(600px, 80vw)
- Fixes white-space property from break-spaces to nowrap for proper ellipsis
- Allows 2-3x more content to display before truncating
- Maintains ellipsis as safety for extremely long titles
- Works responsively on narrow screens (80vw) and wide screens (600px)

Fixes #1122
2025-11-17 23:10:23 +11:00
callumalpass
e2523f97ad Remove glow effects from status and priority dot hovers
Removed box-shadow glow effects from:
- Status dot hover (regular and completed states)
- Priority dot hover

Dots still scale on hover but without the glow ring effect.
2025-11-16 21:46:10 +11:00
callumalpass
bf24c46583 Remove min-width from inline task card title
Removed the 100px min-width constraint on inline task card titles to allow
them to shrink more naturally. Title still takes priority over metadata due
to flex-shrink: 0, but no longer enforces a minimum width.
2025-11-16 21:42:51 +11:00
callumalpass
51c6d14f9f Fix: Prevent subtasks from inheriting parent priority/status styling
Changed CSS selectors to use child combinator (>) instead of descendant
combinator ( ) for priority and status styling. This prevents subtask
priority/status dots from inheriting the parent task's styling.

Before: .task-card--priority-high .task-card__priority-dot
After:  .task-card--priority-high > .task-card__main-row .task-card__priority-dot

This ensures each task card (parent or subtask) displays its own priority
and status colors independently.
2025-11-16 21:21:55 +11:00
callumalpass
83f17cf5d6 Fix: Prevent parent hover background when hovering subtasks/blocking tasks
Added CSS :has() selector to remove parent card hover background and shadow
when the mouse is over the subtasks or blocking tasks containers. This prevents
the washed-out appearance from compounding backgrounds.

Now subtasks and blocking tasks have independent hover states from their parent.
2025-11-16 21:14:29 +11:00
callumalpass
5f0da434c1 Fix: Subtasks and blocking tasks now appear above parent hover background
Added z-index: 1 to .task-card__subtasks and .task-card__blocking to ensure
they render in front of the parent card's hover background color. Previously,
when expanding subtasks or blocking tasks, they would appear behind the
parent's background on hover due to stacking context issues.
2025-11-16 21:10:54 +11:00
callumalpass
d9996cfff2 Refine: Remove lift effects and improve blocked pill contrast
- Removed all translateY lift effects to maintain cleaner feel
- Removed checkmark icon from completed status dots
- Reverted context menu icon size from 20px back to 16px
- Removed letter-spacing adjustments on title
- Fixed blocked pill hover visibility by keeping white text on error background

Status and priority dot hover effects (scale + glow) remain as they provide
good tactile feedback without being distracting.
2025-11-16 21:02:26 +11:00
callumalpass
749810b370 Feature: Enhance task card styling with refined minimalist design
Improved the visual design of task cards throughout the application with
a focus on maintaining minimalism while adding subtle depth and polish.

Key improvements:
- Enhanced visual hierarchy with subtle shadows and smooth transitions
- Improved hover states with scale transforms and glow effects
- Larger status dots (18px) with animated completion state and checkmark
- Refined metadata pills with backdrop blur and improved spacing
- Enhanced interactive elements with lift-on-hover micro-animations
- Better visual separation for subtasks and blocking tasks
- Consistent cubic-bezier easing for polished animations
- Improved accessibility with better touch targets and visual feedback

All changes maintain the minimalist Todoist-inspired aesthetic while
significantly improving visual appeal and user interaction feedback.
2025-11-16 20:51:35 +11:00
callumalpass
ecf6ed793d Feature: Add visual styling for skipped recurring task instances in task cards
Task cards now visually distinguish skipped recurring instances from
completed and pending instances, providing immediate visual feedback
about the current instance state.

Visual Styling:
- Reduced opacity (0.5) for the entire card - similar to archived tasks
- Strike-through title text with muted color
- Special status dot styling:
  - Gray semi-transparent background (rgba(128,128,128,0.4))
  - Dashed border (instead of solid)
  - Faint border color

This creates a clear visual hierarchy:
1. Normal tasks: Full opacity, solid status dot
2. Completed: 0.6 opacity, strike-through, filled status dot
3. Skipped: 0.5 opacity, strike-through, dashed gray status dot
4. Archived: 0.5 opacity

Implementation:
- Added isSkipped check for recurring tasks based on targetDate
- Checks if current instance date is in task.skipped_instances array
- Added task-card--skipped BEM modifier class
- Applied to both createTaskCard() and updateTaskCard() code paths
- Only applies to recurring tasks (non-recurring tasks can't be skipped)

The dashed status dot is the key differentiator - it immediately signals
"skipped" vs "completed" (solid fill) or "pending" (hollow), making it
easy to scan through task lists and understand instance states at a glance.
2025-11-16 17:23:12 +11:00
callumalpass
d5fb266048 Fix: Property mapping for complete_instances and skipped_instances in Bases views
Fixed a critical bug where complete_instances and skipped_instances properties
were not displaying correctly in Bases views. The issue was in PropertyMappingService
and related mapping functions that were converting frontmatter property names
(e.g., "complete_instances") to mapping keys (e.g., "completeInstances"), which
didn't match the TaskCard property extractors and renderers.

Changes:
- PropertyMappingService.basesToInternal(): Return the original property name
  instead of the mapping key when a property is recognized by FieldMapper
- TaskCard.getPropertyValue(): Removed unnecessary FieldMapper conversion that
  was causing the same mapping key mismatch
- mapBasesPropertyToTaskCardProperty(): Keep recognized properties as-is instead
  of converting to mapping keys

This ensures that property names flow consistently from Bases columns through
to TaskCard rendering, allowing the custom renderers to properly display
completion statistics like "✓ 12 completed (75%)" and "⊘ 3 skipped".
2025-11-16 12:41:07 +11:00
callumalpass
4fc16bf18b Fix inline task link overlay layout: prioritize title and add horizontal scrolling for metadata
When task link overlays have many visible metadata properties, the title was
disappearing. This commit ensures the title is always visible and makes the
metadata list horizontally scrollable when too long.

Changes:
- Title now has min-width of 100px and won't shrink (flex-shrink: 0)
- Metadata container uses inline-block with horizontal scrolling
- All metadata children (dates, properties, pills, separators) set to not wrap or shrink
- Scrollbar hidden by default, appears on hover with overlay positioning
- Proper baseline alignment maintained with line-height inheritance
- No vertical shift when scrollbar appears

The metadata section now scrolls horizontally when content is too long, while
keeping the task title always visible and properly aligned with editor text.
2025-11-09 19:41:57 +11:00
callumalpass
9cd3bd1595 Unify property selection UI with user field support
- Extract PropertySelectorModal to shared location (src/modals/)
- Create shared property list builder utility (src/utils/propertyHelpers.ts)
- Update inline properties setting to use shared modal and helpers
- Replace default properties checkboxes with modal UI for consistency
- User-defined fields now automatically available in both property selectors
- Consistent UX across inline and default property configuration
2025-11-09 19:41:57 +11:00
callumalpass
f8ba9a9920 Improve task dependency modelling and selection UI 2025-09-28 15:28:41 +10:00
callumalpass
299cf7f178 Add blocked/blocking task metadata pills 2025-09-28 12:17:51 +10:00
callumalpass
de3d6c0d28 initial implementation of blocking/blocked by 2025-09-28 12:17:51 +10:00
renatomen
663b209371 feat(ui): subtask chevron position setting; default right; update TaskCard/styles; add tests 2025-08-15 22:58:05 +10:00
Callum Alpass
24eeb4a92b feat: Implement task reminders system with iCalendar VALARM support
## New Features

### Core Reminder System
- Add `reminders` field to TaskInfo interface following iCalendar VALARM spec
- Support both relative (`-PT15M`) and absolute (`2025-10-26T09:00:00`) reminders
- Implement reminder data mapping in FieldMapper and MinimalNativeCache
- Add reminders to task creation and edit workflows

### User Interface Components
- **ReminderModal**: Complete modal for managing task reminders
  - Add/remove relative and absolute reminders
  - Visual forms with date/time pickers and duration controls
  - Real-time preview and validation
- **ReminderContextMenu**: Quick access menu for common reminder actions
  - Pre-configured options (5min, 15min, 1hr, 1day before)
  - Context-aware based on task due/scheduled dates
- **Task Cards**: Bell icon indicators for tasks with reminders
  - Click to open reminder management modal
  - Tooltip showing reminder count
  - Proper CSS positioning to avoid icon overlap

### Modal Enhancements
- Add reminder icons to TaskCreationModal and TaskEditModal action bars
- Enhanced event system for real-time UI updates
- Support for reminder preview changes during editing

### Notification Service
- NotificationService foundation for future reminder notifications
- Settings for notification preferences (system vs in-app)
- Integration points for reminder processing

## Technical Implementation

### Data Layer
- Extended TaskInfo with optional `reminders: Reminder[]` field
- Updated FieldMapper to handle reminder array serialization
- Modified MinimalNativeCache and helpers to include reminders in task extraction
- Enhanced TaskService to support reminder CRUD operations

### Event System
- Enhanced ReminderModal with comprehensive event emission
- `reminder-changed` events for saved changes
- `reminder-preview-changed` events for real-time feedback
- Proper cancellation handling and state reset

### Styling
- New reminder-modal.css for modal components
- Updated task-card-bem.css with proper icon positioning
- BEM methodology for consistent component styling
- Responsive design considerations

## Bug Fixes
- Fix icon overlap on task cards by adjusting CSS positioning:
  - Recurring indicator: `right: 26px`
  - Reminder indicator: `right: 44px`
  - Project indicator: `right: 62px`
  - Chevron: `right: 80px`
- Ensure reminders field properly propagates through cache system
- Add TypeScript type safety for reminder data structures

## Settings Integration
- Add notification preferences to settings panel
- Field mapping support for custom reminder property names
- Backward compatibility with existing task data

This implementation provides a complete foundation for task reminders while
maintaining full backward compatibility and following the plugin's architectural patterns.
2025-08-07 13:01:04 +10:00
Callum Alpass
961ed6ec96 fix: Resolve expandable subtasks event bubbling and styling issues
Fix two critical issues with expandable subtasks:

1. **Event bubbling**: Clicking subtasks opened both subtask and parent modals
   - Add click event stopPropagation to subtasks container
   - Prevents parent task card click handlers from firing

2. **Completion styling bleed**: Marking any task complete styled all tasks as complete
   - Make completion CSS selectors more specific using child combinator (>)
   - Scope completion styles to only affect direct main-row children
   - Prevents parent completion styles from affecting nested subtasks

Technical changes:
- Added event.stopPropagation() to subtasks container click handler
- Updated CSS selectors from descendant to child combinator:
  - .task-card--completed → .task-card--completed > .task-card__main-row
  - .task-card--completed .task-card__title → .task-card--completed > .task-card__main-row .task-card__title
  - .task-card--completed .task-card__status-dot → .task-card--completed > .task-card__main-row .task-card__status-dot
2025-08-03 16:06:47 +10:00
Callum Alpass
c83cf83871 feat: Add expandable subtasks to project task cards
Add chevron icon to project task cards that allows users to expand and view
subtasks inline with proper indentation and visual hierarchy.

Key features:
- Chevron icon positioned next to folder icon on project tasks
- Click to expand/collapse shows subtasks below with 20px indentation
- Smooth rotation animation and hover effects
- Configurable via new "Show expandable subtasks" setting (default: enabled)
- Session-persistent expanded state via ExpandedProjectsService
- Proper DOM structure with main-row wrapper for correct layout
- Subtasks render with lighter background and visual separation
- Lazy loading - subtasks only fetch when expanded
- Graceful error handling and loading states

Technical implementation:
- New ExpandedProjectsService for state management
- Enhanced TaskCard component with main-row/subtasks layout
- Comprehensive BEM CSS styling for chevron and subtask containers
- Updated settings interface with new showExpandableSubtasks option
- Integrated with existing ProjectSubtasksService for data fetching
2025-08-03 16:01:24 +10:00
Callum Alpass
8851b1095f style: Apply consistent minimalist styling across UI components
- Remove unnecessary borders and box shadows from multiple components
- Standardize button heights and spacing for consistency
- Clean up hover states and transitions for better UX
- Update calendar, filter bar, modal, note card, pomodoro, and task card styling
- Maintain functionality while achieving cleaner visual appearance

This completes the minimalist design system implementation across
all major UI components in the plugin.
2025-07-26 20:35:18 +10:00
Callum Alpass
be6adb140d feat: Add CSS styling for project indicator icons (#191)
- Add .task-card__project-indicator styles with hover effects
- Position icons at right: 44px after recurring indicator
- Include smooth transitions and scale effects on hover
- Follow existing BEM naming conventions and design patterns
2025-07-16 21:28:17 +10:00
Callum Alpass
cefb1f2113 fix: enhance project link clickability and accessibility in TaskCard
- Add proper project link rendering with click handlers for wikilink projects
- Enhance CSS styling with better focus states and z-index positioning
- Add keyboard support (Enter/Space) for accessibility
- Add error handling for failed file operations
- Improve visual feedback with hover states and focus indicators
- Add comprehensive test coverage for project link functionality
- Ensure proper DOM structure with inline-block display and relative positioning
2025-07-05 11:09:40 +10:00