Pantrix UI

Fitting the window

The window information PantrixTheme gives its content: what it is, where it comes from, how it is read and how it is fixed in a test.

Which helper to use while writing a screen or a component, and how, is in the adaptive usage guide, with three working sample cases. The rules an interface keeps while fitting the window are in its rules (in Turkish).

1. What does it give?

Every screen that uses PantrixTheme finds the window it is drawn in ready. There is no separate wrapper or setup:

PantrixTheme {
    val window = PantrixTheme.window

    window.widthClass                 // Compact, Medium, Expanded, Large, ExtraLarge
    window.heightClass                // Compact, Medium, Expanded
    window.size                       // DpSize
    window.posture.isBook             // half open, the hinge vertical
    window.posture.isTabletop         // half open, the hinge horizontal
    window.posture.separatingFold     // the hinge the content must not cross, or else null
    window.paneCount()                // how many panes there is room for side by side: 1, 2 or 3 (section 10)
    window.breakpoints                // the boundaries where the classes start

    PantrixTheme.layout.margin        // the page's margin, by the window's class
    PantrixTheme.layout.gutter        // the room between columns and panes
}

The types are in the com.pantrixui.foundation.adaptive package. What is looked at is not the device or the screen but the window: an app in a split screen, in a resized desktop window or in a browser tab is as wide as that window.

2. Classes and breakpoints

Width classWidth (dp)Where it is seen
Compact< 600A portrait phone, a foldable's cover screen, a narrow browser window
Medium600–839An open foldable, a portrait tablet, a split screen
Expanded840–1199A landscape tablet, most landscape phones
Large1200–1599A desktop window, a browser, a large tablet
ExtraLarge≥ 1600A wide desktop window, an external display
Height classHeight (dp)Where it is seen
Compact< 480A phone held landscape
Medium480–899A portrait phone, a landscape tablet
Expanded≥ 900A portrait tablet, a desktop window

The breakpoints are Android's window size classes, and stand in PantrixBreakpoints. The classes are ordered; "from this width on" is a comparison:

if (window.widthClass >= WindowWidthClass.Expanded) ListBesideDetail() else ListAlone()

3. Helpers: choosing a value and asking

There are helpers for the choices and the questions a screen writes most often. All are in the com.pantrixui.foundation.adaptive package, and each gives a name to something the window already says.

val window = PantrixTheme.window

// The ones that choose a value: a class not given takes the value of the one below it, a posture not given that of `flat`
val columns = window.byWidth(compact = 2, medium = 4)                    // 2, 4, 4, 4, 4
val barHeight = window.byHeight(compact = 44.dp, medium = 56.dp)
val panes = window.byPosture(flat = 1, book = 2, tabletop = 2)

// Questions
window.isNarrow       // the width is Compact: a portrait phone
window.isShort        // the height is Compact: a landscape phone
window.isSizeKnown    // has the platform told the size

// The short form inside a composable
val cardPadding = responsive(compact = 12.dp, medium = 16.dp, large = 20.dp)  // the same as PantrixTheme.window.byWidth(...)
val threeColumns = rememberWindowIsAtLeast(1000.dp)                      // a width at which no class starts

// The component's own room: the box tells the room given to it as if it were a window
BoxWithPantrixWindow(modifier) { box -> if (box.isNarrow) OrderList() else OrderTable() }
HelperWhat it tellsWhen it sets up again
byWidth(compact, medium, expanded, large, extraLarge)The width class's valueWhen the class changes
byHeight(compact, medium, expanded)The height class's valueWhen the class changes
byPosture(flat, book, tabletop)The posture's value: book in a book, tabletop on a table, flat in every other caseWhen the posture changes
isNarrowWhether the width class is CompactWhen the class changes
isShortWhether the height class is CompactWhen the class changes
isSizeKnownWhether the platform has told the window's width and heightWhen the answer changes
responsive(...)The byWidth of the theme's windowWhen the class changes
rememberWindowIsAtLeast(width)Whether the window is at least width wideWhen the window crosses that width
BoxWithPantrixWindow { box -> … }The room given to the component, as a window (section 10)When the class the content reads changes

Notes:

4. Height: a landscape phone

The width chooses the layout. The height says whether there is room to stack things.

A phone held landscape comes out Medium or Expanded by its width (iPhone 17: 874 × 402 dp), but its height is Compact: every bar that runs across it takes a seventh of the screen. The rule for a window whose height is Compact:

Today the only item of this rule with a counterpart in the components is the first: PantrixScaffold takes the navigation to the side from 600 dp on, on a landscape phone too. For the other items the library gives only the value to ask (heightClass); the components will apply the rule themselves as they come.

5. Where does the size come from?

The theme does no measuring; it reads the size from Compose's own window information (LocalWindowInfo). On 3 October 2026 it was looked at on every platform with the sample app:

PlatformThe size readThe first composition
AndroidThe Activity's window, the system bars included. On a foldable emulator: 852 × 883 when open, 443 × 970 on the cover screen, 970 × 443 with the cover landscapeStarts with the right size
iOSThe bounds of the UIWindow. iPhone 17: 402 × 874, iPad: 820 × 1180Starts with the right size
DesktopThe window's content area (800 × 572 in an 800 × 600 window). It follows the window as it is draggedStarts with a zero size
WebThe box Compose draws in, not the browser window. All five classes were tried, from 375 to 1700Starts with a zero size

On the desktop and the web the first composition sees the window as 0 × 0, so the class is Compact for a moment; the size comes right after. This is Compose's order on those two platforms: on the desktop the content is set up before the window is shown, and on the web the box's size is read after the content's first composition. Nothing is on the screen at that moment, but take care of this:

If there is a decision given once and kept, holding the content back until the size comes is in the app's hands. isSizeKnown is for this; on Android and iOS it is true from the start, so nothing waits there:

PantrixTheme {
    // The app is first set up in a window whose class is real.
    if (PantrixTheme.window.isSizeKnown) App()
}

The theme does not do this by itself: in a setting that never reports its size, the screen would stay empty.

6. Where does the posture come from?

An app that reads the hinge itself gives its posture:

PantrixTheme(window = rememberPantrixWindow(posture = myPosture)) { … }
PostureHow it is knownposture
Flat and openThere is a hinge, and the screen is one piecefolds filled, separatingFold null
BookHalf open, the hinge verticalisBook
TabletopHalf open, the hinge horizontalisTabletop
ClosedThe cover screenWindowPosture.Flat, the window Compact

The hinge's place is in separatingFold.bounds: in pixels, in the window's coordinates. The strip around it that touches leave free is clearance: on iOS it is 20 pt wide on either side of the hinge; on Android and the web it is bounds itself.

Measured in Xcode 27.1's iPhone Duo simulator: the cover screen is 466 × 678 pt and has no hinge; at its right edge stands the system's vertical bar (section 10, "The system's vertical bar"). The inner screen is 951 × 669 pt; the hinge is in its middle (x = 475.5), and its region is 40 pt wide with the 20 pt margins on either side. When the phone is turned, the inner screen becomes 669 × 951 and the hinge stands horizontal. In the simulator the hinge's angle is changed from Xcode's device window; there is no command for it in simctl.

7. Recomposition

PantrixTheme.window is the same object for as long as the theme stands; its values are read when they are asked for.

That is why layouts read the class. If you are to ask about a width that fits none of the classes, do not write window.size.width >= 1000.dp; use rememberWindowIsAtLeast(1000.dp): it sets up again only when the window crosses that width. If the size itself is needed, read it in a small composable of its own; the sample app's WindowSamples does so.

8. Fixing the window

Places where the real window is not the right answer:

// Tests and previews: seeing the layout at a given size
PantrixTheme(window = PantrixWindow(DpSize(700.dp, 900.dp))) { … }

// A part of the screen: let its content fit its own pane, not the window
CompositionLocalProvider(LocalPantrixWindow provides PantrixWindow(DpSize(360.dp, 900.dp))) { … }

In tests the window changes by platform: the window of the Skiko tests (JVM, iOS, web) is 1024 × 768, that is, Expanded. The window of the Android host tests is Robolectric's qualifiers. A test that tries a behaviour bound to the class should fix its window as above; otherwise the same test gives another result by platform.

A nested theme: if a part of the screen differs

A dark panel on a light screen, or a tight table on a roomy page, is a second theme inside the theme. The inner theme takes every setting not given to it from the outer one; what it gives is its own:

PantrixTheme(
    locale = PantrixLocale.Turkish,
    analytics = myAnalytics,
    platform = PantrixPlatform.forType(PlatformType.Desktop, isTouch = true)
) {
    Page()
    PantrixTheme(darkTheme = true) {        // a dark panel: only the colours change
        PantrixSurface {                    // the surface inside draws the dark ground, not the theme
            PantrixButton(text = "Save", onClick = save)
            // the touch target 48 dp, "Yükleniyor" in Turkish, the click goes to myAnalytics
        }
    }
    PantrixTheme(density = PantrixDensity.Compact) {   // a tight table: only the density changes
        OrdersTable()
    }
}

The sample app has a page for this: Theme: Inside Another Theme (on the web, #theme-inside-another). It shows the dark part, the tight part and a part in another language; each writes the theme's values, and the line that differs from the page's is marked "(changed)".

9. Your own breakpoints

PantrixTheme(window = rememberPantrixWindow(breakpoints = PantrixBreakpoints(medium = 640.dp))) { … }

The widths and the heights must be ordered from small to large; if they are not, PantrixBreakpoints throws.

The window tells the breakpoints it is classed by: PantrixTheme.window.breakpoints. Components are classed by them too: BoxWithPantrixWindow takes the breakpoints from the window in force. Code that classes a size by hand does the same:

val pane = PantrixWindow(paneSize, breakpoints = PantrixTheme.window.breakpoints)

10. A component that is a pane does not ask the window

The window is for decisions at the level of the page. A component that is itself a pane (the scaffold, the two panes, the sheets to come) does not ask the window, but measures the room given to it: for a component inside a narrow pane, the window is still wide. PantrixScaffold is so: it takes the navigation to the side when its own width reaches 600 dp.

A component learns the room given to it with BoxWithPantrixWindow. The box is built on top of BoxWithConstraints, and gives the most room it can take as a PantrixWindow: everything a screen asks the window (isNarrow, byWidth, widthClass >= …) is asked of the box.

@Composable
fun OrdersTable(orders: List<Order>, modifier: Modifier = Modifier) {
    BoxWithPantrixWindow(modifier) { box ->
        if (box.isNarrow) OrderList(orders) else OrderGrid(orders, showDate = box.widthClass >= WindowWidthClass.Expanded)
    }
}

The posture is outside this, because it is a property of the window. In the tabletop posture (half open, the hinge horizontal) the scaffold keeps the navigation at the bottom whatever the width: the lower half is where the hands are, and a column at the side would cross the hinge.

Two panes and the hinge

How many panes to show is a decision at the level of the page, and is asked of the window. Where the panes part, though, depends on where the panes stand, and is asked there.

val panes = PantrixTheme.window.paneCount()      // Compact and Medium 1, Expanded 2, from Large on 3 (limited by maxPanes)

if (panes >= 2) {
    PantrixTwoPane(
        first = { Inbox(onOpen = { opened = it }) },
        second = { Message(opened) },
        modifier = Modifier.fillMaxSize(),
        firstSize = PaneSize.Fixed(360.dp)       // or PaneSize.Fraction(0.4f); by default half and half
    )
} else {
    if (opened == null) Inbox(onOpen = { opened = it }) else Message(opened)
}

Code that writes its own layout by the hinge reads the hinge in its node's own coordinates:

val folds = rememberFoldsInNode()
Layout(content, modifier.then(folds.modifier)) { measurables, constraints ->
    val fold = folds.separatingFold          // the hinge that cuts and separates this node, or else null
    // fold.bounds and fold.clearance are in pixels, and are measured from the node's top-left corner
    …
}

folds is read again as the node changes its place (while the page scrolls too), as the window changes and as the device folds, and the layout that measures is measured again. A hinge that does not cut the node is not in the list; a line that runs along the node's edge does not cut it.

A folding window in a preview and a test: PantrixWindowFrame(window, modifier) { … } makes a box a window of its own. What is inside reads the window given with PantrixTheme.window; its hinge is measured from the box's top-left corner, wherever the box is on the screen. Even if the box is drawn small in a scaled layer, the hinge scales together with the content. window = null passes on the window the box stands in: a picker that offers the real window together with made-up windows calls the content from the same place at every choice, and the state is not lost. The "Book" (951 × 669, a vertical hinge) and "Table" (669 × 951, a horizontal hinge) windows on the sample app's cards are drawn this way; they are the measures of the iPhone Duo's inner screen.

val book = with(LocalDensity.current) {
    val x = 475.5.dp.toPx(); val h = 669.dp.toPx(); val pad = 20.dp.toPx()
    PantrixWindow(
        DpSize(951.dp, 669.dp),
        posture = WindowPosture(listOf(WindowFold(
            bounds = Rect(x, 0f, x, h), orientation = FoldOrientation.Vertical,
            isHalfOpened = true, isSeparating = true, isOccluding = false,
            clearance = Rect(x - pad, 0f, x + pad, h)
        )))
    )
}
PantrixWindowFrame(book, Modifier.size(951.dp, 669.dp)) { InboxScreen() }

List and detail: PantrixListDetailScaffold

A list, and the detail of the item opened in the list, is the adapting layout seen most often: an inbox, settings, contacts, files. So that every screen does not write the if (panes >= 2) … else … code above again, PantrixListDetailScaffold manages the number of panes, the move and the back gesture in one pane, the focus, the hinge and the list's width itself.

val inbox = rememberListDetailState()                    // the open item, the extra pane, the list's width; it is saved

PantrixListDetailScaffold(
    state = inbox,
    list = { Messages(onOpen = { id -> inbox.select(id) }) },
    detail = { id ->
        // In one pane the detail is in the list's place: only then does a back button stand.
        Message(id, onBack = if (isSinglePane) ({ inbox.back() }) else null)
    },
    modifier = Modifier.fillMaxSize(),
    emptyDetail = { PantrixText("Choose a message") },        // in two panes, while there is no open item
    listTitle = "Inbox",                                      // the panes' names for the screen reader
    detailTitle = { id -> subjectOf(id) },
    extra = { id -> History(id, showHeader = !isExtraInSheet) },  // an optional third pane
    extraTitle = "History",
    resizable = true                                          // the list's width is dragged
)

On the sample app's "List and detail" page, five cases stand with their cards: an inbox, settings (with the first section open in two panes), contacts with an extra pane, files whose width is dragged, and meeting at the fold on a folding device.

Main content and a supporting pane: PantrixSupportingPaneScaffold

A screen's main content and a pane that supports it: a document and its comments, a chart and its filters, a map and its results. The difference from list and detail is that the main content is always there: the supporting pane either stands beside it or opens over it.

val comments = rememberSupportingPaneState()             // whether it is shown beside, whether it is open over, its width

PantrixSupportingPaneScaffold(
    state = comments,
    main = { Document(onComments = { if (isSupportingShown) comments.hide() else comments.show() }) },
    supporting = {
        // Beside, the pane draws its own title and hide button; in a sheet, the title and the close button are the scaffold's.
        Comments(onHide = if (supportingPlace == SupportingPanePlace.Beside) ({ comments.hide() }) else null)
    },
    modifier = Modifier.fillMaxSize(),
    mainTitle = "Report",                                    // the panes' names for the screen reader
    supportingTitle = "Comments",                            // the sheet's title too
    presentation = SupportingPanePresentation.Sheet,         // in a narrow room a sheet (the default), or Pane: in the main content's place
    resizable = true                                         // the supporting pane's width is dragged
)

On the sample app's "Supporting pane" page five cases stand: a document and its comments, a chart and its filters with a width that is dragged, results that open in the map's place in a narrow room, hiding and showing beside, and parting at the fold on a folding device.

The tabletop posture: PantrixTabletopLayout

Content that is looked at, and controls that are touched: a video and the player's buttons, a video call and its buttons, the camera's picture and its shutter. When a foldable is set half open on a table (the hinge horizontal), what is looked at should be above and the hands below.

PantrixTabletopLayout(
    content = { Video(player) },
    controls = {
        // On a table the whole lower half is the controls': they can be drawn large.
        PlayerControls(player, large = arrangement == TabletopArrangement.Tabletop)
    },
    modifier = Modifier.fillMaxSize(),
    flatControls = TabletopControls.Below                    // while flat: Below (the default) or Overlay
)

On the sample app's "Tabletop" page four cases stand: a video player, a player whose controls are over the video, a video call, and parts that write their measures.

Overlays on a fold

When a foldable is held half open, or when there is a hinge between two screens, a dialog or a popover that falls on the fold is split in two. Pantrix's overlays stay in one half of the fold; the rule is in the overlays' shared code, and the components need no parameter:

OverlayLike a book (the hinge upright)On a table (the hinge horizontal)
Dialogthe middle of the half it was opened from; if that is not known, the start halfthe middle of the half it was opened from; if that is not known, the lower half
Bottom sheetthe half it was opened from, at that half's widththe lower half; a full-screen sheet the whole lower half
Side sheetthe whole end half: from the fold's strip to the window's endthe lower half
Command palettelike a dialogthe upper half, its height limited by that half
Popover, menu, tooltip, a select's listthe half of the control it is tied tothe half of the control it is tied to
Snackbarone half: the end half at the end corner, the start half for the othersin its place

An app that shows its own Dialog or Popup gets the same information with rememberOverlayWindow():

val overlay = rememberOverlayWindow()
// Once, on opening: where it was opened from, and the fold that splits the window in two.
val openedFrom = remember { overlay.openedFrom() }
val fold = overlay.folds.firstOrNull { it.isSeparating }
val onTheLeft = fold != null && openedFrom != null && openedFrom.x < fold.bounds.center.x

The places of OverlayWindow are in the app window's coordinates and in pixels: a Dialog that fills the window places what is inside it there. window is the overlay's window (the frame's or the outermost theme's), frame the place where the frame is drawn in the window, scale the scale the frame is drawn at.

A covering hinge: Modifier.keepClearOfFolds()

On a device with two screens, the hinge covers a strip of the screen: what is drawn under it cannot be seen. A node that runs a little over the hinge (a list a little wider than one screen, a bar along a whole edge) should keep what is inside it on the screen where most of it stands:

Box(Modifier.fillMaxSize()) {
    Inbox()
    // A bar along the whole bottom edge stays on one of the two screens.
    Toolbar(Modifier.align(Alignment.BottomCenter).fillMaxWidth().keepClearOfFolds())
}

On the sample app's "Overlays on a fold" page all of these stand: a dialog opened from two corners, a popover and a menu beside the fold, sheets, the command palette and the snackbar, and keepClearOfFolds on a device with two screens. The examples open in the "Book" and "Table" windows, inside the card, counting the frame as the window.

The system's vertical bar: the iPhone duo's outer screen

iOS 27.1 puts the bars upright on the iPhone Duo's outer screen: it sets aside a column along the screen's end edge, and places the status bar upright at its top; UIKit also brings a tab bar and a navigation bar's buttons down into that column. The app's content keeps away from the column through the safe area. Measured in the simulator (466 × 678 pt): traitCollection.verticalBarEdge tells the end edge, the column is as wide as the right safe area inset (84 pt), the status bar covers the column's top 174 pt, and the room UIKit gives a bar (layoutRegionForBarOnEdge) is between 174 and 644 pt. UIKit's tabs stand at the bottom of this room, in a 48 pt capsule; a button like "…" stands right under the status bar.

Pantrix gives this as a part of the window, and puts its own components there:

PantrixScaffold(
    navigation = { placement, insets ->
        when (placement) {
            ScaffoldNavigationPlacement.Bottom -> PantrixNavigationBar(tabs, where, go, insets = insets)
            ScaffoldNavigationPlacement.VerticalBar ->
                PantrixNavigationBar(tabs, where, go, orientation = NavigationBarOrientation.Vertical)
            ScaffoldNavigationPlacement.Start -> PantrixNavigationRail(tabs, where, go, insets = insets)
        }
    }
) { padding -> Screen(padding) }

A preview or a test sets up a screen with a column with PantrixWindow(size, verticalBar = WindowVerticalBar(...)). The "Cover" window on the sample app's cards is set up this way (466 × 678, with an 84 column); the app's own shell stands so on the Duo's outer screen too.

11. Input: a finger or a mouse?

The window's size does not say what the app is used with: a 400 dp window can be a phone's browser, or a narrowed desktop window. The platform says it:

val platform = PantrixTheme.platform

platform.isTouch          // is the primary pointer a finger
platform.minTouchTarget   // the touch target; components take it from the theme themselves
WhereisTouchTouch target
Androidyes48 dp (Material)
iOSyes44 dp (Apple HIG)
Desktopno32 dp
Web, a browser on a deskno32 dp
Web, a phone's and a tablet's browseryes48 dp

The web runs on both kinds of device, and no guideline covers it; so it looks at its pointer. A finger is given the measure given on Android.

// A touch desktop app
PantrixTheme(platform = PantrixPlatform.forType(PlatformType.Desktop, isTouch = true)) { … }

// A phone's browser in a test and a preview
PantrixTheme(platform = PantrixPlatform.forType(PlatformType.Web, isTouch = true)) { … }

For the question "is it touch", do not look at the platform's type: a phone's browser is PlatformType.Web, but is used by finger. Ask isTouch:

if (PantrixTheme.platform.isTouch) PullToRefreshHint() else KeyboardShortcutsHint()

On the web the "increase contrast" and "reduce motion" settings are read the same way, and are followed if they change while the page is open.

12. Layout measures: the margin, the gutter, the columns and the content's width

The page's four measures change with the window's class, and are read from the theme:

val layout = PantrixTheme.layout

Column(Modifier.padding(horizontal = layout.margin)) { … }             // the page's room at the sides
Row(horizontalArrangement = Arrangement.spacedBy(layout.gutter)) { … }  // the room between columns and panes
layout.columns                                                         // the number of the grid's columns
Column(Modifier.maxContentWidth()) { … }                               // the content at most layout.maxContentWidth
ClassWidth (dp)marginguttercolumnsmaxContentWidth
Compact< 60016164unbounded
Medium600–83924168unbounded
Expanded840–1199242412unbounded
Large1200–15993224121040
ExtraLarge≥ 16003224121040

A phone has little width to give, a desktop window a lot: the margin and the gutter grow with the window. The values of both are steps of the spacing scale (lg, xl, xxl). The number of columns is Material's responsive grid; 1040 is the content's width on a wide screen.

The product gives the theme the measures of the classes it designed; those it does not give stay as they are:

PantrixTheme(layouts = PantrixLayouts(compact = PantrixLayout(margin = 20.dp, gutter = 12.dp))) { … }

The number of columns and the greatest width of a class given its own measures are the ones given too; if they are not given, they are a phone's, 4 columns and unbounded. A product that gives a wider class gives them too:

PantrixLayouts(large = PantrixLayout(margin = 40.dp, gutter = 24.dp, columns = 12, maxContentWidth = 1200.dp))

If ExtraLarge is not given, it takes the measures of Large.

13. Tests

FileWhat it holds
commonTest/.../adaptive/WindowSizeClassTest.ktThe boundaries (599.9 / 600 …), the order of the classes, an unknown size, your own breakpoints
commonTest/.../adaptive/WindowPostureTest.ktBook, tabletop, flat and open, a two-screen hinge
commonTest/.../adaptive/PantrixWindowTest.ktThe window the theme gives, a change of size, recomposition, fixing, a nested theme
commonTest/.../adaptive/WindowHelpersTest.ktSix helpers: the answers they give, and when they set up again
commonTest/.../adaptive/PanesTest.ktThe number of panes (width, book, tabletop, a two-screen hinge, flat and open), the frame's window, the hinge's place in a node: in a frame, in a nested frame, in a frame drawn small, in the app's window when the node changes its place
iosTest/.../adaptive/UIKitFoldTest.ktThe posture from what UIKit says: the cover screen, book, tabletop, flat and open, a region that covers the hinge, an iPhone with no hinge (with the iPhone Duo simulator's numbers)
commonTest/.../adaptive/BoxWithPantrixWindowTest.ktThe component's box: the room it tells, the breakpoints it takes from the window, when it sets up again; the breakpoints the window tells
androidHostTest/.../adaptive/WindowOnAndroidTest.ktThe window Android reports, and the hinge that comes from WindowManager
commonTest/.../adaptive/LayoutColumnsTest.ktEach class's number of columns and greatest content width, the density not scaling them, spanWidth (the columns and the gutters between, a narrow room, the bounds), Modifier.maxContentWidth (the bound, following when the window is resized, at the start, in the middle, at the end, right to left, the product's bound, the component's box, an unbounded width)
commonTest/.../adaptive/PantrixLayoutTest.ktEach class's margin and gutter, following when the class changes, scaling with the density, the product's own measures, the component's box
commonTest/.../a11y/PantrixPlatformTest.ktEach platform's touch target, the touch browser, isTouch, following when the pointer changes, the layout and the hit
commonTest/.../theme/NestedThemeTest.ktA nested theme: what is inherited, scaling once, a dark part and the preset's dark set, what is given being the inner one's, a theme with a preset, following when the outer one changes, a value from outside the theme not being inherited, the surrounding layout placing the content
androidHostTest/.../theme/ThemeOnAndroidTest.ktThe theme in the system's night mode; in a nested theme, the outer theme's darkness, not the system's; the test tags opened to automation once, at the outermost theme
webTest/.../adaptive/WindowPostureWebTest.ktThe hinge the browser tells: book, tabletop, a two-screen hinge, flat and open; reading again when the window and the density change; the segments read from the browser; the browser knowing the three queries; flat in a real browser
webTest/.../platform/MediaQueryTest.ktIn a real browser: the media query's answer, its changing while the page is open, the listening being let go
ui/components · commonTest/.../TouchBrowserTest.ktThe components in a touch browser: the look the same, the room set aside the finger's
ui/components · commonTest/.../NestedThemeTest.ktThe controls in a dark part: the app's platform, language and analytics; the styles in force, in a theme with a preset too
ui/components · commonTest/.../TwoPaneTest.ktThe two panes' share, their own size, one under the other, right to left, meeting at the hinge (vertical and horizontal, right to left), a hinge that does not separate and one outside the room, an unbounded height, an unbounded split direction, the default gap
ui/components · commonTest/.../ListDetailScaffoldTest.ktThe list's width bounds; one pane, back (from the dispatcher), a back gesture that goes on and one that is given up, the back left to the app in two panes; two and three panes, right to left, meeting at the hinge and the handle's absence; the extra pane standing beside, and in a sheet while it scrolls itself; the state kept from one pane to two; dragging the handle (mouse, finger), its arrows, Home and End, the screen reader's setting, right to left; the focus going with the pane shown; the state being saved
ui/components · commonTest/.../ScaffoldTest.ktThe navigation's place in the tabletop posture, a scaffold that fits in one half, the state kept while folding
commonTest/.../adaptive/WindowVerticalBarTest.ktThe window's vertical bar: a fixed window, the system's window following it, its absence on the tests' platforms, the column in the node's coordinates, a node that does not reach the column, the window of the frame and of the theme, before the node is laid out
iosTest/.../adaptive/UIKitVerticalBarTest.ktThe vertical bar from what UIKit says (with the numbers of the iPhone Duo's outer screen), and no bar if there are no numbers
ui/components · commonTest/.../ScaffoldVerticalBarTest.ktThe navigation and the buttons in the column, a scaffold with no column and one that does not reach it, the vertical bar against Start, the content's inset, a column on the left, right to left, a short scaffold, the buttons of the bar that came last, nested scaffolds, the composition kept while entering the column
ui/components · commonTest/.../NavigationBarUprightTest.ktThe upright bar: destinations one under the other, the name of a destination with no label, the tooltip on a long press, the labels and the capsule's padding, a badge that stays inside the capsule (left to right and right to left), icons only in the bottom bar
app/shared · jvmTest/.../demo/AdaptiveSamplesTest.ktThe sample app's three cases: the sign-in screen, the table component, showing and hiding (the usage guide); on the window page, the posture's name and the panes parting at the hinge; on the list and detail page, the number of panes by the window chosen, two equal pages in a book, the message opened in one pane and the back button
app/shared · jvmTest/.../demo/NestedThemeSamplesTest.ktThe sample app's nested theme page: what the page takes from the app, the dark part, the tight part, a part in another language, the events going to the page, a theme inside a Row
./gradlew :ui:foundation:jvmTest --tests 'com.pantrixui.foundation.adaptive.*'
./gradlew :ui:foundation:testAndroidHostTest

14. What is not there yet