Files
twenty/packages/twenty-front-component-renderer/src/__stories__/example-sources/styled-components-example.front-component.tsx
T
Paul Rastoin 37908114fc [SDK] Extract twenty-front-component-renderer outside of twenty-sdk ( 2.8MB ) (#19021)
Followup https://github.com/twentyhq/twenty/pull/19010

## Dependency diagram

```
┌─────────────────────┐
│     twenty-front    │
│   (React frontend)  │
└─────────┬───────────┘
          │ imports runtime:
          │   FrontComponentRenderer
          │   FrontComponentRendererWithSdkClient
          │   useFrontComponentExecutionContext
          ▼
┌──────────────────────────────────┐         ┌─────────────────────────┐
│ twenty-front-component-renderer  │────────▶│       twenty-sdk        │
│   (remote-dom host + worker)     │         │  (app developer SDK)    │
│                                  │         │                         │
│  imports from twenty-sdk:        │         │  Public API:            │
│   • types only:                  │         │   defineFrontComponent  │
│     FrontComponentExecutionContext│         │   navigate, closeSide…  │
│     NavigateFunction             │         │   useFrontComponent…    │
│     CloseSidePanelFunction       │         │   Command components    │
│     CommandConfirmation…         │         │   conditional avail.    │
│     OpenCommandConfirmation…     │         │                         │
│     EnqueueSnackbarFunction      │         │  Internal only:         │
│     etc.                         │         │   frontComponentHost…   │
│                                  │         │   front-component-build │
│  owns locally:                   │         │   esbuild plugins       │
│   • ALLOWED_HTML_ELEMENTS        │         │                         │
│   • EVENT_TO_REACT               │         └────────────┬────────────┘
│   • HTML_TAG_TO_CUSTOM_ELEMENT…  │                      │
│   • SerializedEventData          │                      │ types
│   • PropertySchema               │                      ▼
│   • frontComponentHostComm…      │         ┌─────────────────────────┐
│     (local ref to globalThis)    │         │     twenty-shared       │
│   • setFrontComponentExecution…  │         │  (common types/utils)   │
│     (local impl, same keys)      │         │   AppPath, SidePanelP…  │
│                                  │         │   EnqueueSnackbarParams │
└──────────────────────────────────┘         │   isDefined, …          │
          │                                  └─────────────────────────┘
          │ also depends on
          ▼
    twenty-shared (types)
    @remote-dom/* (runtime)
    @quilted/threads (runtime)
    react (runtime)
```

**Key points:**

- **`twenty-front`** depends on the renderer, **not** on `twenty-sdk`
directly (for rendering)
- **`twenty-front-component-renderer`** depends on `twenty-sdk` for
**types only** (function signatures, `FrontComponentExecutionContext`).
The runtime bridge (`frontComponentHostCommunicationApi`) is shared via
`globalThis` keys, not module imports
- **`twenty-sdk`** has no dependency on the renderer — clean one-way
dependency
- The renderer owns all remote-dom infrastructure (element schemas,
event mappings, custom element tags) that was previously leaking through
the SDK's public API
- The SDK's `./build` entry point was removed entirely (unused)
2026-03-30 17:06:06 +00:00

108 lines
2.6 KiB
TypeScript

import { useState } from 'react';
import styled from 'styled-components';
import { defineFrontComponent } from '@/sdk';
const Card = styled.div`
padding: 24px;
background-color: #fdf2f8;
border: 2px solid #ec4899;
border-radius: 12px;
font-family: system-ui, sans-serif;
max-width: 360px;
display: flex;
flex-direction: column;
gap: 16px;
`;
const Heading = styled.h2`
color: #9d174d;
font-weight: 700;
font-size: 18px;
margin: 0;
`;
const Description = styled.p`
color: #be185d;
font-size: 14px;
margin: 0;
line-height: 1.5;
`;
const ChipRow = styled.div`
display: flex;
gap: 8px;
flex-wrap: wrap;
`;
const Chip = styled.span<{ $color: string }>`
display: inline-block;
padding: 4px 10px;
background-color: ${({ $color }) => $color};
color: white;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
`;
const Count = styled.p`
font-size: 24px;
font-weight: 800;
color: #db2777;
margin: 0;
`;
const ButtonRow = styled.div`
display: flex;
gap: 8px;
`;
const StyledButton = styled.button<{ $variant?: 'outline' }>`
padding: 8px 16px;
background-color: ${({ $variant }) =>
$variant === 'outline' ? 'transparent' : '#ec4899'};
color: ${({ $variant }) => ($variant === 'outline' ? '#9d174d' : 'white')};
border: ${({ $variant }) =>
$variant === 'outline' ? '1px solid #ec4899' : 'none'};
border-radius: 6px;
font-weight: 600;
font-size: 13px;
cursor: pointer;
`;
const StyledComponentsComponent = () => {
const [count, setCount] = useState(0);
return (
<Card data-testid="styled-components-component">
<Heading>Styled Components</Heading>
<Description>
CSS-in-JS with tagged templates and automatic critical CSS extraction.
</Description>
<ChipRow>
<Chip $color="#ec4899">Badge</Chip>
<Chip $color="#8b5cf6">Styled</Chip>
<Chip $color="#f59e0b">Outline</Chip>
</ChipRow>
<Count data-testid="styled-components-count">Count: {count}</Count>
<ButtonRow>
<StyledButton
data-testid="styled-components-button"
onClick={() => setCount((previous) => previous + 1)}
>
Increment
</StyledButton>
<StyledButton $variant="outline" onClick={() => setCount(0)}>
Reset
</StyledButton>
</ButtonRow>
</Card>
);
};
export default defineFrontComponent({
universalIdentifier: 'test-styled-0000-0000-0000-000000000007',
name: 'styled-components-component',
description: 'A front component using styled-components',
component: StyledComponentsComponent,
});