Saltar al contenido
ssntl/ui

Smooth shadows

Sombras de cinco capas que caen como luz real. Tamaño, intensidad, tinte y anillo fino.

size 0.5
size 1
size 2
size 3 · hairline

Instalación

$ pnpm dlx shadcn@latest add @ssntl/shadow-smooth

Uso

css
/* app/globals.css */
@import "../styles/ssntl/shadow-smooth.css";

/* En tu JSX */
<div class="shadow-smooth">…</div>
<div class="shadow-smooth shadow-size-2 shadow-intensity-150">…</div>
<div class="shadow-smooth shadow-tint-blue-600 shadow-hairline">…</div>
  • Cinco capas que duplican distancia y desenfoque: la sombra cae como luz real, no como un solo blur.
  • Dos números la controlan: shadow-size-{n} escala la pila y shadow-intensity-{n} su opacidad en %.
  • En oscuro la pila es 3 veces más fuerte para que se lea; sigue data-theme y el sistema operativo.
  • Solo para lo que flota. Las áreas se separan por tono, no por sombra.

Código

styles/ssntl/shadow-smooth.css
/* Smooth shadows: five layers that double in distance and blur, so the shadow
   falls off like real light instead of one hard blur.

     shadow-smooth                    the stack, size 1, intensity 100
     shadow-size-{n}                  scale the stack (0.5, 2, 3…)
     shadow-intensity-{n}             opacity in % (0–300)
     shadow-tint-{color}              tint the stack with a palette color
     shadow-hairline                  add a hairline ring (0.5px on retina)

   Dark surfaces need more shadow to read, so the stack is 3× stronger in dark. */

:root,
[data-theme="light"],
.light {
  --shadow-strength: 1;
}
[data-theme="dark"],
.dark {
  --shadow-strength: 3;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"], .light) {
    --shadow-strength: 3;
  }
}

@utility shadow-smooth {
  --_s: var(--shadow-size, 1);
  --_a: calc(3% * var(--shadow-intensity, 1) * var(--shadow-strength, 1));
  --_c: var(--shadow-color, #000);
  box-shadow:
    0 0 0 var(--shadow-ring, 0px)
      color-mix(in oklab, var(--_c) calc(var(--_a) * 3), transparent),
    0 calc(1px * var(--_s)) calc(2px * var(--_s))
      color-mix(in oklab, var(--_c) var(--_a), transparent),
    0 calc(2px * var(--_s)) calc(4px * var(--_s))
      color-mix(in oklab, var(--_c) var(--_a), transparent),
    0 calc(4px * var(--_s)) calc(8px * var(--_s))
      color-mix(in oklab, var(--_c) var(--_a), transparent),
    0 calc(8px * var(--_s)) calc(16px * var(--_s))
      color-mix(in oklab, var(--_c) var(--_a), transparent),
    0 calc(16px * var(--_s)) calc(32px * var(--_s))
      color-mix(in oklab, var(--_c) var(--_a), transparent);
}

@utility shadow-size-* {
  --shadow-size: --value(number);
}

@utility shadow-intensity-* {
  --shadow-intensity: calc(--value(integer) / 100);
}

@utility shadow-tint-* {
  --shadow-color: --value(--color-*, [color]);
}

@utility shadow-hairline {
  --shadow-ring: 1px;
  @media (min-resolution: 2dppx) {
    --shadow-ring: 0.5px;
  }
}