or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

component-composition.mdcontext-provider.mdcore-styling.mdindex.mdreact-hooks.md

component-composition.mddocs/

0

# Component Composition

1

2

Utilities for extending and modifying existing styled components with additional styles, transformations, and wrapper components. These functions enable composition and reuse of styled components.

3

4

## Capabilities

5

6

### With Style

7

8

Extends existing styled components with additional styles using deep merge.

9

10

```typescript { .api }

11

/**

12

* Extends existing styled components with additional styles using deep merge

13

* @param component - Existing styled component to extend

14

* @param style - Style object or function to merge with existing styles

15

* @returns New styled component with merged styles

16

*/

17

function withStyle<Base extends StyletronComponent<any, any>, Props = {}>(

18

component: Base,

19

style: StyleObject | ((props: Props) => StyleObject)

20

): Base extends StyletronComponent<infer D, infer P>

21

? StyletronComponent<D, P & Props>

22

: never;

23

```

24

25

**Usage Examples:**

26

27

```typescript

28

import { styled, withStyle } from "styletron-react";

29

30

// Base button component

31

const BaseButton = styled("button", {

32

padding: "8px 16px",

33

border: "none",

34

borderRadius: "4px",

35

fontSize: "14px",

36

":hover": {

37

opacity: 0.8,

38

},

39

});

40

41

// Extend with additional styles (static)

42

const PrimaryButton = withStyle(BaseButton, {

43

backgroundColor: "blue",

44

color: "white",

45

});

46

47

// Extend with dynamic styles

48

const ConditionalButton = withStyle<typeof BaseButton, {$danger: boolean}>(

49

BaseButton,

50

(props) => ({

51

backgroundColor: props.$danger ? "red" : "green",

52

color: "white",

53

})

54

);

55

56

// Deep merge example - hover styles are merged

57

const HoverButton = withStyle(BaseButton, {

58

backgroundColor: "purple",

59

":hover": {

60

backgroundColor: "darkpurple", // Merged with existing hover styles

61

},

62

});

63

```

64

65

### With Transform

66

67

Transforms styles of existing styled components using a transformation function.

68

69

```typescript { .api }

70

/**

71

* Transforms styles of existing styled components using a transformation function

72

* @param component - Existing styled component to transform

73

* @param transformer - Function that receives current style and props, returns new style

74

* @returns New styled component with transformed styles

75

*/

76

function withTransform<

77

Base extends StyletronComponent<any, any>,

78

Props,

79

>(

80

component: Base,

81

transformer: (style: StyleObject, props: Props) => StyleObject

82

): Base extends StyletronComponent<infer D, infer P>

83

? StyletronComponent<D, P & Props>

84

: never;

85

```

86

87

**Usage Examples:**

88

89

```typescript

90

import { styled, withTransform } from "styletron-react";

91

92

const BaseButton = styled("button", {

93

padding: "8px 16px",

94

backgroundColor: "blue",

95

color: "white",

96

});

97

98

// Transform existing styles based on props

99

const ScalableButton = withTransform(

100

BaseButton,

101

(style, props: {$scale: number}) => ({

102

...style,

103

transform: `scale(${props.$scale})`,

104

transformOrigin: "center",

105

})

106

);

107

108

// Conditional transformation

109

const ToggleButton = withTransform(

110

BaseButton,

111

(style, props: {$active: boolean}) => ({

112

...style,

113

backgroundColor: props.$active ? "green" : style.backgroundColor,

114

fontWeight: props.$active ? "bold" : "normal",

115

})

116

);

117

```

118

119

### With Wrapper

120

121

Wraps styled components with additional wrapper components for layout or behavior modifications.

122

123

```typescript { .api }

124

/**

125

* Wraps styled components with additional wrapper components

126

* @param component - Existing styled component to wrap

127

* @param wrapper - Function that receives the component and returns a wrapper component

128

* @returns New styled component with wrapper applied

129

*/

130

function withWrapper<Base extends StyletronComponent<any, any>, Props>(

131

component: Base,

132

wrapper: (

133

component: Base

134

) => React.ComponentType<Props & React.ComponentProps<Base>>

135

): Base extends StyletronComponent<infer D, infer P>

136

? StyletronComponent<D, P & Props>

137

: never;

138

```

139

140

**Usage Examples:**

141

142

```typescript

143

import { styled, withWrapper } from "styletron-react";

144

145

const BaseButton = styled("button", {

146

padding: "8px 16px",

147

backgroundColor: "blue",

148

color: "white",

149

});

150

151

// Wrap with container div

152

const ContainerButton = withWrapper(BaseButton, (StyledButton) => (props) => (

153

<div className="button-container">

154

<StyledButton {...props} />

155

</div>

156

));

157

158

// Wrap with loading state

159

const LoadingButton = withWrapper(

160

BaseButton,

161

(StyledButton) => (props: {$loading?: boolean} & React.ComponentProps<typeof BaseButton>) => (

162

<div style={{position: "relative"}}>

163

<StyledButton {...props} disabled={props.$loading || props.disabled}>

164

{props.$loading ? "Loading..." : props.children}

165

</StyledButton>

166

</div>

167

)

168

);

169

170

// Complex wrapper with additional functionality

171

const TooltipButton = withWrapper(

172

BaseButton,

173

(StyledButton) => (props: {$tooltip?: string} & React.ComponentProps<typeof BaseButton>) => (

174

<div title={props.$tooltip}>

175

<StyledButton {...props} />

176

</div>

177

)

178

);

179

```

180

181

## Composition Patterns

182

183

### Chaining Compositions

184

185

Multiple composition functions can be chained together:

186

187

```typescript

188

import { styled, withStyle, withTransform, withWrapper } from "styletron-react";

189

190

const BaseButton = styled("button", {

191

padding: "8px 16px",

192

border: "none",

193

});

194

195

// Chain multiple compositions

196

const EnhancedButton = withWrapper(

197

withTransform(

198

withStyle(BaseButton, {

199

backgroundColor: "blue",

200

color: "white",

201

}),

202

(style, props: {$size: "small" | "large"}) => ({

203

...style,

204

padding: props.$size === "large" ? "12px 24px" : "6px 12px",

205

})

206

),

207

(StyledButton) => (props) => (

208

<div className="button-wrapper">

209

<StyledButton {...props} />

210

</div>

211

)

212

);

213

```

214

215

### Style Inheritance

216

217

Compositions preserve and extend the type information and styling behavior:

218

219

```typescript

220

// All composition functions maintain prop types

221

const TypedButton = styled<"button", {$variant: "primary" | "secondary"}>("button", {

222

padding: "8px 16px",

223

});

224

225

// withStyle preserves and extends types

226

const ExtendedButton = withStyle<typeof TypedButton, {$size: "small" | "large"}>(

227

TypedButton,

228

(props) => ({

229

fontSize: props.$size === "large" ? "16px" : "14px",

230

backgroundColor: props.$variant === "primary" ? "blue" : "gray",

231

})

232

);

233

234

// Usage with full type safety

235

<ExtendedButton $variant="primary" $size="large">

236

Typed Button

237

</ExtendedButton>

238

```

239

240

## Types

241

242

```typescript { .api }

243

type WithStyleFn = {

244

<Base extends StyletronComponent<any, any>, Props = {}>(

245

component: Base,

246

style: StyleObject | ((props: Props) => StyleObject)

247

): Base extends StyletronComponent<infer D, infer P>

248

? StyletronComponent<D, P & Props>

249

: never;

250

};

251

252

type WithTransformFn = <

253

Base extends StyletronComponent<any, any>,

254

Props,

255

>(

256

component: Base,

257

style: (style: StyleObject, props: Props) => StyleObject

258

) => Base extends StyletronComponent<infer D, infer P>

259

? StyletronComponent<D, P & Props>

260

: never;

261

262

type WithWrapperFn = <Base extends StyletronComponent<any, any>, Props>(

263

component: Base,

264

wrapper: (

265

component: Base

266

) => React.ComponentType<Props & React.ComponentProps<Base>>

267

) => Base extends StyletronComponent<infer D, infer P>

268

? StyletronComponent<D, P & Props>

269

: never;

270

```