@ceed/cds 1.19.0 → 1.19.1-next.1

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.
@@ -2,6 +2,8 @@
2
2
 
3
3
  ## Introduction
4
4
 
5
+ Container is a layout component that centers content horizontally and constrains its maximum width based on predefined breakpoints. It provides consistent padding and ensures content doesn't stretch too wide on large screens, improving readability and maintaining a cohesive layout across different viewport sizes. Container is commonly used as the main wrapper for page content in admin dashboards and web applications.
6
+
5
7
  ```tsx
6
8
  <Container
7
9
  children={<div style={{
@@ -20,4 +22,509 @@
20
22
 
21
23
  ```tsx
22
24
  import { Container } from '@ceed/cds';
25
+
26
+ function PageLayout() {
27
+ return (
28
+ <Container maxWidth="desktop">
29
+ <Typography level="h1">Page Title</Typography>
30
+ <Typography>Page content goes here...</Typography>
31
+ </Container>
32
+ );
33
+ }
34
+ ```
35
+
36
+ ## Examples
37
+
38
+ ### Desktop
39
+
40
+ Maximum width optimized for desktop screens (widest setting).
41
+
42
+ ```tsx
43
+ <Container
44
+ children={<div style={{
45
+ height: '100vh',
46
+ backgroundColor: 'lightgray'
47
+ }}></div>}
48
+ maxWidth="desktop"
49
+ />
50
+ ```
51
+
52
+ ### Laptop
53
+
54
+ Medium maximum width suitable for laptop screens.
55
+
56
+ ```tsx
57
+ <Container
58
+ children={<div style={{
59
+ height: '100vh',
60
+ backgroundColor: 'lightgray'
61
+ }}></div>}
62
+ maxWidth="laptop"
63
+ />
64
+ ```
65
+
66
+ ### Tablet
67
+
68
+ Narrower maximum width for tablet-optimized layouts.
69
+
70
+ ```tsx
71
+ <Container
72
+ children={<div style={{
73
+ height: '100vh',
74
+ backgroundColor: 'lightgray'
75
+ }}></div>}
76
+ maxWidth="tablet"
77
+ />
23
78
  ```
79
+
80
+ ## When to Use
81
+
82
+ ### ✅ Good Use Cases
83
+
84
+ - **Page wrapper**: Main content area of web pages
85
+ - **Dashboard layouts**: Admin panel content sections
86
+ - **Article/Blog content**: Readable width for text-heavy pages
87
+ - **Form layouts**: Centered forms with appropriate width
88
+ - **Card grids**: Constraining grid layouts on large screens
89
+ - **Landing pages**: Centering hero sections and content blocks
90
+
91
+ ### ❌ When Not to Use
92
+
93
+ - **Full-width layouts**: When content should span entire viewport
94
+ - **Sidebars**: Use dedicated sidebar components
95
+ - **Modal content**: Modals have their own sizing
96
+ - **Navigation bars**: Usually span full width
97
+ - **Background elements**: Elements that should fill the screen
98
+
99
+ ## Common Use Cases
100
+
101
+ ### Page Layout with Header
102
+
103
+ ```tsx
104
+ function PageWithHeader() {
105
+ return (
106
+ <>
107
+ <AppBar />
108
+ <Container maxWidth="desktop">
109
+ <Box sx={{ py: 4 }}>
110
+ <Typography level="h1">Dashboard</Typography>
111
+ <Grid container spacing={3} sx={{ mt: 2 }}>
112
+ <Grid xs={12} md={8}>
113
+ <Card>Main Content</Card>
114
+ </Grid>
115
+ <Grid xs={12} md={4}>
116
+ <Card>Sidebar Content</Card>
117
+ </Grid>
118
+ </Grid>
119
+ </Box>
120
+ </Container>
121
+ </>
122
+ );
123
+ }
124
+ ```
125
+
126
+ ### Centered Form Layout
127
+
128
+ ```tsx
129
+ function CenteredForm() {
130
+ return (
131
+ <Container maxWidth="tablet">
132
+ <Box sx={{ py: 4 }}>
133
+ <Typography level="h2" sx={{ mb: 3 }}>
134
+ Contact Us
135
+ </Typography>
136
+ <Stack gap={2}>
137
+ <FormControl>
138
+ <FormLabel>Name</FormLabel>
139
+ <Input placeholder="Enter your name" />
140
+ </FormControl>
141
+ <FormControl>
142
+ <FormLabel>Email</FormLabel>
143
+ <Input type="email" placeholder="Enter your email" />
144
+ </FormControl>
145
+ <FormControl>
146
+ <FormLabel>Message</FormLabel>
147
+ <Textarea minRows={4} placeholder="Your message" />
148
+ </FormControl>
149
+ <Button>Send Message</Button>
150
+ </Stack>
151
+ </Box>
152
+ </Container>
153
+ );
154
+ }
155
+ ```
156
+
157
+ ### Article/Blog Layout
158
+
159
+ ```tsx
160
+ function ArticlePage({ article }) {
161
+ return (
162
+ <Container maxWidth="laptop">
163
+ <Box sx={{ py: 4 }}>
164
+ <Typography level="h1" sx={{ mb: 2 }}>
165
+ {article.title}
166
+ </Typography>
167
+ <Stack direction="row" gap={2} sx={{ mb: 3 }}>
168
+ <Chip size="sm">{article.category}</Chip>
169
+ <Typography level="body-sm" color="neutral">
170
+ {article.date}
171
+ </Typography>
172
+ </Stack>
173
+ <Divider sx={{ mb: 3 }} />
174
+ <Typography sx={{ lineHeight: 1.8 }}>
175
+ {article.content}
176
+ </Typography>
177
+ </Box>
178
+ </Container>
179
+ );
180
+ }
181
+ ```
182
+
183
+ ### Dashboard with Cards
184
+
185
+ ```tsx
186
+ function Dashboard() {
187
+ return (
188
+ <Container maxWidth="desktop">
189
+ <Box sx={{ py: 3 }}>
190
+ <Typography level="h2" sx={{ mb: 3 }}>
191
+ Dashboard Overview
192
+ </Typography>
193
+
194
+ {/* Stats Row */}
195
+ <Grid container spacing={2} sx={{ mb: 3 }}>
196
+ {[
197
+ { label: 'Total Users', value: '1,234' },
198
+ { label: 'Active Sessions', value: '567' },
199
+ { label: 'Revenue', value: '$12,345' },
200
+ { label: 'Growth', value: '+15%' },
201
+ ].map((stat) => (
202
+ <Grid key={stat.label} xs={6} md={3}>
203
+ <Card>
204
+ <CardContent>
205
+ <Typography level="body-sm" color="neutral">
206
+ {stat.label}
207
+ </Typography>
208
+ <Typography level="h3">{stat.value}</Typography>
209
+ </CardContent>
210
+ </Card>
211
+ </Grid>
212
+ ))}
213
+ </Grid>
214
+
215
+ {/* Main Content */}
216
+ <Grid container spacing={2}>
217
+ <Grid xs={12} lg={8}>
218
+ <Card sx={{ height: 400 }}>
219
+ <CardContent>
220
+ <Typography level="title-lg">Activity Chart</Typography>
221
+ {/* Chart component */}
222
+ </CardContent>
223
+ </Card>
224
+ </Grid>
225
+ <Grid xs={12} lg={4}>
226
+ <Card sx={{ height: 400 }}>
227
+ <CardContent>
228
+ <Typography level="title-lg">Recent Activity</Typography>
229
+ {/* Activity list */}
230
+ </CardContent>
231
+ </Card>
232
+ </Grid>
233
+ </Grid>
234
+ </Box>
235
+ </Container>
236
+ );
237
+ }
238
+ ```
239
+
240
+ ### Responsive Container Selection
241
+
242
+ ```tsx
243
+ function ResponsiveLayout({ children }) {
244
+ const isMobile = useMediaQuery('(max-width: 600px)');
245
+ const isTablet = useMediaQuery('(max-width: 900px)');
246
+
247
+ // Choose appropriate container width based on content type
248
+ const maxWidth = isMobile ? 'tablet' : isTablet ? 'laptop' : 'desktop';
249
+
250
+ return (
251
+ <Container maxWidth={maxWidth}>
252
+ {children}
253
+ </Container>
254
+ );
255
+ }
256
+ ```
257
+
258
+ ### Nested Containers
259
+
260
+ ```tsx
261
+ function PageWithSections() {
262
+ return (
263
+ <>
264
+ {/* Full-width hero */}
265
+ <Box sx={{ bgcolor: 'primary.softBg', py: 6 }}>
266
+ <Container maxWidth="desktop">
267
+ <Typography level="h1">Welcome</Typography>
268
+ <Typography>Hero section content</Typography>
269
+ </Container>
270
+ </Box>
271
+
272
+ {/* Narrower content section */}
273
+ <Container maxWidth="laptop">
274
+ <Box sx={{ py: 4 }}>
275
+ <Typography level="h2">Features</Typography>
276
+ {/* Feature cards */}
277
+ </Box>
278
+ </Container>
279
+
280
+ {/* Even narrower for readability */}
281
+ <Container maxWidth="tablet">
282
+ <Box sx={{ py: 4 }}>
283
+ <Typography level="h2">About Us</Typography>
284
+ <Typography>Long form text content...</Typography>
285
+ </Box>
286
+ </Container>
287
+ </>
288
+ );
289
+ }
290
+ ```
291
+
292
+ ## Props and Customization
293
+
294
+ ### Key Props
295
+
296
+ | Prop | Type | Default | Description |
297
+ | ---------- | ----------------------------------- | ----------- | -------------------------------------- |
298
+ | `maxWidth` | `'desktop' \| 'laptop' \| 'tablet'` | `'desktop'` | Maximum width breakpoint |
299
+ | `children` | `ReactNode` | - | Content to render inside the container |
300
+ | `sx` | `SxProps` | - | Custom styles using Joy UI sx prop |
301
+
302
+ ### maxWidth Breakpoints
303
+
304
+ | Value | Max Width | Best For |
305
+ | --------- | --------- | -------------------------------- |
306
+ | `desktop` | \~1200px | Full dashboards, complex layouts |
307
+ | `laptop` | \~900px | Standard content, articles |
308
+ | `tablet` | \~600px | Focused content, forms |
309
+
310
+ ### Custom Styling
311
+
312
+ ```tsx
313
+ // Add custom padding
314
+ <Container maxWidth="desktop" sx={{ py: 4 }}>
315
+ Content
316
+ </Container>
317
+
318
+ // Add background
319
+ <Container maxWidth="laptop" sx={{ bgcolor: 'background.level1', borderRadius: 'lg' }}>
320
+ Content
321
+ </Container>
322
+
323
+ // Combine with other layout props
324
+ <Container
325
+ maxWidth="desktop"
326
+ sx={{
327
+ minHeight: '100vh',
328
+ display: 'flex',
329
+ flexDirection: 'column',
330
+ }}
331
+ >
332
+ <Box sx={{ flex: 1 }}>Content</Box>
333
+ <Footer />
334
+ </Container>
335
+ ```
336
+
337
+ ### Combining with Grid
338
+
339
+ ```tsx
340
+ <Container maxWidth="desktop">
341
+ <Grid container spacing={3}>
342
+ <Grid xs={12} md={8}>
343
+ <Card>Main Content</Card>
344
+ </Grid>
345
+ <Grid xs={12} md={4}>
346
+ <Card>Sidebar</Card>
347
+ </Grid>
348
+ </Grid>
349
+ </Container>
350
+ ```
351
+
352
+ ## Accessibility
353
+
354
+ Container is a layout component with minimal accessibility requirements:
355
+
356
+ ### Semantic Structure
357
+
358
+ ```tsx
359
+ // Use appropriate semantic elements inside Container
360
+ <Container maxWidth="desktop">
361
+ <main>
362
+ <article>
363
+ <h1>Page Title</h1>
364
+ <p>Content...</p>
365
+ </article>
366
+ </main>
367
+ </Container>
368
+ ```
369
+
370
+ ### Landmark Regions
371
+
372
+ ```tsx
373
+ // Combine with ARIA landmarks
374
+ <Container maxWidth="desktop">
375
+ <header role="banner">
376
+ <Typography level="h1">Site Title</Typography>
377
+ </header>
378
+ <main role="main">
379
+ <Typography>Main content</Typography>
380
+ </main>
381
+ <footer role="contentinfo">
382
+ <Typography>Footer</Typography>
383
+ </footer>
384
+ </Container>
385
+ ```
386
+
387
+ ## Best Practices
388
+
389
+ ### ✅ Do
390
+
391
+ 1. **Use consistent container widths**: Maintain visual consistency across pages
392
+
393
+ ```tsx
394
+ // ✅ Good: Consistent width for similar content
395
+ <Container maxWidth="desktop">
396
+ <DashboardContent />
397
+ </Container>
398
+
399
+ <Container maxWidth="desktop">
400
+ <SettingsContent />
401
+ </Container>
402
+ ```
403
+
404
+ 2. **Add appropriate vertical padding**: Give content breathing room
405
+
406
+ ```tsx
407
+ // ✅ Good: Padding for readability
408
+ <Container maxWidth="laptop">
409
+ <Box sx={{ py: 4 }}>
410
+ Content
411
+ </Box>
412
+ </Container>
413
+ ```
414
+
415
+ 3. **Choose width based on content type**: Match container width to content needs
416
+
417
+ ```tsx
418
+ // ✅ Good: Narrow for text, wide for data
419
+ <Container maxWidth="tablet"> {/* Narrow for articles */}
420
+ <ArticleContent />
421
+ </Container>
422
+
423
+ <Container maxWidth="desktop"> {/* Wide for dashboards */}
424
+ <DataTable />
425
+ </Container>
426
+ ```
427
+
428
+ 4. **Combine with full-width sections**: Mix constrained and full-width content
429
+
430
+ ```tsx
431
+ // ✅ Good: Full-width background with constrained content
432
+ <Box sx={{ bgcolor: 'primary.softBg' }}>
433
+ <Container maxWidth="desktop">
434
+ <HeroContent />
435
+ </Container>
436
+ </Box>
437
+ ```
438
+
439
+ ### ❌ Don't
440
+
441
+ 1. **Don't use Container for modals or drawers**: They have their own sizing
442
+
443
+ ```tsx
444
+ // ❌ Bad: Container inside Modal
445
+ <Modal>
446
+ <Container maxWidth="tablet">Content</Container>
447
+ </Modal>
448
+
449
+ // ✅ Good: Modal handles its own sizing
450
+ <Modal>
451
+ <ModalDialog sx={{ maxWidth: 400 }}>Content</ModalDialog>
452
+ </Modal>
453
+ ```
454
+
455
+ 2. **Don't nest Containers unnecessarily**: One level is usually sufficient
456
+
457
+ ```tsx
458
+ // ❌ Bad: Nested containers
459
+ <Container maxWidth="desktop">
460
+ <Container maxWidth="laptop">
461
+ Content
462
+ </Container>
463
+ </Container>
464
+
465
+ // ✅ Good: Single container
466
+ <Container maxWidth="laptop">
467
+ Content
468
+ </Container>
469
+ ```
470
+
471
+ 3. **Don't use wrong width for content type**: Match width to content needs
472
+
473
+ ```tsx
474
+ // ❌ Bad: Wide container for text article
475
+ <Container maxWidth="desktop">
476
+ <LongArticleText /> {/* Hard to read at wide widths */}
477
+ </Container>
478
+
479
+ // ✅ Good: Appropriate width for reading
480
+ <Container maxWidth="laptop">
481
+ <LongArticleText />
482
+ </Container>
483
+ ```
484
+
485
+ 4. **Don't forget responsive considerations**: Content should work at all sizes
486
+
487
+ ## Performance Considerations
488
+
489
+ ### Avoid Unnecessary Re-renders
490
+
491
+ Container is a simple layout component, but avoid changing `maxWidth` frequently:
492
+
493
+ ```tsx
494
+ // ❌ Bad: Changing maxWidth on every render
495
+ <Container maxWidth={isOpen ? 'laptop' : 'desktop'}>
496
+
497
+ // ✅ Good: Stable maxWidth
498
+ <Container maxWidth="desktop">
499
+ <Box sx={{ maxWidth: isOpen ? 900 : '100%' }}>
500
+ ```
501
+
502
+ ### CSS-based Responsiveness
503
+
504
+ Prefer CSS media queries over JavaScript for responsive layouts:
505
+
506
+ ```tsx
507
+ // ✅ Good: CSS handles responsiveness
508
+ <Container
509
+ maxWidth="desktop"
510
+ sx={{
511
+ px: { xs: 2, sm: 3, md: 4 },
512
+ py: { xs: 2, md: 4 },
513
+ }}
514
+ >
515
+ ```
516
+
517
+ ### Minimal DOM Nesting
518
+
519
+ Container adds minimal DOM overhead. Use it at appropriate levels:
520
+
521
+ ```tsx
522
+ // ✅ Good: One container at page level
523
+ <Container maxWidth="desktop">
524
+ <Header />
525
+ <MainContent />
526
+ <Footer />
527
+ </Container>
528
+ ```
529
+
530
+ Container provides a simple yet essential foundation for consistent page layouts. Choose the appropriate `maxWidth` based on your content type—wider for data-heavy dashboards, narrower for text-focused content—and combine with proper vertical spacing for optimal readability.