Skip to content

Commit 938d8c5

Browse files
committed
feat: add documentation for custom hooks including useAutosizeTextArea, useClickAway, useDebouncedCallback, useIsMobile, useMarkdownEditor, useServerFile, and useToggle
1 parent df62a02 commit 938d8c5

File tree

7 files changed

+831
-0
lines changed

7 files changed

+831
-0
lines changed

docs/hooks/useAutosizeTextArea.md

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
# useAutosizeTextArea Hook
2+
3+
A custom hook that automatically resizes a textarea element to fit its content, eliminating the need for manual scrolling.
4+
5+
## Location
6+
`src/hooks/use-auto-resize-textarea.ts`
7+
8+
## Signature
9+
```typescript
10+
function useAutosizeTextArea(
11+
textAreaRef: React.RefObject<HTMLTextAreaElement | null>,
12+
value: string,
13+
initialHeight?: string
14+
): void
15+
```
16+
17+
## Parameters
18+
- `textAreaRef`: React ref object pointing to the textarea element
19+
- `value`: Current text content of the textarea (triggers resize when changed)
20+
- `initialHeight` (optional): Initial height to set before auto-sizing
21+
22+
## Returns
23+
None (void) - This hook has side effects on the referenced textarea
24+
25+
## Usage Example
26+
27+
```typescript
28+
import { useAutosizeTextArea } from '@/hooks/use-auto-resize-textarea';
29+
import { useRef, useState } from 'react';
30+
31+
function AutoResizeTextarea() {
32+
const [text, setText] = useState('');
33+
const textareaRef = useRef<HTMLTextAreaElement>(null);
34+
35+
// Auto-resize textarea based on content
36+
useAutosizeTextArea(textareaRef, text);
37+
38+
return (
39+
<textarea
40+
ref={textareaRef}
41+
value={text}
42+
onChange={(e) => setText(e.target.value)}
43+
placeholder="Start typing... The textarea will auto-resize!"
44+
style={{ minHeight: '40px', resize: 'none' }}
45+
/>
46+
);
47+
}
48+
```
49+
50+
## Usage with Initial Height
51+
52+
```typescript
53+
import { useAutosizeTextArea } from '@/hooks/use-auto-resize-textarea';
54+
import { useRef, useState } from 'react';
55+
56+
function CommentBox() {
57+
const [comment, setComment] = useState('');
58+
const textareaRef = useRef<HTMLTextAreaElement>(null);
59+
60+
// Set initial height and auto-resize
61+
useAutosizeTextArea(textareaRef, comment, '60px');
62+
63+
return (
64+
<div className="comment-box">
65+
<textarea
66+
ref={textareaRef}
67+
value={comment}
68+
onChange={(e) => setComment(e.target.value)}
69+
placeholder="Write your comment..."
70+
className="w-full border rounded p-2"
71+
/>
72+
</div>
73+
);
74+
}
75+
```
76+
77+
## Features
78+
- **Automatic resizing**: Adjusts height based on content
79+
- **Initial height support**: Can set a starting height before auto-sizing
80+
- **Performance optimized**: Only recalculates when value changes
81+
- **No external dependencies**: Uses native DOM properties
82+
- **Smooth resizing**: Provides smooth visual transitions
83+
84+
## Implementation Details
85+
- **Trigger**: Runs whenever `value`, `textAreaRef`, or `initialHeight` changes
86+
- **Reset method**: Sets height to 'auto' or initial height first
87+
- **Calculation**: Uses `scrollHeight` property to determine required height
88+
- **Safety check**: Verifies textarea exists before attempting to resize
89+
90+
## CSS Recommendations
91+
92+
```css
93+
.auto-resize-textarea {
94+
resize: none; /* Disable manual resize */
95+
overflow: hidden; /* Hide scrollbars */
96+
min-height: 40px; /* Set minimum height */
97+
transition: height 0.1s ease; /* Smooth height transitions */
98+
}
99+
```
100+
101+
## Common Use Cases
102+
- **Comment boxes**: Auto-expanding comment inputs
103+
- **Message composition**: Chat message inputs that grow with content
104+
- **Note-taking**: Text areas for notes that expand as user types
105+
- **Form fields**: Multi-line form inputs with dynamic sizing
106+
- **Code editors**: Simple code input areas
107+
- **Rich text areas**: Foundation for rich text editors
108+
109+
## Best Practices
110+
- Always set `resize: none` in CSS to prevent manual resizing conflicts
111+
- Set a reasonable `min-height` to prevent textarea from becoming too small
112+
- Consider setting a `max-height` with `overflow-y: auto` for very long content
113+
- Use with controlled components (useState) for proper value tracking
114+
- Test with various content types (short text, long paragraphs, line breaks)
115+
116+
## Styling Tips
117+
```css
118+
/* Recommended base styles */
119+
.autosize-textarea {
120+
resize: none;
121+
overflow: hidden;
122+
min-height: 2.5rem;
123+
max-height: 300px; /* Optional: prevent excessive height */
124+
transition: height 0.15s ease;
125+
box-sizing: border-box;
126+
}
127+
128+
/* When max-height is reached, show scrollbar */
129+
.autosize-textarea.max-height-reached {
130+
overflow-y: auto;
131+
}
132+
```
133+
134+
## Accessibility Considerations
135+
- Maintains all standard textarea accessibility features
136+
- Screen readers work normally with auto-resizing textareas
137+
- Focus behavior remains unchanged
138+
- Keyboard navigation is unaffected
139+
140+
## Performance Notes
141+
- Very lightweight - no expensive calculations
142+
- Uses native DOM properties for optimal performance
143+
- Effect only runs when dependencies change
144+
- No polling or continuous monitoring required

docs/hooks/useClickAway.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# useClickAway Hook
2+
3+
A custom hook that detects clicks outside of a specified element, commonly used for closing modals, dropdowns, and popovers.
4+
5+
## Location
6+
`src/hooks/use-click-away.ts`
7+
8+
## Signature
9+
```typescript
10+
function useClickAway(
11+
ref: React.RefObject<HTMLElement | null>,
12+
callback: () => void
13+
): React.RefObject<HTMLElement | null>
14+
```
15+
16+
## Parameters
17+
- `ref`: React ref object pointing to the element to monitor
18+
- `callback`: Function to execute when a click occurs outside the element
19+
20+
## Returns
21+
- The same ref object passed as parameter (for convenience)
22+
23+
## Usage Example
24+
25+
```typescript
26+
import { useClickAway } from '@/hooks/use-click-away';
27+
import { useRef, useState } from 'react';
28+
29+
function DropdownComponent() {
30+
const [isOpen, setIsOpen] = useState(false);
31+
const dropdownRef = useRef<HTMLDivElement>(null);
32+
33+
// Close dropdown when clicking outside
34+
useClickAway(dropdownRef, () => {
35+
setIsOpen(false);
36+
});
37+
38+
return (
39+
<div>
40+
<button onClick={() => setIsOpen(!isOpen)}>
41+
Toggle Dropdown
42+
</button>
43+
44+
{isOpen && (
45+
<div ref={dropdownRef} className="dropdown-menu">
46+
<p>Dropdown Content</p>
47+
<p>Click outside to close</p>
48+
</div>
49+
)}
50+
</div>
51+
);
52+
}
53+
```
54+
55+
## Alternative Usage with useToggle
56+
57+
```typescript
58+
import { useClickAway } from '@/hooks/use-click-away';
59+
import { useToggle } from '@/hooks/use-toggle';
60+
import { useRef } from 'react';
61+
62+
function ModalComponent() {
63+
const [isOpen, { close, toggle }] = useToggle();
64+
const modalRef = useRef<HTMLDivElement>(null);
65+
66+
useClickAway(modalRef, close);
67+
68+
return (
69+
<div>
70+
<button onClick={toggle}>Open Modal</button>
71+
72+
{isOpen && (
73+
<div className="modal-overlay">
74+
<div ref={modalRef} className="modal-content">
75+
<h2>Modal Content</h2>
76+
<p>Click outside to close</p>
77+
</div>
78+
</div>
79+
)}
80+
</div>
81+
);
82+
}
83+
```
84+
85+
## Features
86+
- **Event delegation**: Uses `mousedown` event for reliable detection
87+
- **Null safety**: Safely handles cases where ref.current is null
88+
- **Automatic cleanup**: Removes event listeners on unmount
89+
- **TypeScript support**: Fully typed with generic HTMLElement support
90+
- **Performance optimized**: Only adds listeners when ref is available
91+
92+
## Implementation Details
93+
- **Event type**: Uses `mousedown` instead of `click` for better UX
94+
- **Event target**: Checks if click target is contained within the referenced element
95+
- **Cleanup**: Properly removes event listeners in useEffect cleanup function
96+
- **Dependencies**: Includes callback and ref in dependency array
97+
98+
## Common Use Cases
99+
- **Dropdown menus**: Close when clicking outside
100+
- **Modal dialogs**: Close modal on backdrop click
101+
- **Popover components**: Dismiss popovers when clicking elsewhere
102+
- **Context menus**: Hide context menus on outside click
103+
- **Autocomplete**: Close suggestions when clicking away
104+
- **Date pickers**: Close calendar when clicking outside
105+
- **Tooltip management**: Hide tooltips on outside interaction
106+
107+
## Event Handling Details
108+
- **Event**: `mousedown` (more responsive than `click`)
109+
- **Target**: Uses `event.target as Node` for type safety
110+
- **Containment**: Uses `element.contains()` to check if click is inside
111+
- **Bubbling**: Attaches to `document` to catch all clicks
112+
113+
## Best Practices
114+
- Always check if `ref.current` exists before using
115+
- Use with state management hooks like `useToggle` for cleaner code
116+
- Consider accessibility implications (ESC key handling, focus management)
117+
- Test with keyboard navigation and screen readers
118+
119+
## Accessibility Considerations
120+
- Should be combined with keyboard event handlers (ESC key)
121+
- Ensure focus management when closing components
122+
- Consider ARIA attributes for better screen reader support
123+
124+
## Browser Compatibility
125+
- Modern browsers with full Event API support
126+
- Uses standard DOM methods (`addEventListener`, `contains`)
127+
- No special polyfills required

docs/hooks/useDebouncedCallback.md

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
# useDebouncedCallback Hook
2+
3+
A custom hook that creates a debounced version of a callback function, useful for limiting API calls or expensive operations.
4+
5+
## Location
6+
`src/hooks/use-debounced-callback.ts`
7+
8+
## Signature
9+
```typescript
10+
function useDebouncedCallback(
11+
callback: (value: string) => void,
12+
delay: number
13+
): (value: string) => void
14+
```
15+
16+
## Parameters
17+
- `callback`: The function to be debounced. Must accept a string parameter.
18+
- `delay`: The delay in milliseconds before the callback is executed.
19+
20+
## Returns
21+
- `debouncedCallback`: A debounced version of the original callback function.
22+
23+
## Usage Example
24+
25+
```typescript
26+
import { useDebouncedCallback } from '@/hooks/use-debounced-callback';
27+
import { useState } from 'react';
28+
29+
function SearchComponent() {
30+
const [query, setQuery] = useState('');
31+
32+
const debouncedSearch = useDebouncedCallback((searchTerm: string) => {
33+
// This will only execute 500ms after the user stops typing
34+
console.log('Searching for:', searchTerm);
35+
performSearch(searchTerm);
36+
}, 500);
37+
38+
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
39+
const value = e.target.value;
40+
setQuery(value);
41+
debouncedSearch(value); // This is debounced
42+
};
43+
44+
return (
45+
<input
46+
type="text"
47+
value={query}
48+
onChange={handleInputChange}
49+
placeholder="Search..."
50+
/>
51+
);
52+
}
53+
```
54+
55+
## Features
56+
- **Automatic cleanup**: Previous timeouts are cleared when new calls are made
57+
- **Memoized**: The debounced function is memoized to prevent unnecessary re-creations
58+
- **TypeScript support**: Fully typed with proper parameter inference
59+
- **Memory safe**: Properly cleans up timeouts to prevent memory leaks
60+
61+
## Implementation Details
62+
- Uses `useRef` to store the timeout reference
63+
- Uses `useCallback` to memoize the debounced function
64+
- Automatically clears previous timeouts before setting new ones
65+
- Dependencies array includes `callback` and `delay` for proper re-memoization
66+
67+
## Common Use Cases
68+
- **Search input**: Debounce API calls while user types
69+
- **Form validation**: Delay validation until user stops typing
70+
- **Auto-save**: Debounce save operations in editors
71+
- **Resize handlers**: Limit expensive calculations on window resize
72+
- **Scroll handlers**: Reduce scroll event processing
73+
- **API rate limiting**: Prevent excessive API calls
74+
75+
## Performance Benefits
76+
- Reduces unnecessary function calls
77+
- Prevents API spam
78+
- Improves application responsiveness
79+
- Reduces server load
80+
- Minimizes expensive computations
81+
82+
## Best Practices
83+
- Use reasonable delay values (200-500ms for search, 1000ms+ for auto-save)
84+
- Consider user experience when choosing delay duration
85+
- Test with real user interaction patterns
86+
- Monitor for memory leaks in long-running applications

0 commit comments

Comments
 (0)