Skip to content

Commit 65e359d

Browse files
committed
Rename Arrow sizing properties
- length to size - spread to base
1 parent d33fca6 commit 65e359d

File tree

9 files changed

+101
-27
lines changed

9 files changed

+101
-27
lines changed

CLAUDE.md

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Commands
6+
7+
### Development
8+
- `npm run watch` - Build and watch for changes (uses tsup)
9+
- `npm run build` - Clean and build the library for production
10+
11+
### Testing
12+
- `npm test` - Run tests in watch mode (development)
13+
- `npm run test:coverage` - Run tests with coverage report
14+
- Run a single test: `vitest run test/index.spec.tsx`
15+
16+
### Quality Checks
17+
- `npm run lint` - Lint and fix code issues
18+
- `npm run typecheck` - Run TypeScript type checking
19+
- `npm run validate` - Run full validation suite (lint, typecheck, test, build, size check)
20+
- `npm run size` - Check bundle size limits
21+
22+
## Architecture
23+
24+
### Core Component Flow
25+
The library uses a state machine pattern for managing the floater lifecycle:
26+
27+
1. **Main Entry** (`src/index.tsx`): The `ReactFloater` component manages state using `useReducer` and handles:
28+
- Popper.js instance creation/management for positioning
29+
- Event handling (click/hover) with mobile detection
30+
- Portal rendering for the floating element
31+
- Status transitions: IDLE → OPENING → OPEN → CLOSING → IDLE
32+
33+
2. **Component Structure**:
34+
- `Portal` (`src/components/Portal.tsx`): Manages DOM portal rendering
35+
- `Floater` (`src/components/Floater/index.tsx`): The floating UI container
36+
- `Container` (`src/components/Floater/Container.tsx`): Content wrapper with title/footer
37+
- `Arrow` (`src/components/Floater/Arrow.tsx`): Customizable arrow element
38+
- `Wrapper` (`src/components/Wrapper.tsx`): Target element wrapper for beacon mode
39+
40+
3. **Positioning System**: Uses Popper.js v2 with:
41+
- Custom modifiers configuration via `getModifiers()` helper
42+
- Fallback placements for auto-positioning
43+
- Fixed positioning detection for proper scrolling behavior
44+
45+
### Key Patterns
46+
47+
**State Management**: The component uses `useReducer` with status-based state transitions. Changes are tracked using `tree-changes-hook` for efficient callback triggers.
48+
49+
**Style Merging**: Custom styles are deeply merged with defaults using `deepmerge-ts`. The styles object structure is defined in `src/modules/styles.ts`.
50+
51+
**Event Handling**: Special handling for mobile devices (converts hover to click) and delayed hiding for hover events using timeouts.
52+
53+
**Type Safety**: Uses TypeScript with strict typing. Key type definitions in:
54+
- `src/types/common.ts`: Component props, states, and common types
55+
- `src/types/popper.ts`: Popper.js related types
56+
57+
### Testing Approach
58+
- Uses Vitest with React Testing Library
59+
- Test files in `test/` directory
60+
- Coverage requirements: 90% for all metrics
61+
- Mock components in `test/__fixtures__/`

demo/src/examples/WithCustomStyles.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ export default function WithCustomStyles({ cb }: any) {
2828
textAlign: 'right',
2929
},
3030
arrow: {
31+
base: 10,
3132
color: '#000',
32-
length: 8,
33-
spread: 10,
33+
size: 8,
3434
},
3535
}}
3636
title={

demo/src/examples/WithStyledComponents.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Floater, { CustomComponentProps } from 'react-floater';
1+
import Floater, { CustomComponentProps } from 'react-floater';
22
import styled from '@emotion/styled';
33
import { Button } from '@gilbarbara/components';
44

@@ -39,11 +39,11 @@ export default function WithStyledComponents({ cb }: any) {
3939
arrow={
4040
<svg
4141
height="100px"
42+
transform="rotate(180)"
4243
version="1.1"
4344
viewBox="0 0 10 100"
4445
width="10px"
4546
xmlns="http://www.w3.org/2000/svg"
46-
transform="rotate(180)"
4747
>
4848
<g>
4949
<path
@@ -60,9 +60,9 @@ export default function WithStyledComponents({ cb }: any) {
6060
portalElement="#portalElement"
6161
styles={{
6262
arrow: {
63-
length: 80,
64-
spread: 10,
63+
base: 10,
6564
color: '#6ba2ff',
65+
size: 80,
6666
},
6767
}}
6868
>

demo/src/examples/WithTitleAndFooter.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ export default function WithTitleAndFooter({ cb }: any) {
1717
placement="left"
1818
styles={{
1919
arrow: {
20-
length: 64,
21-
spread: 12,
20+
base: 12,
21+
size: 64,
2222
},
2323
}}
2424
title="Oi, I have a title!"

src/components/Floater/Arrow.tsx

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,38 @@ interface Props {
1212
export default function FloaterArrow(props: Props) {
1313
const { arrow, arrowRef, placement, styles } = props;
1414
const {
15-
arrow: { color, display, length, position, spread },
15+
arrow: { base, color, display, position, size },
1616
} = styles;
1717
const arrowStyles: CSSProperties = { display, position };
1818

1919
let points;
20-
let x = spread;
21-
let y = length;
20+
let x = base;
21+
let y = size;
2222

2323
if (placement.startsWith('top')) {
2424
points = `0,0 ${x / 2},${y} ${x},0`;
2525
} else if (placement.startsWith('bottom')) {
2626
points = `${x},${y} ${x / 2},0 0,${y}`;
2727
} else if (placement.startsWith('left')) {
28-
y = spread;
29-
x = length;
28+
y = base;
29+
x = size;
3030
points = `0,0 ${x},${y / 2} 0,${y}`;
3131
} else if (placement.startsWith('right')) {
32-
y = spread;
33-
x = length;
32+
y = base;
33+
x = size;
3434
points = `${x},${y} ${x},0 0,${y / 2}`;
3535
}
3636

3737
if (arrow) {
3838
return (
39-
<span ref={arrowRef} style={{ color, height: length, width: spread }}>
39+
<span
40+
ref={arrowRef}
41+
style={{
42+
color,
43+
height: placement.startsWith('left') || placement.startsWith('right') ? base : size,
44+
width: placement.startsWith('left') || placement.startsWith('right') ? size : base,
45+
}}
46+
>
4047
{arrow}
4148
</span>
4249
);

src/components/Floater/index.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function Floater(props: Props) {
4040

4141
const style = useMemo(() => {
4242
const {
43-
arrow: { length },
43+
arrow: { size },
4444
floater,
4545
floaterCentered,
4646
floaterClosing,
@@ -51,13 +51,13 @@ function Floater(props: Props) {
5151

5252
if (!hideArrow) {
5353
if (placement.startsWith('top')) {
54-
element.padding = `0 0 ${length}px`;
54+
element.padding = `0 0 ${size}px`;
5555
} else if (placement.startsWith('bottom')) {
56-
element.padding = `${length}px 0 0`;
56+
element.padding = `${size}px 0 0`;
5757
} else if (placement.startsWith('left')) {
58-
element.padding = `0 ${length}px 0 0`;
58+
element.padding = `0 ${size}px 0 0`;
5959
} else if (placement.startsWith('right')) {
60-
element.padding = `0 0 0 ${length}px`;
60+
element.padding = `0 0 0 ${size}px`;
6161
}
6262
}
6363

src/modules/styles.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ export default function getStyles(styles?: PartialDeep<Styles>): Styles {
1313
return deepmerge(
1414
{
1515
arrow: {
16+
base: 32,
1617
color: '#fff',
1718
display: 'inline-flex',
18-
length: 16,
1919
position: 'absolute',
20-
spread: 32,
20+
size: 16,
2121
},
2222
close: {
2323
backgroundColor: 'transparent',

src/types/common.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,14 @@ export interface State {
136136

137137
export interface Styles {
138138
arrow: CSSProperties & {
139-
length: number;
140-
spread: number;
139+
/**
140+
* The distance from the tip of the arrow to the edge of the Floater.
141+
*/
142+
base: number;
143+
/**
144+
* The width of the base of the arrow.
145+
*/
146+
size: number;
141147
};
142148
close: CSSProperties;
143149
container: CSSProperties;

test/index.spec.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -699,8 +699,8 @@ describe('ReactFloater', () => {
699699
styles: {
700700
arrow: {
701701
color: '#6ba2ff',
702-
length: 80,
703-
spread: 10,
702+
size: 80,
703+
base: 10,
704704
},
705705
},
706706
});

0 commit comments

Comments
 (0)