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ón | Qué entrega |
|---|---|
@tiendana/web-foundation | API pública: tokens, colores, mixins y funciones. No emite CSS |
@tiendana/web-foundation/styles | Todo 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/css | El 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';
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
}
}
| Nombre | Valor | Variable |
|---|---|---|
sm | 800px | tdn.$breakpoint-sm |
md | 1200px | tdn.$breakpoint-md |
lg | 1600px | tdn.$breakpoint-lg |
El mapa completo es tdn.$breakpoints.
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.
| Variable | Valor 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ón | Estrategia |
|---|---|
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);
scheme-darkLas 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
- Usa un namespace (
as tdn) en lugar deas *, para queremoemno choquen con otras funciones. - Prefiere variables CSS (
var(--spacing-md)) para valores de diseño; deja los tokens SCSS para mixins y cálculos. - Importa la raíz para mixins y tokens, y
/styleso/csssolo una vez para el CSS global: la raíz no emite CSS,/stylessí.
Ver También
- CSS Overview - Visión general del sistema
- Foundations - Colors - Paleta de colores
- Foundations - Spacing - Tokens de espaciado
- Utilities Overview - Clases de utilidad