Panel
//<code-header>
fiddle.title = 'Panel';
//</code-header>
const panel = new Panel({
appendTo : targetElement,
width : '40em',
header : {
title : 'Panel header',
iconCls : 'fa fa-users'
},
tools : {
destroy : {
cls : 'fa fa-times',
// 'up.' means look in owning widgets.
// Implemented on the Panel
handler : 'up.onPanelCloseClick',
tooltip : 'Close this Panel'
}
},
tbar : {
items : {
save : {
icon : 'fa-save',
tooltip : 'Save content'
},
remove : {
icon : 'fa-trash',
tooltip : 'Delete content'
},
change : {
icon : 'fa-arrow-left',
tooltip : 'Move toolbar',
onClick : 'up.onChangeButtonClick'
}
}
},
bbar : {
items : {
myButtonRef : {
text : 'Button in bottom toolbar',
rendition : 'filled'
}
}
},
html : `Bacon ipsum dolor amet flank ribeye ham hock rump,
alcatra pork belly pancetta leberkas bacon shoulder
meatloaf ball tip pig. Tongue jerky meatloaf pancetta
pork sirloin. Hamburger corned beef ball tip cupim
sirloin frankfurter tri-tip. Swine kevin ham hock,
drumstick flank pig shoulder shankle. Tri-tip pork
chop fatback turducken pork salami. Tongue boudin
salami flank bacon sirloin`,
// Close Tool's handler resolved here
onPanelCloseClick(e, panel) {
panel.destroy();
},
// Change button's onClick handler resolved here
onChangeButtonClick({ source : button }) {
const dock = { t : 'left', r : 'top', b : 'right', l : 'bottom' }[this.tbar.dock[0]];
this.tbar.dock = dock;
button.icon = `fa-arrow-${dock === 'bottom' ? 'right' : 'left'}`;
}
});A Panel may also dock a header and footer either at top/bottom or left/right:
const panel = new Panel({
items : {
customerName : { type : 'text', placeholder: 'Text' },
},
header : {
title : 'Customer Details'
}
});
Toolbars with buttons and other widgets
The Panel has two built-in toolbars, tbar and bbar, which are toolbars docked to the top and bottom of the panel. You can easily add any widgets to them using the code below:
const panel = new Panel({
title : 'A Test Panel',
items : {
customerName : {
type : 'text', placeholder: 'Text'
},
},
bbar : {
items : {
proceedButton : {
text : 'Proceed',
onClick : () => {
alert('Proceeding!');
}
}
}
});
Panel with a form
You can use a Panel to create forms containing any Bryntum widgets. The Panel can load data into its field from a record since it subclasses the Container which has a record config.
//<code-header>
fiddle.title = 'Panel form';
CSSHelper.insertRule('.b-panel { --b-panel-header-background : var(--b-primary-40); --b-toolbar-background : transparent; }', targetElement);
CSSHelper.insertRule('.user-panel header { height:6em; }', targetElement);
CSSHelper.insertRule('.user-panel header.b-panel-header, .user-panel .b-panel-header .b-header-title { overflow:visible; }', targetElement);
CSSHelper.insertRule('.user-panel .b-panel-content { padding-top:0; }', targetElement);
CSSHelper.insertRule('.user-panel .b-has-label .b-label { font-weight:600; }', targetElement);
CSSHelper.insertRule(`.verified-badge {
position: absolute;
font-weight: 400;
top: 7.5em;
inset-inline-end: .25em;
color: rgb(255, 255, 255);
background: rgb(34, 150, 243);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
width: 1.25em;
height: 1.25em;
}`, targetElement);
CSSHelper.insertRule(`.avatar {
margin-inline-start: 1em;
border-radius: 50%;
width: 6em;
outline: 3px solid var(--b-panel-background);
position: relative;
top: 3em;
background-color : var(--b-primary-90);
}`, targetElement);
//</code-header>
const userPanel = new Panel({
appendTo : targetElement,
// Panel CSS class applied to the panel element
cls : 'user-panel',
// Optional: set a width or layout if needed
width : 600,
header : {
height : '5em',
title : `<div style="display: inline-flex; position: relative;">
<img src="data/Grid/images/transparent-users/emilia.png" alt="Emilia" class="avatar"/>
<span data-btip="Verified user" class="verified-badge">✓</span>
</div>`
},
// A top toolbar with quick actions (Copy link, View profile)
tbar : [
'->',
{
type : 'button',
text : 'Copy link',
cls : 'b-transparent',
icon : 'fa fa-link',
onAction : () => {
// Handler for copying the user’s profile link to clipboard
Toast.show('Copy link clicked');
}
},
{
type : 'button',
text : 'View profile',
cls : 'b-transparent',
icon : 'fa fa-user',
onAction : () => {
// Handler for viewing user profile
Toast.show('View profile clicked');
}
}
],
items : {
// Container for the form fields (name, email, username)
userForm : {
type : 'container',
labelPosition : 'align-before',
cls : 'user-form-container',
items : {
header : {
type : 'widget',
style : 'flex-direction: column; grid-column : span 4',
html : `
<h2 style="margin-bottom:0;">Emilia Baker</h2>
<div style="color: #777;font-size:.9em">Regional Sales</div>
`
},
firstName : {
type : 'text',
label : 'First name',
name : 'firstName',
value : 'Emilia'
},
lastName : {
type : 'text',
label : 'Last name',
name : 'lastName',
value : 'Baker'
},
email : {
type : 'text',
label : 'Email address',
name : 'email',
value : '[email protected]',
span : 3
},
username : {
type : 'text',
label : 'Username',
name : 'username',
value : 'emilia.baker',
span : 3
}
}
}
},
// Bottom toolbar with Delete, Cancel, and Save
bbar : {
items : {
deleteUser : {
type : 'button',
text : 'Delete user',
cls : 'delete-user-btn',
color : 'b-red',
style : 'margin-inline-end: auto;', // push to the left
onAction() {
// Handler for deleting the user
Toast.show('Delete user clicked');
}
},
cancel : {
type : 'button',
text : 'Cancel',
onAction() {
// Cancel changes
Toast.show('Cancel clicked');
}
},
save : {
type : 'button',
rendition : 'filled',
text : 'Save changes',
onAction() {
// Save form changes
const htmlFormatted = Object.entries(userPanel.values)
.map(([key, value]) => `<b>${key}:</b> ${value}<br>`)
.join('');
Toast.show(`Save changes clicked<br>${htmlFormatted}`);
}
}
}
}
});Collapsible Panel
Panels can also be collapsible. The collapsible panel can be collapsed and expanded by clicking the icon on the far-right end of the header.
//<code-header>
fiddle.title = 'Collapsible panel';
//</code-header>
// Description: This file is an example of the Panel widget with collapsible feature.
const invoicePanel = new Panel({
appendTo : targetElement,
cls : 'invoice-panel',
title : 'Create Invoice',
labelPosition : 'align-before',
revealed : true,
collapsible : {
direction : 'up'
},
width : 600,
items : {
invoiceNumber : {
type : 'textfield',
label : 'Invoice Number',
value : '01020304'
},
fiscalYear : {
type : 'combo',
label : 'Fiscal Year',
items : ['2022', '2023', '2024', '2025'],
value : '2023',
editable : false
},
invoiceStatus : {
type : 'combo',
label : 'Status',
items : ['Draft', 'Received', 'Paid'],
value : 'Received',
editable : false
},
invoiceType : {
type : 'combo',
label : 'Type',
items : ['Invoice', 'Credit Note', 'Receipt'],
value : 'Invoice',
editable : false
},
amount : {
type : 'numberfield',
label : 'Amount',
ref : 'amount',
value : '10,000.00',
step : 1000,
format : {
style : 'currency',
currency : 'USD'
},
labelWidth : '50%'
},
invoiceDate : {
type : 'datefield',
label : 'Invoice Date',
ref : 'invoiceDate',
// Note: month is 0-based, so (2022, 1, 1) is 01 Feb 2022
value : new Date(2022, 1, 1)
},
invoiceNote : {
type : 'textarea',
label : 'Note',
emptyText : 'Add your note here...',
span : 4,
height : 100
}
},
bbar : {
items : {
save : {
type : 'button',
text : 'Save',
onAction : () => {
// Gather field values from the panel
const
wm = invoicePanel.widgetMap,
data = {
invoiceNumber : wm.invoiceNumber.value,
fiscalYear : wm.fiscalYear.value,
invoiceStatus : wm.invoiceStatus.value,
invoiceType : wm.invoiceType.value,
amount : wm.amount.value,
invoiceDate : wm.invoiceDate.value,
invoiceNote : wm.invoiceNote.value
},
htmlFormattedData = Object.entries(data)
.map(([key, value]) => `<b>${key}:</b> ${value}<br>`)
.join('');
Toast.show(`Invoice saved!<br>${htmlFormattedData}`);
}
}
}
}
});Panel as a drawer
Panels can be used as drawers which slide out from the side of the viewport, by using the drawer config:
//<code-header>
fiddle.title = 'Panel drawer';
//</code-header>
const button = new Button({
appendTo : targetElement,
text : 'Show drawer',
ref : 'showButton',
onClick() {
const panel = this.panel || (this.panel = new Panel({
drawer : {
side : 'end',
autoClose : {
// Close on click outside, but *not* when clicking
// on our show button
mousedown : ':not(button[data-ref="showButton"])'
}
},
title : 'Settings',
rootElement : document.body,
width : 400,
labelPosition : 'align-before',
items : {
name : { type : 'text', label : 'Name' },
email : { type : 'text', label : 'Email' },
phone : { type : 'text', label : 'Phone' },
address : { type : 'text', label : 'Address' }
},
bbar : {
items : {
close : {
text : 'Close',
icon : 'fa fa-times',
style : 'margin-inline-start: auto',
onClick : () => {
panel.hide();
}
}
}
}
}));
panel.show();
}
});Panel with strips
Panels can have strips docked to the top, right, bottom, or left. Strips are widgets that are docked
to the panel's sides. The higher the weight assigned to a widget, the closer that widget will be to the panel body.
This is useful for adding slide-out containers to the panel. For example, a settings panel shown on the right as seen below (click the hamburger icon to show the settings panel).
//<code-header>
fiddle.title = 'Panel strips';
CSSHelper.insertRule('.strips-panel .b-sidebar .b-panel-body-wrap { background : var(--b-neutral-97)}', targetElement);
CSSHelper.insertRule('strong { font-weight : 600 !important; }', targetElement);
//</code-header>
// This example show the Panel widget using the strips feature.
const invoicePanel = new Panel({
appendTo : targetElement,
cls : 'strips-panel',
title : 'Application Form',
width : 700,
height : 270,
labelPosition : 'align-before',
items : {
name : {
type : 'textfield',
label : 'Name',
value : 'Johnny Coder'
},
skills : {
type : 'combo',
label : 'Skills',
multiSelect : true,
items : ['Coding', 'UX', 'Design', 'Database'],
value : ['Coding', 'UX'],
editable : false
},
framework : {
type : 'radiogroup',
label : 'Favorite JS Framework',
value : 'D',
inline : true,
options : {
A : 'React',
B : 'Angular',
C : 'Vue',
D : 'Svelte'
}
},
jsOrTs : {
type : 'radiogroup',
label : 'JS or TS',
hidden : true,
value : 'B',
name : 'jsOrTs',
inline : true,
options : {
A : 'JS',
B : 'TS'
}
},
tabsOrSpaces : {
type : 'radiogroup',
label : 'Tabs or Spaces',
hidden : true,
value : 'A',
name : 'tabsOrSpaces',
inline : true,
options : {
A : 'Tabs',
B : 'Spaces'
}
}
},
strips : {
right : {
type : 'panel',
dock : 'right',
collapsible : true,
width : '15em',
header : false,
cls : 'b-sidebar',
collapsed : true,
layout : 'vbox',
labelPosition : 'before',
items : {
label : {
tag : 'strong',
html : 'Settings'
},
toughQuestion : {
type : 'slidetoggle',
label : 'Show tough questions',
onChange : 'up.onShowToughQuestionsChange'
}
}
}
},
tools : [
{
cls : 'fa fa-bars',
onClick : 'up.onToggleSettingsClick'
}
],
onToggleSettingsClick() {
this.strips.right.toggleCollapsed();
},
onShowToughQuestionsChange({ value }) {
this.widgetMap.jsOrTs.hidden = !value;
this.widgetMap.tabsOrSpaces.hidden = !value;
}
});Configs
108
Configs
108Common
Content
A Config object representing the configuration of a Toolbar, or array of config objects representing the child items of a Toolbar. Another way to add a bbar is to use strips.
// Text only
bbar : [`Total number of students: ${totalStds}`, '->', `Passed Students: ${passedStds}`],
// Buttons
bbar : [
{
type : 'button',
ref : 'addButton',
text : 'Add column',
icon : 'fa-plus',
tooltip : 'Add new column',
onAction : ({ source }) => addColumn(source.element) // add new column
},
{
type : 'button',
ref : 'removeButton',
text : 'Remove last',
icon : 'fa-minus',
tooltip : 'Remove last column',
onAction : () => grid.columns.count > 1 && grid.columns.last.remove() // remove last column
}
]
// ToolbarConfig
bbar : {
height : '4em',
items : {
button1 : { text : 'A button', icon : 'fa fa-plus' },
button2 : { text : 'Right button 1', icon : 'fa fa-trash', style : 'margin-inline-start:auto' },
button3 : { icon : 'fa fa-gear' }
}
}
This creates a toolbar docked to the bottom of the panel immediately above the footer.
An object containing widgets keyed by name. By default (when no type is given), strips are
toolbars. If you want to pass an array, you can use
the toolbar's items.
The bbar and tbar configs are shortcuts for adding toolbars to the
panel's strips.
Strips are arranged based on their dock and weight configs.
For widgets using a dock of 'top', 'bottom', 'left', 'right', 'start' or 'end'(an "edge
strip"), the higher the weight assigned to a widget, the closer that widget will be to the panel body.
For widgets with 'header' or 'pre-header' for dock (a "header strip"), higher weight values
cause the widget to be placed closer to the panel's title.
new Panel({
title : 'Test',
html : 'Panel strip test',
strips : {
left : {
dock : 'left'
items : {
go : {
text : 'Go'
}
}
}
}
});
// Pass an array to tbar
strips : {
tbar : {
items: {
addButton : {
type : 'button',
text : 'Add column',
icon : 'fa-plus',
onAction : ({ source }) => addColumn(source.element)
},
// consider 'getCurrentDate()` a custom function
today : `Today is ${getCurrentDate()}`
}
}
}
A Config object representing the configuration of a Toolbar, or array of config objects representing the child items of a Toolbar. This creates a toolbar docked to the top of the panel immediately below the header.
To add toolbars not docked to the top, see bbar and strips.
// Text only
tbar : ['Project Timeline Overview', '->', 'Key Milestones & Deadlines'],
// Buttons
tbar : [
{
type : 'button',
ref : 'addButton',
text : 'Add column',
icon : 'fa-plus',
tooltip : 'Add new column',
onAction : ({ source }) => addColumn(source.element) // add new column
},
{
type : 'button',
ref : 'removeButton',
text : 'Remove last',
icon : 'fa-minus',
tooltip : 'Remove last column',
onAction : () => grid.columns.count > 1 && grid.columns.last.remove() // remove last column
}
]
// ToolbarConfig
tbar : {
height : '4em',
items : {
button1 : { text : 'A button', icon : 'fa fa-plus' },
button2 : { text : 'Right button 1', icon : 'fa fa-trash', style : 'margin-inline-start:auto' },
button3 : { icon : 'fa fa-gear' }
}
}
By default, tabbing within a Panel is not contained, ie you can TAB out of the Panel
forwards or backwards.
Configure this as true to disallow tabbing out of the Panel, and make tabbing circular within this Panel.
CSS
Custom CSS classes to add to the panel's body element.
May be specified as a space separated string, or as an object in which property names with truthy values are used as the class names:
bodyCls : {
'b-my-class' : 1,
[this.extraCls] : 1,
[this.activeCls] : this.isActive
}
Custom CSS class name suffixes to apply to the elements rendered by this widget. This may be specified as a space separated string, an array of strings, or as an object in which property names with truthy values are used as the class names.
The panel supports a few special UIs, such as plain rendition where toolbars and header have no
background/borders, and toolbar.
For example, consider a Panel with a ui config like so:
new Panel({
text : 'OK',
ui : 'light'
});
This will apply the CSS class 'b-panel-ui-light' to the main element of the panel as well as its many
child elements. This allows simpler CSS selectors to match the child elements of this particular panel
UI:
.b-panel-content.b-panel-ui-light {
background-color : #eee;
}
Using the cls config would make matching the content element more complex, and in the presence of docked items and nested panels, impossible to target accurately.
Layout
Controls whether the panel is collapsed (the body of the panel is hidden while only the header is visible). Only valid if the panel is collapsible.
This config enables collapsibility for the panel. See collapsed.
For example:
{
type : 'panel',
collapsible : true
}
This is managed by an instance of PanelCollapser which can be configured if an object is passed for this config property:
{
type : 'panel',
collapsible : {
direction : 'left'
}
}
The config object form can contain a type property to specify the type of collapse the panel will use.
This property can be one of the following:
'inline'(see PanelCollapser)'overlay'(see PanelCollapserOverlay)
The default direction property is inferred from the position of the Panel in a flexbox layout.
If the Panel is the last child of a flexbox container, the direction is 'right' for a horizontal
flexbox layout and 'down' for a vertical layout.
All other Panels in a flexbox container have the direction set to 'left' for a horizontal layout and
'up' for a vertical layout.
Misc
A title to display in the header or owning TabPanel. Causes creation and docking of a header to the top if no header is configured.
If a header has been disabled by configuring the headeras false, setting it will have
no effect.
Other
Make this Panel a docked drawer which slides out from one side of the browser viewport by default.
If this Panel is a child of another widget, the drawer will slide out from the side of the parent widget.
By default, it floats above the content of its host. If you want the drawer to be inline within the host,
consuming content space in the host, set the drawer inline property to true.
//<code-header>
fiddle.title = 'Panel drawer';
//</code-header>
const button = new Button({
appendTo : targetElement,
text : 'Show drawer',
ref : 'showButton',
onClick() {
const panel = this.panel || (this.panel = new Panel({
drawer : {
side : 'end',
autoClose : {
// Close on click outside, but *not* when clicking
// on our show button
mousedown : ':not(button[data-ref="showButton"])'
}
},
title : 'Settings',
rootElement : document.body,
width : 400,
labelPosition : 'align-before',
items : {
name : { type : 'text', label : 'Name' },
email : { type : 'text', label : 'Email' },
phone : { type : 'text', label : 'Phone' },
address : { type : 'text', label : 'Address' }
},
bbar : {
items : {
close : {
text : 'Close',
icon : 'fa fa-times',
style : 'margin-inline-start: auto',
onClick : () => {
panel.hide();
}
}
}
}
}));
panel.show();
}
});| Parameter | Type | Description |
|---|---|---|
side | start | left | end | right | top | bottom | The side of the viewport to dock the drawer to.
|
size | String | Number | The size of the drawer in its collapsible axis. |
inline | Boolean | If using the appendTo config to place the drawer inside a host
widget, this may be set to |
autoClose | Boolean | Object | Specifies what user actions should automatically close the drawer. Defaults to closing when the user clicks outside of the drawer or when focus moves outside of the drawer. |
autoClose.mousedown | Boolean | String | If the user clicks outside of the drawer, the drawer will automatically be hidden. If the value is a string, it is used as a CSS selector to filter clicks which should close the drawer. |
autoClose.focusout | Boolean | String | If focus moves outside of the drawer, the drawer will automatically be hidden. |
autoClose.mouseout | String | Hides the drawer when the mouse leaves the drawer after the |
autoCloseDelay | Number | When using |
DOM
Float & align
misc
Scrolling
Properties
93
Properties
93Class hierarchy
Content
Get toolbar Toolbar docked to the bottom of the panel
Get toolbar Toolbar docked to the top of the panel
Layout
Controls whether the panel is collapsed (the body of the panel is hidden while only the header is visible). Only valid if the panel is collapsible.
This property is true if the panel is currently collapsing.
This property is true if the panel is currently expanding.
Misc
A title to display in the header or owning TabPanel. Causes creation and docking of a header to the top if no header is configured.
If a header has been disabled by configuring the headeras false, setting it will have
no effect.
Other
CSS
DOM
State
Widget hierarchy
Functions
74
Functions
74Misc
Toggles collapsed state of the panel.
| Parameter | Type | Description |
|---|---|---|
collapse | Boolean | Pass |
true value for collapsed panel or false for expanded
Other
Collapse the panel.
Expand the panel.
Configuration
Events
Widget hierarchy
Events
21
Events
21Fires when a Panel is collapsed using the collapsible setting.
// Adding a listener using the "on" method
panel.on('collapse', ({ source }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Panel | This Panel. |
Fires when a Panel is expanded using the collapsible setting.
// Adding a listener using the "on" method
panel.on('expand', ({ source }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Panel | This Panel. |
A header tool has been clicked.
// Adding a listener using the "on" method
panel.on('toolClick', ({ source, tool }) => {
});| Parameter | Type | Description |
|---|---|---|
source | Tool | This Panel. |
tool | Tool | The tool which is being clicked. |
Event handlers
21
Event handlers
21Called when a Panel is collapsed using the collapsible setting.
new Panel({
onCollapse({ source }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Panel | This Panel. |
Called when a Panel is expanded using the collapsible setting.
new Panel({
onExpand({ source }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Panel | This Panel. |
A header tool has been clicked.
new Panel({
onToolClick({ source, tool }) {
}
});| Parameter | Type | Description |
|---|---|---|
source | Tool | This Panel. |
tool | Tool | The tool which is being clicked. |
Typedefs
7
Typedefs
7An object that describes a Panel's header.
| Parameter | Type | Description |
|---|---|---|
cls | String | Object | Additional CSS class or classes to add to the header element. |
dock | top | right | bottom | left | Specify "left", "bottom", or "right" to control panel edge to which the header docks. |
title | String | The panel title or raw HTML (not automatically HTML-encoded). |
iconCls | String | A CSS class representing an icon to display in the header |
titleAlign | start | center | end | Specify "center" or "end" to align the panel's title differently. |
style | Object<String, (String|Number)> | String | A style string or object to apply to the header |
CSS variables
52
CSS variables
52| Name | Description |
|---|---|
--b-panel-gap | Gap between items in the panel |
--b-panel-background | Panel background-color |
--b-panel-header-color | Header color |
--b-panel-overlay-box-shadow | Box-shadow for overlaid panel |
--b-panel-drawer-box-shadow | Box-shadow for drawer panels |
--b-panel-header-font-size | Header font-size |
--b-panel-header-font-weight | Header font-weight |
--b-panel-header-text-align | Header text-align |
--b-panel-header-gap | Gap between the header's different parts |
--b-panel-padding | Panel padding |
--b-panel-with-header-padding | Panel padding when there is a header |
--b-panel-bottom-toolbar-padding | Bottom toolbar padding |
--b-panel-bottom-toolbar-background | Bottom toolbar background |
--b-panel-top-toolbar-margin-inline | Top toolbar margin-inline (only applies when there is no header) |
--b-panel-top-toolbar-border-radius | Top toolbar border-radius (only applies when there is a header) |
--b-panel-header-padding | Header padding |
--b-panel-header-border-bottom | Header bottom border |
--b-panel-border | Panel border |
--b-panel-header-background | Header background |
--b-panel-overlay-border | Panel border when overlaid |
--b-default-panel-transition | The default set of transitions which applies to the panel's encapulating element Subclasses may add their own using this variable followed by their own transitions. |