Skip to main content

Draw a Studio App

Goal​

Draw a screen on the canvas, and say what each object is.

Where it opens​

Open your solution, choose Studio apps, select one, and press Design. The canvas opens in place, under the same breadcrumb and the same environment and solution pickers — the same canvas the report and dashboard designers use, so nothing you already know about it has changed.

An app is several screens​

Every frame you tag as the screen is a screen of this app. Draw a second one beside the first, tag it the same way, and your app has two — on one canvas, side by side, where you can see both at once.

A screen is called what its frame is called. Rename the frame in the Layers list and you have renamed the screen. That name is not decoration: it is what navigation will ask for, so two screens with the same name is refused when you save, naming the one to rename.

Say which one it opens at. As soon as an app has two screens, an Opens at picker appears in the title bar. Pick the screen somebody arriving at your app should land on. With one screen there is no picker, because there is nothing to choose.

Moving between them comes next

Drawing two screens works today, and so does choosing which one opens. What is not here yet is navigate — the action that takes somebody from one to the other — and the buttons that call it. It is the next slice, and it is deliberately absent rather than present and silent: an action that does nothing is worse than one that is not offered.

The one new thing: what an object is​

Select an object and open the Screen tab beside Graphic. There is one question there:

This object is …

Answer it, and you have told the platform something it cannot work out for itself. A rectangle of text that is a heading and a rectangle of text that is a paragraph look identical on the canvas; only you know which is which, and the difference is what a screen reader will announce and what the finished screen will look like.

AnswerUse it for
The screenThe frame everything else is drawn inside. Its size is the screen's size.
A regionA box that groups other things — a header strip, a sidebar, a card.
A headingA title.
A paragraphA run of ordinary text.
A list / A list itemA list, and one entry in it.
A buttonSomething to be pressed.
An imageA picture that means something, as opposed to decoration.
(left blank)The screen's graphic — drawn, but saying nothing about what the screen contains.

Under those, the same list offers Control: a Button, a Text box, a Text area, a Tick box, a Dropdown or a Date picker. See below — those are not drawings.

You will notice the list changes with what you have selected. A frame can be the screen; a text object cannot, because the screen's size is the screen's size. A line or a shape has no answer at all, and the tab says so rather than showing you an empty panel.

Start by drawing a frame and marking it as the screen. Everything else goes inside it, and objects inside a frame can be pinned to its edges so they follow when it resizes — the same pinning you already use in the other two designers.

Sizing a run of text​

Select any text and its Text section ends with two buttons:

  • Set size — the default, and what text has always done. The width is yours and the words wrap in it. The height is yours too, and it is a floor: make the box taller if you like, and it will never be shorter than the words. (Before this the vertical handles moved and the box snapped straight back, which is what made a text feel like the one object you could not resize.)
  • Fit the text — the box becomes exactly the text: as wide as the longest line you typed and as tall as those lines. Nothing wraps, and the resize handles go away, because there is nothing left for them to decide. Press Set size to get them back.

There is deliberately no third mode that lets a box be shorter than its words. A box that hides what you typed behind its own edge is a mistake you cannot see, and a floor gives you everything "change the size" needs without it.

Where the words sit in the box​

The alignment row in Text has a second group of three: Words at the top, in the middle and at the bottom. It says which edge the words are anchored to when the box is taller than they are.

The middle is the default, and it is what a caption inside a button needs — a caption box drawn inside a 40px button is deliberately taller than its one line, and centring is what puts the words where you drew the button.

Choose the top for anything that might grow. A centred box that turns out to be too small overflows in both directions, so a note that wrapped to three lines climbs up over the label above it. Anchoring it to the top means it can only grow downwards, into space you can see. It is also what the canvas has always drawn, so it is the one setting where the drawing and the screen agree exactly.

To select the screen frame again later, click its empty background once — clicking a frame usually reaches whatever is drawn inside it, and a single click on a bare patch selects the frame itself, handles and all. When nothing bare is left, right-click → Select layer, or use the Layers panel. Resize it by dragging a handle or by typing a width and height in the inspector; either way, the pinned objects inside follow.

Drawing on one thing when several are stacked​

A tabbed screen is several panels drawn in the same rectangle, one shown at a time. On the canvas they are all drawn, so only the top one can be clicked, dragged or resized — and the others are somewhere underneath it, unreachable.

Press the target button on a layer's row (beside the eye and the padlock) and everything else disappears from the canvas. Draw on it, then press it again — or Show everything in the banner at the top of the Layers list, which is there so a canvas that has gone half-empty always says why.

It changes nothing about your app. The eye beside it would clear the way too, and the eye is the drawing's own visibility: a layer you hid is a layer that does not appear in your app at all, so hiding two panels and forgetting to unhide them would publish a screen missing two panels. This is the canvas only, it is not saved, and it is gone when you next open the designer.

The Layers list has the same right-click menu​

Right-click a row in the Layers tree and you get the menu the canvas gives you: reorder, group, mask, flip, make a component, lock, duplicate, delete — all of it, acting on that row.

It selects the row first, so the menu always acts on what you pointed at rather than on whatever happened to be selected before. There is no Select layer submenu here: that one exists to disambiguate a click over stacked shapes, and a row in a tree is already one object.

This is most useful for exactly the objects the canvas makes awkward — something buried inside a frame, behind something else, or scrolled off the view. Find it in the tree and act on it there.

Keys for the view and the shapes​

  • Zoom with Ctrl+= and Ctrl+- (⌘ on a Mac), or Ctrl with the mouse wheel. Ctrl+0 goes back to 100%.
  • Shift+1 shows everything on the canvas. Shift+2 fills the window with what you have selected.
  • Pan with the mouse wheel (Shift for sideways), by holding Space and dragging, or with the Hand tool (H).
  • Arrow keys move the selection one pixel; with Shift, ten. Each press is one undo step.
  • A shape you have just drawn is selected, and the Select tool is back, so you can colour and name it straight away.
  • Typing a Rotation turns a shape about its centre, as the rotate handle does.
  • While you drag, guides line edges and centres up with what is on screen. Hold Alt to place a shape freely.
  • Click with the Text tool and type. The new text is selected with its placeholder highlighted, so the first key replaces it.
  • A click on a shape in a group selects the whole group. Double-click to reach the one shape.
  • Union, Subtract, Intersect and Exclude leave the result where the bottom shape was: in the same frame, under its name, with its corners rounded if they were.
  • Ctrl+D on something inside an auto layout puts the copy right after it, in the row.

Prerequisites​

Steps​

  1. Open your solution, choose Screens, select one and press Design.
  2. Draw a frame. With it selected, open the Screen tab and set This object is to The screen.
  3. Draw inside it: frames for the regions, text for the headings and the prose, images where you want pictures.
  4. Select each one and say what it is. Leave the purely decorative ones blank.
  5. Press Preview to see the screen as a user will.
  6. Press Save.

Reopening the screen brings your drawing back exactly as you left it.

Preview shows you the real thing​

Preview swaps the canvas for the screen itself — not a picture of it, and not the canvas with the guides turned off. It is the same component the Platform Shell mounts, so what you see is what a user gets. Select some text in it and you will find it selects; press Ctrl+F and the browser finds it.

Press Design to go back. Preview always shows what is on the canvas now, including edits you have not saved.

What Save actually does​

Saving stores two things: your drawing, and the screen compiled into ordinary web elements. A heading becomes a real heading, a paragraph a real paragraph, a button a real button. That is what makes the text selectable and searchable, gives the button a focus ring, and lets a screen reader announce the page properly — none of which a drawing can do on its own.

So your answers in the This object is list are not labels. They decide what each object becomes.

Two things follow from it that are worth knowing:

  • Your screen mirrors for Persian and Arabic readers. Anything you pinned to the left appears on the right, and text you aligned left aligns to the reading edge. You do not have to draw it twice.
  • Resizing costs nothing. Pinning an object to both edges makes it stretch, and pinning it to the bottom keeps it there — the browser does that itself, so a screen stays smooth however it is resized. Narrowed far enough, the page scrolls rather than shrinking: a screen is something people read and type into, and shrinking it produces text nobody can read.

If Save tells you something​

Saving can come back with a remark. None of them stops the save:

  • No object is tagged as the screen — the whole drawing was used instead. Tag a frame as the screen so the objects inside it have something to be pinned to.
  • Another object is also tagged as the screen — only the first is used; the rest became ordinary boxes.
  • A button has no text in it — there is nothing for a screen reader to announce. Draw a text object inside the button.
  • A state was drawn for a control — it was not used. A control already knows how it looks when pointed at, pressed, focused and disabled.

When you want a real control, not a drawing of one​

Draw a box, and in the Screen tab pick one of the Control entries instead of an element. What appears on the finished screen is the platform's own control — the same date picker the record forms use, the same text box, the same button.

That matters more than it sounds. A rectangle that looks like a date field has no calendar. A rectangle that looks like a text box has no caret, no selection, no autofill and no keyboard behaviour. And when a Persian user opens your screen, the real date picker shows a Jalali calendar — with nothing for you to do, because it was never re-drawn.

What you keep, and what stays the platform's. Where you drew it, how big it is, and how you painted it are all yours — the fill, the border, the corner radius, and the colour and weight of the words inside. What stays the platform's is everything a drawing cannot say: the caret, the calendar, the numerals, the keyboard behaviour, and the focus ring you did not paint over.

Anything you leave alone stays the platform's, and that is the point rather than a limitation. A control you never painted looks exactly like every other control in the product, and follows the theme when it changes. Paint only the border, and only the border is yours.

Paint with a token, not a colour

Pick a swatch from the token row under the fill rather than typing a hex. Primary is the tenant's accent in light mode and dark; a hex is right in one of them. A control dropped from the Controls palette already arrives painted in tokens, which is why it looks right in both.

Write the label inside the box. The words you draw in it become a button's caption, a tick box's label, or the greyed placeholder in a text box — there is no separate field to fill in.

Things you type rather than draw:

  • Options, on a dropdown, one per line. It is the one thing about a control you cannot draw: a closed dropdown shows a value and never the list.
  • Takes, on a text box — what kind of value it holds: Text, A password, An email address, A number, A phone number, A web address. Not decoration: a password box masks what is typed and comes with the platform's reveal toggle, an email or web address box brings up the right keyboard on a phone, a number box a numeric keypad.
  • Read-only, on a text box or text area — it can be read, selected and copied, but not changed. Different from Disabled, which is on every control and means the control is not for this user at all: a disabled control is skipped by the keyboard and by a screen reader, where a read-only one is not.
  • Most characters, on a text box or text area — the browser stops typing at that length.
  • Takes, on a file picker — Any file or An image. It decides two things at once: what the file dialog offers, and whether what was picked is shown as a picture.
  • Picks, on a date picker — A date, A date and a time, or A time.
  • Calendar, on a date picker — The tenant's setting, Gregorian or Persian. Leave it on the first one unless the calendar is a fact about the data rather than about the reader: a passport expiry is Gregorian for everybody, where "the date this was approved" should be shown in whichever calendar the person reading it uses.
A file picker holds the file; a handler stores it

Bind Value to a state field and the picked file lands in it. A text bound to the same field shows the file's name. To keep the file, pass the field to createRecord or updateRecord as the value of a File or Image field — updateRecord("contact", id, { new_photo: getState("photo") }) — and it is stored with the record. Until a handler does that, the file stays in the page and is gone when you leave the screen. A file over 4 MB is refused in the picker, before it is read.

note

If you have bound Enabled to an expression, the Disabled tick is greyed out and says why: the expression already answers when the control may be used, and a tick beside it would be a second answer. Bind enabled or tick Disabled, not both.

Controls take drawn states too. Draw the control, duplicate it, change the copy's colours, and tag the copy as invalid — exactly as you would for a box you drew. What travels is the difference, and it lands on the control itself. See Reuse a design with components for how a state is declared.

So which do you use? Draw it when the look is the point — a call to action in your own colours, with a hover you drew. Pick a control when the behaviour is the point: a calendar, a caret, a keyboard.

Making a "danger button"​

There is no Look dropdown, and there does not need to be one. To get a red button:

  1. Drop a Button from the Controls palette.
  2. Set its fill to the Error token and the caption's colour to white.
  3. Select it and press Make component — the button itself becomes the component. Rename the layer Danger button, and the component is renamed with it.

Now it is in the Components list, and every screen that places one gets the same red button. Want a hover? Add a state to the component and draw the copy darker. Want a Success button too? Do the same thing again — which is one gesture you already know, rather than a fifth entry in a dropdown somebody has to add for you.

Select a box or a run of text, and in the Screen tab choose A link. Two fields follow:

  • Address — where it goes: https://example.com/docs, mailto:someone@example.com, tel:+441234567890, or a path inside this app like /reports/monthly.
  • Opens — In this window (the usual) or In a new tab.

To go to another screen of this app, type its name: Contacts. The link goes to that screen wherever the app is opened, on its own or inside a model-driven app, whose addresses for the same screen differ. Pressing it moves inside the app without reloading the page, and middle-clicking still opens the screen in a new tab.

Why this is a link and not a button with a handler. Middle-clicking it opens a tab. Right-clicking offers Open link in new tab and Copy link address. Hovering shows the destination in the browser's status bar. A screen reader can list every link on the screen and read yours out among them. Not one of those comes from a handler — they all come from the element being a real link, which is the whole reason this is a thing you tag rather than a thing you script.

When the destination is computed, bind Address instead of typing it — "https://example.com/" + state.topic. The binding wins, and the panel greys the box and says so. See Make a screen react.

Some addresses are refused, and the panel turns red while you type one: only web addresses (http, https), email addresses, phone numbers and paths inside this app are allowed. A link that runs script is not a link, and a screen can arrive from an import rather than from your own hands.

tip

When it is the screen that decides where to go — after a Save, or based on what somebody picked — use openUrl("…") in a handler instead. Same rule about addresses, and see Make a screen react.

Draw what it looks like when pointed at​

States belong to a component. Select what you want to give a state to, right-click, and choose Make component — then add its states on the component, where they are listed together. Full walk-through: Reuse a design with components.

That is one place rather than two. There used to be a Draw a state box on this tab as well, which asked for a name and an interaction before you had drawn anything and sat on objects with no list of states to add to; the Screen tab now says where states live instead.

A component with one instance is a perfectly good component. If all you want is a hover on one button, make it a component and give it the state — that is the price, and it is also what lets you place that button twice tomorrow.

What a state's name is, and what While is​

A state has two halves, and you say them in two places:

  • The name is yours — invalid, overBudget, awaitingApproval. Selected, Ticked, Invalid, Success, Warning, Loading and Read-only are only suggestions.
  • While — on the variant's own panel: Always, or Hover, Pressed, Focused. Those three are the browser's, so they are the ones you cannot invent.
note

Disabled is a name, not a While. It used to sit in that picker, and it does not belong there: Hover, Pressed and Focused are things somebody is doing, and each stops the moment they stop. Disabled is what the control is — your screen decided it — so it is a state name like any other, typed as disabled.

You do not have to say when it is on. The screen already knows, from the control's Disabled tick or its Enabled expression, and it turns the state on for you. Draw a variant, name it disabled, and a control that may not be used wears it.

Set both and you have a combination — Invalid while pointed at. You never have to draw every combination: if a user points at something in the Invalid state and you only drew Invalid, they get Invalid.

Use letters, digits, - and _, starting with a letter. A name that could not be a state greys the button out and says so, rather than letting you draw four of them and meet the refusal at Save.

Three things worth knowing:

  • Only the differences are kept. If you change the copy's background, only the background is remembered. So resizing the original, or editing its caption, does not have to be repeated in every state — which is what stops a button that jumps when you point at it.
  • Move the copy wherever you like. Where the copy sits on the canvas is not part of the state; it is just somewhere to look at it.
  • But moving something inside the copy is. Slide the knob of a switch to the other end of its track in the copy, and the switch's knob slides when the state comes on — it eases across rather than jumping. That is how you draw a switch, a stepper or a highlight that travels. Resizing something inside the copy counts too, and it snaps rather than easing: growing a box reflows what is around it, and animating that is what makes a screen stutter.
  • Nothing runs. The browser does the whole thing, so a screen with fifty hover states is exactly as fast as one with none.

Add or remove an object in the copy and the state stops working, and Save says so, naming it. A state has to be the same shape as what it mirrors. To show something extra when pointed at, draw it in the original, hide it there, and make it visible in the state — hidden and visible is a difference in how it looks, which is a thing a state can do.

Put an icon on it​

Components → Icon… opens the platform's own icon picker — the whole Lucide set, searchable by what an icon means rather than by its exact name. Pick one and it lands on the canvas.

What lands is an ordinary drawn object, not a special kind of thing:

  • it is painted with the same fills as everything else, so give it a design token and it follows the reader's light/dark mode;
  • it takes drawn states, so it can change colour on hover along with the card it is in;
  • it can bind Shown, which is how one button carries two glyphs and shows the one that fits — the sample's colour-mode button draws a moon and a sun and shows whichever the mode is not.

It arrives stroked rather than filled, painted color.text, 24 by 24. Resize it, recolour it, drop it inside a button beside the caption. Nothing about it is special afterwards.

A button with only an icon in it is refused. Save warns has no text in it, so a screen reader has nothing to announce — put the words beside the glyph, as the Support desk sample's Dark mode control does. That is also the friendlier control: not everybody has learned that a moon means dark.

The row is click-only and does not drag, because a drag has to know what it is carrying and this one would be carrying a dialog.

Picked the wrong one? Change it​

Select the icon and the property panel shows an Icon field under its name, with the same picker in it. Choose another and only the drawing is replaced — its size, its colour, its states and its bindings all stay exactly as you set them.

That is the whole reason to change it there rather than deleting it and placing a new one: a fresh icon arrives 24 by 24 in color.text and knows nothing about the button you had put it in.

An icon you drew yourself with the pen has no Icon field, and should not: there is no name behind it to swap, and the only thing a picker could do is throw your drawing away.

Put an icon in a button​

Select a button and the property panel shows a Button icon field, with the same picker. Pick an icon and it is drawn inside the button: in the middle when the button has no words, before them when it has, half the button's height and kept in place when the button is resized. Pick another to swap it, or clear the field to take it out.

A list, a table or a menu: paint the rows​

Draw a box, put the rows inside it, and the box's Rows fields paint them — on top of whatever you drew each row as. Four of them:

  • Every other row — the zebra. The first row keeps what you drew, so what you see while drawing is what row one looks like.

  • Row under the pointer — the highlight that follows the mouse down a list. It costs nothing: the browser does it, so a table of two hundred rows is as fast as an empty one.

  • Chosen row — the row somebody picked. See below for how a row says it is the chosen one.

  • Chosen row's edge — a bar on the same row, and The bar goes says on which edge:

    • Down the leading edge — the left in English, the right in Persian and Arabic, with nothing for you to set twice. What a navigation rail wants.
    • Under the row, like a tab — what a strip of tabs wants, because that is how a chosen tab is marked in every product there is. A row of tabs runs across, so a bar down the left of the first one is a control nobody recognises.

    It is the accent by default, because on a quiet list a chosen row and a pointed-at row are two shades of one grey, and the bar is what says you are here at a glance.

Where two colours would paint the same row, the later one in that list wins: the pointer covers the zebra, and the chosen row keeps its own colour even under the pointer. Making a chosen row look unchosen just as somebody reaches for it would be worse than the highlight going quiet for one row. The edge is not a colour of the row and is outside that contest — it paints as well as whatever won, and it moves nothing on the row, so nothing jumps sideways when the selection moves.

tip

Do not draw the bar. A rectangle beside one item cannot move, so pressing a different item leaves it where it was — which is a picture of a selection rather than a selection. Set Chosen row's edge and it follows the same answer the fill does.

They apply to the boxes directly inside the one you set them on, and no deeper — so a list of cards stripes the cards, not the boxes inside each card.

Pick a theme colour rather than a colour of your own wherever you can. A grey you sampled is right in light mode and wrong in dark, and it is wrong invisibly: the drawing still looks like a drawing of a light screen.

When there are more rows than the box is tall​

A box you drew to hold six rows holds a hundred the moment a real table is behind it, so every list has to answer this. The frame's Content that does not fit dropdown is where:

  • Show it — it spills out is what a drawing does, and is right for a card with a shadow on it. On a list it is what makes the rows run down over the pager and everything under it.
  • Hide it cuts them off. The seventh row is then unreachable, which is rarely what anybody meant.
  • Scroll to it is the answer for a list: the box stays the size you drew it and its contents scroll inside. A list short enough to fit shows no scrollbar at all.

Then say which way it scrolls. A second dropdown, Which way it scrolls, appears as soon as you have chosen Scroll to it:

  • Both ways is what a list wants.
  • Down — words wrap is what a column of prose wants. The axis you do not scroll is clipped, and clipping the horizontal is exactly what makes a paragraph turn over instead of running off the side of the box. Reach for this whenever the box holds a long text field.
  • Across — rows stay on one line is what a wide table of columns wants, so a row stays a row.
A long text field is a frame you draw around the text

The dropdown is on a frame. A run of text has nothing of its own to clip against, because it grows to fit its words — so draw a frame the size the note should occupy, put the text inside it, and set that frame to Scroll to it and Down — words wrap.

How much you see at once is how big you drew the frame. Making the text object taller changes nothing you can see, because the frame is what is holding the view. The Support desk sample's details dialog is exactly this, over a two-thousand-character Notes field.

Two things worth doing at the same time:

  • Pin the box top and bottom in Constraints, so a taller window shows more rows instead of more empty space under them.
  • Keep the header outside the box. A header drawn as the list's own first row scrolls away with the rows; drawn as a separate frame above it, it stays. The Support desk sample's board does exactly this.

Draw one row, get one per record​

A table's rows are not twenty boxes you drew. Draw one, and say what it repeats over:

  1. Load the records. In the screen's Loaded handler, write loadRecords("par_account", "accounts") — the table's name, and a state field to put the rows in. A third argument says how many at most, or asks a fuller question: { top: 20, where: { par_status: "Open" }, orderBy: "par_name" }. See Reading and writing records.
  2. Say what repeats. Select the row you drew and fill in One of these per with state.accounts.
  3. Say what each cell shows. Bind a caption inside the row to row.par_name — row is that record. rowIndex is its position, counting from zero.

Two things about the box around the row:

  • It has to stack its children — turn auto layout on. Every copy of a box you placed keeps the position you placed it at, so all forty would land on top of the first. Save says so if you forget.
  • Anything else in that box is left alone. A header row drawn above the body does not repeat, because the repeat is on the row rather than on the box.

You can repeat a control as easily as a box — a tick box per row is how somebody selects several records, and it is an ordinary tick box with row.id in the handler.

One limit worth knowing before you hit it: a repeat cannot go inside a repeat. row would mean two different things in the same place, so Save refuses the inner one and says which.

Which row is the chosen one​

Two halves, and neither is more than a line:

  1. Say which — bind each row's Chosen property to a comparison, like row.id == state.picked. It is a binding rather than something you switch on, and that is what makes the previous row stop being chosen at the same moment: every row re-answers the question when the state changes.
  2. Set it when a row is pressed — setState("picked", "…") in the row's Pressed handler.

If you also drew a Chosen variant of the row, the same binding turns that on too. There is one idea of "chosen" here, not two: the fill and the variant read the same answer.

Fill the row, and a menu for a phone​

Every object inside an auto layout frame is the length you drew it — so a row can never be narrower than what is in it, and on a phone it runs off the side. Select the object and, under Resizing on the Graphic tab, tick Fill the row (or Fill the column): it takes whatever length the others leave, and gives it back when there is less.

That is how a website's top bar is drawn: the site's name fills the row, so the links stay against the far edge at any width.

A form that is a phone's whole width, and a card on a desktop. Select a frame inside a vertical auto layout and set Max width under Resizing: the column stretches it across a narrow screen and, on a wider one, stops at that many pixels and centres it. A sign-in card or a contact form is drawn once this way — not once per width. Empty is no limit.

Three cards across a desktop, one above another on a phone. Select a horizontal auto layout and tick Wrap onto more lines under Auto layout. Each thing in the row starts at the width you drew it; when the screen is too narrow for all of them, the ones that no longer fit move to the next line. Give each card Fill the row and it also stretches across what is left of its line — three cards share a desktop, a tablet puts the third on a line of its own, and a phone takes one per line. Drawn once: there is no second copy of the cards to hide. The canvas shows the one line you drew; wrapping is what a narrower screen does to it.

For a phone, draw the links and a Menu button, and give each a Shown binding on the width of the page:

screen.width >= 720 on the links
screen.width < 720 on the Menu button

screen.width is the width of the box the screen is shown in, and it changes as the window does. Put the Menu button at the start of the bar and make it run openStartDrawer("Site menu"), where Site menu is an overlay card with the same links in it — so the menu opens from the side its button is on (the left in English, the right in Persian). Give each link's Chosen screen.name == "Home", and the row it is in a hover and a chosen fill, and the menu marks where you are. The portal-pages-and-navigation sample draws one for you.

Draw the bar once. A bar on every screen is a component: draw it, make it a component, and place an instance on each screen — change the master and every page follows. Because a link reads screen.name, an instance needs to be told nothing about which page it is on.

A frame inside a manual frame (auto layout off) has Constraints instead — pin it to edges, and it keeps its distance from them as the frame changes size. Inside an auto layout the layout decides where things go, so Resizing is the only question left.

Generate screens with AI​

Press AI, describe the app in a sentence or a paragraph, and press Generate (or Ctrl/⌘+Enter). For example: "An orders app with a home screen, a list of orders and a new-order form, all sharing a top bar and a side menu." What comes back is added to the canvas. Nothing you drew is replaced.

What you get is an app, not a picture of one:

  • Screens are frames tagged as screens and named in words, so the buttons that move between them work in Preview.
  • Controls are the real ones. A text box is the platform's text box, and a date is the date picker. They are not rectangles with words on them.
  • Things happen. Buttons have click handlers, a text box writes to the screen's state, and a list can load records when its screen opens.
  • Anything on more than one screen is a component. A top bar, a side menu or a footer is drawn once, on the shelf below the screens, and placed on every screen as an instance. Change the master and every screen follows. If the reply draws the same band on two screens anyway, the designer makes it one component for you, and the dialog says which part it joined up.

Ask for "a card component" and you get exactly that: a component on the shelf, ready to place from Components.

An app is drawn for a desktop unless you say phone. Ask for a phone app and its screens are phone-sized. Its top bar has a menu button that opens the navigation as a drawer, and a details screen has a back arrow instead.

Name the table, and the AI uses its real columns. In Parsware for Power Apps, when your description names a table, by its name (expenses) or its logical name (par_expense), the AI is told that table's columns before it draws. A list then shows the columns the table really has instead of guessed ones.

Afterwards, check what the AI could not know. Look at the table names a list loads from, and the words on the screens. The dialog names anything it found unfinished, such as a button whose click does nothing yet or a list that nothing loads. Then press Preview. A generated screen is a starting point you edit like any other drawing.

It corrects itself before it gives up, as a report does. When nothing usable comes back, the reply goes back to the model with the problem named, up to three times. A reply that is only a picture, with no screen and no component in it, counts as nothing usable.

If there is no AI button, AI is not set up here. On the platform, an administrator connects an AI provider once (Connect an AI provider). In Parsware for Power Apps, the button uses your environment's own AI Builder credits.

What a generated app does for you. A top bar's title takes the room, so its buttons sit at the bar's end whatever width it is placed in, including beside a side menu. A list scrolls inside itself, under the bar, rather than scrolling the whole screen; on a desktop its rows read like a table. Icons are picked from the platform's set by name, so an icon button has the real icon in its middle, no border, and an Icon field to change it. A component declares every property it reads.

It also tidies what the AI drew. Parts drawn beside each other in a column become a row inside it, so a card keeps its padding and its spacing. A desktop list's rows are square with no border of their own: the list stripes them and lights the one under the pointer. Words or controls placed straight under a bar get a padded body. A form on a desktop is a readable column, not the width of the window. A button in a shared bar that one screen does not use, like Back on the first screen, is hidden on that screen. A picture has a Radius in its properties, and the canvas shows it: an avatar is round because its radius is half its size.

The dialog closes only with its Close button. A click beside it or Escape no longer throws your description away.

A screen waiting for its data shows it. While a list loads or a record saves, a busy circle turns in the middle of the screen. In Parsware for Power Apps, something a screen could not do appears as a message that floats over the screen and goes away, rather than a strip that pushes the app down.

What is not here yet​

Deliberately, and each in its own release:

  • Saved views, and the parts of a filter that are not one line. A screen names a table, with equality pairs, "contains" pairs, a sort and a page — see Show a list a page at a time. It cannot name one of the platform's saved views, so a filter you have already drawn there is drawn again here. And there is no or, no range and no nesting: that is where a filter stops being a line in a handler and becomes the query designer.
  • Sums and averages. A screen counts rows — that is what the dashboard sample's tiles are — but it cannot total a column or group by one.
  • A Lookup control. The others have arrived: a grid and a quick form are the Table view or form control (Put a dashboard on a drawn screen), a dialog is an overlay card, tabs are one chosen value and a Shown binding per panel, and moving between screens is navigate. What still has no control of its own is the record picker — the component library has one drawn, which the Support desk sample places and gives its own state to.
  • Slots. A component takes properties and raises events; what it cannot yet do is leave a hole for the screen that places it to fill.
  • The keyboard, and anything on a timer. There are eight events, and the only one about the screen's own life is Loaded.

The tab offers only what means something today. A control that did nothing would teach you a gesture that does nothing.

Troubleshooting​

  • The Screen tab says my object is part of the graphic. — lines, shapes and paths have no meaning to give. Frames, text and images are the ones you can answer for.
  • "The screen" is not on offer. — you have a text object or an image selected. Only a frame can be the screen.
  • My control looks nothing like the box I drew. — that is the point: a control brings its own look. Only its position and size come from your drawing. If you wanted the colours you chose, leave it as a box and give it the A button element instead.
  • There is nowhere to draw a state. — states belong to a component. Right-click the object, choose Make component, and add the state on the component. (If the object is a control, it has none by design: it already knows how it looks in every state.)
  • Save is greyed out. — nothing has changed since the last save.
  • Preview is empty. — nothing is tagged as the screen, or the screen frame has nothing inside it. Draw a frame, mark it as the screen, and put something in it.
  • My state does nothing. — either the copy is identical to the original (there is no difference to keep), or you only moved it, which a state deliberately ignores. Change a colour.
  • Save says a state changes the structure. — the copy has more or fewer objects in it than the original. See above.
  • The object I copied from is gone. — Save says so: a state with nothing to be a state of draws nothing. Delete the copy, or draw the object again.
  • My screen does not appear in an app. — a screen has to be placed in one; see Open a Studio app from a model-driven app.
  • My drawing looks right but the screen looks plain. — check what each object is set to. An object left blank is part of the graphic; it is drawn, but it says nothing about what the screen contains.