Skip to main content

Styling Components

NubeSDK provides multiple ways to style your components, ensuring flexibility while maintaining consistency with the store's theme. You can use the styled() function for CSS-in-JS, StyleSheet.create() for reusable styles, and the theme system for design tokens.

Overview

There are three main approaches to styling components in NubeSDK:

  1. styled() function - CSS-in-JS with template literals
  2. StyleSheet.create() - Reusable style objects
  3. Theme integration - Design tokens and CSS variables

Styled Components

The styled() function allows you to apply custom CSS to components using template literals, similar to styled-components.

Basic Usage

import { styled } from "@tiendanube/nube-sdk-ui";
import { Box } from "@tiendanube/nube-sdk-jsx";

const StyledBox = styled(Box)`
background-color: red;
padding: 16px;
border-radius: 8px;
`;

<StyledBox>Custom styled content</StyledBox>

or

import { styled } from "@tiendanube/nube-sdk-ui";
import { box } from "@tiendanube/nube-sdk-ui";

const StyledBox = styled(box)`
background-color: red;
padding: 16px;
border-radius: 8px;
`;

StyledBox({
children: "Custom styled content"
});

Template Literal Interpolation

You can use JavaScript expressions within your CSS:

const primaryColor = "var(--primary-color)";
const StyledBox = styled(box)`
background-color: ${primaryColor};
padding: ${16}px;
margin: ${getSpacing()}px;
`;

function getSpacing() {
return 20;
}

CSS Features

The styled() function supports all CSS features:

const StyledButton = styled(Button)`
background-color: blue;
color: white;
padding: 12px 24px;
border: none;
border-radius: 4px;
transition: background-color 0.2s;

&:hover {
background-color: darkblue;
}

&:active {
background-color: navy;
}

&:disabled {
background-color: gray;
cursor: not-allowed;
}
`;

Media Queries

const ResponsiveBox = styled(Box)`
background-color: red;
padding: 16px;

@media (max-width: 768px) {
padding: 8px;
background-color: blue;
}

@media (min-width: 1024px) {
padding: 24px;
background-color: green;
}
`;

Keyframes

You can create and use CSS keyframe animations with the keyframes function:

import { styled, keyframes } from "@tiendanube/nube-sdk-ui";
import { Box } from "@tiendanube/nube-sdk-jsx";

const pulse = keyframes`
0% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.1);
opacity: 0.8;
}
100% {
transform: scale(1);
opacity: 1;
}
`;

const slideIn = keyframes`
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
`;

const AnimatedBox = styled(Box)`
animation: ${pulse} 2s ease-in-out infinite;
`;

const SlideInBox = styled(Box)`
animation: ${slideIn} 0.5s ease-out;
`;

<AnimatedBox>Pulsing content</AnimatedBox>
<SlideInBox>Sliding content</SlideInBox>

or

import { styled, keyframes } from "@tiendanube/nube-sdk-ui";
import { box } from "@tiendanube/nube-sdk-ui";

const pulse = keyframes`
0% {
transform: scale(1);
opacity: 1;
}
50% {
transform: scale(1.1);
opacity: 0.8;
}
100% {
transform: scale(1);
opacity: 1;
}
`;

const slideIn = keyframes`
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
`;

const AnimatedBox = styled(box)`
animation: ${pulse} 2s ease-in-out infinite;
`;

const SlideInBox = styled(box)`
animation: ${slideIn} 0.5s ease-out;
`;

AnimatedBox({
children: "Pulsing content"
});

SlideInBox({
children: "Sliding content"
});

Complex Animations

You can create more complex animations with multiple keyframes:

const bounce = keyframes`
0%, 20%, 53%, 80%, 100% {
transform: translate3d(0, 0, 0);
}
40%, 43% {
transform: translate3d(0, -30px, 0);
}
70% {
transform: translate3d(0, -15px, 0);
}
90% {
transform: translate3d(0, -4px, 0);
}
`;

const fadeInUp = keyframes`
0% {
opacity: 0;
transform: translate3d(0, 40px, 0);
}
100% {
opacity: 1;
transform: translate3d(0, 0, 0);
}
`;

const AnimatedComponent = styled(box)`
animation: ${bounce} 1s ease-in-out infinite;

&:hover {
animation: ${fadeInUp} 0.6s ease-out;
}
`;

Animation with Theme Integration

Combine keyframes with theme tokens for consistent animations:

import { styled, keyframes, theme } from "@tiendanube/nube-sdk-ui";

const glow = keyframes`
0% {
box-shadow: 0 0 5px ${theme.color.accent};
}
50% {
box-shadow: 0 0 20px ${theme.color.accent}, 0 0 30px ${theme.color.accent};
}
100% {
box-shadow: 0 0 5px ${theme.color.accent};
}
`;

const GlowingButton = styled(button)`
background-color: ${theme.color.accent};
color: white;
padding: 12px 24px;
border-radius: ${theme.border.radius};
animation: ${glow} 2s ease-in-out infinite;
`;

CSS Custom Properties

const ThemedBox = styled(Box)`
--custom-color: #ff6b6b;
--custom-padding: 20px;

background-color: var(--custom-color);
padding: var(--custom-padding);
border-radius: 8px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
`;

Component Composition

You can chain styled components:

const BaseStyledBox = styled(box)`
background-color: red;
padding: 16px;
`;

const FinalStyledBox = styled(BaseStyledBox)`
border: 2px solid black;
margin: 8px;
`;

StyleSheet

The StyleSheet.create() function allows you to create reusable style objects with type safety.

Basic Usage

import { StyleSheet } from "@tiendanube/nube-sdk-ui";
import { Box } from "@tiendanube/nube-sdk-jsx";

const styles = StyleSheet.create({
container: {
backgroundColor: "red",
padding: "16px",
borderRadius: "8px",
},
button: {
backgroundColor: "blue",
color: "white",
padding: "12px 24px",
},
});

<Box style={styles.container}>
<Button style={styles.button}>Click me</Button>
</Box>

or

import { StyleSheet } from "@tiendanube/nube-sdk-ui";
import { box, button } from "@tiendanube/nube-sdk-ui";

const styles = StyleSheet.create({
container: {
backgroundColor: "red",
padding: "16px",
borderRadius: "8px",
},
button: {
backgroundColor: "blue",
color: "white",
padding: "12px 24px",
},
});

box({
style: styles.container,
children: [
button({
style: styles.button,
children: "Click me"
})
]
});

Type Safety

StyleSheet provides full TypeScript support with CSS property validation:

const styles = StyleSheet.create({
container: {
// ✅ Valid CSS properties
backgroundColor: "red",
padding: "16px",
margin: "8px",
width: "100%",
height: "200px",

// ✅ Size type support
fontSize: "18px",
lineHeight: "1.5",
borderRadius: "8px",

// ❌ TypeScript will catch invalid properties
// invalidProperty: "value", // Error
},
});

Theme Integration

StyleSheet works seamlessly with the theme system:

import { StyleSheet, theme } from "@tiendanube/nube-sdk-ui";

const styles = StyleSheet.create({
primaryButton: {
backgroundColor: theme.color.accent,
color: theme.color.main.foreground,
padding: "12px 24px",
borderRadius: theme.border.radius,
},
card: {
backgroundColor: theme.color.main.background,
border: `1px solid ${theme.border.color}`,
borderRadius: theme.box.border.radius,
padding: "16px",
},
});

Theme System

The theme system provides design tokens and CSS variables that automatically adapt to the store's theme. The theme object gives you access to the variables configured in each store, allowing your components to integrate seamlessly with each store's unique styling.

Available Theme Tokens

import { theme } from "@tiendanube/nube-sdk-ui";

// Base Colors
theme.color.accent // Primary accent color
theme.color.main.foreground // Main text color
theme.color.main.background // Main background color

// Status Colors
theme.color.success.light // Success light variant
theme.color.success.medium // Success medium variant
theme.color.success.dark // Success dark variant

theme.color.warning.light // Warning light variant
theme.color.warning.medium // Warning medium variant
theme.color.warning.dark // Warning dark variant

theme.color.danger.light // Danger light variant
theme.color.danger.medium // Danger medium variant
theme.color.danger.dark // Danger dark variant

theme.color.info.light // Info light variant
theme.color.info.medium // Info medium variant
theme.color.info.dark // Info dark variant

theme.color.neutral.light // Neutral light variant
theme.color.neutral.medium // Neutral medium variant
theme.color.neutral.dark // Neutral dark variant

// Text Colors
theme.color.text.high // High contrast text color
theme.color.text.medium // Medium contrast text color
theme.color.text.low // Low contrast text color

// Typography
theme.typography.body.font // Body font family
theme.typography.body.fontSize // Body font size
theme.typography.body.lineHeight // Body line height

theme.typography.xl.fontSize // Extra large font size
theme.typography.xl.lineHeight // Extra large line height

theme.typography.lg.fontSize // Large font size
theme.typography.lg.lineHeight // Large line height

theme.typography.base.fontSize // Base font size
theme.typography.base.lineHeight // Base line height

theme.typography.md.fontSize // Medium font size
theme.typography.md.lineHeight // Medium line height

theme.typography.sm.fontSize // Small font size
theme.typography.sm.lineHeight // Small line height

theme.typography.xs.fontSize // Extra small font size
theme.typography.xs.lineHeight // Extra small line height

// Borders
theme.border.color // Default border color
theme.border.radius // Default border radius

theme.box.border.color // Box border color
theme.box.border.radius // Box border radius

// Component-specific tokens
theme.button.foreground // Button text color
theme.button.background // Button background color
theme.button.border.color // Button border color
theme.button.border.radius // Button border radius
theme.button.border.width // Button border width

theme.label.foreground // Label text color
theme.label.background // Label background color

theme.input.border.color // Input border color

theme.header.foreground // Header text color
theme.header.background // Header background color
theme.header.logo.maxWidth // Header logo max width
theme.header.logo.maxHeight // Header logo max height
theme.header.logo.font // Header logo font family
theme.header.logo.fontSize // Header logo font size
theme.header.logo.fontWeight // Header logo font weight
theme.header.logo.textTransform // Header logo text transform
theme.header.logo.letterSpacing // Header logo letter spacing

theme.footer.foreground // Footer text color
theme.footer.background // Footer background color

theme.heading.font // Heading font family
theme.heading.fontWeight // Heading font weight
theme.heading.textTransform // Heading text transform
theme.heading.letterSpacing // Heading letter spacing

Using Theme Colors

Theme colors automatically adapt to the store's theme:

import { theme } from "@tiendanube/nube-sdk-ui";

const styles = StyleSheet.create({
adaptiveButton: {
backgroundColor: theme.color.accent,
color: theme.color.main.foreground,
},
});

// The button will automatically use the store's theme colors

Theme Color Opacity

You can create transparent versions of theme base colors using predefined opacity values:

import { theme } from "@tiendanube/nube-sdk-ui";

const styles = StyleSheet.create({
overlay: {
backgroundColor: theme.color.accent.opacity(50), // 50% opacity
},
subtle: {
backgroundColor: theme.color.main.background.opacity(10), // 10% opacity
},
transparent: {
backgroundColor: theme.color.main.foreground.opacity(0), // 0% opacity
},
});

Available opacity values: 0, 5, 10, 20, 30, 40, 50, 60, 70, 80, 90

Best Practices

1. Use Theme Tokens When Possible

Prefer theme tokens over hardcoded values to maintain consistency:

// ✅ Good - uses theme tokens
const styles = StyleSheet.create({
button: {
backgroundColor: theme.color.accent,
borderRadius: theme.border.radius,
},
});

// ❌ Avoid - hardcoded values
const styles = StyleSheet.create({
button: {
backgroundColor: "#007bff",
borderRadius: "4px",
},
});

2. Combine Styling Approaches

Use different approaches for different use cases:

// Reusable styles with StyleSheet
const baseStyles = StyleSheet.create({
card: {
backgroundColor: theme.color.main.background,
borderRadius: theme.border.radius,
padding: "16px",
},
});

// Static styles with styled()
const HighlightCard = styled(box)`
background-color: ${theme.color.accent};
border: 2px solid ${theme.border.color};
`;

3. Responsive Design

Use media queries for responsive layouts:

const ResponsiveContainer = styled(box)`
padding: 16px;
flex-direction: column;

@media (min-width: 768px) {
padding: 24px;
flex-direction: row;
}
`;

4. CSS Custom Properties

Use CSS custom properties for dynamic values:

const DynamicBox = styled(box)`
--custom-color: #ff6b6b;
--custom-size: 16px;

background-color: var(--custom-color);
padding: var(--custom-size);
`;

Examples

Complete Component with Multiple Styling Approaches

import { styled, StyleSheet, theme } from "@tiendanube/nube-sdk-ui";
import { Box, Button, Text } from "@tiendanube/nube-sdk-jsx";

// Reusable styles
const styles = StyleSheet.create({
container: {
backgroundColor: theme.color.main.background,
borderRadius: theme.border.radius,
padding: "24px",
},
title: {
color: theme.color.main.foreground,
fontSize: "24px",
fontWeight: "bold",
marginBottom: "16px",
},
});

// Static styled component
const StyledButton = styled(Button)`
background-color: ${theme.color.accent};
color: white;
padding: 12px 24px;
border-radius: ${theme.border.radius};
border: 1px solid ${theme.border.color};
transition: all 0.2s;

&:hover {
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
}
`;

// Usage
<Box style={styles.container}>
<Text style={styles.title}>Welcome to NubeSDK</Text>
<StyledButton>Get Started</StyledButton>
</Box>

This comprehensive styling system gives you the flexibility to create beautiful, consistent, and theme-aware components while maintaining type safety and developer experience.