Public Access
Move SFTP and S3 into the tab strip, and the host list into a card grid
Four asks in one pass over the desktop head, and two of them are furniture moving rather than anything new. THE STRIP IS THE WINDOW'S NOW, not the terminal's. Vaults, SFTP and S3 sit at its head and cannot be closed, and open terminals follow them. SFTP and S3 left the nav rail to get there, which is the one semantic change: they are the two destinations you stay in while something runs, and a rail entry is for somewhere you go and come back from. So the rail belongs to the Vaults tab and collapses with it, which also means SFTP, S3 and a terminal each get the full 1016 rather than the 826 a page gets. The tab is expressed as "a page, and not one of the two the strip took" rather than as a fourth ShellSurface. Both are still ShellScreen members and have to be — that is what they are on the phone, where they are two rows in a hub — so a surface each would have been a second way to say a thing Screen already says. IsTransfersShowing and IsBucketsShowing light the other two tabs unchanged. What is new is one field: the page Vaults comes back to, because it is the one tab with sub-navigation and therefore the one that can return to the wrong place. That is not the hidden field ShellSurface argues against — that one would be a second copy of "which page"; this is a tab remembering its own. THE HOSTS SCREEN IS A GRID, and the 268-pixel sidebar is gone. That column was choosing among forty machines and editing one of them at two-thirds width, and it was narrow so the editor beneath it could be a column at all. Cards took the first job at full width; a 304-pixel drawer took the second and collapses when nothing is selected. Pressing a group card narrows the grid; SHOW ALL is the way back. The group editor moved into the drawer as well, which finally makes IsEditingGroup mean the same thing on both heads — it was the phone's alone, because the desktop's editor was a bar that was always on screen. AreHostsExpanded and ToggleHosts went with the control that used them. They folded the whole list away under one heading, an affordance that existed because the column was narrow. Folding a single group is a different thing and is still here. THE TYPE SCALE IS A POINT LARGER and the text ramp is white. The base size was never stated anywhere — a bare TextBlock took TextElement's default of 12 — so raising the scale meant naming it, on Window and on UserControl. The second selector is not redundancy: the layout harness hosts a UserControl in a window it builds itself, and without it the suite would measure every screen a point smaller than it ships, silently. A selector on TextBlock would have been the obvious way and is wrong, because a style setter beats an inherited value and would collapse every deliberate step back to one number. #E3E7F4 is a blue-tinted white on blue-black surfaces, which costs contrast twice — once for being darker than white and once for sharing a hue with what it is drawn on. Pure white is 18.3:1 against the canvas where that was 15.5:1. Every step below moved with the top, so the intervals the design chose are kept and TextDim clears 9:1 against 6.4:1. The palette is shared, so the phone has both changes too. TWO DEFECTS THE HARNESS STRUCTURALLY CANNOT SEE, found by rendering the screen rather than by measuring it, and both now covered. The tile was 232 and was first written as 248, from arithmetic that left out the scrolling stack's own margins. Every layout test passed — the harness asks whether a control is inside the window, never how many fit on a line — so the grid quietly became one column wide at exactly the minimum this application guarantees, which is the shape cards exist to avoid. TheHostsGridKeepsTwoColumnsAtTheMinimumWithTheDrawerOpen counts columns instead, and fails at 248. And a card's text ran past its own border, because a horizontal StackPanel measures children with infinite width: a TextBlock inside one never learns it is short of room, so TextTrimming never fires. Both card rows are grids with a star column that gives way and an Auto column that does not — a hostname with its tail cut is still the machine you were looking for, where a badge or the word naming an auth method is not. The keychain header changed shape for the same class of reason. It was Auto,Auto,*,Auto with the buttons last, so the slack column was the only thing absorbing a change of width and five buttons fell off the right edge the moment the type grew. That is how GENERATE lost the word KEY once already. The summary sits in the star column and trims now, so the buttons always get their width. HostSidebarTests became HostGridTests and moved to the grid with the gestures it drives. docs/design-import-gaps.md gains a v3 section naming the five toolbar controls in the design with nothing behind them — a view-mode switch, a tag filter, a calendar, a share control and Serial — and manual-checks.md and the README follow the controls that moved.
This commit is contained in:
@@ -35,13 +35,40 @@
|
||||
wraps in the application and does not wrap in the harness makes every measured height too small, which
|
||||
is the one way this kind of test lies quietly.
|
||||
-->
|
||||
<!--
|
||||
◆ THE BASE SIZE, and it is set here rather than on the window.
|
||||
|
||||
Every explicit FontSize below is a step off a base nothing was stating: a bare TextBlock took
|
||||
TextElement's own default of 12, which meant the one number the whole scale is measured from lived in
|
||||
Avalonia rather than in this file. Raising the scale meant naming it.
|
||||
|
||||
Declared on Window *and* on UserControl, which is not redundancy. FontSize inherits, so the window
|
||||
alone would reach everything the application draws — but the layout harness hosts a UserControl in a
|
||||
plain `new Window()` it constructs itself, and that window has no style of this application's on it.
|
||||
Without the second selector the harness would measure every screen a point smaller than it ships,
|
||||
which is the failure mode App.axaml's own note at the top of this block was written about: a test that
|
||||
lays out text smaller than the application does reports heights that are all slightly too small, and
|
||||
it does it silently.
|
||||
|
||||
A selector on TextBlock would have been the obvious way and is wrong. Style setters beat inherited
|
||||
values in Avalonia, so `Selector="TextBlock"` would win over the size a Button sets on itself and
|
||||
reach the TextBlock inside that button's template — collapsing every deliberate step below back to one
|
||||
number.
|
||||
-->
|
||||
<Style Selector="Window">
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
</Style>
|
||||
<Style Selector="UserControl">
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="TextBlock.hint">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
|
||||
<Setter Property="TextWrapping" Value="Wrap" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.heading">
|
||||
<Setter Property="Foreground" Value="{StaticResource Text}" />
|
||||
<Setter Property="FontSize" Value="18" />
|
||||
<Setter Property="FontSize" Value="19" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
</Style>
|
||||
<Style Selector="Border.card">
|
||||
@@ -74,7 +101,7 @@
|
||||
-->
|
||||
<Style Selector="TextBlock.label">
|
||||
<Setter Property="FontFamily" Value="{StaticResource MonoFont}" />
|
||||
<Setter Property="FontSize" Value="10" />
|
||||
<Setter Property="FontSize" Value="11" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="LetterSpacing" Value="1.2" />
|
||||
<Setter Property="Foreground" Value="{StaticResource TextFaint}" />
|
||||
@@ -93,7 +120,7 @@
|
||||
</Style>
|
||||
<Style Selector="Border.chip > TextBlock">
|
||||
<Setter Property="FontFamily" Value="{StaticResource MonoFont}" />
|
||||
<Setter Property="FontSize" Value="10" />
|
||||
<Setter Property="FontSize" Value="11" />
|
||||
<Setter Property="FontWeight" Value="Medium" />
|
||||
<Setter Property="LetterSpacing" Value="0.5" />
|
||||
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
|
||||
@@ -215,7 +242,7 @@
|
||||
<!-- Every button in this window is small, mono and tracked out; only the colours differ. -->
|
||||
<Style Selector="Button.ghost, Button.accent, Button.danger">
|
||||
<Setter Property="FontFamily" Value="{StaticResource MonoFont}" />
|
||||
<Setter Property="FontSize" Value="10.5" />
|
||||
<Setter Property="FontSize" Value="11.5" />
|
||||
<Setter Property="FontWeight" Value="SemiBold" />
|
||||
<Setter Property="LetterSpacing" Value="0.8" />
|
||||
<Setter Property="Padding" Value="10,5" />
|
||||
@@ -259,7 +286,7 @@
|
||||
<Setter Property="HorizontalAlignment" Value="Stretch" />
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="FontFamily" Value="{StaticResource MonoFont}" />
|
||||
<Setter Property="FontSize" Value="10" />
|
||||
<Setter Property="FontSize" Value="11" />
|
||||
<Setter Property="FontWeight" Value="Medium" />
|
||||
<Setter Property="LetterSpacing" Value="0.5" />
|
||||
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
|
||||
@@ -289,7 +316,7 @@
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="FontWeight" Value="Medium" />
|
||||
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
|
||||
</Style>
|
||||
@@ -315,7 +342,7 @@
|
||||
because a number that lit with its row would compete with the word beside it for the same emphasis.
|
||||
-->
|
||||
<Style Selector="TextBlock.navicon">
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="Width" Value="20" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
@@ -325,7 +352,7 @@
|
||||
</Style>
|
||||
<Style Selector="TextBlock.navcount">
|
||||
<Setter Property="FontFamily" Value="{StaticResource MonoFont}" />
|
||||
<Setter Property="FontSize" Value="10" />
|
||||
<Setter Property="FontSize" Value="11" />
|
||||
<Setter Property="Foreground" Value="{StaticResource TextFaint}" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
@@ -343,7 +370,7 @@
|
||||
<Setter Property="Margin" Value="0,0,6,0" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="FontWeight" Value="Medium" />
|
||||
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
|
||||
</Style>
|
||||
@@ -375,6 +402,19 @@
|
||||
<Setter Property="Foreground" Value="{StaticResource Text}" />
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
One of the strip's three fixed tabs — Vaults, SFTP, S3. A pill in every respect except that it has no
|
||||
close box, so it takes its padding back on the right: the base rule is short there to leave room for
|
||||
the cross a terminal tab carries inside itself, and a fixed tab with the same asymmetry sits visibly
|
||||
off-centre beside one that has a reason for it.
|
||||
|
||||
Nothing else differs, deliberately. These are tabs and have to read as tabs — the whole point of the
|
||||
strip is that "where the window is" is one row of one kind of control.
|
||||
-->
|
||||
<Style Selector="Button.tab.fixed">
|
||||
<Setter Property="Padding" Value="12,0" />
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
The button that opens a connection. A tab in every respect but the marks a tab carries: no active
|
||||
state, because it is never the thing showing, and no outline, because it is not one of the things
|
||||
@@ -411,7 +451,7 @@
|
||||
<Style Selector="Button.choice">
|
||||
<Setter Property="Padding" Value="10,5" />
|
||||
<Setter Property="FontFamily" Value="{StaticResource MonoFont}" />
|
||||
<Setter Property="FontSize" Value="9.5" />
|
||||
<Setter Property="FontSize" Value="10.5" />
|
||||
<Setter Property="LetterSpacing" Value="0.5" />
|
||||
<Setter Property="Foreground" Value="{StaticResource TextFaint}" />
|
||||
</Style>
|
||||
@@ -461,9 +501,9 @@
|
||||
<Setter Property="Foreground" Value="{StaticResource Text}" />
|
||||
<Setter Property="SelectionBrush" Value="{StaticResource AccentSoft}" />
|
||||
<Setter Property="CaretBrush" Value="{StaticResource Accent}" />
|
||||
<Setter Property="MinHeight" Value="28" />
|
||||
<Setter Property="MinHeight" Value="30" />
|
||||
<Setter Property="Padding" Value="8,4" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
</Style>
|
||||
<Style Selector="TextBox /template/ Border#PART_BorderElement">
|
||||
<Setter Property="Background" Value="{StaticResource Field}" />
|
||||
@@ -512,6 +552,76 @@
|
||||
<Setter Property="Background" Value="{StaticResource AccentWash}" />
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
◆ A LIST OF TILES, which is the hosts screen's grid of group and host cards.
|
||||
|
||||
The three rules above paint the *item* — a full-bleed rectangle behind whatever the template draws —
|
||||
and that is right for a row and wrong for a card: a square wash behind a 10-pixel-rounded tile shows
|
||||
as four grey corners, and it does it on hover as well as on selection, which is most of the time the
|
||||
pointer is anywhere near the grid. So a tiles list clears all three and the tile paints its own
|
||||
states.
|
||||
|
||||
Declared after them and not before. Avalonia has no specificity: two rules matching one element are
|
||||
settled by declaration order, so an exception stated above the rule it excepts does nothing at all.
|
||||
That trap is recorded twice more in this file, for Button.tab and for Border.rowmark.
|
||||
-->
|
||||
<Style Selector="ListBox.tiles > ListBoxItem:pointerover /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
<Style Selector="ListBox.tiles > ListBoxItem:selected /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
<Style Selector="ListBox.tiles > ListBoxItem:selected:pointerover /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
The card itself. A fixed width and a free height, which is the pair that makes a WrapPanel of these
|
||||
into a grid: equal columns, and a card that grew a third line of tags is taller than its neighbours
|
||||
rather than narrower.
|
||||
|
||||
◆ 232 IS DERIVED, and the arithmetic is written out because getting it wrong is invisible. The grid's
|
||||
column at the window's minimum is 1016 less the rail's 190 and the drawer's 304, which is 522. The
|
||||
scrolling stack inside it takes 16 of margin on each side, and the vertical scrollbar takes its own —
|
||||
call the usable width 490. A WrapPanel fits floor(490 / (Width + 10)) per row, so two columns needs
|
||||
Width no more than 235.
|
||||
|
||||
The first number here was 248, from the same reasoning with the two margins left out. It laid out
|
||||
cleanly and the layout harness passed it, because the harness asks whether a control is inside the
|
||||
window and not how many of them fit on a line — so the grid quietly became one column wide at exactly
|
||||
the size this application guarantees, which is the shape the cards exist to avoid.
|
||||
-->
|
||||
<Style Selector="Border.tile">
|
||||
<Setter Property="Background" Value="{StaticResource Raised}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource Border}" />
|
||||
<Setter Property="BorderThickness" Value="1" />
|
||||
<Setter Property="CornerRadius" Value="10" />
|
||||
<Setter Property="Padding" Value="12,10" />
|
||||
<Setter Property="Width" Value="232" />
|
||||
<Setter Property="Margin" Value="0,0,10,10" />
|
||||
</Style>
|
||||
<Style Selector="ListBoxItem:pointerover Border.tile">
|
||||
<Setter Property="BorderBrush" Value="{StaticResource BorderHover}" />
|
||||
</Style>
|
||||
<!--
|
||||
Selected is the accent outline *and* the filled surface, which is the same pair the nav rail and the
|
||||
tab strip use for "you are here". A tile marked by its border alone is legible on a card you are
|
||||
looking at and invisible in peripheral vision, which is where a selected card usually is once the
|
||||
drawer beside it has opened.
|
||||
-->
|
||||
<Style Selector="ListBoxItem:selected Border.tile">
|
||||
<Setter Property="Background" Value="{StaticResource Active}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource Accent}" />
|
||||
</Style>
|
||||
|
||||
<!-- The square a tile carries on its left: a group's mark, or a host's prompt. -->
|
||||
<Style Selector="Border.tileicon">
|
||||
<Setter Property="Width" Value="32" />
|
||||
<Setter Property="Height" Value="32" />
|
||||
<Setter Property="CornerRadius" Value="8" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
The status dot, in one place rather than as a converter in code.
|
||||
|
||||
@@ -558,7 +668,7 @@
|
||||
|
||||
Set from the code-behind rather than by a binding, for the reason the whole gesture is code: the rows
|
||||
are rebuilt from scratch on every filter keystroke and every sync pass, so a flag on the view model
|
||||
would be state the list throws away halfway through the drag. See HostSidebar.axaml.cs.
|
||||
would be state the list throws away halfway through the drag. See HostsScreen.axaml.cs.
|
||||
-->
|
||||
<Style Selector="ListBoxItem.droptarget /template/ ContentPresenter#PART_ContentPresenter">
|
||||
<Setter Property="Background" Value="{StaticResource AccentWash}" />
|
||||
@@ -577,7 +687,7 @@
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
</Style>
|
||||
<Style Selector="MenuItem">
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="Foreground" Value="{StaticResource Text}" />
|
||||
</Style>
|
||||
|
||||
@@ -602,16 +712,16 @@
|
||||
<Setter Property="BorderBrush" Value="{StaticResource Border}" />
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
<Setter Property="Foreground" Value="{StaticResource Text}" />
|
||||
<Setter Property="MinHeight" Value="28" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="MinHeight" Value="30" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
</Style>
|
||||
<Style Selector="NumericUpDown">
|
||||
<Setter Property="Background" Value="{StaticResource Field}" />
|
||||
<Setter Property="BorderBrush" Value="{StaticResource Border}" />
|
||||
<Setter Property="CornerRadius" Value="4" />
|
||||
<Setter Property="Foreground" Value="{StaticResource Text}" />
|
||||
<Setter Property="MinHeight" Value="28" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="MinHeight" Value="30" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
</Style>
|
||||
<!--
|
||||
The foreground goes on the content presenter as well as on the control, for the same reason the
|
||||
@@ -621,7 +731,7 @@
|
||||
-->
|
||||
<Style Selector="CheckBox">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
|
||||
<Setter Property="FontSize" Value="12" />
|
||||
<Setter Property="FontSize" Value="13" />
|
||||
<Setter Property="MinHeight" Value="0" />
|
||||
</Style>
|
||||
<Style Selector="CheckBox /template/ ContentPresenter#PART_ContentPresenter">
|
||||
|
||||
Reference in New Issue
Block a user