or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

context-management.mdhook-interface.mdindex.mdpositioned-elements.mdreference-handling.md

positioned-elements.mddocs/

0

# Positioned Elements

1

2

Positioned element creation functionality that renders elements with precise positioning relative to reference elements. The Popper component provides comprehensive configuration options and render props containing positioning data and styling.

3

4

## Capabilities

5

6

### Popper Component

7

8

Creates positioned elements with advanced configuration options. Uses render props to provide positioning data, styles, and utility functions.

9

10

```typescript { .api }

11

/**

12

* Creates positioned popper element with comprehensive configuration

13

* @param children - Render prop function receiving positioning data and styles

14

* @param innerRef - Optional ref to the popper element for external access

15

* @param modifiers - Array of Popper.js modifiers for behavior customization

16

* @param placement - Preferred placement position relative to reference

17

* @param strategy - Positioning strategy (absolute or fixed)

18

* @param referenceElement - Override reference element (bypasses Manager context)

19

* @param onFirstUpdate - Callback fired after first positioning update

20

* @returns React element with positioned content

21

*/

22

function Popper<Modifiers>({

23

children,

24

innerRef,

25

modifiers,

26

placement,

27

strategy,

28

referenceElement,

29

onFirstUpdate,

30

}: PopperProps<Modifiers>): React.Node;

31

32

interface PopperProps<Modifiers> {

33

/** Render prop function that receives positioning data and controls */

34

children: (props: PopperChildrenProps) => React.ReactNode;

35

/** Optional ref for external access to the popper element */

36

innerRef?: React.Ref<any>;

37

/** Array of Popper.js modifiers for customizing behavior */

38

modifiers?: ReadonlyArray<Modifier<Modifiers>>;

39

/** Preferred placement position (default: 'bottom') */

40

placement?: PopperJS.Placement;

41

/** Positioning strategy - 'absolute' or 'fixed' (default: 'absolute') */

42

strategy?: PopperJS.PositioningStrategy;

43

/** Override reference element, bypassing Manager context */

44

referenceElement?: HTMLElement | PopperJS.VirtualElement;

45

/** Callback fired after first positioning update */

46

onFirstUpdate?: (state: Partial<PopperJS.State>) => void;

47

}

48

```

49

50

### Render Props Interface

51

52

The Popper component provides comprehensive positioning data through render props:

53

54

```typescript { .api }

55

interface PopperChildrenProps {

56

/** Ref that must be attached to the popper DOM element */

57

ref: React.Ref<any>;

58

/** Computed styles for positioning the popper element */

59

style: React.CSSProperties;

60

/** Final computed placement after auto-positioning */

61

placement: PopperJS.Placement;

62

/** Whether the reference element is hidden from view */

63

isReferenceHidden?: boolean;

64

/** Whether the popper has escaped its boundary constraints */

65

hasPopperEscaped?: boolean;

66

/** Async function to manually update popper positioning */

67

update: () => Promise<null | Partial<PopperJS.State>>;

68

/** Synchronous function to force immediate positioning update */

69

forceUpdate: () => Partial<PopperJS.State>;

70

/** Props and styling for arrow elements */

71

arrowProps: PopperArrowProps;

72

}

73

74

interface PopperArrowProps {

75

/** Ref for the arrow element */

76

ref: React.Ref<any>;

77

/** Computed styles for positioning the arrow */

78

style: React.CSSProperties;

79

}

80

```

81

82

**Usage Examples:**

83

84

```tsx

85

import React from "react";

86

import { Manager, Reference, Popper } from "react-popper";

87

88

// Basic popper with tooltip

89

function BasicTooltip() {

90

const [visible, setVisible] = React.useState(false);

91

92

return (

93

<Manager>

94

<Reference>

95

{({ ref }) => (

96

<button

97

ref={ref}

98

onMouseEnter={() => setVisible(true)}

99

onMouseLeave={() => setVisible(false)}

100

>

101

Hover for tooltip

102

</button>

103

)}

104

</Reference>

105

{visible && (

106

<Popper placement="top">

107

{({ ref, style, placement }) => (

108

<div

109

ref={ref}

110

style={{

111

...style,

112

background: "black",

113

color: "white",

114

padding: "4px 8px",

115

borderRadius: "4px",

116

}}

117

data-placement={placement}

118

>

119

Tooltip content

120

</div>

121

)}

122

</Popper>

123

)}

124

</Manager>

125

);

126

}

127

128

// Popper with arrow

129

function TooltipWithArrow() {

130

const [visible, setVisible] = React.useState(false);

131

132

return (

133

<Manager>

134

<Reference>

135

{({ ref }) => (

136

<button ref={ref} onClick={() => setVisible(!visible)}>

137

Toggle tooltip

138

</button>

139

)}

140

</Reference>

141

{visible && (

142

<Popper placement="top">

143

{({ ref, style, placement, arrowProps }) => (

144

<div

145

ref={ref}

146

style={{

147

...style,

148

background: "black",

149

color: "white",

150

padding: "8px",

151

borderRadius: "4px",

152

}}

153

data-placement={placement}

154

>

155

Tooltip with arrow

156

<div

157

ref={arrowProps.ref}

158

style={{

159

...arrowProps.style,

160

background: "black",

161

width: "8px",

162

height: "8px",

163

transform: "rotate(45deg)",

164

}}

165

/>

166

</div>

167

)}

168

</Popper>

169

)}

170

</Manager>

171

);

172

}

173

174

// Advanced popper with modifiers

175

function AdvancedPopper() {

176

const [visible, setVisible] = React.useState(false);

177

178

const modifiers = React.useMemo(

179

() => [

180

{

181

name: "offset",

182

options: {

183

offset: [0, 8], // 8px distance from reference

184

},

185

},

186

{

187

name: "preventOverflow",

188

options: {

189

padding: 8, // Keep 8px from viewport edges

190

},

191

},

192

],

193

[]

194

);

195

196

return (

197

<Manager>

198

<Reference>

199

{({ ref }) => (

200

<button ref={ref} onClick={() => setVisible(!visible)}>

201

Advanced positioning

202

</button>

203

)}

204

</Reference>

205

{visible && (

206

<Popper

207

placement="bottom-start"

208

modifiers={modifiers}

209

onFirstUpdate={(state) => {

210

console.log("Popper positioned:", state);

211

}}

212

>

213

{({ ref, style, placement, update, forceUpdate, isReferenceHidden, hasPopperEscaped }) => (

214

<div

215

ref={ref}

216

style={{

217

...style,

218

background: "white",

219

border: "1px solid #ccc",

220

borderRadius: "4px",

221

padding: "12px",

222

boxShadow: "0 2px 8px rgba(0,0,0,0.1)",

223

opacity: isReferenceHidden ? 0.5 : 1,

224

}}

225

data-placement={placement}

226

>

227

<div>Advanced tooltip content</div>

228

<div style={{ fontSize: "12px", color: "#666" }}>

229

Escaped: {hasPopperEscaped ? "Yes" : "No"}

230

</div>

231

<button onClick={() => update()}>Update Position</button>

232

<button onClick={() => { const state = forceUpdate(); console.log('Force updated:', state); }}>Force Update</button>

233

</div>

234

)}

235

</Popper>

236

)}

237

</Manager>

238

);

239

}

240

```

241

242

### Placement Options

243

244

The Popper component supports all Popper.js placement options:

245

246

```typescript { .api }

247

type Placement =

248

| "auto"

249

| "auto-start"

250

| "auto-end"

251

| "top"

252

| "top-start"

253

| "top-end"

254

| "bottom"

255

| "bottom-start"

256

| "bottom-end"

257

| "right"

258

| "right-start"

259

| "right-end"

260

| "left"

261

| "left-start"

262

| "left-end";

263

```

264

265

### Modifiers

266

267

Modifiers customize Popper behavior. Common built-in modifiers:

268

269

```typescript { .api }

270

// Common modifier configurations

271

type CommonModifiers =

272

| { name: "offset"; options: { offset: [number, number] } }

273

| { name: "preventOverflow"; options: { padding: number } }

274

| { name: "flip"; options: { fallbackPlacements: Placement[] } }

275

| { name: "arrow"; options: { element: HTMLElement } }

276

| { name: "hide"; enabled: boolean };

277

```

278

279

## Error Handling

280

281

The Popper component handles various edge cases:

282

283

- **Missing reference**: Gracefully handles cases where reference element is not available

284

- **Boundary constraints**: Respects viewport and container boundaries

285

- **Dynamic updates**: Automatically updates position when reference or popper elements change

286

- **Memory management**: Properly cleans up Popper instances on unmount

287

288

## Best Practices

289

290

1. **Always provide a ref to the popper element:**

291

```tsx

292

<Popper>

293

{({ ref, style }) => (

294

<div ref={ref} style={style}>Content</div>

295

)}

296

</Popper>

297

```

298

299

2. **Use the provided styles for positioning:**

300

```tsx

301

// ✅ Include provided styles

302

<div ref={ref} style={{ ...style, background: "white" }}>

303

304

// ❌ Don't ignore positioning styles

305

<div ref={ref} style={{ background: "white" }}>

306

```

307

308

3. **Handle arrow positioning correctly:**

309

```tsx

310

<Popper>

311

{({ ref, style, arrowProps }) => (

312

<div ref={ref} style={style}>

313

Content

314

<div ref={arrowProps.ref} style={arrowProps.style} />

315

</div>

316

)}

317

</Popper>

318

```

319

320

4. **Use modifiers for advanced positioning:**

321

```tsx

322

const modifiers = [

323

{ name: "offset", options: { offset: [0, 8] } },

324

{ name: "preventOverflow", options: { padding: 8 } }

325

];

326

<Popper modifiers={modifiers}>...</Popper>

327

```