Hooks
useListFormat
Locale-aware list formatting with Intl.ListFormat and animated parts support.
useListFormat
A hook that wraps Intl.ListFormat with enhanced features for animated list displays, including an index property on parts and overflow handling.
Import
import { useListFormat } from '@mks2508/mks-ui/react';Why This Hook?
Intl.ListFormat is great for formatting lists with locale-aware separators, but it has limitations:
- No index -
formatToParts()returns{ type, value }without position info - No overflow - Can't add "+N more" without breaking grammar
- No animation support - Hard to animate individual items
This hook solves all three:
// Native Intl.ListFormat
const parts = new Intl.ListFormat('en').formatToParts(['a', 'b', 'c']);
// [{ type: 'element', value: 'a' }, { type: 'literal', value: ', ' }, ...]
// No way to know which element is at index 0, 1, 2!
// useListFormat
const parts = useListFormat(['a', 'b', 'c'], { type: 'conjunction' });
// [{ type: 'element', value: 'a', index: 0 }, { type: 'literal', value: ', ' }, ...]
// Index included for animation mapping!Basic Usage
import { useListFormat } from '@mks2508/mks-ui/react';
function FruitList({ fruits }) {
const parts = useListFormat(fruits, {
locale: 'en-US',
type: 'conjunction',
style: 'long',
});
return (
<span>
{parts.map((part, i) => (
part.type === 'element'
? <span key={part.index}>{part.value}</span>
: <span key={i}>{part.value}</span>
))}
</span>
);
}
// Output: "apple, banana, and orange"List Types
| Type | Description | English Example |
|---|---|---|
conjunction | And-joined list | "a, b, and c" |
disjunction | Or-joined list | "a, b, or c" |
unit | Unit list | "a, b, c" |
List Styles
| Style | Description | English Example |
|---|---|---|
long | Full words | "a, b, and c" |
short | Abbreviated | "a, b, & c" |
narrow | Minimal | "a, b, c" |
Overflow Handling
The hasOverflow parameter adds a placeholder to prevent "and" before overflow text:
function TagList({ tags, maxVisible = 3 }) {
const visible = tags.slice(0, maxVisible);
const overflow = tags.length - maxVisible;
const parts = useListFormat(visible, {
type: 'conjunction',
hasOverflow: overflow > 0, // Prevents "and" before overflow
});
return (
<span>
{parts.map((part, i) => (
part.type === 'element'
? <Tag key={part.index}>{part.value}</Tag>
: <span key={i}>{part.value}</span>
))}
{overflow > 0 && <span>+{overflow} more</span>}
</span>
);
}
// Input: ['a', 'b', 'c', 'd', 'e'], maxVisible=3
// Output: "a, b, c +2 more" (not "a, b, and c +2 more")Custom Separator
Override the default separator:
const parts = useListFormat(items, {
separator: ' | ',
});
// Output: "a | b | c"With Animation
Combine with SlidingText for animated lists:
import { useListFormat, SlidingText } from '@mks2508/mks-ui/react';
function AnimatedList({ items }) {
const parts = useListFormat(items, { type: 'conjunction' });
return (
<span className="inline-flex items-center gap-1">
{parts.map((part, i) =>
part.type === 'element' ? (
<SlidingText
key={part.index}
text={part.value}
mode="character"
/>
) : (
<span key={i}>{part.value}</span>
)
)}
</span>
);
}API Reference
Parameters
useListFormat(
items: string[],
options?: IUseListFormatOptions
): IListPart[]IUseListFormatOptions
| Option | Type | Default | Description |
|---|---|---|---|
locale | string | 'en-US' | Locale for formatting |
type | ListFormatType | 'conjunction' | List type |
style | ListFormatStyle | 'long' | Style length |
separator | string | — | Custom separator override |
hasOverflow | boolean | false | Add placeholder for overflow |
Return Type
interface IListPart {
type: 'element' | 'literal';
value: string;
index?: number; // Only present for 'element' type
}
type ListFormatType = 'conjunction' | 'disjunction' | 'unit';
type ListFormatStyle = 'long' | 'short' | 'narrow';Browser Support
Intl.ListFormat is supported in all modern browsers:
- Chrome 72+
- Firefox 78+
- Safari 14.1+
- Edge 79+
For older browsers, the hook falls back gracefully.
Related
- SlidingText - Text animations
- Reorder - List FLIP animations
- TextFlow - Complete animated list component