Moodinary/UI

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.json
import
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.

Muy bajoBajoNeutralBienMuy bien
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

PropTipoDefaultDescripción
level1 | 2 | 3 | 4 | 5-Nivel de la escala, obligatorio.
classNamestring-Clases del punto de 8 px.

MoodWord

PropTipoDefaultDescripción
level1 | 2 | 3 | 4 | 5-Nivel que determina punto y palabra.
classNamestring-Clases del conjunto.

moodLevel

PropTipoDefaultDescripción
scorenumber-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.