アバター(イニシャル/画像)
:LiTarget: 用途
画像 or イニシャル表示のアバター。色は名前から自動算出。
:LiSparkle: 特徴
- 画像/イニシャル切替
- 名前から色算出
- サイズ可変
- グループ表示
:LiCode: コード(コピペ用)
function colorFromName(name: string): string {
let h = 0;
for (let i = 0; i < name.length; i++) h = ((h << 5) - h) + name.charCodeAt(i);
return `hsl(${Math.abs(h) % 360}, 60%, 55%)`;
}
export function Avatar({ name, src, size = 32 }: {
name: string; src?: string; size?: number;
}) {
const initial = name.charAt(0).toUpperCase();
return (
<span aria-label={name} title={name} style={{
display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
width: size, height: size, borderRadius: '50%',
background: src ? 'transparent' : colorFromName(name),
color: '#fff', fontSize: size * 0.4, fontWeight: 600,
overflow: 'hidden', flexShrink: 0,
}}>
{src ? <img src={src} alt={name} style={{ width: '100%', height: '100%', objectFit: 'cover' }} /> : initial}
</span>
);
}
// グループ表示
export function AvatarGroup({ users, max = 4, size = 32 }: {
users: { name: string; src?: string }[]; max?: number; size?: number;
}) {
const display = users.slice(0, max);
const more = users.length - max;
return (
<div style={{ display: 'inline-flex' }}>
{display.map((u, i) => (
<div key={i} style={{ marginLeft: i === 0 ? 0 : -size * 0.3, border: '2px solid #08080a', borderRadius: '50%' }}>
<Avatar {...u} size={size} />
</div>
))}
{more > 0 && <div style={{
marginLeft: -size * 0.3, width: size, height: size, borderRadius: '50%',
background: 'rgba(255,255,255,.1)', color: '#fff', display: 'inline-flex',
alignItems: 'center', justifyContent: 'center', fontSize: size * 0.35,
border: '2px solid #08080a',
}}>+{more}</div>}
</div>
);
}
:LiHandPointer: 使い方
対象プロジェクトに該当ファイルをコピーして、props を流し込むだけ。
:LiAlertCircle: 注意事項
- 依存パッケージを忘れず追加