Mood dot / word / score
Todo valor de ánimo. Color solo para ánimo, siempre acompañado de la palabra.
La misma escala en cada lectura de ánimo. MoodDot aporta el color; MoodWord agrega el nombre. La app redondea el promedio al nivel más cercano (clampLevel); moodLevel usa los cortes de la galería y hoy no se usa en la app. Sin datos (promedio 0) se muestra un punto gris, nunca Muy bajo.
Instalación
shadcn
npx shadcn@latest add https://design.moodinary.com/r/mood-dot.jsonimport
import { MoodDot, MoodWord, moodLevel, MOOD_NAMES } from "@moodinary/ui/components/mood-dot";Ejemplos
Los cinco niveles
Muy bajo, Bajo, Neutral, Bien y Muy bien. El color acompaña la palabra; nunca la reemplaza.
Código
words.tsx
import { MoodWord } from "@moodinary/ui/components/mood-dot";
export default function MoodWords() {
return (
<>
<MoodWord level={1} />
<MoodWord level={2} />
<MoodWord level={3} />
<MoodWord level={4} />
<MoodWord level={5} />
</>
);
}Puntos en una lista
Como la columna Nivel de la lista de pulsos: punto y nombre visible, después fecha y equipo.
- Bien5 oct4.º A
- Neutral5 octVentas
- Bajo4 oct5.º B
Código
dots.tsx
import { MOOD_NAMES, MoodDot } from "@moodinary/ui/components/mood-dot";
/* Como la columna Nivel de PulseRow (pulse-row.tsx): punto + nombre visible del nivel. */
const rows = [
{ date: "5 oct", level: 4, team: "4.º A" },
{ date: "5 oct", level: 3, team: "Ventas" },
{ date: "4 oct", level: 2, team: "5.º B" },
] as const;
export default function MoodDots() {
return (
<ul className="m-0 grid w-full max-w-[360px] list-none gap-2 p-0 text-[13px]">
{rows.map((r) => (
<li className="flex items-center gap-4" key={`${r.team}-${r.date}`}>
<span className="flex w-28 shrink-0 items-center gap-2">
<MoodDot className="mr-0" level={r.level} />
<span className="truncate font-medium text-ink">
{MOOD_NAMES[r.level - 1]}
</span>
</span>
<span className="w-16 shrink-0 text-ink-3">{r.date}</span>
<span className="truncate text-ink-2">{r.team}</span>
</li>
))}
</ul>
);
}Promedios
Redondeo al nivel más cercano, como en la app. Decimal con coma y siempre el nombre del nivel.
1,4Muy bajo
2,4Bajo
3,1Neutral
3,6Bien
4,5Muy bien
El promedio se redondea al nivel más cercano: 3,6 se lee como Bien.
Código
score.tsx
import { MoodWord } from "@moodinary/ui/components/mood-dot";
/* La app redondea el promedio al nivel más cercano (clampLevel en apps/pulses/src/lib/mood.ts), no usa los umbrales de moodLevel. */
const scores = [1.4, 2.4, 3.1, 3.6, 4.5];
const toLevel = (s: number) =>
Math.max(1, Math.min(5, Math.round(s))) as 1 | 2 | 3 | 4 | 5;
export default function MoodScore() {
return (
<div className="grid w-full gap-3">
<div className="flex flex-wrap gap-7">
{scores.map((score) => (
<div className="grid gap-0.5" key={score}>
<b className="font-medium text-[22px] text-ink tabular-nums">
{score.toLocaleString("es-AR", {
maximumFractionDigits: 1,
minimumFractionDigits: 1,
})}
</b>
<MoodWord
className="text-[12px] text-ink-2"
level={toLevel(score)}
/>
</div>
))}
</div>
<p className="m-0 text-[12px] text-ink-3">
El promedio se redondea al nivel más cercano: 3,6 se lee como Bien.
</p>
</div>
);
}Props
MoodDot
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| level | 1 | 2 | 3 | 4 | 5 | - | Nivel de la escala, obligatorio. |
| className | string | - | Clases del punto de 8 px. |
MoodWord
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| level | 1 | 2 | 3 | 4 | 5 | - | Nivel que determina punto y palabra. |
| className | string | - | Clases del conjunto. |
moodLevel
| Prop | Tipo | Default | Descripción |
|---|---|---|---|
| score | number | - | Promedio validado. Devuelve un nivel de 1 a 5. |
Cuándo sí y cuándo no
Hacé
- Acompañá cada color con su palabra.
- Formateá los promedios con es-AR.
- Usá moodLevel para mantener los mismos cortes.
Evitá
- No uses la rampa de ánimo para decorar acciones.
- No pases datos faltantes como cero.
- No confundas nivel de ánimo con condición meteorológica.
Accesibilidad
- El punto es decorativo y está oculto a lectores de pantalla; la palabra comunica el nivel.
- No es un control y no entra en el recorrido de Tab.