Skip to content

PlBox

A sheet of glass with content on it. The plainest surface in the library: it groups things, and that is all it does.

React
tsx
import { PlBox } from 'plass-ui';

<PlBox>
  <p>Everything in here is grouped, and nothing else is claimed.</p>
</PlBox>;
dart
import 'package:plass_ui/plass_ui.dart';

PlBox(child: Text('Everything in here is grouped, and nothing else is claimed.'));

Props

PropTypeDefaultDescription
variantshared'solid' | 'glass' | 'ghost''glass'What the sheet is made of. None of the three is dyed: what a box holds arrives with its own colours
sizeshared'xs' | 'sm' | 'md' | 'lg' | 'xl''md'The size of the **sheet**: its radius and its padding. Never a height, never the type scale
colorshared'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info''primary'Semantic colour role. Arbitrary colour values are not accepted
densityshared'default' | 'compact''default'Padding only — never the height, never the type scale
elevationshared0 | 1 | 2 | 30Drop shadow depth. 0 and flat: the glass edge is what separates the box from the page
paddedbooleantrueInner padding. Turn it off for content that should reach the edges
renderuseRender.RenderPropRenders something other than a div — a section, an li, anything
PropTypeDefaultDescription
childWidget?What is on the sheet
variantsharedPlassVariantPlassVariant.glassWhat the sheet is made of. None of the three is dyed: what a box holds arrives with its own colours
sizesharedPlassSizePlassSize.mdThe size of the **sheet**: its radius and its padding. Never a height, never the type scale
colorsharedPlassColorPlassColor.primarySemantic colour role. Arbitrary colour values are not accepted
densitysharedPlassDensityPlassDensity.standardPadding only — never the height, never the type scale
elevationsharedint0Drop shadow depth. 0 and flat: the glass edge is what separates the box from the page
paddedbooltrueInner padding. Turn it off for content that should reach the edges
clippedboolfalseClips the content to the sheet's own corners. Off by default: a clip also cuts anything a child draws outside itself

Every other <div> attribute passes through, and render swaps the element.

What the shared axes mean across the library is in prop conventions.

PlBox or PlCard

Everything structural (a title, a subtitle, a footer, hairlines between sections) belongs to PlCard, which is a box with those sections laid out on it. What is left here is the sheet itself, and it is worth having on its own because most of what a screen groups has no heading: a well behind a form, a tile in a shelf, a panel round a chart.

The moment you find yourself putting a heading and a body inside a box by hand, the component you wanted was a card.

size means the sheet

size means something different here from what it means on a control, and this is the one place in the library where that is true.

A box is as tall as what it holds, and its children bring their own typography, a container that reset the type scale would render the same paragraph at two sizes depending on what it was wrapped in. So size is the size of the sheet: its radius and its padding, and nothing else.

React

Examples

variant

The three materials say what they say everywhere else, read as a container's: the sheet is never dyed. What a box holds arrives with its own colours, and tinting the pane under them puts every one on a background it was not chosen against, so the family reaches the hairline and the focus ring and stops.

ghost is the one to use inside another surface, where a second bordered rectangle is a second rectangle.

React

padded

On by default. Turn it off for content that should reach the edges, an image, a table, a list that draws its own rows.

Add overflow-hidden so the content is cut by the sheet's own corners.

clipped is what cuts the content at the sheet's own corners, and it is a parameter here where the React build needs only a class. It is off by default because a clip also cuts off anything a child draws outside itself, a focus ring included.

React

elevation

0 and flat, which is the right default: the glass edge is what separates the box from the page. Raise it only for a surface that genuinely floats above the content around it, and remember that a ghost box has no sheet for a shadow to fall from.

tsx
<PlBox elevation={2}>Floating clear of the page</PlBox>
dart
PlBox(elevation: 2, child: Text('Floating clear of the page'));

Accessibility

  • A box is a <div> and claims nothing. It has no role, no name and no place in the document outline, which is correct: grouping for the eye is not grouping for a screen reader.
  • When the group is meaningful (a region of the page, a list item, a section with a heading) say so with the element rather than with the sheet.

render={<section aria-label="Storage" />} and render={<li />} are the two that come up most.

A Semantics(container: true, label: …) around the box is what says the group is one, and it belongs outside the sheet rather than inside it.

Differences from the React build

ReactFlutterWhy
renderThere is no element to swap. What a <section> was saying is said by a Semantics around the box.
overflow-hidden as a classclippedA clip is a widget here rather than a property, so it has to be somebody's decision, and it is off by default, because a clip also cuts anything a child draws outside itself.
className, styleThere is no class list and no style attribute to pass through.

Released under the MIT License