Pular para o conteúdo principal

styled()

The styled() function lets you apply custom CSS to any component using template literals (similar to styled-components). You get a new component that accepts the same props as the original plus your styles.

Basic Usage

import type { NubeSDK } from "@tiendanube/nube-sdk-types";
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;
`;

function MyComponent() {
return <StyledBox>Custom styled content</StyledBox>;
}

export function App(nube: NubeSDK) {
nube.render("before_main_content", <MyComponent />);
}

or

import type { NubeSDK } from "@tiendanube/nube-sdk-types";
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;
`;

export function App(nube: NubeSDK) {
nube.render(
"before_main_content",
StyledBox({
children: "Custom styled content",
}),
);
}

Template Literal Interpolation

You can use JavaScript expressions within your CSS:

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

const primaryColor = "var(--primary-color)";

function getSpacing() {
return 20;
}

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

function MyComponent() {
return <StyledBox>Interpolated styled content</StyledBox>;
}

export function App(nube: NubeSDK) {
nube.render("before_main_content", <MyComponent />);
}

CSS Features

The styled() function supports all CSS features:

import type { NubeSDK } from "@tiendanube/nube-sdk-types";
import { styled } from "@tiendanube/nube-sdk-ui";
import { Button } from "@tiendanube/nube-sdk-jsx";

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;
}
`;

function MyComponent() {
return <StyledButton>Click me</StyledButton>;
}

export function App(nube: NubeSDK) {
nube.render("before_main_content", <MyComponent />);
}

Media Queries

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

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;
}
`;

function MyComponent() {
return <ResponsiveBox>Responsive content</ResponsiveBox>;
}

export function App(nube: NubeSDK) {
nube.render("before_main_content", <MyComponent />);
}

Keyframes

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

import type { NubeSDK } from "@tiendanube/nube-sdk-types";
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`
0% {
transform: translateX(-20px);
opacity: 0;
}
50% {
transform: translateX(0);
opacity: 1;
}
100% {
transform: translateX(-20px);
opacity: 0;
}
`;

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

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

function MyComponent() {
return (
<Box>
<AnimatedBox>Pulsing content</AnimatedBox>
<SlideInBox>Sliding content</SlideInBox>
</Box>
);
}

export function App(nube: NubeSDK) {
nube.render("before_main_content", <MyComponent />);
}

Complex Animations

You can create more complex animations with multiple keyframes:

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

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;
}
`;

function MyComponent() {
return <AnimatedComponent>Bouncing content</AnimatedComponent>;
}

export function App(nube: NubeSDK) {
nube.render("before_main_content", <MyComponent />);
}

Animation with Theme Integration

Combine keyframes with theme tokens for consistent animations:

Testing this example

In order to see this example in action, navigate to the checkout in your store.

import type { NubeSDK } from "@tiendanube/nube-sdk-types";
import { styled, keyframes, theme } from "@tiendanube/nube-sdk-ui";
import { Button } from "@tiendanube/nube-sdk-jsx";

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;
`;

function MyComponent() {
return <GlowingButton>Glowing action</GlowingButton>;
}

export function App(nube: NubeSDK) {
nube.render("after_line_items", <MyComponent />);
}

CSS Custom Properties

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

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);
`;

function MyComponent() {
return <ThemedBox>Custom properties content</ThemedBox>;
}

export function App(nube: NubeSDK) {
nube.render("before_main_content", <MyComponent />);
}

Component Composition

You can chain styled components:

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

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

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

function MyComponent() {
return <FinalStyledBox>Composed styled content</FinalStyledBox>;
}

export function App(nube: NubeSDK) {
nube.render("before_main_content", <MyComponent />);
}