Botón
Los botones permiten a los usuarios realizar acciones y tomar decisiones con un solo toque.
Guías de Diseño
Cuándo Usar
- Acciones primarias en formularios o diálogos
- Activadores de navegación
- Envío de formularios
- Confirmación o cancelación de operaciones
Variantes
Nuestros botones vienen en múltiples variantes de color para diferentes contextos:
- Primary - Mayor énfasis, acciones principales
- Secondary - Énfasis medio, acciones secundarias
- Lavender - Acento alternativo
- Sky - Acento alternativo
- Sun - Acento alternativo
- Green Neon - Acento alternativo
- Error - Acciones destructivas
- Outlined - Versión delineada (sin fondo) de cualquier variante
Estilos
Tres estilos principales están disponibles:
- Sólido - Relleno completo (predeterminado)
- Outlined - Solo borde sin fondo
- Icon - Botón circular solo ícono
Tamaños
Dos tamaños están disponibles:
- Normal - Tamaño predeterminado (40px de altura)
- Small - Espacios compactos (26px de altura)
Estados
- Predeterminado - Estado interactivo normal
- Hover - Ratón sobre el botón
- Activo (
.bttn--active) - Mantiene el efecto de hover, por ejemplo para la opción seleccionada - Deshabilitado - Estado no interactivo
- Foco - Indicador de foco del teclado
Accesibilidad
- Usa el elemento semántico
<button>(HTML/CSS) o equivalente - Incluye etiquetas descriptivas
- Proporciona etiquetas ARIA apropiadas cuando sea solo icono
- Asegura contraste de color suficiente (mínimo 4.5:1)
- Soporta navegación por teclado (Enter/Espacio)
- Incluye indicadores de foco visibles
- El estado deshabilitado debe ser determinable programáticamente
Mejores Prácticas
✅ Haz:
- Usa etiquetas claras y orientadas a la acción ("Guardar", "Enviar", "Cancelar")
- Limita los botones primarios a uno por sección
- Proporciona retroalimentación visual en la interacción
- Haz los botones lo suficientemente grandes para objetivos táctiles (mínimo 44x44px)
- Usa colocación consistente de botones en contextos similares
❌ No hagas:
- Usar etiquetas genéricas como "Haz clic aquí"
- Deshabilitar botones sin explicación
- Usar demasiadas variantes de botones en una vista
- Hacer los botones demasiado pequeños para una interacción cómoda
- Usar botones para navegación (usa enlaces en su lugar)
Implementación por Plataforma
- CSS/HTML
- Angular
- Flutter
Paquete: @tiendana/web-foundation
CSS/HTML
Variables CSS @tiendana/web-foundation
Tokens usados
/* Colores de Marca */
--color-natura: #00D47E; /* Verde primario */
--color-forrest: #1B434C; /* Verde oscuro */
--color-light-forrest: #E4ECE3; /* Verde claro */
--color-lavender: #9687F2; /* Lavanda */
--color-sky: #75DBD2; /* Cielo */
--color-sun: #FF7834; /* Sol */
--color-green-neon: #C6F54F; /* Verde neón */
--color-error: #F54F4F; /* Error/rojo */
/* Espaciado */
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-button: 40px; /* Altura normal */
--spacing-button-sm: 26px; /* Altura small */
/* Radio de Borde */
--border-radius-button: 14px; /* Esquinas de botones sólidos/outlined */
--border-radius-lg: 8px; /* Para botones small */
--border-radius-full: 9999px; /* Para botones icon (círculo perfecto) */
/* Tipografía */
--font-size-xs: 12px;
--font-weight-extrabold: 800;
--line-height-tight: 1; /* Altura de línea del botón */
--border-radius-button(14px): esquinas de los botones sólidos y outlined--border-radius-full(9999px): círculo perfecto para botones icon
Variaciones
Cada variación tiene su demo individual:
.bttn
Ver código
.bttn--primary
Ver código
.bttn--secondary
Ver código
.bttn--lavender
Ver código
.bttn--sky
Ver código
.bttn--sun
Ver código
.bttn--green-neon
Ver código
.bttn--error
Ver código
.bttn--outlined + .bttn--primary
Ver código
.bttn--outlined + .bttn--secondary
Ver código
.bttn--outlined + .bttn--lavender
Ver código
.bttn--outlined + .bttn--sky
Ver código
.bttn--outlined + .bttn--sun
Ver código
.bttn--outlined + .bttn--green-neon
Ver código
.bttn--outlined + .bttn--error
Ver código
.bttn--small
Ver código
.bttn--icon
Ver código
.bttn--icon + .bttn--secondary
Ver código
.bttn--icon + .bttn--lavender
Ver código
.bttn--icon + .bttn--sky
Ver código
.bttn--icon + .bttn--sun
Ver código
.bttn--icon + .bttn--green-neon
Ver código
.bttn--icon + .bttn--error
Ver código
Estado disabled
Ver código
.bttn--active
Ver código
.bttn-group
Ver código
Paquetes: @tiendana/web-foundation @tiendana/ngx-core/ui
Angular
Componente ButtonIconCover @tiendana/ngx-core/ui
El componente ButtonIconCoverComponent es una característica exclusiva de Angular que añade un ícono animado con efecto de expansión al final de los botones.
Uso básico:
import { Component } from '@angular/core';
import { ButtonIconCoverComponent } from '@tiendana/ngx-core/ui';
@Component({
selector: 'app-my-button',
imports: [ButtonIconCoverComponent],
template: `
<button type="button" class="bttn bttn--primary">
Continuar
<button-icon-cover matIcon="arrow_forward_ios" />
</button>
`
})
export class MyButtonComponent {}
Props:
matIcon- Nombre del ícono de Material IconssvgIcon- Nombre del ícono SVG registrado en MatIconRegistryactive- Fuerza el estado expandido (boolean)
Características:
- Animación de expansión con física de resorte
- Detección automática de hover (desktop) o touch (móvil)
- Adaptación automática a botones
.bttn--small - Canvas animado con color configurable vía CSS variable
--bttn-icon-canvas-color
Variables CSS
Tokens usados
/* Colores de Marca */
--color-natura: #00D47E; /* Verde primario */
--color-forrest: #1B434C; /* Verde oscuro */
--color-light-forrest: #E4ECE3; /* Verde claro */
--color-lavender: #9687F2; /* Lavanda */
--color-sky: #75DBD2; /* Cielo */
--color-sun: #FF7834; /* Sol */
--color-green-neon: #C6F54F; /* Verde neón */
--color-error: #F54F4F; /* Error/rojo */
/* Espaciado */
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-button: 40px; /* Altura normal */
--spacing-button-sm: 26px; /* Altura small */
/* Radio de Borde */
--border-radius-button: 14px; /* Esquinas de botones sólidos/outlined */
--border-radius-lg: 8px; /* Para botones small */
--border-radius-full: 9999px; /* Para botones icon (círculo perfecto) */
/* Tipografía */
--font-size-xs: 12px;
--font-weight-extrabold: 800;
--line-height-tight: 1; /* Altura de línea del botón */
--border-radius-button(14px): esquinas de los botones sólidos y outlined--border-radius-full(9999px): círculo perfecto para botones icon
Variaciones
Cada variación tiene su demo individual:
.bttn
Ver código
.bttn--primary
Ver código
.bttn--secondary
Ver código
.bttn--lavender
Ver código
.bttn--sky
Ver código
.bttn--sun
Ver código
.bttn--green-neon
Ver código
.bttn--error
Ver código
.bttn--outlined + .bttn--primary
Ver código
.bttn--outlined + .bttn--secondary
Ver código
.bttn--outlined + .bttn--lavender
Ver código
.bttn--outlined + .bttn--sky
Ver código
.bttn--outlined + .bttn--sun
Ver código
.bttn--outlined + .bttn--green-neon
Ver código
.bttn--outlined + .bttn--error
Ver código
.bttn--outlined (default)
Ver código
.bttn--small
Ver código
.bttn--small (default)
Ver código
.bttn--small + .bttn--secondary
Ver código
.bttn--small + .bttn--lavender
Ver código
.bttn--small + .bttn--sky
Ver código
.bttn--small + .bttn--sun
Ver código
.bttn--small + .bttn--green-neon
Ver código
.bttn--small + .bttn--error
Ver código
.bttn--small + .bttn--outlined + .bttn--primary
Ver código
.bttn--small + .bttn--outlined (default)
Ver código
.bttn--small + .bttn--outlined + .bttn--secondary
Ver código
.bttn--small + .bttn--outlined + .bttn--lavender
Ver código
.bttn--small + .bttn--outlined + .bttn--sky
Ver código
.bttn--small + .bttn--outlined + .bttn--sun
Ver código
.bttn--small + .bttn--outlined + .bttn--green-neon
Ver código
.bttn--small + .bttn--outlined + .bttn--error
Ver código
.bttn--icon + .bttn--primary
Ver código
.bttn--icon (default)
Ver código
.bttn--icon + .bttn--secondary
Ver código
.bttn--icon + .bttn--lavender
Ver código
.bttn--icon + .bttn--sky
Ver código
.bttn--icon + .bttn--sun
Ver código
.bttn--icon + .bttn--green-neon
Ver código
.bttn--icon + .bttn--error
Ver código
Estado disabled
Ver código
.bttn--active
Ver código
.bttn-group
Ver código
Paquete: tiendana_uikit
Flutter
Tokens de Diseño tiendana_uikit
TiendanaColors y constantes
// Colores primarios
TiendanaColors.natura // #00D47E - Verde primario
TiendanaColors.forrest // #1B434C - Verde oscuro
TiendanaColors.lightForrest // #E4ECE3 - Verde claro
TiendanaColors.lavender // #9687F2 - Lavanda
TiendanaColors.sky // #75DBD2 - Cielo
TiendanaColors.sun // #FF7834 - Sol
TiendanaColors.greenNeon // #C6F54F - Verde neón
TiendanaColors.error // #F54F4F - Error/rojo
// Espaciado (crear constantes o usar valores directos)
const kButtonHeight = 40.0;
const kButtonHeightSmall = 26.0;
const kSpacingXs = 4.0;
const kSpacingSm = 8.0;
const kSpacingMd = 16.0;
// BorderRadius (Flutter usa Radius.circular)
BorderRadius.circular(9999); // Pill shape para botones sólidos/outlined
BorderRadius.circular(8); // Para botones small
BorderRadius.circular(50); // Círculo para icon buttons (o usa shape: BoxShape.circle)
Flutter no usa porcentajes para border-radius. Para círculos perfectos (icon buttons), usa shape: BoxShape.circle o un valor grande como BorderRadius.circular(50).
Variaciones
Botón base
Ver código
variant: ButtonVariant.primary
Ver código
variant: ButtonVariant.secondary
Ver código
variant: ButtonVariant.lavender
Ver código
variant: ButtonVariant.sky
Ver código
variant: ButtonVariant.sun
Ver código
variant: ButtonVariant.greenNeon
Ver código
variant: ButtonVariant.error
Ver código
Botones Outlined - Default
Ver código
Botones Outlined - Primary
Ver código
Botones Outlined - Secondary
Ver código
Botones Outlined - Lavender
Ver código
Botones Outlined - Sky
Ver código
Botones Outlined - Sun
Ver código
Botones Outlined - Green Neon
Ver código
Botones Outlined - Error
Ver código
Text Button - Default
Ver código
Text Button - Primary
Ver código
Text Button - Secondary
Ver código
Text Button - Red
Ver código
Text Button - Lavender
Ver código
Text Button - Sky
Ver código
Text Button - Sun
Ver código
Text Button - Green Neon
Ver código
size: ButtonSize.small
Ver código
Small - Default
Ver código
Small - Secondary
Ver código
Small - Red
Ver código
Small - Lavender
Ver código
Small - Sky
Ver código
Small - Sun
Ver código
Small - Green Neon
Ver código
Small Outlined - Default
Ver código
Small Outlined - Primary
Ver código
Small Outlined - Secondary
Ver código
Small Outlined - Red
Ver código
Small Outlined - Lavender
Ver código
Small Outlined - Sky
Ver código
Small Outlined - Sun
Ver código
Small Outlined - Green Neon
Ver código
Small Text - Default
Ver código
Small Text - Primary
Ver código
Small Text - Secondary
Ver código
Small Text - Red
Ver código
Small Text - Lavender
Ver código
Small Text - Sky
Ver código
Small Text - Sun
Ver código
Small Text - Green Neon
Ver código
Icon Button - Default
Ver código
Botón con icono - Primary
Ver código
Botón con icono - Secondary
Ver código
Botón con icono - Lavender
Ver código
Botón con icono - Sky
Ver código
Botón con icono - Sun
Ver código
Botón con icono - Green Neon
Ver código
Botón con icono - Error
Ver código
Icon Button Small - Default
Ver código
Icon Button Small - Primary
Ver código
Round Icon Button - Default
Ver código
Round Icon Button - Primary
Ver código
Round Icon Button - Secondary
Ver código
Round Icon Button - Red
Ver código
Round Icon Button - Green Neon
Ver código
Round Icon Button Small - Default
Ver código
Round Icon Button Small - Primary
Ver código
Ejemplos de uso
Con icono leading/trailing
Ver código
TdnButton(
label: 'Guardar',
variant: ButtonVariant.primary,
leadingIcon: Icon(Icons.save, size: 18),
onPressed: () {},
)
TdnButton(
label: 'Siguiente',
variant: ButtonVariant.primary,
trailingIcon: Icon(Icons.arrow_forward, size: 18),
onPressed: () {},
)
Estado de carga
Ver código
class SubmitButton extends StatefulWidget {
_SubmitButtonState createState() => _SubmitButtonState();
}
class _SubmitButtonState extends State<SubmitButton> {
bool _isLoading = false;
Future<void> _handleSubmit() async {
setState(() => _isLoading = true);
await Future.delayed(Duration(seconds: 2));
setState(() => _isLoading = false);
}
Widget build(BuildContext context) {
return TdnButton(
label: 'Enviar',
variant: ButtonVariant.primary,
isLoading: _isLoading,
onPressed: _isLoading ? null : _handleSubmit,
);
}
}
Botón de ancho completo
Ver código
TdnButton(
label: 'Continuar',
variant: ButtonVariant.primary,
fullWidth: true,
onPressed: () {},
)
Props / API
- CSS/HTML
- Flutter
CSS Classes
Todas las clases se combinan sobre .bttn. Solo existen las clases listadas aquí: el estilo outlined es un modificador (.bttn--outlined) y no una familia .bttn-outlined--*.
Base y variantes de color
| Clase | Descripción |
|---|---|
.bttn | Clase base: fondo --color-light-forrest, 40px de altura (--spacing-button), min-width de --spacing-xl (32px), texto en mayúsculas |
.bttn--primary | Botón primario (--color-natura) |
.bttn--secondary | Botón secundario (--color-forrest) |
.bttn--lavender | Botón lavender |
.bttn--sky | Botón sky |
.bttn--sun | Botón sun |
.bttn--green-neon | Botón green neon. Sus colores se resuelven en compilación desde los tokens SCSS (no son var() en tiempo de ejecución) |
.bttn--error | Botón destructivo (--color-error) |
Estilos y layouts
| Clase | Descripción |
|---|---|
.bttn--outlined | Fondo transparente y borde de --border-width-thin. Se combina con cualquier variante de color: .bttn--primary, .bttn--lavender, .bttn--sky, .bttn--error, .bttn--green-neon y .bttn--sun cambian el color del borde |
.bttn--small | Botón compacto: 26px de altura (--spacing-button-sm), padding de 4px 8px y radio --border-radius-lg |
.bttn--icon | Botón circular de solo icono: 40x40px, min-width: var(--spacing-button) para que el contenido no lo aplaste, sin sombra de hover |
.bttn--column | Apila el contenido en vertical: altura automática, padding --spacing-sm --spacing-lg y radio --border-radius-xl |
.bttn define min-width: var(--spacing-xl) (32px), menor que los 40px del botón icon. .bttn--icon lo sobrescribe con var(--spacing-button) para que el botón conserve su forma circular aunque el contenedor sea angosto.
Estados
| Clase | Descripción |
|---|---|
:disabled / .bttn--disabled | Opacidad 0.5 y sin efectos de hover ni foco |
.bttn--active | Mantiene el efecto de hover de forma persistente |
Agrupación
| Clase | Descripción |
|---|---|
.bttn-group | Contenedor flex que agrupa varios .bttn con gap de --border-width-medium y esquinas internas reducidas a --border-radius-md |
Variantes de color de .bttn--icon
Con .bttn--icon cada variante usa un fondo claro y el color pleno en el icono; el hover invierte los colores:
| Combinación | Reposo | Hover |
|---|---|---|
.bttn--icon | Fondo --color-light-forrest, icono --color-dark-forrest | Fondo --color-forrest, icono --color-light-forrest |
.bttn--icon.bttn--primary | Fondo --color-natura | Fondo --color-forrest, icono --color-green-neon |
.bttn--icon.bttn--secondary | Transparente con borde --color-dark-forrest | Borde de --border-width-medium |
.bttn--icon.bttn--error | Fondo --color-error-light, icono --color-error | Fondo --color-error, icono --color-light-sun |
.bttn--icon.bttn--lavender | Fondo --color-light-lavender, icono --color-lavender | Fondo --color-lavender, icono --color-light-lavender |
.bttn--icon.bttn--sky | Fondo --color-light-sky | Fondo --color-sky |
.bttn--icon.bttn--sun | Fondo --color-light-sun, icono --color-sun | Fondo --color-sun, icono --color-light-sun |
.bttn--icon.bttn--green-neon | Fondo --color-light-green-neon | Fondo --color-green-neon |
TdnButton / TdnElevatedButton
| Propiedad | Tipo | Default | Descripción |
|---|---|---|---|
text | String | required | Texto del botón |
onPressed | VoidCallback? | required | Callback al presionar |
variant | ButtonVariant | ButtonVariant.primary | Variante de color |
isLoading | bool | false | Mostrar indicador de carga |
fullWidth | bool | false | Ancho completo |
leadingIcon | Icon? | null | Ícono al inicio |
trailingIcon | Icon? | null | Ícono al final |
TdnOutlinedButton
| Propiedad | Tipo | Default | Descripción |
|---|---|---|---|
text | String | required | Texto del botón |
onPressed | VoidCallback? | required | Callback al presionar |
variant | ButtonVariant | ButtonVariant.primary | Variante de color |
TdnTextButton
| Propiedad | Tipo | Default | Descripción |
|---|---|---|---|
text | String | required | Texto del botón |
onPressed | VoidCallback? | required | Callback al presionar |
variant | ButtonVariant | ButtonVariant.primary | Variante de color |
TdnIconButton
| Propiedad | Tipo | Default | Descripción |
|---|---|---|---|
icon | IconData | required | Ícono a mostrar |
onPressed | VoidCallback? | required | Callback al presionar |
variant | ButtonVariant | ButtonVariant.primary | Variante de color |
TdnRoundIconButton
| Propiedad | Tipo | Default | Descripción |
|---|---|---|---|
icon | IconData | required | Ícono a mostrar |
onPressed | VoidCallback? | required | Callback al presionar |
variant | ButtonVariant | ButtonVariant.primary | Variante de color |
ButtonVariant (Enum)
| Valor | Descripción |
|---|---|
ButtonVariant.primary | Verde natura |
ButtonVariant.secondary | Forrest |
ButtonVariant.lavender | Lavender |
ButtonVariant.sky | Sky |
ButtonVariant.sun | Sun |
ButtonVariant.greenNeon | Green neon |
ButtonVariant.red | Rojo (destructivo) |
Constructores Tamaño Small
Todos los botones tienen constructor .small() para tamaño compacto:
TdnElevatedButton.small(text: 'Small', onPressed: () {})
TdnOutlinedButton.small(text: 'Small', onPressed: () {})
TdnTextButton.small(text: 'Small', onPressed: () {})
TdnIconButton.small(icon: Icons.add, onPressed: () {})
TdnRoundIconButton.small(icon: Icons.add, onPressed: () {})