Panel Component
Create flexible container layouts for terminal applications. Panels can arrange content in vertical (rows) or horizontal (columns) layouts with optional borders and dividers.
Basic Usage
use Ajaxray\AnsiKit\Components\Panel;
use Ajaxray\AnsiKit\Components\PanelBlock;
$panel = new Panel();
$block1 = (new PanelBlock())->content('First Block (70%)')->width(40);
$block2 = (new PanelBlock())->content('Second Block (30%)')->width(17);
$panel->layout(Panel::LAYOUT_HORIZONTAL)
->border(true)
->dividers(true)
->addBlock($block1)
->addBlock($block2)
->render();
The output will be:
┌──────────────────────────────────────────────────────────────┐
│First Block (70%) │Second Block (30%) │
└──────────────────────────────────────────────────────────────┘
Configuration Options
Panel Configuration
| Method | Parameters | Default | Description |
|---|---|---|---|
layout() | Panel::LAYOUT_VERTICAL or Panel::LAYOUT_HORIZONTAL | Panel::LAYOUT_VERTICAL | Set layout direction |
border() | bool $enabled | false | Enable/disable panel border |
dividers() | bool $enabled, string $char | false, '│' | Enable dividers between blocks |
corners() | Panel::CORNER_SHARP or Panel::CORNER_ROUNDED | Panel::CORNER_SHARP | Set corner style |
addBlock() | Renderable $block | - | Add a block or nested panel to the panel |
PanelBlock Configuration
| Method | Parameters | Default | Description |
|---|---|---|---|
content() | string $content | '' | Set text content |
width() | int $width | 0 (auto) | Set fixed width |
height() | int $height | 0 (auto) | Set fixed height |
border() | bool $enabled | false | Enable/disable block border |
corners() | PanelBlock::CORNER_SHARP or PanelBlock::CORNER_ROUNDED | PanelBlock::CORNER_SHARP | Set corner style |
overflow() | PanelBlock::OVERFLOW_EXPAND or PanelBlock::OVERFLOW_WORDWRAP | PanelBlock::OVERFLOW_EXPAND | Handle content overflow |
Layout Examples
Vertical Layout (Default)
$panel = new Panel();
$panel->layout(Panel::LAYOUT_VERTICAL)
->border(true)
->dividers(true)
->addBlock((new PanelBlock())->content('Row 1'))
->addBlock((new PanelBlock())->content('Row 2'))
->addBlock((new PanelBlock())->content('Row 3'))
->render();
Output:
┌────────────────────────────────────────┐
│Row 1 │
├────────────────────────────────────────┤
│Row 2 │
├────────────────────────────────────────┤
│Row 3 │
└────────────────────────────────────────┘
Horizontal Layout
$panel = new Panel();
$panel->layout(Panel::LAYOUT_HORIZONTAL)
->border(true)
->dividers(true)
->addBlock((new PanelBlock())->content('Left')->width(20))
->addBlock((new PanelBlock())->content('Middle')->width(20))
->addBlock((new PanelBlock())->content('Right')->width(20))
->render();
Output:
┌──────────────────────────────────────────────────────────────┐
│Left │Middle │Right │
└──────────────────────────────────────────────────────────────┘
Corner Styles
Sharp Corners (Default)
$panel = new Panel();
$panel->corners(Panel::CORNER_SHARP)
->border(true)
->addBlock((new PanelBlock())->content('Sharp corners'))
->render();
Output:
┌──────────────────────────────┐
│Sharp corners │
└──────────────────────────────┘
Rounded Corners
$panel = new Panel();
$panel->corners(Panel::CORNER_ROUNDED)
->border(true)
->addBlock((new PanelBlock())->content('Rounded corners'))
->render();
Output:
╭──────────────────────────────╮
│Rounded corners │
╰──────────────────────────────╯
Block Borders
PanelBlocks can have their own borders, independent of the panel:
$panel = new Panel();
$borderedBlock1 = (new PanelBlock())
->content('Bordered Block 1')
->width(25)
->border(true)
->corners(Panel::CORNER_ROUNDED);
$borderedBlock2 = (new PanelBlock())
->content('Bordered Block 2')
->width(25)
->border(true)
->corners(Panel::CORNER_SHARP);
$panel->layout(Panel::LAYOUT_VERTICAL)
->addBlock($borderedBlock1)
->addBlock($borderedBlock2)
->render();
Output:
╭───────────────────────╮
│Bordered Block 1 │
╰───────────────────────╯
┌───────────────────────┐
│Bordered Block 2 │
└───────────────────────┘
Word Wrapping
Control how content overflows the block boundaries:
$longText = "This is a very long text that will be wrapped automatically when it exceeds the specified width of the block.";
$wrappedBlock = (new PanelBlock())
->content($longText)
->width(40)
->overflow(PanelBlock::OVERFLOW_WORDWRAP)
->border(true);
echo $wrappedBlock->render();
Output:
┌──────────────────────────────────────┐
│This is a very long text that will be │
│wrapped automatically when it exceeds │
│the specified width of the block. The │
│word wrap feature ensures content fits│
│nicely. │
└──────────────────────────────────────┘
Custom Column Sizes
For horizontal layouts, specify custom column sizes:
$panel = new Panel();
$panel->layout(Panel::LAYOUT_HORIZONTAL)
->border(true)
->dividers(true)
->addBlock((new PanelBlock())->content('Small')->width(10))
->addBlock((new PanelBlock())->content('Medium')->width(20))
->addBlock((new PanelBlock())->content('Large')->width(30))
->render();
Output:
┌──────────────────────────────────────────────────────────────┐
│Small │Medium │Large │
│10 cols │20 cols │30 cols │
└──────────────────────────────────────────────────────────────┘
PanelBlock as Writer
PanelBlocks implement WriterInterface, so you can use them as writers for other components:
use Ajaxray\AnsiKit\Components\Table;
use Ajaxray\AnsiKit\Components\Banner;
$panel = new Panel();
$tableBlock = new PanelBlock();
$bannerBlock = new PanelBlock();
// Render table into block
$table = new Table($tableBlock);
$table->setHeaders('Name', 'Status')
->addRow('Task 1', 'Done')
->addRow('Task 2', 'Pending')
->render();
// Render banner into block
$banner = new Banner($bannerBlock);
$banner->render('Success!', ['All tasks completed']);
$panel->layout(Panel::LAYOUT_VERTICAL)
->border(true)
->dividers(true)
->addBlock($tableBlock)
->addBlock($bannerBlock)
->render();
Output:
┌─────────────────────────┐
│┌────────┬─────────┐ │
││ Name │ Status │ │
│├────────┼─────────┤ │
││ Task 1 │ Done │ │
││ Task 2 │ Pending │ │
│└────────┴─────────┘ │
├─────────────────────────┤
│╭───────────────────────╮│
││ Success! ││
│├───────────────────────┤│
││ All tasks completed ││
│╰───────────────────────╯│
└─────────────────────────┘
Nested Panels
Panels can be nested within other panels to create complex layouts. Both Panel and PanelBlock implement the Renderable interface, allowing them to be used interchangeably:
$panel = new Panel();
// Create a nested horizontal panel
$nestedPanel = new Panel();
$nestedPanel->layout(Panel::LAYOUT_HORIZONTAL)
->border(true)
->dividers(true)
->addBlock((new PanelBlock())->content('Col 1')->width(15))
->addBlock((new PanelBlock())->content('Col 2')->width(15))
->addBlock((new PanelBlock())->content('Col 3')->width(15));
// Add the nested panel to the main panel
$panel->layout(Panel::LAYOUT_VERTICAL)
->border(true)
->dividers(true)
->addBlock((new PanelBlock())->content('Header')->width(47))
->addBlock($nestedPanel) // Nested panel here
->addBlock((new PanelBlock())->content('Footer')->width(47))
->render();
Output:
┌───────────────────────────────────────────────┐
│Header │
├───────────────────────────────────────────────┤
│┌───────────────────────────────────────────┐ │
││Col 1 │Col 2 │Col 3 │ │
│└───────────────────────────────────────────┘ │
├───────────────────────────────────────────────┤
│Footer │
└───────────────────────────────────────────────┘
This allows you to create dashboard-style layouts with mixed vertical and horizontal sections.
Tips
- Panels automatically size blocks equally unless custom widths/heights are specified
- Use
overflow('wordwrap')for long text content - Panel and PanelBlock can have different corner styles
- Panels can be nested within other panels for complex multi-directional layouts
- Both
PanelandPanelBlockimplementRenderableinterface - Be careful about using emoji in bordered structures, as their width can vary by terminal