Skip to content

chamie/container

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@chamie/container (working title)

A React container component that lets you define complex grid layouts using ASCII-art-style strings. Stop mentally executing walls of JSX to figure out what your UI looks like — just draw it.

<Container
  order={`
    Title_________|ActionButtons
    ==
    HitsTitle_____|HitsMeter
    TotalLoadTitle|TotalLoadMeter
  `}
  layout={`
    _|
    ==
    _|__
    _|__
  `}
>
  <Header layoutSlot="Title" />
  <ActionButtons layoutSlot="ActionButtons" />
  <div layoutSlot="HitsTitle">Hits:</div>
  <Meter layoutSlot="HitsMeter" />
  <div layoutSlot="TotalLoadTitle">Total Load:</div>
  <Meter layoutSlot="TotalLoadMeter" />
</Container>

Install

npm install @chamie/container
# or
yarn add @chamie/container

How it works

The Container component renders a flex-based grid. You describe it with two string props:

order (required)

Defines which components go where. Each line is a row, cells are separated by |. Underscores are visual padding and are ignored during parsing.

Title_________|ActionButtons
==
HitsTitle_____|HitsMeter
  • | separates cells in a row
  • == lines (or any line starting with ==) are ignored — use them as visual separators. Or adding comments, if you feel like those are needed for some reason
  • Underscores in component names are stripped, so HitsTitle_____ and HitsTitle resolve to the same slot
  • An empty cell (only underscores, no name) renders as a spacer with no matching child required

layout (optional)

Defines the size of each cell, row by row, matching the structure of order. If omitted, cells share space equally.

_|
==
_|__
_|__

Each cell value can be:

Format Meaning Example
Underscores Flex ratio by character count ___flex: 3
Plain number Explicit flex value 5flex: 5
CSS size unit Fixed width 20px, 10%, 4vw

Mixed formats are supported per row:

___|10%|20px

== lines are ignored here too, so you can keep order and layout visually aligned.

layoutSlot prop

Every child that should be placed by the container needs a layoutSlot prop matching the name used in order. Works on any element — custom components, plain <div>s, anything React can render.

<div layoutSlot="HitsTitle">Hits:</div>
<Meter layoutSlot="HitsMeter" value={hits} />

Children without a layoutSlot are ignored.


Props

Prop Type Required Description
order string ASCII-art slot layout
layout string Cell sizing configuration
children ReactElement[] Components with layoutSlot props
strict boolean Throw on mismatches instead of warning
classNamePrefix string Prefix for generated class names (container, row, col)

Examples

Equal columns, no layout prop needed

<Container order="Left|Center|Right">
  <Nav layoutSlot="Left" />
  <Main layoutSlot="Center" />
  <Aside layoutSlot="Right" />
</Container>

Fixed sidebar + fluid content

<Container
  order="Sidebar|Content"
  layout="240px|_"
>
  <Sidebar layoutSlot="Sidebar" />
  <Content layoutSlot="Content" />
</Container>

Spacer cells

Empty cells (pure underscores) render as unstyled divs with no child required:

<Container
  order={`
    Logo___|_|NavLinks
  `}
  layout={`
    __|_|__
  `}
>
  <Logo layoutSlot="Logo" />
  <NavLinks layoutSlot="NavLinks" />
  {/* middle cell is a spacer, no child needed */}
</Container>

Nesting

And of course you can nest them if you want a more complex layout:

<Container order="Sidebar|Main">
    <Sidebar layoutSlot="Sidebar" />

    <Container layoutSlot="Main"
        order={`
            Header
            Content
        `}
    >
        <Header layoutSlot="Header" />
        <Content layoutSlot="Content" />
    </Container>
</Container>

Compile-time slot name safety

If you want typos caught by TypeScript:

const slots = {
  Title: "Title",
  Actions: "Actions",
  Chart: "Chart",
} as const;

<Container
  order={`
    ${slots.Title}__|${slots.Actions}
    ==
    ${slots.Chart}
  `}
>
  <Header layoutSlot={slots.Title} />
  <Toolbar layoutSlot={slots.Actions} />
  <Chart layoutSlot={slots.Chart} />
</Container>

Error handling

By default, mismatches warn to the console and render a red Missing: SlotName placeholder in place of the absent child.

Pass strict to throw instead — useful for catching layout/child mismatches at development time:

<Container order="A|B" strict>
  <A layoutSlot="A" />
  {/* B missing → throws */}
</Container>

CSS classes

The container generates three class names, optionally prefixed via classNamePrefix:

Element Default class With classNamePrefix="my"
Root div container my-container
Row div row my-row
Cell div col my-col

License

MIT

About

A React container component that lets you define complex grid layouts using ASCII-art-style strings

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors