Files
PLib/src/PLib.Desktop/Themes/LibraryStyles.axaml
T

333 lines
14 KiB
XML

<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:PLib.Desktop.Controls">
<!-- ============================ Card ============================ -->
<!--
The card is a Button so that keyboard focus, Enter/Space and the pointer all activate it
for free. Its template is reduced to a single surface Border because the Semi button
chrome would fight the artwork.
-->
<Style Selector="Button.card">
<Setter Property="Padding" Value="0" />
<Setter Property="Background" Value="Transparent" />
<!-- Without these the card keeps its desired size inside the grid cell the layout
hands it, which leaves the cards small and the grid full of gaps. -->
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="RenderTransform" Value="none" />
<Setter Property="Transitions">
<Transitions>
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.16" Easing="CubicEaseOut" />
</Transitions>
</Setter>
<Setter Property="Template">
<ControlTemplate>
<Border Name="PART_Surface"
Background="{DynamicResource CardBackgroundBrush}"
BorderBrush="{DynamicResource CardBorderBrush}"
BorderThickness="1"
CornerRadius="14"
Padding="8,8,8,10">
<Border.Transitions>
<Transitions>
<BrushTransition Property="BorderBrush" Duration="0:0:0.16" />
</Transitions>
</Border.Transitions>
<ContentPresenter Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch" />
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="Button.card:pointerover">
<Setter Property="RenderTransform" Value="scale(1.025)" />
</Style>
<Style Selector="Button.card:pointerover /template/ Border#PART_Surface">
<Setter Property="BorderBrush" Value="{DynamicResource CardHoverBorderBrush}" />
</Style>
<Style Selector="Button.card:pressed">
<Setter Property="RenderTransform" Value="scale(0.99)" />
</Style>
<Style Selector="Button.card:focus-visible /template/ Border#PART_Surface">
<Setter Property="BorderBrush" Value="{DynamicResource AccentBrush}" />
</Style>
<!-- Play affordance: invisible until the pointer is over the card. -->
<Style Selector="Border.playOverlay">
<Setter Property="Opacity" Value="0" />
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Opacity" Duration="0:0:0.16" Easing="CubicEaseOut" />
</Transitions>
</Setter>
</Style>
<Style Selector="Button.card:pointerover Border.playOverlay">
<Setter Property="Opacity" Value="1" />
</Style>
<!--
The animated preview follows the same hover state as the play affordance, rather than
watching the pointer itself: the pointer is over the card even while it is over the
caption, and a preview that stopped when the pointer crossed the title would flicker.
-->
<Style Selector="Button.card:pointerover controls|FilmstripImage">
<Setter Property="IsPlaying" Value="True" />
</Style>
<!-- ========================== Navigation ========================== -->
<!--
Tabs are buttons rather than a TabControl: the pages they switch between are columns of a
layout that also holds the settings panel and the media page, and a TabControl would want
to own that arrangement.
-->
<Style Selector="Button.sectionTab">
<Setter Property="Padding" Value="12,6" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="CornerRadius" Value="8" />
<Setter Property="FontSize" Value="12.5" />
<Setter Property="Foreground" Value="{DynamicResource TextSecondaryBrush}" />
</Style>
<Style Selector="Button.sectionTab:pointerover">
<Setter Property="Foreground" Value="{DynamicResource TextPrimaryBrush}" />
</Style>
<Style Selector="Button.sectionTab.active">
<Setter Property="Background" Value="{DynamicResource AccentSoftBrush}" />
<Setter Property="Foreground" Value="{DynamicResource AccentBrush}" />
<Setter Property="FontWeight" Value="SemiBold" />
</Style>
<!--
A row of controls that belongs to the page below it rather than to the window. Lighter
than the window bars on purpose: it sits inside the content, and giving it the same weight
would make the window read as three stacked strips of chrome.
-->
<Style Selector="Border.filterBar, Border.navBar">
<Setter Property="Padding" Value="20,9" />
<Setter Property="BorderBrush" Value="{DynamicResource SurfaceBorderBrush}" />
<Setter Property="BorderThickness" Value="0,0,0,1" />
</Style>
<!--
Also used by the task panel and the filter bar, which had been asking for it since before
it existed — the class was on the buttons with nothing behind it.
-->
<Style Selector="Button.transport">
<Setter Property="Padding" Value="8" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Foreground" Value="{DynamicResource TextPrimaryBrush}" />
</Style>
<!-- One tag, performer, studio or collection in a browsing tab. -->
<Style Selector="Button.entity">
<Setter Property="Padding" Value="8,8,8,10" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Background" Value="{DynamicResource CardBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource CardBorderBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="12" />
</Style>
<Style Selector="Button.entity:pointerover">
<Setter Property="BorderBrush" Value="{DynamicResource CardHoverBorderBrush}" />
</Style>
<!-- ============================ Text ============================ -->
<Style Selector="TextBlock.cardTitle">
<Setter Property="Foreground" Value="{DynamicResource TextPrimaryBrush}" />
<Setter Property="FontSize" Value="13" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="LineHeight" Value="18" />
<Setter Property="MaxLines" Value="2" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
</Style>
<Style Selector="TextBlock.cardMeta">
<Setter Property="Foreground" Value="{DynamicResource TextTertiaryBrush}" />
<Setter Property="FontSize" Value="11.5" />
</Style>
<Style Selector="TextBlock.sectionTitle">
<Setter Property="Foreground" Value="{DynamicResource TextPrimaryBrush}" />
<Setter Property="FontSize" Value="17" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style Selector="TextBlock.subtle">
<Setter Property="Foreground" Value="{DynamicResource TextSecondaryBrush}" />
<Setter Property="FontSize" Value="12.5" />
</Style>
<!-- ========================= Window bars ========================= -->
<!--
The library and the settings panel sit side by side, so their top and bottom bars have to
line up: the separators read as one continuous line across the window. Fixing the heights
here, in one place, is what keeps them from drifting apart as either side gains controls.
-->
<Style Selector="Border.appBar">
<Setter Property="Height" Value="62" />
<Setter Property="Padding" Value="20,0" />
<Setter Property="Background" Value="{DynamicResource SurfaceBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource SurfaceBorderBrush}" />
<Setter Property="BorderThickness" Value="0,0,0,1" />
</Style>
<Style Selector="Border.statusBar">
<Setter Property="Height" Value="50" />
<Setter Property="Padding" Value="20,0" />
<Setter Property="Background" Value="{DynamicResource SurfaceBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource SurfaceBorderBrush}" />
<Setter Property="BorderThickness" Value="0,1,0,0" />
</Style>
<!--
The panel's own header and action row. Deliberately lighter than the window bars above:
they belong to a region inside the content, and giving them the same weight made the two
halves read as two applications stitched together.
-->
<Style Selector="Border.panelHeader">
<Setter Property="Padding" Value="16,13" />
<Setter Property="BorderBrush" Value="{DynamicResource SurfaceBorderBrush}" />
<Setter Property="BorderThickness" Value="0,0,0,1" />
</Style>
<Style Selector="Border.panelFooter">
<Setter Property="Padding" Value="16,12" />
<Setter Property="BorderBrush" Value="{DynamicResource SurfaceBorderBrush}" />
<Setter Property="BorderThickness" Value="0,1,0,0" />
</Style>
<Style Selector="TextBlock.panelTitle">
<Setter Property="Foreground" Value="{DynamicResource TextPrimaryBrush}" />
<Setter Property="FontSize" Value="14" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="VerticalAlignment" Value="Center" />
</Style>
<!-- ======================== Settings panel ======================== -->
<!--
The panel is a column of the layout rather than an overlay, so opening it squeezes the
grid instead of covering it. Width is animated because Avalonia has no transition for
GridLength; the content inside keeps its full width and is simply clipped while the
column grows, which stops the whole panel reflowing on every animation frame.
-->
<Style Selector="Border.settingsPanel">
<Setter Property="Width" Value="0" />
<Setter Property="ClipToBounds" Value="True" />
<!-- Its own backdrop, so the panel reads as a separate region even where the bars on
both sides share a colour. The divider itself is a sibling element, not this
border: a border belongs to the panel and is only as visible as the panel's own
background, whereas the separation has to hold across the bars too. -->
<Setter Property="Background" Value="{DynamicResource PanelBackgroundBrush}" />
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Width" Duration="0:0:0.22" Easing="CubicEaseOut" />
</Transitions>
</Setter>
</Style>
<Style Selector="Border.settingsPanel.open">
<Setter Property="Width" Value="400" />
</Style>
<!--
Drawn after the panel and over both bars, so nothing can paint across it. This is the
one line that tells the eye where the library ends and the settings begin.
-->
<Style Selector="Rectangle.panelDivider">
<Setter Property="Width" Value="1" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="Fill" Value="{DynamicResource PanelDividerBrush}" />
</Style>
<!-- ========================== Task panel ========================== -->
<!--
Anchored to the bottom-right corner above the status bar. Kept in the tree and hidden by
opacity so the slide has something to animate from, the same trick the settings panel uses.
-->
<Style Selector="Border.taskPanel">
<Setter Property="Width" Value="330" />
<Setter Property="Margin" Value="0,0,16,8" />
<Setter Property="HorizontalAlignment" Value="Right" />
<Setter Property="VerticalAlignment" Value="Bottom" />
<Setter Property="Background" Value="{DynamicResource SurfaceBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource PanelDividerBrush}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="CornerRadius" Value="12" />
<Setter Property="Padding" Value="14,12" />
<Setter Property="Opacity" Value="0" />
<Setter Property="IsHitTestVisible" Value="False" />
<Setter Property="RenderTransform" Value="translateY(10px)" />
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Opacity" Duration="0:0:0.16" Easing="CubicEaseOut" />
<TransformOperationsTransition Property="RenderTransform" Duration="0:0:0.18" Easing="CubicEaseOut" />
</Transitions>
</Setter>
</Style>
<Style Selector="Border.taskPanel.open">
<Setter Property="Opacity" Value="1" />
<Setter Property="IsHitTestVisible" Value="True" />
<Setter Property="RenderTransform" Value="none" />
</Style>
<!--
Says where a picture came from. Every frame on the metadata page carries one: the page
exists to decide whether a proposal is the same video as the file, and two unlabelled
frames side by side make that decision impossible to state, let alone make.
-->
<Style Selector="TextBlock.imageCaption">
<Setter Property="FontSize" Value="10.5" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="MaxWidth" Value="128" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="Foreground" Value="{DynamicResource TextTertiaryBrush}" />
</Style>
<Style Selector="TextBlock.taskTitle">
<Setter Property="Foreground" Value="{DynamicResource TextPrimaryBrush}" />
<Setter Property="FontSize" Value="12.5" />
</Style>
<!-- ============================ Badge ============================ -->
<Style Selector="Border.badge">
<Setter Property="Background" Value="{DynamicResource BadgeBackgroundBrush}" />
<Setter Property="CornerRadius" Value="6" />
<Setter Property="Padding" Value="6,2" />
</Style>
<Style Selector="Border.badge > TextBlock">
<Setter Property="Foreground" Value="{DynamicResource BadgeForegroundBrush}" />
<Setter Property="FontSize" Value="11" />
<Setter Property="FontWeight" Value="SemiBold" />
</Style>
</Styles>