Saltar al contenido principal

Mixins y Funciones SCSS

Paquete: @tiendana/web-foundation

Funciones y mixins SCSS para breakpoints, conversión de unidades, URLs de assets, bordes anidados y colores de modo oscuro.

Características​

✅ Breakpoints mobile-first - Media queries con respond-to() y respond-to-max()
✅ Conversión de unidades - rem() y em() con contexto configurable (14px por defecto)
✅ Asset URLs - asset-url() resuelve primero el CDN de Tiendana, luego CloudFront y por último S3
✅ Border helpers - inner-radius() para esquinas anidadas
✅ Funciones de color - Cálculo de variantes oscuras y hex-to-rgb()
✅ Un solo punto de entrada - Todo se usa desde @use '@tiendana/web-foundation' as tdn;

Rutas de importación​

El package.json del paquete define este mapa de exports. No existe un subpath mixins/*: los mixins y funciones se importan siempre desde la raíz.

ImportaciónQué entrega
@tiendana/web-foundationAPI pública: tokens, colores, mixins y funciones. No emite CSS
@tiendana/web-foundation/stylesTodo el CSS: variables, base, componentes y utilidades
@tiendana/web-foundation/tokens/*Un archivo de tokens (spacing, typography, shadows, borders, z-index)
@tiendana/web-foundation/colors/*Una paleta (primary, secondary, neutral, semantic, common)
@tiendana/web-foundation/base/*Estilos base (fonts, reset, typography, layout, scrollbars)
@tiendana/web-foundation/components/*Un componente (buttons, chips, badges, tables...)
@tiendana/web-foundation/utilities/*Un grupo de utilidades (spacing, text, display, background, borders, shadows, animations)
@tiendana/web-foundation/cssEl CSS ya compilado
@use '@tiendana/web-foundation' as tdn;
@use '@tiendana/web-foundation/tokens/spacing' as spacing;
@use '@tiendana/web-foundation/utilities/animations';
@use '@tiendana/web-foundation/components/buttons';
Sass CLI

Angular CLI, Vite y webpack resuelven estas rutas con el nombre de paquete. Con el CLI de sass hay que activar el importador (--pkg-importer=node) y usar el esquema pkg:, por ejemplo @use 'pkg:@tiendana/web-foundation' as tdn;.

Para el CSS compilado importa el subpath @tiendana/web-foundation/css, nunca una ruta de archivo dentro de node_modules: la carpeta interna cambió entre versiones y el export map la mantiene estable.

Breakpoints Responsivos​

respond-to($breakpoint) y respond-to-max($breakpoint)​

respond-to genera @media (min-width: ...) y respond-to-max genera @media (max-width: calc(... - 1px)). Un nombre desconocido emite un @warn y no genera nada.

@use '@tiendana/web-foundation' as tdn;

.component {
padding: 1rem;

@include tdn.respond-to(sm) {
padding: 1.5rem; // ≥800px
}

@include tdn.respond-to(md) {
padding: 2rem; // ≥1200px
}

@include tdn.respond-to-max(sm) {
display: none; // ≤799px
}
}
NombreValorVariable
sm800pxtdn.$breakpoint-sm
md1200pxtdn.$breakpoint-md
lg1600pxtdn.$breakpoint-lg

El mapa completo es tdn.$breakpoints.

Los breakpoints no son configurables

Las variables de breakpoints no están declaradas con !default, así que @use ... with ($breakpoint-sm: 768px) falla con "This variable was not declared with !default in the @used module".

Conversión de Unidades​

rem($pixels, $context) / em($pixels, $context)​

Convierten píxeles a rem o em. El contexto por defecto es $browser-context: 14px. rem es relativo al html, y web-foundation no fija su font-size (queda en el valor del navegador, normalmente 16px): fija html { font-size: 14px } en tu app o configura $browser-context: 16px para que rem(28px) mida 28px. em() con 14px coincide con el cuerpo. Aceptan valores con o sin unidad.

@use '@tiendana/web-foundation' as tdn;

.text {
font-size: tdn.rem(28px); // 2rem
padding: tdn.rem(21); // 1.5rem
margin: tdn.rem(20, 16); // 1.25rem (contexto de 16px)
}

.relative {
font-size: tdn.em(18px); // 1.28571em
}

Cambiar el contexto​

La variable se llama $browser-context (no $base-font-size):

@use '@tiendana/web-foundation' as tdn with (
$browser-context: 16px
);

URLs de Assets​

Funciones para generar url(...) hacia el CDN de Tiendana, CloudFront o S3. Devuelven una cadena vacía si $key está vacío y lanzan @error si falta la configuración que necesitan.

VariableValor por defecto
$cdn-domain'd320eox725dcq1.cloudfront.net'
$cloudfront-id''
$s3-bucket''
$s3-region'us-east-1'

asset-url($key, $force-s3: false)​

Elige el destino por prioridad: primero $cdn-domain (que viene configurado por defecto), luego $cloudfront-id y, si ninguno aplica o pasas $force-s3: true, S3.

.logo {
background-image: tdn.asset-url('assets/images/logo.svg');
// → url("https://d320eox725dcq1.cloudfront.net/assets/images/logo.svg")
}

cdn-url($key, $domain: $cdn-domain)​

.font {
src: tdn.cdn-url('assets/fonts/host-grotesk/co3BmWBnlCJ3U42vbbfdwMjZpFjm.woff2');
// → url("https://d320eox725dcq1.cloudfront.net/assets/fonts/host-grotesk/co3BmWBnlCJ3U42vbbfdwMjZpFjm.woff2")
}

cloudfront-url($key, $distribution: $cloudfront-id)​

.image {
background-image: tdn.cloudfront-url('assets/photo.jpg', 'd123abc456');
// → url("https://d123abc456.cloudfront.net/assets/photo.jpg")
}

s3-url($key, $bucket: $s3-bucket, $region: $s3-region)​

.banner {
background-image: tdn.s3-url('banners/hero.jpg', 'my-assets');
// → url("https://my-assets.s3.us-east-1.amazonaws.com/banners/hero.jpg")
}

Configurar URLs​

Estas variables sí llevan !default y se configuran al cargar el módulo:

@use '@tiendana/web-foundation' as tdn with (
$s3-bucket: 'my-assets',
$s3-region: 'us-east-1',
$cloudfront-id: 'd123abc456',
$cdn-domain: 'cdn.mysite.com'
);

Border Helpers​

inner-radius($outer-radius, $padding)​

Radio interno para un elemento anidado: max(0, outer - padding). Un radio externo de 9999px se conserva.

.card {
border-radius: 12px;
padding: 4px;

.content {
border-radius: tdn.inner-radius(12px, 4px); // 8px
}
}

inner-border-radius($outer-radius, $padding)​

Mixin que aplica border-radius: inner-radius(...) directamente.

.content {
@include tdn.inner-border-radius(12px, 4px); // border-radius: 8px
}

Funciones de Color​

hex-to-rgb($color)​

Devuelve los canales como r, g, b, pensado para variables CSS con canal separado.

.overlay {
--overlay-rgb: #{tdn.hex-to-rgb(#00D47E)}; // 0, 212, 126
background: rgba(var(--overlay-rgb), 0.5);
}

Funciones de modo oscuro​

Las paletas usan estas funciones para calcular sus variantes $color-*-dark. Todas reciben un solo color.

FunciónEstrategia
dark-text-color($color)Si la luminosidad es mayor a 50% lo deja igual; si no, invierte la luminosidad (#0A0A0A → #F5F5F5)
dark-brand-color($color)Lleva la luminosidad al rango 45-75% y suma 12 puntos de saturación (tope 100%)
dark-surface-color($color)Invierte la escala de luminosidad manteniendo el tono: superficies claras (L > 85/75/60%) pasan a 12/15/17%, medias a 25% y oscuras a 44% o 63%
$text-dark: tdn.dark-text-color(#0A0A0A);
$brand-dark: tdn.dark-brand-color(#00D47E);
$surface-dark: tdn.dark-surface-color(#F6F6F6);
Qué cambia realmente con scheme-dark

Las variantes -dark de las paletas existen como tokens SCSS, pero el CSS que emite body.scheme-dark solo redefine la escala de grises, --color-light-forrest, --color-dark-forrest, --color-text-primary, las superficies --bg-*dp, --input-border, --border y --ds-shadow-border. Ver Foundations - Colores.

Configuración global​

Todo lo configurable se pasa en un único @use ... with (...):

@use '@tiendana/web-foundation' as tdn with (
$browser-context: 16px,
$cdn-domain: 'cdn.mysite.com',
$s3-bucket: 'prod-assets'
);

La configuración solo se acepta la primera vez que se carga el módulo en la compilación.

Mejores Prácticas​

  1. Usa un namespace (as tdn) en lugar de as *, para que rem o em no choquen con otras funciones.
  2. Prefiere variables CSS (var(--spacing-md)) para valores de diseño; deja los tokens SCSS para mixins y cálculos.
  3. Importa la raíz para mixins y tokens, y /styles o /css solo una vez para el CSS global: la raíz no emite CSS, /styles sí.

Ver También​