Skip to main content

Overview

Flowery.Uno provides a comprehensive size system based on DaisySize enum, allowing controls to adapt to different screen sizes and device types. This guide covers the size system, responsive patterns, and mobile-specific considerations.

DaisySize System

The DaisySize enum provides five standard size variants:
public enum DaisySize
{
    ExtraSmall,  // Compact, dense UIs
    Small,       // Mobile-friendly
    Medium,      // Default size
    Large,       // Desktop optimized
    ExtraLarge   // Large displays
}

Default Size

Most controls default to DaisySize.Medium, which provides a balanced experience across platforms.
<!-- Default: Medium -->
<daisy:DaisyButton Content="Default Size" />

<!-- Explicit size -->
<daisy:DaisyButton Content="Large Button" Size="Large" />

Size Tokens

Touch Target Heights

Flowery.Uno enforces mobile-friendly minimum touch targets on mobile platforms:
SizeDesktop HeightMobile Height
ExtraSmall24px36px
Small28px40px
Medium32px44px
Large36px48px
ExtraLarge40px56px
Mobile touch targets meet accessibility guidelines (minimum 44px for tappable elements).

Icon Sizes

SizeIcon Dimension
ExtraSmall8px
Small12px
Medium16px
Large20px
ExtraLarge24px

Spacing

SizeSpacing
ExtraSmall4px
Small4px
Medium8px
Large8px
ExtraLarge8px

Font Sizes

Based on a 4px grid for consistent vertical rhythm:
SizeFont SizeLine Height
ExtraSmall20pxTight
Small21pxNormal
Medium22pxNormal
Large24pxRelaxed
ExtraLarge26pxRelaxed

Responsive Patterns

Pattern 1: Size Binding

Bind control size to a view model property for centralized control:
<StackPanel>
    <!-- Size selector -->
    <daisy:DaisySizeDropdown SelectedSize="{x:Bind ViewModel.CurrentSize, Mode=TwoWay}" />
    
    <!-- Controls adapt automatically -->
    <daisy:DaisyButton Content="Adaptive Button" 
                       Size="{x:Bind ViewModel.CurrentSize, Mode=OneWay}" />
    <daisy:DaisyInput PlaceholderText="Type here" 
                      Size="{x:Bind ViewModel.CurrentSize, Mode=OneWay}" />
</StackPanel>
public class MainViewModel : INotifyPropertyChanged
{
    private DaisySize _currentSize = DaisySize.Medium;
    
    public DaisySize CurrentSize
    {
        get => _currentSize;
        set
        {
            if (_currentSize != value)
            {
                _currentSize = value;
                OnPropertyChanged();
            }
        }
    }
}

Pattern 2: Platform-Specific Sizing

Use conditional compilation or runtime checks for platform-specific sizes:
public DaisySize GetPlatformSize()
{
#if __ANDROID__ || __IOS__
    return DaisySize.Large;  // Touch-friendly on mobile
#elif __WASM__
    return DaisySize.Medium; // Balanced for web
#else
    return DaisySize.Small;  // Compact for desktop
#endif
}

Pattern 3: Adaptive Window Size

Adjust control size based on window width:
public class AdaptiveViewModel : INotifyPropertyChanged
{
    private double _windowWidth;
    
    public DaisySize CurrentSize => _windowWidth switch
    {
        < 640 => DaisySize.Small,      // Mobile
        < 1024 => DaisySize.Medium,    // Tablet
        < 1440 => DaisySize.Large,     // Desktop
        _ => DaisySize.ExtraLarge      // Large displays
    };
    
    public double WindowWidth
    {
        get => _windowWidth;
        set
        {
            if (_windowWidth != value)
            {
                _windowWidth = value;
                OnPropertyChanged();
                OnPropertyChanged(nameof(CurrentSize));
            }
        }
    }
}

Pattern 4: Visual State Manager

Use Visual State Manager for responsive layouts:
<Grid>
    <VisualStateManager.VisualStateGroups>
        <VisualStateGroup>
            <VisualState x:Name="Mobile">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="0" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="PrimaryButton.Size" Value="Large" />
                    <Setter Target="NavPanel.Orientation" Value="Vertical" />
                </VisualState.Setters>
            </VisualState>
            <VisualState x:Name="Desktop">
                <VisualState.StateTriggers>
                    <AdaptiveTrigger MinWindowWidth="1024" />
                </VisualState.StateTriggers>
                <VisualState.Setters>
                    <Setter Target="PrimaryButton.Size" Value="Medium" />
                    <Setter Target="NavPanel.Orientation" Value="Horizontal" />
                </VisualState.Setters>
            </VisualState>
        </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    
    <StackPanel x:Name="NavPanel">
        <daisy:DaisyButton x:Name="PrimaryButton" Content="Adaptive" />
    </StackPanel>
</Grid>

Control-Specific Sizing

Buttons

<StackPanel Spacing="8">
    <daisy:DaisyButton Content="Extra Small" Size="ExtraSmall" Variant="Primary" />
    <daisy:DaisyButton Content="Small" Size="Small" Variant="Primary" />
    <daisy:DaisyButton Content="Medium" Size="Medium" Variant="Primary" />
    <daisy:DaisyButton Content="Large" Size="Large" Variant="Primary" />
    <daisy:DaisyButton Content="Extra Large" Size="ExtraLarge" Variant="Primary" />
</StackPanel>

Inputs

<StackPanel Spacing="12">
    <daisy:DaisyInput PlaceholderText="Extra Small Input" 
                      Size="ExtraSmall" Variant="Bordered" />
    <daisy:DaisyInput PlaceholderText="Small Input" 
                      Size="Small" Variant="Bordered" />
    <daisy:DaisyInput PlaceholderText="Medium Input (Default)" 
                      Size="Medium" Variant="Bordered" />
    <daisy:DaisyInput PlaceholderText="Large Input" 
                      Size="Large" Variant="Bordered" />
    <daisy:DaisyInput PlaceholderText="Extra Large Input" 
                      Size="ExtraLarge" Variant="Bordered" />
</StackPanel>

Toggles

<StackPanel Spacing="12">
    <daisy:DaisyToggle Header="Extra Small" Size="ExtraSmall" Variant="Primary" />
    <daisy:DaisyToggle Header="Small" Size="Small" Variant="Primary" />
    <daisy:DaisyToggle Header="Medium" Size="Medium" Variant="Primary" />
    <daisy:DaisyToggle Header="Large" Size="Large" Variant="Primary" />
    <daisy:DaisyToggle Header="Extra Large" Size="ExtraLarge" Variant="Primary" />
</StackPanel>
Mobile Touch Targets: On mobile platforms, DaisyToggle enforces minimum touch targets even for smaller sizes to maintain accessibility.

Mobile-Specific Considerations

Platform Detection

Flowery.Uno automatically detects mobile platforms and adjusts touch targets:
// Internal platform detection (simplified)
if (PlatformCompatibility.IsMobile)
{
    // Use mobile-optimized touch targets (minimum 44px)
    minHeight = 44;
}
else
{
    // Use desktop-optimized compact sizes
    minHeight = 32;
}

Touch-Friendly Spacing

Increase spacing between interactive elements on mobile:
<StackPanel Spacing="{x:Bind GetMobileSpacing()}">
    <daisy:DaisyButton Content="Action 1" Size="Large" />
    <daisy:DaisyButton Content="Action 2" Size="Large" />
    <daisy:DaisyButton Content="Action 3" Size="Large" />
</StackPanel>
public double GetMobileSpacing()
{
#if __ANDROID__ || __IOS__
    return 16; // Generous spacing for touch
#else
    return 8;  // Compact for mouse/keyboard
#endif
}

Orientation Changes

Handle orientation changes gracefully:
public void OnOrientationChanged(bool isLandscape)
{
    if (isLandscape)
    {
        // Landscape: More horizontal space, use compact sizes
        ButtonSize = DaisySize.Small;
        PanelOrientation = Orientation.Horizontal;
    }
    else
    {
        // Portrait: Limited horizontal space, use larger sizes
        ButtonSize = DaisySize.Large;
        PanelOrientation = Orientation.Vertical;
    }
}

Breakpoint Strategies

Common Breakpoints

BreakpointWidthRecommended Size
Mobile< 640pxLarge or ExtraLarge
Tablet640px - 1024pxMedium or Large
Desktop1024px - 1440pxSmall or Medium
Large Display> 1440pxMedium or Large

Breakpoint Helper

public static class ResponsiveHelper
{
    public static DaisySize GetSizeForWidth(double width)
    {
        return width switch
        {
            < 640 => DaisySize.Large,      // Mobile: touch-friendly
            < 1024 => DaisySize.Medium,    // Tablet: balanced
            < 1440 => DaisySize.Small,     // Desktop: compact
            _ => DaisySize.Medium          // Large: comfortable
        };
    }
    
    public static double GetSpacingForWidth(double width)
    {
        return width switch
        {
            < 640 => 16,   // Mobile: generous
            < 1024 => 12,  // Tablet: balanced
            _ => 8         // Desktop: compact
        };
    }
}

Global Size Control

DaisySizeDropdown

Provide a global size selector for users:
<daisy:DaisySizeDropdown SelectedSize="{x:Bind ViewModel.GlobalSize, Mode=TwoWay}" 
                         MinWidth="200" />
The dropdown includes localized size names in 12 languages.

Application-Wide Size

Store and persist user’s size preference:
public class AppSettings
{
    private const string SizeKey = "GlobalSize";
    
    public static DaisySize LoadSize()
    {
        var value = ApplicationData.Current.LocalSettings.Values[SizeKey];
        if (value is int sizeInt && Enum.IsDefined(typeof(DaisySize), sizeInt))
        {
            return (DaisySize)sizeInt;
        }
        return DaisySize.Medium;
    }
    
    public static void SaveSize(DaisySize size)
    {
        ApplicationData.Current.LocalSettings.Values[SizeKey] = (int)size;
    }
}

Layout Containers

Adaptive Grid

Create responsive grid layouts:
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>
    
    <!-- Sidebar: Collapses on mobile -->
    <StackPanel x:Name="Sidebar" 
                Grid.Column="0" 
                Visibility="{x:Bind IsDesktop, Mode=OneWay}">
        <!-- Sidebar content -->
    </StackPanel>
    
    <!-- Main content: Full width on mobile -->
    <ScrollViewer Grid.Column="1">
        <!-- Main content -->
    </ScrollViewer>
</Grid>

Adaptive StackPanel

Switch between vertical and horizontal layouts:
<StackPanel Orientation="{x:Bind LayoutOrientation, Mode=OneWay}" 
            Spacing="{x:Bind LayoutSpacing, Mode=OneWay}">
    <daisy:DaisyButton Content="Action 1" />
    <daisy:DaisyButton Content="Action 2" />
    <daisy:DaisyButton Content="Action 3" />
</StackPanel>
public Orientation LayoutOrientation => WindowWidth < 640 
    ? Orientation.Vertical 
    : Orientation.Horizontal;

public double LayoutSpacing => WindowWidth < 640 ? 16 : 8;

Best Practices

1

Start with Medium size as default

Use DaisySize.Medium as the baseline and adjust for specific scenarios.
2

Use Large/ExtraLarge on mobile

Ensure touch targets meet minimum 44px height for accessibility on mobile devices.
3

Test on multiple screen sizes

Verify your UI works on phones (< 640px), tablets (640-1024px), and desktops (> 1024px).
4

Provide user control

Consider adding a DaisySizeDropdown in settings to let users choose their preferred size.
5

Use consistent spacing

Match spacing to control size for visual harmony.
Mobile-First Approach: Design for mobile first with touch-friendly sizes, then scale down for desktop.

Troubleshooting

Controls Too Small on Mobile

Cause: Using ExtraSmall or Small sizes on touch devices. Solution: Use Large or ExtraLarge on mobile, or rely on automatic mobile touch target enforcement.

Inconsistent Sizes Across Controls

Cause: Mixing explicit sizes without a centralized binding. Solution: Bind all control sizes to a single view model property.

Layout Doesn’t Adapt on Window Resize

Cause: Using static sizes instead of responsive bindings or Visual States. Solution: Implement Visual State Manager or bind sizes to a computed property based on window width.

Next Steps

Styling Guide

Learn about control customization and resource overrides

Accessibility

Build accessible UIs with proper ARIA support

Theming

Master theme switching and customization

Component Reference

Explore all available controls

Build docs developers (and LLMs) love