@pyreon/coolgrid 0.21.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +117 -139
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -1,167 +1,134 @@
|
|
|
1
1
|
# @pyreon/coolgrid
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Context-cascading responsive grid — Container, Row, Col with custom columns and breakpoints.
|
|
4
4
|
|
|
5
|
-
Bootstrap-
|
|
5
|
+
`@pyreon/coolgrid` is a Bootstrap-style flexbox grid where every numeric prop is responsive (single value, mobile-first array, or breakpoint-keyed object). Configuration (`columns`, `gap`, `gutter`, `padding`, `contentAlignX`) cascades through Pyreon's context system — set it on `Container` and every nested `Row` / `Col` inherits, with explicit per-element overrides. Breakpoint names and column counts are not hardcoded: ship with the default Bootstrap-4 theme or define your own (`{ phone: 0, tablet: 600, desktop: 1024 }` × `columns: 24`). Built on `@pyreon/unistyle` + `@pyreon/styler`.
|
|
6
6
|
|
|
7
|
-
##
|
|
8
|
-
|
|
9
|
-
- **Familiar mental model** — Container, Row, Col just like Bootstrap
|
|
10
|
-
- **Context cascading** — set columns, gaps, and gutters at Container level, inherited by all Rows and Cols
|
|
11
|
-
- **Responsive values** — single value, mobile-first array, or breakpoint object on every prop
|
|
12
|
-
- **Custom breakpoints** — name and size them however you want
|
|
13
|
-
- **Custom column counts** — 12, 24, 5 — any number
|
|
14
|
-
- **Custom components** — swap Container, Row, or Col underlying elements
|
|
15
|
-
- **Default Bootstrap theme** — included and ready to use
|
|
16
|
-
|
|
17
|
-
## Installation
|
|
7
|
+
## Install
|
|
18
8
|
|
|
19
9
|
```bash
|
|
20
|
-
bun add @pyreon/coolgrid
|
|
10
|
+
bun add @pyreon/coolgrid @pyreon/core @pyreon/reactivity @pyreon/ui-core @pyreon/unistyle @pyreon/styler
|
|
21
11
|
```
|
|
22
12
|
|
|
23
|
-
## Quick
|
|
13
|
+
## Quick start
|
|
24
14
|
|
|
25
|
-
```
|
|
26
|
-
import { Container, Row, Col,
|
|
27
|
-
|
|
28
|
-
Provider
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
15
|
+
```tsx
|
|
16
|
+
import { Provider, Container, Row, Col, theme } from '@pyreon/coolgrid'
|
|
17
|
+
|
|
18
|
+
<Provider theme={theme}>
|
|
19
|
+
<Container>
|
|
20
|
+
<Row>
|
|
21
|
+
<Col size={{ xs: 12, md: 8 }}>Main content</Col>
|
|
22
|
+
<Col size={{ xs: 12, md: 4 }}>Sidebar</Col>
|
|
23
|
+
</Row>
|
|
24
|
+
</Container>
|
|
25
|
+
</Provider>
|
|
36
26
|
```
|
|
37
27
|
|
|
28
|
+
Provider wraps `@pyreon/unistyle`'s provider — it scopes breakpoints, root-size, and grid defaults to the subtree. One provider per app at the root.
|
|
29
|
+
|
|
38
30
|
## Components
|
|
39
31
|
|
|
40
|
-
### Container
|
|
32
|
+
### `<Container>` — outermost grid boundary
|
|
41
33
|
|
|
42
|
-
|
|
34
|
+
Sets max-width and seeds the configuration context for descendants.
|
|
43
35
|
|
|
44
|
-
```
|
|
45
|
-
Container
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
gutter: 24,
|
|
49
|
-
padding: 16,
|
|
50
|
-
children: Row({ children: '...' }),
|
|
51
|
-
})
|
|
36
|
+
```tsx
|
|
37
|
+
<Container columns={12} gap={16} gutter={24} padding={16} width={{ xs: '100%', lg: 1140 }}>
|
|
38
|
+
<Row>…</Row>
|
|
39
|
+
</Container>
|
|
52
40
|
```
|
|
53
41
|
|
|
54
|
-
| Prop
|
|
55
|
-
|
|
56
|
-
| columns
|
|
57
|
-
| gap
|
|
58
|
-
| gutter
|
|
59
|
-
| padding
|
|
60
|
-
|
|
|
61
|
-
|
|
|
62
|
-
|
|
|
63
|
-
|
|
|
42
|
+
| Prop | Type | Description |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| `columns` | `ValueType` | Number of grid columns (default 12) |
|
|
45
|
+
| `gap` | `ValueType` | Space between columns |
|
|
46
|
+
| `gutter` | `ValueType` | Outer gutter (negative-margin offset on Row) |
|
|
47
|
+
| `padding` | `ValueType` | Column inner padding |
|
|
48
|
+
| `contentAlignX` | `'center' \| 'left' \| 'right' \| 'spaceAround' \| 'spaceBetween' \| 'spaceEvenly'` | Horizontal alignment |
|
|
49
|
+
| `width` | `ContainerWidth \| (widths) => ContainerWidth` | Container max-width override |
|
|
50
|
+
| `component` | `ComponentFn` | Custom root element |
|
|
51
|
+
| `css` | `ExtraStyles` | Extend container styling |
|
|
64
52
|
|
|
65
|
-
|
|
53
|
+
Container-level configuration props cascade to every nested Row and Col through context (built on Pyreon's `pushContext` / `popContext`).
|
|
66
54
|
|
|
67
|
-
### Row
|
|
55
|
+
### `<Row>` — flex wrapper
|
|
68
56
|
|
|
69
|
-
|
|
57
|
+
Inherits Container config; can override any cascading prop.
|
|
70
58
|
|
|
71
|
-
```
|
|
72
|
-
Row
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
})
|
|
59
|
+
```tsx
|
|
60
|
+
<Row contentAlignX="center" gap={[8, 16, 24]}>
|
|
61
|
+
<Col>One</Col>
|
|
62
|
+
<Col>Two</Col>
|
|
63
|
+
</Row>
|
|
77
64
|
```
|
|
78
65
|
|
|
79
|
-
Setting `size` on Row applies it
|
|
66
|
+
Setting `size` on Row applies it as the DEFAULT for every Col inside:
|
|
80
67
|
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
})
|
|
68
|
+
```tsx
|
|
69
|
+
<Row size={6}>
|
|
70
|
+
<Col>Half</Col>
|
|
71
|
+
<Col>Half</Col>
|
|
72
|
+
</Row>
|
|
87
73
|
```
|
|
88
74
|
|
|
89
|
-
|
|
90
|
-
| ------------- | ------------- | --------------------------------------- |
|
|
91
|
-
| size | `number` | Default column size for all Cols inside |
|
|
92
|
-
| component | `ComponentFn` | Custom row element |
|
|
93
|
-
| css | `ExtendCss` | Extend row styling |
|
|
94
|
-
| contentAlignX | `AlignX` | Override horizontal alignment |
|
|
95
|
-
|
|
96
|
-
### Col
|
|
75
|
+
### `<Col>` — individual column
|
|
97
76
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
```ts
|
|
101
|
-
// Fixed size
|
|
102
|
-
Col({ size: 4, children: '1/3 width' })
|
|
77
|
+
Width is calculated as `(size / columns)` of the parent Row.
|
|
103
78
|
|
|
104
|
-
|
|
105
|
-
Col
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
Col({ size: { xs: 0, md: 6 }, children: 'Hidden on xs' })
|
|
79
|
+
```tsx
|
|
80
|
+
<Col size={4}>1/3 width on every breakpoint</Col>
|
|
81
|
+
<Col size={{ xs: 12, sm: 6, lg: 4 }}>Responsive</Col>
|
|
82
|
+
<Col size={{ xs: 0, md: 6 }}>Hidden on xs (size 0 → display:none)</Col>
|
|
109
83
|
```
|
|
110
84
|
|
|
111
|
-
| Prop
|
|
112
|
-
|
|
113
|
-
| size
|
|
114
|
-
| padding
|
|
115
|
-
| component | `ComponentFn` | Custom column element
|
|
116
|
-
| css
|
|
85
|
+
| Prop | Type | Description |
|
|
86
|
+
|---|---|---|
|
|
87
|
+
| `size` | `ValueType` | Column span (of `columns`) |
|
|
88
|
+
| `padding` | `ValueType` | Override inner padding |
|
|
89
|
+
| `component` | `ComponentFn` | Custom column element |
|
|
90
|
+
| `css` | `ExtraStyles` | Extend column styling |
|
|
117
91
|
|
|
118
|
-
##
|
|
92
|
+
## Responsive values
|
|
119
93
|
|
|
120
|
-
|
|
94
|
+
Every numeric prop accepts three shapes:
|
|
121
95
|
|
|
122
96
|
```ts
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
rootSize: 16,
|
|
126
|
-
breakpoints: {
|
|
127
|
-
phone: 0,
|
|
128
|
-
tablet: 600,
|
|
129
|
-
desktop: 1024,
|
|
130
|
-
wide: 1440,
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
children: [
|
|
134
|
-
/* ... */
|
|
135
|
-
],
|
|
136
|
-
})
|
|
137
|
-
```
|
|
97
|
+
// Single value — applies at every breakpoint
|
|
98
|
+
size={6}
|
|
138
99
|
|
|
139
|
-
|
|
100
|
+
// Mobile-first array — positional [xs, sm, md, lg, xl]
|
|
101
|
+
size={[12, 6, 4]}
|
|
140
102
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
columns: 24,
|
|
144
|
-
children: Row({
|
|
145
|
-
children: [Col({ size: 16, children: 'Two thirds' }), Col({ size: 8, children: 'One third' })],
|
|
146
|
-
}),
|
|
147
|
-
})
|
|
103
|
+
// Breakpoint-keyed object — explicit
|
|
104
|
+
size={{ xs: 12, md: 6, lg: 4 }}
|
|
148
105
|
```
|
|
149
106
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
Configuration flows from Container through Row to Col via Pyreon's context system (`pushContext`/`popContext`):
|
|
107
|
+
## Custom breakpoints / columns
|
|
153
108
|
|
|
154
|
-
```
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
109
|
+
```tsx
|
|
110
|
+
<Provider
|
|
111
|
+
theme={{
|
|
112
|
+
rootSize: 16,
|
|
113
|
+
breakpoints: { phone: 0, tablet: 600, desktop: 1024, wide: 1440 },
|
|
114
|
+
grid: {
|
|
115
|
+
columns: 24,
|
|
116
|
+
container: { phone: '100%', tablet: 540, desktop: 960, wide: 1400 },
|
|
117
|
+
},
|
|
118
|
+
}}
|
|
119
|
+
>
|
|
120
|
+
<Container columns={24}>
|
|
121
|
+
<Row>
|
|
122
|
+
<Col size={16}>Two thirds of 24</Col>
|
|
123
|
+
<Col size={8}>One third of 24</Col>
|
|
124
|
+
</Row>
|
|
125
|
+
</Container>
|
|
126
|
+
</Provider>
|
|
158
127
|
```
|
|
159
128
|
|
|
160
|
-
|
|
129
|
+
## Default theme
|
|
161
130
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
The included `theme` export provides Bootstrap 4 defaults:
|
|
131
|
+
The `theme` export ships Bootstrap-4 defaults:
|
|
165
132
|
|
|
166
133
|
```ts
|
|
167
134
|
{
|
|
@@ -174,30 +141,41 @@ The included `theme` export provides Bootstrap 4 defaults:
|
|
|
174
141
|
}
|
|
175
142
|
```
|
|
176
143
|
|
|
177
|
-
##
|
|
144
|
+
## Cascading model
|
|
178
145
|
|
|
179
|
-
|
|
146
|
+
```text
|
|
147
|
+
<Container columns={12} gap={16}>
|
|
148
|
+
↓ context push
|
|
149
|
+
<Row> inherits columns=12, gap=16; can override
|
|
150
|
+
↓ context push
|
|
151
|
+
<Col size={4}> inherits columns, gap → width = 4 / 12 = 33.33%
|
|
152
|
+
```
|
|
180
153
|
|
|
181
|
-
|
|
182
|
-
// Single value
|
|
183
|
-
Col({ size: 6 })
|
|
154
|
+
Each level pushes its overrides into the context; children read the merged stack. Props set at a deeper level override the ancestor for that subtree only.
|
|
184
155
|
|
|
185
|
-
|
|
186
|
-
Col({ size: [12, 6, 4] })
|
|
156
|
+
## Custom underlying elements
|
|
187
157
|
|
|
188
|
-
|
|
189
|
-
|
|
158
|
+
Swap any layer's root element via `component`:
|
|
159
|
+
|
|
160
|
+
```tsx
|
|
161
|
+
<Container component={MyContainerWrapper}>
|
|
162
|
+
<Row component="section">
|
|
163
|
+
<Col component="article">…</Col>
|
|
164
|
+
</Row>
|
|
165
|
+
</Container>
|
|
190
166
|
```
|
|
191
167
|
|
|
192
|
-
##
|
|
168
|
+
## Gotchas
|
|
169
|
+
|
|
170
|
+
- **`Provider` is the unistyle provider** under the hood. If you already render `<PyreonUI>` (from `@pyreon/ui-core`) at your app root, it sets up unistyle context — you only need a fresh `<Provider>` if you want different breakpoints in a subtree.
|
|
171
|
+
- **`size: 0` is meaningful** — it sets the column to `display: none` at that breakpoint (hidden), not "zero-width but still in flow".
|
|
172
|
+
- **`gutter` is negative-margin on the Row** + matching padding on each Col. Setting `gutter` and `padding` independently is fine but be aware of the visual offset.
|
|
173
|
+
- **`columns` MUST be set on a Container** if you want a non-default count. Setting it on a Row works for that Row only, but the visual cascade is harder to reason about — keep it at Container level.
|
|
174
|
+
- **Context is per-Provider.** If you nest two `<Provider>` blocks, the inner one starts fresh from its own theme — not from the outer Provider's overrides.
|
|
175
|
+
|
|
176
|
+
## Documentation
|
|
193
177
|
|
|
194
|
-
|
|
195
|
-
| ------------------ | -------- |
|
|
196
|
-
| @pyreon/core | >= 0.0.1 |
|
|
197
|
-
| @pyreon/reactivity | >= 0.0.1 |
|
|
198
|
-
| @pyreon/ui-core | >= 0.0.1 |
|
|
199
|
-
| @pyreon/unistyle | >= 0.0.1 |
|
|
200
|
-
| @pyreon/styler | >= 0.0.1 |
|
|
178
|
+
Full docs: [docs.pyreon.dev/docs/coolgrid](https://docs.pyreon.dev/docs/coolgrid) (or `docs/docs/coolgrid.md` in this repo).
|
|
201
179
|
|
|
202
180
|
## License
|
|
203
181
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pyreon/coolgrid",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "Responsive grid system for Pyreon",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -42,20 +42,20 @@
|
|
|
42
42
|
"typecheck": "tsc --noEmit"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@pyreon/test-utils": "^0.13.
|
|
46
|
-
"@pyreon/typescript": "^0.
|
|
47
|
-
"@pyreon/ui-core": "^0.
|
|
45
|
+
"@pyreon/test-utils": "^0.13.10",
|
|
46
|
+
"@pyreon/typescript": "^0.23.0",
|
|
47
|
+
"@pyreon/ui-core": "^0.23.0",
|
|
48
48
|
"@vitest/browser-playwright": "^4.1.4",
|
|
49
|
-
"@vitus-labs/tools-rolldown": "^2.
|
|
49
|
+
"@vitus-labs/tools-rolldown": "^2.4.0"
|
|
50
50
|
},
|
|
51
51
|
"engines": {
|
|
52
52
|
"node": ">= 22"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"@pyreon/core": "^0.
|
|
56
|
-
"@pyreon/reactivity": "^0.
|
|
57
|
-
"@pyreon/styler": "^0.
|
|
58
|
-
"@pyreon/ui-core": "^0.
|
|
59
|
-
"@pyreon/unistyle": "^0.
|
|
55
|
+
"@pyreon/core": "^0.23.0",
|
|
56
|
+
"@pyreon/reactivity": "^0.23.0",
|
|
57
|
+
"@pyreon/styler": "^0.23.0",
|
|
58
|
+
"@pyreon/ui-core": "^0.23.0",
|
|
59
|
+
"@pyreon/unistyle": "^0.23.0"
|
|
60
60
|
}
|
|
61
61
|
}
|