PlMockup
A device with a screen you can put anything on: a phone, a tablet, a monitor or a laptop, with the system's own bars drawn on it.
import { PlMockup } from 'plass-ui';
<PlMockup device="mobile">
<MyScreen />
</PlMockup>;import 'package:plass_ui/plass_ui.dart';
PlMockup(device: PlMockupDevice.mobile, child: MyScreen());The screen is a real viewport at the device's own resolution, an md phone is 390 by 844, and the whole device is then scaled once to whatever room it has been given. So the content inside is laid out against a screen rather than against the page: a 390-pixel column wraps where it would wrap on a phone, and the mockup can be 200 pixels wide on the page without the content knowing.
That scale is the one transform in the library. The rule it is an exception to is about controls, where a scale resamples the label under the pointer pressing it. Nothing here is pressed, and the scale never changes on an interaction. It is set once from the space available, which is the only way to draw a 1440-pixel desktop in a paragraph's width at all.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| device * | 'desktop' | 'tablet' | 'mobile' | — | Which machine this is a picture of. The one prop with no default |
| os | 'macos' | 'windows' | 'linux' | 'ios' | 'ipados' | 'android' | — | The system whose chrome is drawn. Anything the device does not run falls back to its default |
| hardware | 'monitor' | 'laptop' | 'monitor' | What holds a desktop screen up. Ignored on a tablet and a phone |
| resolution | { width: number; height: number } | — | The screen's logical resolution, when none of the five steps is the machine you mean |
| orientation | 'portrait' | 'landscape' | 'portrait' | Which way a handheld is held. Turns the screen, the bezel and the cut-out together |
| bezel | 'none' | 'thin' | 'standard' | 'thick' | 'standard' | How much hardware there is around the screen. none is no hardware at all, not a thinner bezel |
| finish | 'graphite' | 'silver' | 'white' | 'graphite' | What the hardware is made of. Fixed colours rather than theme tokens |
| notch | 'none' | 'notch' | 'dynamic-island' | 'punch-hole' | — | The camera cut-out. Hardware rather than chrome, so it is drawn whether or not systemUi is on |
| systemUi | boolean | true | Draws the system's own bars. Each takes its own space, so turning it off gives the screen back |
| scroll | boolean | false | Whether content taller than the screen scrolls. Off, it is clipped |
| wallpaper | string | — | What is behind the content: any CSS background value |
| time | string | '9:41' | The clock in the status bar. The only text the chrome draws |
| width | number | string | '100%' | The rendered width of the whole device on the page |
| height | number | string | — | The rendered height. Given on its own it decides the size and the width follows |
| elevation | 0 | 1 | 2 | 3 | 0 | How far off the page the device sits. Drawn as a silhouette rather than a box |
| render | ReactElement | — | Renders something other than a div |
| children | ReactNode | — | What is on the screen |
| colorshared | 'primary' | 'secondary' | 'success' | 'warning' | 'danger' | 'info' | 'primary' | Reaches the accent in the chrome — a dock's first icon, a taskbar's |
| sizeshared | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'md' | The resolution of the screen. Not a control height and not a type scale |
| Prop | Type | Default | Description |
|---|---|---|---|
| device * | PlMockupDevice | — | Which machine this is a picture of. The one prop with no default |
| os | PlMockupOs? | — | The system whose chrome is drawn. Anything the device does not run falls back to its default |
| hardware | PlMockupHardware | PlMockupHardware.monitor | What holds a desktop screen up. Ignored on a tablet and a phone |
| resolution | PlMockupResolution? | — | The screen's logical resolution, when none of the five steps is the machine you mean |
| orientation | PlMockupOrientation | PlMockupOrientation.portrait | Which way a handheld is held. Turns the screen, the bezel and the cut-out together |
| bezel | PlMockupBezel | PlMockupBezel.standard | How much hardware there is around the screen. none is no hardware at all, not a thinner bezel |
| finish | PlMockupFinish | PlMockupFinish.graphite | What the hardware is made of. Fixed colours rather than theme tokens |
| notch | PlMockupNotch? | — | The camera cut-out. Hardware rather than chrome, so it is drawn whether or not systemUi is on |
| systemUi | bool | true | Draws the system's own bars. Each takes its own space, so turning it off gives the screen back |
| wallpaper | Decoration? | — | What is behind the content. A Decoration, where React takes a CSS background string |
| time | String | '9:41' | The clock in the status bar. The only text the chrome draws |
| width | double? | '100%' | The rendered width of the whole device on the page |
| height | double? | — | The rendered height. Given on its own it decides the size and the width follows |
| elevation | int | 0 | How far off the page the device sits. Drawn as a silhouette rather than a box |
| child | Widget? | — | What is on the screen |
| colorshared | PlassColor | PlassColor.primary | Reaches the accent in the chrome — a dock's first icon, a taskbar's |
| sizeshared | PlassSize | PlassSize.md | The resolution of the screen. Not a control height and not a type scale |
device is the one prop with no default: a mockup that has not said what it is a mockup of has not said anything.
size does not set a height or a type scale here. It sets the resolution of the screen, which is the only thing about a device there is to scale, the second component after PlBox where the ladder means something other than a control height.
Examples
device and hardware
A desktop is held up by a stand or by a keyboard; a tablet and a phone hold themselves up, and ignore hardware entirely.
os picks the chrome. A desktop runs macos, windows or linux; a tablet runs ipados or android; a phone runs ios or android. Anything else falls back to the device's own default, with one nicety: ios on a tablet and ipados on a phone both mean the Apple one, and get it.
finish
Fixed colours rather than theme tokens, because hardware is hardware. A graphite phone is the same graphite on a page switched to dark, and a device that changed colour with the theme would read as a drawing of the theme rather than of a device.
bezel
none is not a thinner bezel. It is no hardware at all, leaving the screen on its own with its corners cut, which is what a mockup that only wants the viewport asks for. thick is an older device: narrow sides, a forehead and a chin.
systemUi and notch
The system's bars each take their own space rather than covering the content: a caller putting a screenshot in a mockup wants all of the screenshot, and a status bar over the top of it would be a crop nobody asked for. Turning systemUi off gives that room back rather than uncovering anything.
The cut-out is the exception, because that one really is a hole in the glass, so it is drawn whether or not the bars are. It defaults to what the device would have: a dynamic island on an iOS phone, a punch hole on an Android one, nothing anywhere else.
orientation
Landscape turns the screen, the bezel and the cut-out together. The forehead and chin of a thick-bezelled phone become its left and right edges, and the island moves out from under the status bar.
A desktop ignores it. Rotating a monitor is a thing people do, but a mockup of it is a different picture (the stand does not move), and pretending otherwise would draw a landscape stand under a portrait screen.
Accessibility
- The hardware is decoration: the bezel, the stand, the cut-out and every system bar are hidden from assistive technology. What is announced is whatever the caller put on the screen.
- The chrome's only text is the clock, which is a prop rather than the real time. A mockup's clock is part of the picture, and reading the real one would differ between the server that renders the page and the browser that hydrates it.
- On React the screen is a container (
plass-screen), so content inside can answer to the device's width with a container query rather than to the window's.