diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bbb0f1d..2af6cba7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Changed +- `ui_navbar`, `ui_navigation`'s top bar and sidebar, `ui_bottom_nav`, `ui_mobile_header`, `ui_mobile_actions`, `ui_breadcrumbs` and the desktop back link are left off a printed page, so a page prints with its content only. + ## [0.47.0] - 2026-10-15 ### Changed diff --git a/app/components/keystone/ui/bottom_nav_component.rb b/app/components/keystone/ui/bottom_nav_component.rb index e2dae567..6f169a45 100644 --- a/app/components/keystone/ui/bottom_nav_component.rb +++ b/app/components/keystone/ui/bottom_nav_component.rb @@ -3,7 +3,7 @@ module Keystone module Ui class BottomNavComponent < ViewComponent::Base - NAV_CLASSES = "ks-bottom-nav lg:hidden hotwire-native:hidden" + NAV_CLASSES = "ks-bottom-nav lg:hidden hotwire-native:hidden print:hidden" def nav_classes NAV_CLASSES diff --git a/app/components/keystone/ui/breadcrumbs_component.rb b/app/components/keystone/ui/breadcrumbs_component.rb index 2968ce9e..23823d67 100644 --- a/app/components/keystone/ui/breadcrumbs_component.rb +++ b/app/components/keystone/ui/breadcrumbs_component.rb @@ -3,7 +3,7 @@ module Keystone module Ui class BreadcrumbsComponent < ViewComponent::Base - CLASSES = "ks-mobile-header-back ks-breadcrumbs hidden lg:block text-sm" + CLASSES = "ks-mobile-header-back ks-breadcrumbs hidden lg:block text-sm print:hidden" SEPARATOR = "›" def initialize(trail:, current: nil) diff --git a/app/components/keystone/ui/desktop_back_link_component.rb b/app/components/keystone/ui/desktop_back_link_component.rb index 5ce990a8..97cb0832 100644 --- a/app/components/keystone/ui/desktop_back_link_component.rb +++ b/app/components/keystone/ui/desktop_back_link_component.rb @@ -3,7 +3,7 @@ module Keystone module Ui class DesktopBackLinkComponent < ViewComponent::Base - CLASSES = "ks-mobile-header-back ks-page-back hidden lg:inline-flex items-center" + CLASSES = "ks-mobile-header-back ks-page-back hidden lg:inline-flex items-center print:hidden" LABEL = "Back" def initialize(url:) diff --git a/app/components/keystone/ui/mobile_actions_component.rb b/app/components/keystone/ui/mobile_actions_component.rb index f6124b58..f2decd94 100644 --- a/app/components/keystone/ui/mobile_actions_component.rb +++ b/app/components/keystone/ui/mobile_actions_component.rb @@ -9,7 +9,7 @@ class MobileActionsComponent < ViewComponent::Base SVG - WRAPPER_CLASSES = "relative lg:hidden" + WRAPPER_CLASSES = "relative lg:hidden print:hidden" BUTTON_CLASSES = "ks-action-menu-button" DROPDOWN_CLASSES = "ks-action-menu hidden absolute right-0 z-50 w-48 origin-top-right" diff --git a/app/components/keystone/ui/mobile_header_component.rb b/app/components/keystone/ui/mobile_header_component.rb index aa41dc36..580c10da 100644 --- a/app/components/keystone/ui/mobile_header_component.rb +++ b/app/components/keystone/ui/mobile_header_component.rb @@ -15,7 +15,7 @@ class MobileHeaderComponent < ViewComponent::Base SVG - WRAPPER_CLASSES = "lg:hidden" + WRAPPER_CLASSES = "lg:hidden print:hidden" BACK_LINK_CLASSES = "ks-mobile-header-back" TITLE_CLASSES = "ks-mobile-header-title absolute left-1/2 -translate-x-1/2 lg:hidden truncate max-w-[60%]" SUBTITLE_CLASSES = "ks-mobile-header-subtitle block text-xs truncate text-center" diff --git a/app/components/keystone/ui/navbar_component.rb b/app/components/keystone/ui/navbar_component.rb index cc4412b8..553de3a1 100644 --- a/app/components/keystone/ui/navbar_component.rb +++ b/app/components/keystone/ui/navbar_component.rb @@ -3,7 +3,7 @@ module Keystone module Ui class NavbarComponent < ViewComponent::Base - NAV_BASE = "top-nav" + NAV_BASE = "top-nav print:hidden" NAV_STICKY = "sticky top-0 z-40" MOBILE_LEFT_CLASSES = "lg:hidden flex items-center" LOGO_CLASSES = "logo" diff --git a/app/components/keystone/ui/navigation_component.rb b/app/components/keystone/ui/navigation_component.rb index 0f46c129..75f68a0b 100644 --- a/app/components/keystone/ui/navigation_component.rb +++ b/app/components/keystone/ui/navigation_component.rb @@ -5,9 +5,9 @@ module Keystone module Ui class NavigationComponent < ViewComponent::Base - TOP_BAR_CLASSES = "hidden lg:block sticky top-0 z-40" + TOP_BAR_CLASSES = "hidden lg:block sticky top-0 z-40 print:hidden" SIDEBAR_ROW_CLASSES = "lg:flex" - SIDEBAR_CLASSES = "ks-sidebar hidden lg:flex lg:sticky lg:top-0 lg:h-screen shrink-0 overflow-y-auto" + SIDEBAR_CLASSES = "ks-sidebar hidden lg:flex lg:sticky lg:top-0 lg:h-screen shrink-0 overflow-y-auto print:hidden" SIDEBAR_LOGO_CLASSES = "ks-sidebar-logo" SIDEBAR_GROUP_CLASSES = "flex flex-col" SIDEBAR_GROUP_LABEL_CLASSES = "ks-sidebar-group-label" diff --git a/test/keystone/ui/printed_navigation_test.rb b/test/keystone/ui/printed_navigation_test.rb new file mode 100644 index 00000000..0a2fd7ce --- /dev/null +++ b/test/keystone/ui/printed_navigation_test.rb @@ -0,0 +1,37 @@ +# frozen_string_literal: true + +require "test_helper" + +class Keystone::Ui::PrintedNavigationTest < Minitest::Test + def test_the_navbar_is_left_off_a_printed_page + assert_includes Keystone::Ui::NavbarComponent.new.nav_classes.split, "print:hidden" + end + + def test_the_bottom_nav_is_left_off_a_printed_page + assert_includes Keystone::Ui::BottomNavComponent::NAV_CLASSES.split, "print:hidden" + end + + def test_the_navigation_top_bar_is_left_off_a_printed_page + assert_includes Keystone::Ui::NavigationComponent::TOP_BAR_CLASSES.split, "print:hidden" + end + + def test_the_navigation_sidebar_is_left_off_a_printed_page + assert_includes Keystone::Ui::NavigationComponent::SIDEBAR_CLASSES.split, "print:hidden" + end + + def test_the_mobile_header_is_left_off_a_printed_page + assert_includes Keystone::Ui::MobileHeaderComponent::WRAPPER_CLASSES.split, "print:hidden" + end + + def test_the_mobile_actions_menu_is_left_off_a_printed_page + assert_includes Keystone::Ui::MobileActionsComponent::WRAPPER_CLASSES.split, "print:hidden" + end + + def test_the_breadcrumbs_are_left_off_a_printed_page + assert_includes Keystone::Ui::BreadcrumbsComponent::CLASSES.split, "print:hidden" + end + + def test_the_back_link_is_left_off_a_printed_page + assert_includes Keystone::Ui::DesktopBackLinkComponent::CLASSES.split, "print:hidden" + end +end diff --git a/test/keystone_ui/host_stylesheet_test.rb b/test/keystone_ui/host_stylesheet_test.rb index 5876f76c..f8341275 100644 --- a/test/keystone_ui/host_stylesheet_test.rb +++ b/test/keystone_ui/host_stylesheet_test.rb @@ -16,7 +16,7 @@ def test_a_host_build_importing_keystone_source_compiles_keystone_ui_styles_clas def test_dark_classes_in_host_html_follow_keystones_explicit_dark_choice css = compile_host_stylesheet(%(
)) - assert_match(/\.dark\\:bg-red-500:where\(\[data-theme="dark"\]/, css) + assert_match(/\.dark\\:bg-red-500:where\(:is\(\[data-theme="dark"\]/, css) end def test_a_dark_theme_choice_marks_the_page_with_the_attribute_keystones_dark_styles_select_on diff --git a/the_local/agents/keystone_ui-develop.md b/the_local/agents/keystone_ui-develop.md index 0d4bb08b..e5fe55ef 100644 --- a/the_local/agents/keystone_ui-develop.md +++ b/the_local/agents/keystone_ui-develop.md @@ -198,6 +198,9 @@ two exceptions: `ui_page`'s `padding:` treats any value other than `:none` as 5. Wire navigation in the layout. + Every navigation component is left off a printed page, so a printed page or + a PDF holds only the page's content. + - `ui_navigation` takes no keywords and a block holding the page content, so it goes around `yield`. It draws the tabs the app declares with `config.navigation_group` as a top bar of menus from `lg:` up, then the