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:
styled()
function - CSS-in-JS with template literalsStyleSheet.create()
- Reusable style objects- 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";
// Colors
theme.color.accent // Primary accent color
theme.color.main.foreground // Main text color
theme.color.main.background // Main background color
// Borders
theme.border.color // Default border color
theme.border.radius // Default border radius
// Component-specific tokens
theme.button.foreground // Button text color
theme.button.background // Button background color
theme.button.borderColor // Button border color
theme.button.borderRadius // Button border radius
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.fontSize // Header logo font size
theme.footer.foreground // Footer text color
theme.footer.background // Footer background color
theme.heading.font // Heading font family
theme.heading.fontWeight // Heading font weight
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 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.accent.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.