// DragonX Wallet - ImGui Edition // Copyright 2024-2026 The Hush Developers // Released under the GPLv3 #pragma once #include "imgui.h" namespace dragonx { namespace ui { namespace material { // ============================================================================ // Material Design 8dp Grid System // ============================================================================ // All spacing in Material Design is based on an 8dp grid. // https://m2.material.io/design/layout/spacing-methods.html constexpr float kGridUnit = 8.0f; // Base unit in dp (device-independent pixels) // ============================================================================ // Spacing Scale // ============================================================================ // Use these values for all margins, padding, and gaps namespace spacing { constexpr float Xxs = 2.0f; // 0.25x - Very tight spacing constexpr float Xs = 4.0f; // 0.5x - Extra small constexpr float Sm = 8.0f; // 1x - Small (default minimum) constexpr float Md = 16.0f; // 2x - Medium (default standard) constexpr float Lg = 24.0f; // 3x - Large constexpr float Xl = 32.0f; // 4x - Extra large constexpr float Xxl = 40.0f; // 5x - Double extra large constexpr float Xxxl = 48.0f; // 6x - Triple extra large // Multiplier helpers constexpr float Grid(float multiplier) { return kGridUnit * multiplier; } } // namespace spacing // ============================================================================ // Component Dimensions // ============================================================================ // Standard sizes for Material Design components namespace size { // Buttons constexpr float ButtonHeight = 36.0f; constexpr float ButtonMinWidth = 64.0f; constexpr float ButtonPaddingH = 16.0f; constexpr float ButtonPaddingV = 8.0f; constexpr float ButtonIconGap = 8.0f; // Gap between icon and label constexpr float ButtonCornerRadius = 4.0f; // FAB (Floating Action Button) constexpr float FabSize = 56.0f; constexpr float FabMiniSize = 40.0f; constexpr float FabExtendedHeight = 48.0f; constexpr float FabExtendedPadding = 16.0f; constexpr float FabCornerRadius = 16.0f; // Half of mini size for circle // Icons constexpr float IconSize = 24.0f; constexpr float IconSizeSm = 18.0f; constexpr float IconSizeLg = 36.0f; constexpr float IconButtonSize = 48.0f; // Touch target for icon buttons // App Bar / Toolbar constexpr float AppBarHeight = 56.0f; // Mobile constexpr float AppBarHeightLarge = 64.0f; // Desktop constexpr float AppBarPadding = 16.0f; // Navigation constexpr float NavDrawerWidth = 256.0f; constexpr float NavRailWidth = 72.0f; constexpr float NavItemHeight = 48.0f; constexpr float NavItemPadding = 12.0f; constexpr float NavSectionPadding = 8.0f; // Cards constexpr float CardCornerRadius = 4.0f; constexpr float CardPadding = 16.0f; constexpr float CardElevation = 1.0f; // Default elevation in dp // Dialogs constexpr float DialogMinWidth = 280.0f; constexpr float DialogMaxWidth = 560.0f; constexpr float DialogPadding = 24.0f; constexpr float DialogTitlePadding = 20.0f; constexpr float DialogActionGap = 8.0f; constexpr float DialogCornerRadius = 4.0f; // Lists constexpr float ListItemHeight = 48.0f; // Single line constexpr float ListItemHeightTwoLine = 64.0f; constexpr float ListItemHeightThreeLine = 88.0f; constexpr float ListItemPaddingH = 16.0f; constexpr float ListAvatarSize = 40.0f; constexpr float ListIconMargin = 32.0f; // Text Fields constexpr float TextFieldHeight = 56.0f; constexpr float TextFieldPadding = 16.0f; constexpr float TextFieldDenseHeight = 40.0f; constexpr float TextFieldCornerRadius = 4.0f; // Chips constexpr float ChipHeight = 32.0f; constexpr float ChipPaddingH = 12.0f; constexpr float ChipCornerRadius = 16.0f; // Tabs constexpr float TabHeight = 48.0f; constexpr float TabMinWidth = 90.0f; constexpr float TabMaxWidth = 360.0f; constexpr float TabPaddingH = 16.0f; constexpr float TabIndicatorHeight = 2.0f; // Snackbar constexpr float SnackbarMinWidth = 288.0f; constexpr float SnackbarMaxWidth = 568.0f; constexpr float SnackbarHeight = 48.0f; constexpr float SnackbarPadding = 8.0f; constexpr float SnackbarMargin = 8.0f; // Dividers constexpr float DividerThickness = 1.0f; constexpr float DividerInset = 16.0f; // For inset dividers } // namespace size // ============================================================================ // Responsive Breakpoints // ============================================================================ // Based on Material Design responsive layout grid namespace breakpoint { constexpr float Xs = 0.0f; // Extra small: 0-599dp constexpr float Sm = 600.0f; // Small: 600-904dp constexpr float Md = 905.0f; // Medium: 905-1239dp constexpr float Lg = 1240.0f; // Large: 1240-1439dp constexpr float Xl = 1440.0f; // Extra large: 1440dp+ // Returns the current breakpoint category enum class Category { Xs, Sm, Md, Lg, Xl }; inline Category GetCategory(float windowWidth) { if (windowWidth >= Xl) return Category::Xl; if (windowWidth >= Lg) return Category::Lg; if (windowWidth >= Md) return Category::Md; if (windowWidth >= Sm) return Category::Sm; return Category::Xs; } // Margin values for each breakpoint inline float GetMargin(Category cat) { switch (cat) { case Category::Xs: return 16.0f; case Category::Sm: return 32.0f; case Category::Md: return 32.0f; // Or fluid centering case Category::Lg: return 200.0f; case Category::Xl: return 200.0f; // Or fluid centering } return 16.0f; } // Column count for each breakpoint inline int GetColumns(Category cat) { switch (cat) { case Category::Xs: return 4; case Category::Sm: return 8; default: return 12; } } // Recommended navigation style enum class NavStyle { BottomNav, NavRail, NavDrawer }; inline NavStyle GetNavStyle(Category cat) { switch (cat) { case Category::Xs: return NavStyle::BottomNav; case Category::Sm: case Category::Md: return NavStyle::NavRail; default: return NavStyle::NavDrawer; } } } // namespace breakpoint // ============================================================================ // Layout Helpers // ============================================================================ /** * @brief Get current window's breakpoint category */ inline breakpoint::Category GetCurrentBreakpoint() { ImVec2 windowSize = ImGui::GetWindowSize(); return breakpoint::GetCategory(windowSize.x); } /** * @brief Get recommended margin for current window */ inline float GetCurrentMargin() { return breakpoint::GetMargin(GetCurrentBreakpoint()); } /** * @brief Add horizontal spacing (uses 8dp grid) * @param units Number of 8dp units (default 1) */ inline void HSpace(float units = 1.0f) { ImGui::SameLine(0, kGridUnit * units); } /** * @brief Add vertical spacing (uses 8dp grid) * @param units Number of 8dp units (default 1) */ inline void VSpace(float units = 1.0f) { ImGui::Dummy(ImVec2(0, kGridUnit * units)); } /** * @brief Begin a padded region * @param padding Padding in pixels (use spacing:: constants) */ inline void BeginPadding(float padding) { ImGui::BeginGroup(); ImGui::Dummy(ImVec2(0, padding)); ImGui::Indent(padding); } /** * @brief End a padded region * @param padding Same padding used in BeginPadding */ inline void EndPadding(float padding) { ImGui::Unindent(padding); ImGui::Dummy(ImVec2(0, padding)); ImGui::EndGroup(); } /** * @brief Center the next item horizontally within available width * @param itemWidth Width of the item to center */ inline void CenterHorizontally(float itemWidth) { float availWidth = ImGui::GetContentRegionAvail().x; float offset = (availWidth - itemWidth) * 0.5f; if (offset > 0) { ImGui::SetCursorPosX(ImGui::GetCursorPosX() + offset); } } /** * @brief Calculate column width for responsive grid * @param numColumns Number of columns to span * @param gutterWidth Gap between columns (default 16dp) */ inline float GetColumnWidth(int numColumns = 1, float gutterWidth = spacing::Md) { float availWidth = ImGui::GetContentRegionAvail().x; auto cat = GetCurrentBreakpoint(); int totalColumns = breakpoint::GetColumns(cat); float totalGutter = gutterWidth * (totalColumns - 1); float columnWidth = (availWidth - totalGutter) / totalColumns; return columnWidth * numColumns + gutterWidth * (numColumns - 1); } // ============================================================================ // Card Layout Helper // ============================================================================ struct CardLayout { float width; float minHeight; float padding; float cornerRadius; int elevation; CardLayout() : width(0) // 0 = auto width , minHeight(0) , padding(size::CardPadding) , cornerRadius(size::CardCornerRadius) , elevation(1) {} CardLayout& Width(float w) { width = w; return *this; } CardLayout& MinHeight(float h) { minHeight = h; return *this; } CardLayout& Padding(float p) { padding = p; return *this; } CardLayout& CornerRadius(float r) { cornerRadius = r; return *this; } CardLayout& Elevation(int e) { elevation = e; return *this; } }; // ============================================================================ // Navigation Drawer Item // ============================================================================ struct NavItem { const char* label; const char* icon; // Icon font glyph or nullptr bool selected; bool enabled; NavItem(const char* lbl, const char* ico = nullptr) : label(lbl), icon(ico), selected(false), enabled(true) {} NavItem& Selected(bool s) { selected = s; return *this; } NavItem& Enabled(bool e) { enabled = e; return *this; } }; // ============================================================================ // Alignment Helpers // ============================================================================ /** * @brief Align item to right edge of available space * @param itemWidth Width of the item */ inline void AlignRight(float itemWidth) { float availWidth = ImGui::GetContentRegionAvail().x; ImGui::SetCursorPosX(ImGui::GetCursorPosX() + availWidth - itemWidth); } /** * @brief Push items to start from right side (call before group of items) */ inline void BeginRightAlign() { ImGui::BeginGroup(); } /** * @brief End right-aligned group and position it */ inline void EndRightAlign() { ImGui::EndGroup(); float groupWidth = ImGui::GetItemRectSize().x; AlignRight(groupWidth); } } // namespace material } // namespace ui } // namespace dragonx