poetry-ui 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitattributes +6 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +87 -0
- data/THIRD_PARTY_NOTICES.md +201 -0
- data/app/components/poetry/ui/accordion/component.html.erb +3 -0
- data/app/components/poetry/ui/accordion/component.rb +197 -0
- data/app/components/poetry/ui/accordion/preview.rb +39 -0
- data/app/components/poetry/ui/accordion/style.rb +37 -0
- data/app/components/poetry/ui/alert/component.html.erb +6 -0
- data/app/components/poetry/ui/alert/component.rb +61 -0
- data/app/components/poetry/ui/alert/preview.rb +35 -0
- data/app/components/poetry/ui/alert/style.rb +24 -0
- data/app/components/poetry/ui/alert_dialog/component.html.erb +17 -0
- data/app/components/poetry/ui/alert_dialog/component.rb +208 -0
- data/app/components/poetry/ui/alert_dialog/preview.rb +48 -0
- data/app/components/poetry/ui/alert_dialog/style.rb +46 -0
- data/app/components/poetry/ui/aspect_ratio/component.rb +63 -0
- data/app/components/poetry/ui/aspect_ratio/preview.rb +29 -0
- data/app/components/poetry/ui/aspect_ratio/style.rb +13 -0
- data/app/components/poetry/ui/attachment/component.html.erb +13 -0
- data/app/components/poetry/ui/attachment/component.rb +139 -0
- data/app/components/poetry/ui/attachment/preview.rb +83 -0
- data/app/components/poetry/ui/attachment/style.rb +59 -0
- data/app/components/poetry/ui/autocomplete/component.html.erb +16 -0
- data/app/components/poetry/ui/autocomplete/component.rb +193 -0
- data/app/components/poetry/ui/autocomplete/preview.rb +39 -0
- data/app/components/poetry/ui/autocomplete/style.rb +18 -0
- data/app/components/poetry/ui/avatar/component.rb +103 -0
- data/app/components/poetry/ui/avatar/group_preview.html.erb +11 -0
- data/app/components/poetry/ui/avatar/preview.rb +50 -0
- data/app/components/poetry/ui/avatar/style.rb +34 -0
- data/app/components/poetry/ui/badge/component.rb +73 -0
- data/app/components/poetry/ui/badge/preview.rb +54 -0
- data/app/components/poetry/ui/badge/style.rb +35 -0
- data/app/components/poetry/ui/breadcrumb/component.html.erb +32 -0
- data/app/components/poetry/ui/breadcrumb/component.rb +102 -0
- data/app/components/poetry/ui/breadcrumb/dropdown_crumb_preview.html.erb +21 -0
- data/app/components/poetry/ui/breadcrumb/preview.rb +45 -0
- data/app/components/poetry/ui/breadcrumb/style.rb +25 -0
- data/app/components/poetry/ui/bubble/component.html.erb +4 -0
- data/app/components/poetry/ui/bubble/component.rb +106 -0
- data/app/components/poetry/ui/bubble/preview.rb +62 -0
- data/app/components/poetry/ui/bubble/style.rb +47 -0
- data/app/components/poetry/ui/button/component.html.erb +14 -0
- data/app/components/poetry/ui/button/component.rb +168 -0
- data/app/components/poetry/ui/button/preview.rb +94 -0
- data/app/components/poetry/ui/button/style.rb +41 -0
- data/app/components/poetry/ui/button_group/component.rb +70 -0
- data/app/components/poetry/ui/button_group/popup_triggers_preview.html.erb +21 -0
- data/app/components/poetry/ui/button_group/preview.rb +46 -0
- data/app/components/poetry/ui/button_group/style.rb +27 -0
- data/app/components/poetry/ui/button_group/text_prefix_preview.html.erb +7 -0
- data/app/components/poetry/ui/calendar/component.html.erb +72 -0
- data/app/components/poetry/ui/calendar/component.rb +366 -0
- data/app/components/poetry/ui/calendar/preview.rb +55 -0
- data/app/components/poetry/ui/calendar/style.rb +55 -0
- data/app/components/poetry/ui/card/component.html.erb +11 -0
- data/app/components/poetry/ui/card/component.rb +90 -0
- data/app/components/poetry/ui/card/preview.rb +29 -0
- data/app/components/poetry/ui/card/style.rb +23 -0
- data/app/components/poetry/ui/carousel/component.html.erb +17 -0
- data/app/components/poetry/ui/carousel/component.rb +179 -0
- data/app/components/poetry/ui/carousel/preview.rb +67 -0
- data/app/components/poetry/ui/carousel/style.rb +39 -0
- data/app/components/poetry/ui/checkbox/component.html.erb +22 -0
- data/app/components/poetry/ui/checkbox/component.rb +179 -0
- data/app/components/poetry/ui/checkbox/preview.rb +68 -0
- data/app/components/poetry/ui/checkbox/style.rb +28 -0
- data/app/components/poetry/ui/clipboard_text/component.html.erb +15 -0
- data/app/components/poetry/ui/clipboard_text/component.rb +154 -0
- data/app/components/poetry/ui/clipboard_text/preview.rb +24 -0
- data/app/components/poetry/ui/clipboard_text/style.rb +23 -0
- data/app/components/poetry/ui/code_block/component.html.erb +13 -0
- data/app/components/poetry/ui/code_block/component.rb +141 -0
- data/app/components/poetry/ui/code_block/preview.rb +40 -0
- data/app/components/poetry/ui/code_block/style.rb +38 -0
- data/app/components/poetry/ui/collapsible/component.html.erb +4 -0
- data/app/components/poetry/ui/collapsible/component.rb +134 -0
- data/app/components/poetry/ui/collapsible/preview.rb +24 -0
- data/app/components/poetry/ui/combobox/component.html.erb +49 -0
- data/app/components/poetry/ui/combobox/component.rb +1086 -0
- data/app/components/poetry/ui/combobox/preview.rb +164 -0
- data/app/components/poetry/ui/combobox/style.rb +148 -0
- data/app/components/poetry/ui/command/component.html.erb +20 -0
- data/app/components/poetry/ui/command/component.rb +526 -0
- data/app/components/poetry/ui/command/dialog_component.html.erb +14 -0
- data/app/components/poetry/ui/command/dialog_component.rb +206 -0
- data/app/components/poetry/ui/command/dialog_preview.rb +39 -0
- data/app/components/poetry/ui/command/preview.rb +121 -0
- data/app/components/poetry/ui/command/style.rb +78 -0
- data/app/components/poetry/ui/composable_trigger.rb +63 -0
- data/app/components/poetry/ui/context_menu/component.html.erb +6 -0
- data/app/components/poetry/ui/context_menu/component.rb +358 -0
- data/app/components/poetry/ui/context_menu/preview.rb +111 -0
- data/app/components/poetry/ui/context_menu/style.rb +59 -0
- data/app/components/poetry/ui/data_table/component.html.erb +78 -0
- data/app/components/poetry/ui/data_table/component.rb +277 -0
- data/app/components/poetry/ui/data_table/preview.rb +68 -0
- data/app/components/poetry/ui/data_table/state.rb +115 -0
- data/app/components/poetry/ui/data_table/style.rb +42 -0
- data/app/components/poetry/ui/date_field/component.html.erb +7 -0
- data/app/components/poetry/ui/date_field/component.rb +209 -0
- data/app/components/poetry/ui/date_field/preview.rb +42 -0
- data/app/components/poetry/ui/date_field/style.rb +35 -0
- data/app/components/poetry/ui/date_picker/component.html.erb +23 -0
- data/app/components/poetry/ui/date_picker/component.rb +242 -0
- data/app/components/poetry/ui/date_picker/preview.rb +31 -0
- data/app/components/poetry/ui/date_picker/style.rb +25 -0
- data/app/components/poetry/ui/deferred/component.html.erb +16 -0
- data/app/components/poetry/ui/deferred/component.rb +90 -0
- data/app/components/poetry/ui/deferred/preview.rb +24 -0
- data/app/components/poetry/ui/dialog/component.html.erb +21 -0
- data/app/components/poetry/ui/dialog/component.rb +194 -0
- data/app/components/poetry/ui/dialog/preview.rb +33 -0
- data/app/components/poetry/ui/dialog/style.rb +30 -0
- data/app/components/poetry/ui/drawer/component.html.erb +16 -0
- data/app/components/poetry/ui/drawer/component.rb +207 -0
- data/app/components/poetry/ui/drawer/preview.rb +69 -0
- data/app/components/poetry/ui/drawer/style.rb +105 -0
- data/app/components/poetry/ui/dropdown_menu/component.html.erb +6 -0
- data/app/components/poetry/ui/dropdown_menu/component.rb +350 -0
- data/app/components/poetry/ui/dropdown_menu/preview.rb +101 -0
- data/app/components/poetry/ui/dropdown_menu/style.rb +60 -0
- data/app/components/poetry/ui/empty/component.html.erb +10 -0
- data/app/components/poetry/ui/empty/component.rb +79 -0
- data/app/components/poetry/ui/empty/preview.rb +27 -0
- data/app/components/poetry/ui/empty/style.rb +27 -0
- data/app/components/poetry/ui/family_identity.rb +52 -0
- data/app/components/poetry/ui/field/component.html.erb +19 -0
- data/app/components/poetry/ui/field/component.rb +183 -0
- data/app/components/poetry/ui/field/preview.html.erb +30 -0
- data/app/components/poetry/ui/field/preview.rb +72 -0
- data/app/components/poetry/ui/field/style.rb +68 -0
- data/app/components/poetry/ui/field_group/component.rb +61 -0
- data/app/components/poetry/ui/field_group/preview.html.erb +30 -0
- data/app/components/poetry/ui/field_group/preview.rb +20 -0
- data/app/components/poetry/ui/field_group/style.rb +25 -0
- data/app/components/poetry/ui/field_separator/component.rb +70 -0
- data/app/components/poetry/ui/field_separator/preview.rb +18 -0
- data/app/components/poetry/ui/field_separator/style.rb +20 -0
- data/app/components/poetry/ui/fieldset/component.rb +90 -0
- data/app/components/poetry/ui/fieldset/preview.html.erb +22 -0
- data/app/components/poetry/ui/fieldset/preview.rb +25 -0
- data/app/components/poetry/ui/fieldset/style.rb +18 -0
- data/app/components/poetry/ui/file_input/component.html.erb +14 -0
- data/app/components/poetry/ui/file_input/component.rb +188 -0
- data/app/components/poetry/ui/file_input/preview.rb +30 -0
- data/app/components/poetry/ui/file_input/style.rb +35 -0
- data/app/components/poetry/ui/hover_card/component.html.erb +6 -0
- data/app/components/poetry/ui/hover_card/component.rb +201 -0
- data/app/components/poetry/ui/hover_card/preview.rb +60 -0
- data/app/components/poetry/ui/hover_card/style.rb +17 -0
- data/app/components/poetry/ui/icon/component.rb +127 -0
- data/app/components/poetry/ui/icon/preview.rb +21 -0
- data/app/components/poetry/ui/input/component.rb +80 -0
- data/app/components/poetry/ui/input/preview.rb +35 -0
- data/app/components/poetry/ui/input/style.rb +18 -0
- data/app/components/poetry/ui/input_group/button_preview.html.erb +12 -0
- data/app/components/poetry/ui/input_group/component.rb +69 -0
- data/app/components/poetry/ui/input_group/preview.rb +23 -0
- data/app/components/poetry/ui/input_group/search_preview.html.erb +13 -0
- data/app/components/poetry/ui/input_group/style.rb +40 -0
- data/app/components/poetry/ui/input_group/textarea_preview.html.erb +10 -0
- data/app/components/poetry/ui/input_group_field.rb +61 -0
- data/app/components/poetry/ui/input_otp/component.html.erb +25 -0
- data/app/components/poetry/ui/input_otp/component.rb +250 -0
- data/app/components/poetry/ui/input_otp/preview.rb +91 -0
- data/app/components/poetry/ui/input_otp/style.rb +36 -0
- data/app/components/poetry/ui/item/component.html.erb +13 -0
- data/app/components/poetry/ui/item/component.rb +99 -0
- data/app/components/poetry/ui/item/group_preview.html.erb +15 -0
- data/app/components/poetry/ui/item/preview.rb +52 -0
- data/app/components/poetry/ui/item/style.rb +45 -0
- data/app/components/poetry/ui/kbd/component.rb +47 -0
- data/app/components/poetry/ui/kbd/group_preview.html.erb +4 -0
- data/app/components/poetry/ui/kbd/preview.rb +23 -0
- data/app/components/poetry/ui/kbd/style.rb +13 -0
- data/app/components/poetry/ui/label/component.rb +46 -0
- data/app/components/poetry/ui/label/preview.html.erb +5 -0
- data/app/components/poetry/ui/label/preview.rb +16 -0
- data/app/components/poetry/ui/label/style.rb +13 -0
- data/app/components/poetry/ui/link/component.rb +62 -0
- data/app/components/poetry/ui/link/preview.rb +31 -0
- data/app/components/poetry/ui/link/style.rb +20 -0
- data/app/components/poetry/ui/marker/component.html.erb +4 -0
- data/app/components/poetry/ui/marker/component.rb +81 -0
- data/app/components/poetry/ui/marker/preview.rb +43 -0
- data/app/components/poetry/ui/marker/style.rb +24 -0
- data/app/components/poetry/ui/menubar/component.html.erb +3 -0
- data/app/components/poetry/ui/menubar/component.rb +493 -0
- data/app/components/poetry/ui/menubar/preview.rb +164 -0
- data/app/components/poetry/ui/menubar/style.rb +71 -0
- data/app/components/poetry/ui/menus.rb +386 -0
- data/app/components/poetry/ui/message/component.html.erb +8 -0
- data/app/components/poetry/ui/message/component.rb +64 -0
- data/app/components/poetry/ui/message/preview.rb +33 -0
- data/app/components/poetry/ui/message/style.rb +29 -0
- data/app/components/poetry/ui/message_scroller/component.html.erb +15 -0
- data/app/components/poetry/ui/message_scroller/component.rb +163 -0
- data/app/components/poetry/ui/message_scroller/preview.rb +33 -0
- data/app/components/poetry/ui/message_scroller/style.rb +39 -0
- data/app/components/poetry/ui/metadata_list/component.rb +88 -0
- data/app/components/poetry/ui/metadata_list/preview.rb +55 -0
- data/app/components/poetry/ui/metadata_list/style.rb +35 -0
- data/app/components/poetry/ui/meter/component.rb +117 -0
- data/app/components/poetry/ui/meter/preview.rb +28 -0
- data/app/components/poetry/ui/meter/style.rb +16 -0
- data/app/components/poetry/ui/native_select/component.rb +124 -0
- data/app/components/poetry/ui/native_select/labelled_preview.html.erb +7 -0
- data/app/components/poetry/ui/native_select/preview.rb +20 -0
- data/app/components/poetry/ui/native_select/style.rb +22 -0
- data/app/components/poetry/ui/navigation_menu/bar_preview.html.erb +14 -0
- data/app/components/poetry/ui/navigation_menu/component.html.erb +25 -0
- data/app/components/poetry/ui/navigation_menu/component.rb +254 -0
- data/app/components/poetry/ui/navigation_menu/preview.rb +20 -0
- data/app/components/poetry/ui/navigation_menu/style.rb +73 -0
- data/app/components/poetry/ui/navigation_menu/viewport_preview.html.erb +23 -0
- data/app/components/poetry/ui/number_field/component.html.erb +19 -0
- data/app/components/poetry/ui/number_field/component.rb +263 -0
- data/app/components/poetry/ui/number_field/preview.rb +66 -0
- data/app/components/poetry/ui/number_field/style.rb +14 -0
- data/app/components/poetry/ui/pagination/component.html.erb +40 -0
- data/app/components/poetry/ui/pagination/component.rb +182 -0
- data/app/components/poetry/ui/pagination/preview.rb +47 -0
- data/app/components/poetry/ui/pagination/style.rb +27 -0
- data/app/components/poetry/ui/popover/component.html.erb +17 -0
- data/app/components/poetry/ui/popover/component.rb +203 -0
- data/app/components/poetry/ui/popover/preview.html.erb +29 -0
- data/app/components/poetry/ui/popover/preview.rb +66 -0
- data/app/components/poetry/ui/popover/style.rb +26 -0
- data/app/components/poetry/ui/popper_consumer.rb +69 -0
- data/app/components/poetry/ui/progress/component.rb +95 -0
- data/app/components/poetry/ui/progress/preview.rb +22 -0
- data/app/components/poetry/ui/progress/style.rb +19 -0
- data/app/components/poetry/ui/questionnaire/component.html.erb +80 -0
- data/app/components/poetry/ui/questionnaire/component.rb +396 -0
- data/app/components/poetry/ui/questionnaire/preview.rb +99 -0
- data/app/components/poetry/ui/questionnaire/style.rb +53 -0
- data/app/components/poetry/ui/radio_group/component.html.erb +4 -0
- data/app/components/poetry/ui/radio_group/component.rb +323 -0
- data/app/components/poetry/ui/radio_group/preview.rb +109 -0
- data/app/components/poetry/ui/radio_group/style.rb +53 -0
- data/app/components/poetry/ui/resizable/component.html.erb +10 -0
- data/app/components/poetry/ui/resizable/component.rb +178 -0
- data/app/components/poetry/ui/resizable/preview.rb +42 -0
- data/app/components/poetry/ui/resizable/style.rb +30 -0
- data/app/components/poetry/ui/scroll_area/component.rb +76 -0
- data/app/components/poetry/ui/scroll_area/preview.rb +35 -0
- data/app/components/poetry/ui/scroll_area/style.rb +19 -0
- data/app/components/poetry/ui/search_field/component.html.erb +15 -0
- data/app/components/poetry/ui/search_field/component.rb +137 -0
- data/app/components/poetry/ui/search_field/preview.rb +23 -0
- data/app/components/poetry/ui/search_field/style.rb +18 -0
- data/app/components/poetry/ui/select/component.html.erb +15 -0
- data/app/components/poetry/ui/select/component.rb +639 -0
- data/app/components/poetry/ui/select/preview.rb +113 -0
- data/app/components/poetry/ui/select/style.rb +58 -0
- data/app/components/poetry/ui/sensitive_input/component.html.erb +29 -0
- data/app/components/poetry/ui/sensitive_input/component.rb +274 -0
- data/app/components/poetry/ui/sensitive_input/preview.rb +40 -0
- data/app/components/poetry/ui/sensitive_input/style.rb +49 -0
- data/app/components/poetry/ui/separator/component.rb +57 -0
- data/app/components/poetry/ui/separator/preview.rb +19 -0
- data/app/components/poetry/ui/separator/style.rb +15 -0
- data/app/components/poetry/ui/sheet/component.html.erb +21 -0
- data/app/components/poetry/ui/sheet/component.rb +97 -0
- data/app/components/poetry/ui/sheet/preview.rb +57 -0
- data/app/components/poetry/ui/sheet/style.rb +47 -0
- data/app/components/poetry/ui/sidebar/component.html.erb +20 -0
- data/app/components/poetry/ui/sidebar/component.rb +249 -0
- data/app/components/poetry/ui/sidebar/preview.rb +21 -0
- data/app/components/poetry/ui/sidebar/shell_preview.html.erb +47 -0
- data/app/components/poetry/ui/sidebar/style.rb +139 -0
- data/app/components/poetry/ui/skeleton/component.rb +39 -0
- data/app/components/poetry/ui/skeleton/preview.rb +22 -0
- data/app/components/poetry/ui/skeleton/style.rb +13 -0
- data/app/components/poetry/ui/slider/component.html.erb +13 -0
- data/app/components/poetry/ui/slider/component.rb +360 -0
- data/app/components/poetry/ui/slider/preview.rb +73 -0
- data/app/components/poetry/ui/slider/style.rb +55 -0
- data/app/components/poetry/ui/spinner/component.rb +58 -0
- data/app/components/poetry/ui/spinner/preview.rb +22 -0
- data/app/components/poetry/ui/spinner/style.rb +12 -0
- data/app/components/poetry/ui/stat/component.html.erb +13 -0
- data/app/components/poetry/ui/stat/component.rb +102 -0
- data/app/components/poetry/ui/stat/preview.rb +47 -0
- data/app/components/poetry/ui/stat/style.rb +29 -0
- data/app/components/poetry/ui/switch/component.html.erb +15 -0
- data/app/components/poetry/ui/switch/component.rb +136 -0
- data/app/components/poetry/ui/switch/preview.rb +66 -0
- data/app/components/poetry/ui/switch/style.rb +22 -0
- data/app/components/poetry/ui/table/component.html.erb +3 -0
- data/app/components/poetry/ui/table/component.rb +93 -0
- data/app/components/poetry/ui/table/preview.rb +96 -0
- data/app/components/poetry/ui/table/style.rb +26 -0
- data/app/components/poetry/ui/tabs/component.html.erb +10 -0
- data/app/components/poetry/ui/tabs/component.rb +253 -0
- data/app/components/poetry/ui/tabs/preview.rb +43 -0
- data/app/components/poetry/ui/tabs/style.rb +49 -0
- data/app/components/poetry/ui/tag_group/component.html.erb +8 -0
- data/app/components/poetry/ui/tag_group/component.rb +203 -0
- data/app/components/poetry/ui/tag_group/preview.rb +43 -0
- data/app/components/poetry/ui/tag_group/style.rb +29 -0
- data/app/components/poetry/ui/textarea/component.rb +64 -0
- data/app/components/poetry/ui/textarea/preview.rb +75 -0
- data/app/components/poetry/ui/textarea/style.rb +18 -0
- data/app/components/poetry/ui/time_field/component.html.erb +6 -0
- data/app/components/poetry/ui/time_field/component.rb +85 -0
- data/app/components/poetry/ui/time_field/preview.rb +40 -0
- data/app/components/poetry/ui/time_field/style.rb +30 -0
- data/app/components/poetry/ui/timeline/component.rb +134 -0
- data/app/components/poetry/ui/timeline/preview.rb +61 -0
- data/app/components/poetry/ui/timeline/style.rb +54 -0
- data/app/components/poetry/ui/toast/component.html.erb +24 -0
- data/app/components/poetry/ui/toast/component.rb +178 -0
- data/app/components/poetry/ui/toast/preview.rb +69 -0
- data/app/components/poetry/ui/toast/style.rb +33 -0
- data/app/components/poetry/ui/toast_trigger/addressed_preview.html.erb +12 -0
- data/app/components/poetry/ui/toast_trigger/component.html.erb +3 -0
- data/app/components/poetry/ui/toast_trigger/component.rb +82 -0
- data/app/components/poetry/ui/toast_trigger/default_preview.html.erb +11 -0
- data/app/components/poetry/ui/toast_trigger/preview.rb +19 -0
- data/app/components/poetry/ui/toaster/component.html.erb +1 -0
- data/app/components/poetry/ui/toaster/component.rb +99 -0
- data/app/components/poetry/ui/toaster/positions_preview.html.erb +24 -0
- data/app/components/poetry/ui/toaster/preview.rb +46 -0
- data/app/components/poetry/ui/toaster/stamp_preview.html.erb +15 -0
- data/app/components/poetry/ui/toaster/style.rb +26 -0
- data/app/components/poetry/ui/toggle/component.rb +120 -0
- data/app/components/poetry/ui/toggle/preview.rb +79 -0
- data/app/components/poetry/ui/toggle/style.rb +33 -0
- data/app/components/poetry/ui/toggle_group/component.html.erb +4 -0
- data/app/components/poetry/ui/toggle_group/component.rb +252 -0
- data/app/components/poetry/ui/toggle_group/preview.rb +143 -0
- data/app/components/poetry/ui/toggle_group/style.rb +33 -0
- data/app/components/poetry/ui/toolbar/component.rb +125 -0
- data/app/components/poetry/ui/toolbar/preview.rb +41 -0
- data/app/components/poetry/ui/toolbar/style.rb +20 -0
- data/app/components/poetry/ui/tooltip/component.html.erb +20 -0
- data/app/components/poetry/ui/tooltip/component.rb +185 -0
- data/app/components/poetry/ui/tooltip/preview.rb +74 -0
- data/app/components/poetry/ui/tooltip/previews/provider_row.html.erb +25 -0
- data/app/components/poetry/ui/tooltip/style.rb +24 -0
- data/app/components/poetry/ui/tree/component.html.erb +32 -0
- data/app/components/poetry/ui/tree/component.rb +233 -0
- data/app/components/poetry/ui/tree/preview.rb +55 -0
- data/app/components/poetry/ui/tree/style.rb +29 -0
- data/app/components/poetry/ui/typeset/component.rb +73 -0
- data/app/components/poetry/ui/typeset/preview.rb +45 -0
- data/app/components/poetry/ui/typeset/style.rb +15 -0
- data/app/controllers/poetry/ui/llms_controller.rb +28 -0
- data/app/helpers/poetry/ui/components_helper.rb +1794 -0
- data/app/helpers/poetry/ui/form_builder/type_inference.rb +117 -0
- data/app/helpers/poetry/ui/form_builder.rb +916 -0
- data/app/helpers/poetry/ui/optimistic_form_builder.rb +55 -0
- data/app/helpers/poetry/ui/toast_stream_actions.rb +27 -0
- data/config/component_descriptions.yml +96 -0
- data/config/component_registry.yml +12257 -0
- data/config/locales/en.yml +93 -0
- data/config/routes.rb +8 -0
- data/config/template_classes.txt +113 -0
- data/lib/generators/poetry/add/add_generator.rb +218 -0
- data/lib/generators/poetry/agent_rules/agent_rules_generator.rb +91 -0
- data/lib/generators/poetry/agents/agents_generator.rb +24 -0
- data/lib/generators/poetry/agents_section.rb +148 -0
- data/lib/generators/poetry/block/block_generator.rb +67 -0
- data/lib/generators/poetry/block/templates/action_bar.html.erb +45 -0
- data/lib/generators/poetry/block/templates/app_shell.html.erb +139 -0
- data/lib/generators/poetry/block/templates/data_index.html.erb +85 -0
- data/lib/generators/poetry/block/templates/destructive_panel.html.erb +26 -0
- data/lib/generators/poetry/block/templates/page_header.html.erb +25 -0
- data/lib/generators/poetry/block/templates/section_card.html.erb +42 -0
- data/lib/generators/poetry/block/templates/stepper.html.erb +79 -0
- data/lib/generators/poetry/block/templates/top_nav.html.erb +44 -0
- data/lib/generators/poetry/diff/diff_generator.rb +135 -0
- data/lib/generators/poetry/editor/editor_generator.rb +344 -0
- data/lib/generators/poetry/editor/templates/poetry-check-hook +81 -0
- data/lib/generators/poetry/install/install_generator.rb +364 -0
- data/lib/generators/poetry/pagination/pagination_generator.rb +76 -0
- data/lib/generators/poetry/pagination/templates/kaminari_paginator.html.erb +29 -0
- data/lib/generators/poetry/pagination/templates/poetry_link_renderer.rb +34 -0
- data/lib/generators/poetry/pagination/templates/poetry_pagy_helper.rb +28 -0
- data/lib/generators/poetry/recipes/agent_embed/app/javascript/controllers/agent_demo_controller.js +131 -0
- data/lib/generators/poetry/recipes/screen_data_index/app/controllers/orders_controller.rb +15 -0
- data/lib/generators/poetry/recipes/screen_data_index/app/views/orders/index.html.erb +7 -0
- data/lib/generators/poetry/recipes/screen_data_index/test/system/orders_index_test.rb +16 -0
- data/lib/generators/poetry/recipes/screen_settings/app/controllers/settings_controller.rb +14 -0
- data/lib/generators/poetry/recipes/screen_settings/app/views/settings/show.html.erb +9 -0
- data/lib/generators/poetry/recipes/screen_settings/test/system/settings_show_test.rb +16 -0
- data/lib/generators/poetry/scaffold_templates/scaffold_templates_generator.rb +60 -0
- data/lib/generators/poetry/scaffold_templates/templates/_form.html.erb.tt +77 -0
- data/lib/generators/poetry/scaffold_templates/templates/controller.rb.tt +78 -0
- data/lib/generators/poetry/scaffold_templates/templates/edit.html.erb.tt +14 -0
- data/lib/generators/poetry/scaffold_templates/templates/index.html.erb.tt +24 -0
- data/lib/generators/poetry/scaffold_templates/templates/new.html.erb.tt +11 -0
- data/lib/generators/poetry/scaffold_templates/templates/partial.html.erb.tt +13 -0
- data/lib/generators/poetry/scaffold_templates/templates/show.html.erb.tt +18 -0
- data/lib/generators/poetry/skill/skill_generator.rb +34 -0
- data/lib/generators/poetry/skill/templates/poetry-component/SKILL.md +58 -0
- data/lib/generators/poetry/skill/templates/poetry-component/references/anatomy.md +152 -0
- data/lib/generators/poetry/skill/templates/poetry-component/references/checklist.md +67 -0
- data/lib/generators/poetry/skill/templates/poetry-component/references/documentation.md +137 -0
- data/lib/generators/poetry/skill/templates/poetry-design/SKILL.md +56 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/audit.md +123 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/compose.md +73 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/figma.md +68 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/paper.md +56 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/study.md +47 -0
- data/lib/generators/poetry/skill/templates/poetry-design/references/theme.md +70 -0
- data/lib/generators/poetry/skills_section.rb +58 -0
- data/lib/poetry/ui/chat.rb +283 -0
- data/lib/poetry/ui/code_block_highlighter.rb +60 -0
- data/lib/poetry/ui/engine.rb +55 -0
- data/lib/poetry/ui/recipes.rb +157 -0
- data/lib/poetry/ui/testing/combobox.rb +167 -0
- data/lib/poetry/ui/testing/dialog.rb +73 -0
- data/lib/poetry/ui/testing/menu.rb +127 -0
- data/lib/poetry/ui/testing/registration.rb +58 -0
- data/lib/poetry/ui/testing/select.rb +147 -0
- data/lib/poetry/ui/testing/tester.rb +130 -0
- data/lib/poetry/ui/testing.rb +130 -0
- data/lib/poetry/ui/themes.rb +109 -0
- data/lib/poetry/ui/version.rb +8 -0
- data/lib/poetry/ui/webmcp.rb +91 -0
- data/lib/poetry/ui.rb +285 -0
- data/lib/poetry-ui.rb +5 -0
- data/lib/tasks/poetry/check.rake +73 -0
- data/lib/tasks/poetry/design.rake +293 -0
- data/lib/tasks/poetry/verify.rake +36 -0
- data/themes/default.css +1793 -0
- data/themes/luma.css +1764 -0
- data/themes/lyra.css +1768 -0
- data/themes/maia.css +1768 -0
- data/themes/mira.css +1760 -0
- data/themes/nova.css +1755 -0
- data/themes/rhea.css +1771 -0
- data/themes/sera.css +1757 -0
- data/themes/vega.css +1775 -0
- data/typeset/typeset.css +499 -0
- metadata +502 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%= content_tag(:div, **root_attributes.to_attributes) do %>
|
|
2
|
+
<%= trigger %>
|
|
3
|
+
<%= content_tag(:dialog, **Poetry::Core::HTML::Attributes.new(dialog_attributes).to_attributes) do %>
|
|
4
|
+
<div data-slot="sheet-header" class="<%= css(:header) %>">
|
|
5
|
+
<h2 id="<%= title_id %>" data-slot="sheet-title" class="<%= css(:title) %>"><%= title %></h2>
|
|
6
|
+
<% if description? %>
|
|
7
|
+
<p id="<%= description_id %>" data-slot="sheet-description" class="<%= css(:description) %>"><%= description %></p>
|
|
8
|
+
<% end %>
|
|
9
|
+
</div>
|
|
10
|
+
<%= content %>
|
|
11
|
+
<% if footer? %><div data-slot="sheet-footer" class="<%= css(:footer) %>"><%= footer %></div><% end %>
|
|
12
|
+
<% if show_close_button %>
|
|
13
|
+
<%= render Poetry::Ui::Button::Component.new(variant: :ghost, size: :"icon-sm",
|
|
14
|
+
label: t("poetry.sheet.close"),
|
|
15
|
+
class: css(:close),
|
|
16
|
+
data: { slot: "sheet-close", action: close_action }) do %>
|
|
17
|
+
<%= render Poetry::Ui::Icon::Component.new(name: :x) %>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% end %>
|
|
21
|
+
<% end %>
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# A modal panel that slides in from a screen edge.
|
|
6
|
+
module Sheet
|
|
7
|
+
# A modal panel that slides in from a screen edge - navigation on
|
|
8
|
+
# the left, detail/edit panels on the right, pickers on the bottom.
|
|
9
|
+
# A re-skinned Dialog, so everything hard is INHERITED: the native
|
|
10
|
+
# <dialog> + showModal() platform behavior (focus trap, Esc, top
|
|
11
|
+
# layer, focus return), the data-open/data-closed pair, backdrop
|
|
12
|
+
# dismissal, scroll lock, dismissible:, show_close_button:, and the
|
|
13
|
+
# required title. The deltas: the side style (edge-anchored margins
|
|
14
|
+
# replace the parent's centering) and the slide-in animation.
|
|
15
|
+
#
|
|
16
|
+
# @example
|
|
17
|
+
# render Poetry::Ui::Sheet::Component.new(side: :right) do |sheet|
|
|
18
|
+
# sheet.with_trigger { "Edit profile" }
|
|
19
|
+
# sheet.with_title { "Edit profile" }
|
|
20
|
+
# "Sheet body"
|
|
21
|
+
# end
|
|
22
|
+
class Component < Dialog::Component
|
|
23
|
+
# The closed vocabulary for the side style axis.
|
|
24
|
+
SIDES = %i[top right bottom left].freeze
|
|
25
|
+
|
|
26
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
27
|
+
AGENT_RULES = [
|
|
28
|
+
"Open sheets with with_trigger(...) - never a hand-wired button.",
|
|
29
|
+
"with_title is REQUIRED (the accessible name) - the inherited Dialog rule.",
|
|
30
|
+
"Pick side by content: navigation left, detail/edit right, pickers bottom.",
|
|
31
|
+
"Do not put must-not-lose confirmations in a Sheet - that is AlertDialog.",
|
|
32
|
+
"Do not rebuild a centered Dialog with a Sheet; use Dialog."
|
|
33
|
+
].freeze
|
|
34
|
+
|
|
35
|
+
# The Sheet gets its OWN controller - the dialog machinery plus
|
|
36
|
+
# the presence-hold close (the closed slide-out finishes before
|
|
37
|
+
# the panel hides).
|
|
38
|
+
# Redeclaring both elements REPLACES Dialog's :dialog controller
|
|
39
|
+
# wholesale (replace-on-redeclare); the inherited trigger lambda and
|
|
40
|
+
# close_action late-bind here through stimulus_action.
|
|
41
|
+
use_stimulus do
|
|
42
|
+
on :root do
|
|
43
|
+
controller :sheet do
|
|
44
|
+
register
|
|
45
|
+
value :dismissible
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
on :content do
|
|
49
|
+
controller :sheet do
|
|
50
|
+
target :dialog
|
|
51
|
+
action :close, on: :cancel
|
|
52
|
+
action :backdrop_close, on: :click
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
on :trigger do
|
|
56
|
+
controller(:sheet) { action :open }
|
|
57
|
+
end
|
|
58
|
+
on :close do
|
|
59
|
+
controller(:sheet) { action :close }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
style :side, default: :right, required: true, variants: SIDES,
|
|
64
|
+
doc: "The edge the sheet slides in from - a physical direction (right stays right in RTL)."
|
|
65
|
+
|
|
66
|
+
part "sheet", "Root wrapper around the trigger and the <dialog> element"
|
|
67
|
+
part "sheet-content", "The <dialog> panel, anchored to a screen edge - the slide " \
|
|
68
|
+
"animation and the open state ride here",
|
|
69
|
+
states: {
|
|
70
|
+
"data-open" => "panel is open (the controller flips the pair at runtime)",
|
|
71
|
+
"data-closed" => "panel is closed or animating out (the server-rendered state; " \
|
|
72
|
+
"the presence-hold close rides the closed slide-out)",
|
|
73
|
+
"data-side" => { condition: "always - the edge the sheet slides in from",
|
|
74
|
+
values: SIDES.map(&:to_s) }
|
|
75
|
+
}
|
|
76
|
+
part "sheet-header", "Title block at the top of the panel"
|
|
77
|
+
part "sheet-title", "The heading - the sheet's accessible name (required slot)"
|
|
78
|
+
part "sheet-description", "Muted copy under the title, wired to aria-describedby"
|
|
79
|
+
part "sheet-footer", "Action row pinned to the bottom of the panel"
|
|
80
|
+
|
|
81
|
+
private
|
|
82
|
+
|
|
83
|
+
# The Sheet deltas on the inherited panel: the side's edge classes
|
|
84
|
+
# (the resolver applies variants only at the dictionary root; the
|
|
85
|
+
# Sheet's visual root IS the :content element, so the side branch
|
|
86
|
+
# merges in here) and the data-side stamp.
|
|
87
|
+
def panel_classes
|
|
88
|
+
[Style.side(side), content_class]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def panel_stamps
|
|
92
|
+
{ "data-side" => side }
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Sheet
|
|
6
|
+
# The Sheet preview: one example per edge (previews render CLOSED,
|
|
7
|
+
# the trigger page - the Dialog convention).
|
|
8
|
+
class Preview < Poetry::Core::Preview::Base
|
|
9
|
+
# side: :right - the detail/edit panel default.
|
|
10
|
+
def default
|
|
11
|
+
side_example(:right)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def left
|
|
15
|
+
side_example(:left)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def top
|
|
19
|
+
side_example(:top)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def bottom
|
|
23
|
+
side_example(:bottom)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# The canonical Sheet recipe: an edit form beside the page context,
|
|
27
|
+
# footer actions pinned to the edge by mt-auto.
|
|
28
|
+
def form
|
|
29
|
+
render_component(side: :right) do |sheet|
|
|
30
|
+
sheet.with_trigger(variant: :outline) { "Edit profile" }
|
|
31
|
+
sheet.with_title { "Edit profile" }
|
|
32
|
+
sheet.with_description { "Make changes to your profile here. Click save when you're done." }
|
|
33
|
+
sheet.with_footer do
|
|
34
|
+
embed(Poetry::Ui::Button::Component.new(type: :submit).with_content("Save changes"))
|
|
35
|
+
end
|
|
36
|
+
embed(Poetry::Ui::Label::Component.new(for_id: "sheet-demo-name").with_content("Name")) +
|
|
37
|
+
embed(Poetry::Ui::Input::Component.new(name: "name", value: "Pedro Duarte", id: "sheet-demo-name"))
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def side_example(side)
|
|
44
|
+
render_component(side: side) do |sheet|
|
|
45
|
+
sheet.with_trigger(variant: :outline) { "Open #{side} sheet" }
|
|
46
|
+
sheet.with_title { "Slide from the #{side}" }
|
|
47
|
+
sheet.with_description { "A Dialog that stays visually adjacent to the page." }
|
|
48
|
+
sheet.with_footer do
|
|
49
|
+
embed(Poetry::Ui::Button::Component.new.with_content("Apply"))
|
|
50
|
+
end
|
|
51
|
+
"Sheet body content."
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Sheet
|
|
6
|
+
# Style dictionary for the Sheet family, on the native-dialog spine.
|
|
7
|
+
# m-0 and the per-side auto margins live in the theme TOGETHER (the
|
|
8
|
+
# side margins must beat m-0, which they only can from the same
|
|
9
|
+
# layer); the UA display guard stays inline.
|
|
10
|
+
class Style < Poetry::Core::Style
|
|
11
|
+
# open:flex, NOT flex: a bare display class would defeat the UA's
|
|
12
|
+
# dialog:not([open]) { display: none }.
|
|
13
|
+
# w-full rides the theme so the sides' w-3/4 beats it in-layer.
|
|
14
|
+
# No `relative`: the top layer discards it and the UA reasserts
|
|
15
|
+
# `absolute`, which pins the sheet to the DOCUMENT edge (it scrolls
|
|
16
|
+
# off-screen when opened below the fold). The UA `:modal` rule keeps
|
|
17
|
+
# it viewport-fixed, so the side auto-margins pin it to the viewport
|
|
18
|
+
# edge as intended.
|
|
19
|
+
element :content, "cn-sheet-content open:flex flex-col"
|
|
20
|
+
|
|
21
|
+
# The side branches ride cn-sheet-side-* theme rules (margins,
|
|
22
|
+
# edge borders, sizes, slide animations). Applied to :content by
|
|
23
|
+
# the component via Style.side - the resolver renders variants only
|
|
24
|
+
# at the dictionary root, and the Sheet's root wrapper is
|
|
25
|
+
# non-visual.
|
|
26
|
+
variant :side, {
|
|
27
|
+
top: "cn-sheet-side-top",
|
|
28
|
+
right: "cn-sheet-side-right",
|
|
29
|
+
bottom: "cn-sheet-side-bottom",
|
|
30
|
+
left: "cn-sheet-side-left"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
element :header, "cn-sheet-header flex flex-col"
|
|
34
|
+
element :title, "cn-sheet-title"
|
|
35
|
+
element :description, "cn-sheet-description"
|
|
36
|
+
# mt-auto pins the footer to the bottom edge.
|
|
37
|
+
element :footer, "cn-sheet-footer mt-auto flex flex-col"
|
|
38
|
+
element :close, "cn-sheet-close"
|
|
39
|
+
|
|
40
|
+
# The side's edge classes for the <dialog> element.
|
|
41
|
+
def self.side(value)
|
|
42
|
+
resolver.variants.fetch(:side).fetch(value.to_sym)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<%= content_tag(:div, **root_attributes.to_attributes) do %>
|
|
2
|
+
<%= content_tag(:div, peer_attributes) do %>
|
|
3
|
+
<div data-slot="sidebar-gap" class="<%= gap_classes %>"></div>
|
|
4
|
+
<div data-slot="sidebar-container" data-side="<%= side %>" class="<%= container_classes %>">
|
|
5
|
+
<div data-slot="sidebar-inner" class="<%= css(:inner) %>" <%= tag.attributes(**stimulus_attributes_for(:inner)) %>><%= nav %></div>
|
|
6
|
+
</div>
|
|
7
|
+
<% end %>
|
|
8
|
+
<%# The mobile sheet (DOM-move): rendered EMPTY; the controller
|
|
9
|
+
adopts the nav children on open and returns them on close. %>
|
|
10
|
+
<%= content_tag(:dialog, **mobile_dialog_attributes) do %>
|
|
11
|
+
<div class="sr-only">
|
|
12
|
+
<h2 id="<%= mobile_title_id %>">Sidebar</h2>
|
|
13
|
+
<p>Displays the mobile sidebar.</p>
|
|
14
|
+
</div>
|
|
15
|
+
<div data-slot="sidebar-mobile-inner" class="<%= css(:mobile_inner) %>" <%= tag.attributes(**stimulus_attributes_for(:mobile_inner)) %>></div>
|
|
16
|
+
<% end %>
|
|
17
|
+
<% if inset? %>
|
|
18
|
+
<main data-slot="sidebar-inset" class="<%= css(:inset) %>"><%= inset %></main>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% end %>
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# The app-shell frame: collapsible navigation column plus content inset.
|
|
6
|
+
module Sidebar
|
|
7
|
+
# The app-shell frame: a collapsible navigation column plus the main
|
|
8
|
+
# content inset. Reach for it as the outermost layout of an
|
|
9
|
+
# application screen. The collapse is pure CSS off data-state; the
|
|
10
|
+
# controller flips the attribute, persists the sidebar_state cookie,
|
|
11
|
+
# and binds Cmd/Ctrl+B. Server-first: pass open: from the cookie
|
|
12
|
+
# (cookies[:sidebar_state] != "false") so the first paint matches the
|
|
13
|
+
# user's last choice with no flash. Below the md breakpoint the
|
|
14
|
+
# column becomes a slide-in sheet.
|
|
15
|
+
#
|
|
16
|
+
# @example App shell wired to the persisted cookie
|
|
17
|
+
# <%= poetry_sidebar(open: cookies[:sidebar_state] != "false", collapsible: :icon) do |shell| %>
|
|
18
|
+
# <% shell.with_nav do %>
|
|
19
|
+
# <%= poetry_sidebar_group do %>...menu...<% end %>
|
|
20
|
+
# <% end %>
|
|
21
|
+
# <% shell.with_inset do %>
|
|
22
|
+
# <%= poetry_sidebar_trigger %>
|
|
23
|
+
# <main>...page...</main>
|
|
24
|
+
# <% end %>
|
|
25
|
+
# <% end %>
|
|
26
|
+
class Component < Poetry::Core::Component
|
|
27
|
+
# The closed vocabulary for the side axis.
|
|
28
|
+
SIDES = %i[left right].freeze
|
|
29
|
+
# The closed vocabulary for the column-treatment axis.
|
|
30
|
+
VARIANTS = %i[sidebar floating inset].freeze
|
|
31
|
+
# The closed vocabulary for the collapse-mode axis.
|
|
32
|
+
COLLAPSIBLE = %i[offcanvas icon none].freeze
|
|
33
|
+
|
|
34
|
+
# The expanded column width.
|
|
35
|
+
WIDTH = "16rem"
|
|
36
|
+
# The collapsed icon-rail width.
|
|
37
|
+
WIDTH_ICON = "3rem"
|
|
38
|
+
# The mobile sheet's panel width.
|
|
39
|
+
WIDTH_MOBILE = "18rem"
|
|
40
|
+
|
|
41
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
42
|
+
AGENT_RULES = [
|
|
43
|
+
"Wrap the WHOLE shell: with_nav is the sidebar column, with_inset is the page area " \
|
|
44
|
+
"(the trigger lives in the inset).",
|
|
45
|
+
"Read the persisted state server-side - open: cookies[:sidebar_state] != \"false\" - so the " \
|
|
46
|
+
"first paint has no collapse flash.",
|
|
47
|
+
"collapsible: :icon keeps icon rails visible when collapsed; :offcanvas slides it fully away; " \
|
|
48
|
+
":none is a static column.",
|
|
49
|
+
"Menu entries are poetry_sidebar_menu_button(href:) links (active: marks the current route) - " \
|
|
50
|
+
"navigation navigates."
|
|
51
|
+
].freeze
|
|
52
|
+
|
|
53
|
+
# The same facts the before_render raise enforces, stated statically
|
|
54
|
+
# so static checks can flag a missing nav without rendering.
|
|
55
|
+
REQUIRED_SLOTS = { nav: "the sidebar column" }.freeze
|
|
56
|
+
|
|
57
|
+
renders_one :nav, doc: "The sidebar column's content (required) - groups, menus, header/footer."
|
|
58
|
+
renders_one :inset, doc: "The page area beside the column - rendered as the <main> inset."
|
|
59
|
+
|
|
60
|
+
use_stimulus do
|
|
61
|
+
on :root do
|
|
62
|
+
controller :sidebar do
|
|
63
|
+
register
|
|
64
|
+
value :open
|
|
65
|
+
value :collapsible
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
on :peer do
|
|
69
|
+
controller(:sidebar) { target :sidebar }
|
|
70
|
+
end
|
|
71
|
+
on :inner do
|
|
72
|
+
controller(:sidebar) { target :inner }
|
|
73
|
+
end
|
|
74
|
+
# The mobile sheet <dialog>: the Dialog-family cancel/backdrop
|
|
75
|
+
# pair under sidebar-namespaced action names.
|
|
76
|
+
on :mobile do
|
|
77
|
+
controller :sidebar do
|
|
78
|
+
target :mobile_dialog
|
|
79
|
+
action :close_mobile, on: :cancel
|
|
80
|
+
action :mobile_backdrop_close, on: :click
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
on :mobile_inner do
|
|
84
|
+
controller(:sidebar) { target :mobile_inner }
|
|
85
|
+
end
|
|
86
|
+
# Rendered by the poetry_sidebar_trigger / poetry_sidebar_rail
|
|
87
|
+
# helpers (helper-side strings; declared here so the contract
|
|
88
|
+
# covers the whole family surface).
|
|
89
|
+
on :trigger do
|
|
90
|
+
controller(:sidebar) { action :toggle, on: :click }
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
option :open, :boolean, default: true,
|
|
95
|
+
doc: "The expanded/collapsed state at first paint - feed it from the persisted " \
|
|
96
|
+
"cookie so there is no collapse flash."
|
|
97
|
+
option :side, :symbol, default: :left, doc: "Which edge the column hangs on."
|
|
98
|
+
option :variant, :symbol, default: :sidebar,
|
|
99
|
+
doc: "The column treatment: flush column, floating card, or inset panel."
|
|
100
|
+
option :collapsible, :symbol, default: :offcanvas,
|
|
101
|
+
doc: "What collapsing does: slide fully away, shrink to an icon rail, or :none " \
|
|
102
|
+
"for a static column."
|
|
103
|
+
|
|
104
|
+
validates :side, inclusion: { in: SIDES }
|
|
105
|
+
validates :variant, inclusion: { in: VARIANTS }
|
|
106
|
+
validates :collapsible, inclusion: { in: COLLAPSIBLE }
|
|
107
|
+
|
|
108
|
+
part "sidebar-wrapper", "The provider shell around the column, the mobile dialog, and the inset",
|
|
109
|
+
vars: {
|
|
110
|
+
"--sidebar-width" => "the expanded column width (16rem) - the gap/container geometry reads it",
|
|
111
|
+
"--sidebar-width-icon" => "the collapsed icon-rail width (3rem)"
|
|
112
|
+
}
|
|
113
|
+
part "sidebar", "The desktop state peer - the collapse state lives here and the pure-CSS " \
|
|
114
|
+
"group-data chrome keys on it",
|
|
115
|
+
states: {
|
|
116
|
+
"data-state" => "expanded or collapsed - the controller flips it and persists the cookie",
|
|
117
|
+
"data-collapsible" => { condition: "the collapse mode WHILE collapsed (empty while expanded " \
|
|
118
|
+
"- source parity)",
|
|
119
|
+
values: %w[offcanvas icon none] },
|
|
120
|
+
"data-variant" => { condition: "the column treatment", values: %w[sidebar floating inset] },
|
|
121
|
+
"data-side" => { condition: "which edge the column hangs on", values: %w[left right] }
|
|
122
|
+
}
|
|
123
|
+
part "sidebar-gap", "The in-flow width ghost that pushes the inset over - its width animates " \
|
|
124
|
+
"on collapse"
|
|
125
|
+
part "sidebar-container", "The fixed-position column itself",
|
|
126
|
+
states: {
|
|
127
|
+
"data-side" => { condition: "which edge it pins to", values: %w[left right] }
|
|
128
|
+
}
|
|
129
|
+
part "sidebar-inner", "The flex column receiving the nav slot - the mobile mode adopts its " \
|
|
130
|
+
"children from here"
|
|
131
|
+
part "sidebar-mobile", "The mobile sheet <dialog> (below md) - server-rendered empty; the " \
|
|
132
|
+
"controller adopts the nav children on open",
|
|
133
|
+
states: {
|
|
134
|
+
"data-open" => "sheet is open (presence flips the pair at runtime)",
|
|
135
|
+
"data-closed" => "sheet is closed (the server-rendered state)",
|
|
136
|
+
"data-mobile" => "always \"true\" - the mobile-mode marker",
|
|
137
|
+
"data-side" => { condition: "which edge the sheet slides from", values: %w[left right] },
|
|
138
|
+
"data-sidebar" => "always \"sidebar\" - the suite-wide sub-part marker"
|
|
139
|
+
},
|
|
140
|
+
vars: {
|
|
141
|
+
"--sidebar-width" => "overridden inline to the mobile sheet width (18rem)"
|
|
142
|
+
}
|
|
143
|
+
part "sidebar-mobile-inner", "The adoption container the nav children move into while the " \
|
|
144
|
+
"sheet is open"
|
|
145
|
+
part "sidebar-inset", "The <main> page area beside the column"
|
|
146
|
+
part "sidebar-header", "Top block of the column (with_nav content)"
|
|
147
|
+
part "sidebar-footer", "Bottom block of the column"
|
|
148
|
+
part "sidebar-content", "The scrollable middle of the column"
|
|
149
|
+
part "sidebar-group", "One titled section inside the content"
|
|
150
|
+
part "sidebar-group-label", "The section heading - fades and collapses away in icon mode"
|
|
151
|
+
part "sidebar-menu", "The <ul> of menu items inside a group"
|
|
152
|
+
part "sidebar-menu-item", "One <li> menu row (the group/menu-item hover scope)"
|
|
153
|
+
part "sidebar-menu-button", "The row's link (href:) or button - the navigation entry itself",
|
|
154
|
+
states: {
|
|
155
|
+
"data-active" => "the current route (active: - links also get aria-current=page)",
|
|
156
|
+
"data-open" => "when the button is a collapsible's trigger - the disclosure state the " \
|
|
157
|
+
"collapsible controller flips",
|
|
158
|
+
"data-size" => "the row size variant (default, sm, or lg) - the action/badge tops key on it",
|
|
159
|
+
"data-variant" => { condition: "always - the treatment", values: %w[default outline] }
|
|
160
|
+
}
|
|
161
|
+
part "sidebar-menu-action", "The item-corner action button, absolutely positioned in the row",
|
|
162
|
+
states: {
|
|
163
|
+
"data-sidebar" => "always \"menu-action\" - the suite-wide sub-part marker"
|
|
164
|
+
}
|
|
165
|
+
part "sidebar-menu-badge", "The trailing count/status chrome in the row corner - " \
|
|
166
|
+
"pointer-transparent",
|
|
167
|
+
states: {
|
|
168
|
+
"data-sidebar" => "always \"menu-badge\" - the suite-wide sub-part marker"
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
# @api private
|
|
172
|
+
def before_render
|
|
173
|
+
raise ArgumentError, "Sidebar requires with_nav (the sidebar column)" unless nav?
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
# @api private
|
|
177
|
+
def data_state
|
|
178
|
+
open ? "expanded" : "collapsed"
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# data-collapsible carries the mode only WHILE collapsed - the
|
|
182
|
+
# expanded peer has an empty data-collapsible.
|
|
183
|
+
# @api private
|
|
184
|
+
def data_collapsible
|
|
185
|
+
open ? "" : collapsible.to_s
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# @api private
|
|
189
|
+
def inset_variant?
|
|
190
|
+
%i[floating inset].include?(variant)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# @api private
|
|
194
|
+
def root_attributes
|
|
195
|
+
html_attributes.merge_if_not_set(
|
|
196
|
+
{
|
|
197
|
+
"data-slot" => "sidebar-wrapper",
|
|
198
|
+
"style" => "--sidebar-width: #{WIDTH}; --sidebar-width-icon: #{WIDTH_ICON};",
|
|
199
|
+
"class" => css(:wrapper)
|
|
200
|
+
}.merge(stimulus_attributes_for(:root)).merge(component_data_attributes)
|
|
201
|
+
)
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
# @api private
|
|
205
|
+
def peer_attributes
|
|
206
|
+
{
|
|
207
|
+
"data-slot" => "sidebar", "class" => css(:peer),
|
|
208
|
+
"data-state" => data_state, "data-collapsible" => data_collapsible,
|
|
209
|
+
"data-variant" => variant, "data-side" => side
|
|
210
|
+
}.merge(stimulus_attributes_for(:peer))
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
# @api private
|
|
214
|
+
def gap_classes
|
|
215
|
+
inset_variant? ? "#{css(:gap)} #{css(:gap_inset)}" : css(:gap)
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
# @api private
|
|
219
|
+
def container_classes
|
|
220
|
+
inset_variant? ? "#{css(:container)} #{css(:container_inset)}" : css(:container)
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# The mobile sheet <dialog> (DOM-move): server-rendered
|
|
224
|
+
# EMPTY - the controller adopts the nav children on open. Skinned
|
|
225
|
+
# with the Sheet's presence classes off the sidebar dictionary;
|
|
226
|
+
# md:hidden keeps it out of the desktop layout wholesale.
|
|
227
|
+
# @api private
|
|
228
|
+
def mobile_dialog_attributes
|
|
229
|
+
attrs = {
|
|
230
|
+
"data-slot" => "sidebar-mobile", "data-sidebar" => "sidebar",
|
|
231
|
+
"data-mobile" => "true", "data-side" => side, "data-closed" => "",
|
|
232
|
+
"class" => "#{css(:mobile)} #{Style.mobile_side(side)}",
|
|
233
|
+
"style" => "--sidebar-width: #{WIDTH_MOBILE};",
|
|
234
|
+
"aria-labelledby" => mobile_title_id
|
|
235
|
+
}
|
|
236
|
+
attrs.merge(stimulus_attributes_for(:mobile))
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# @api private
|
|
240
|
+
def mobile_title_id
|
|
241
|
+
@mobile_title_id ||= poetry_instance_id("poetry-sidebar-mobile")
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
private :data_state, :data_collapsible, :inset_variant?, :root_attributes, :peer_attributes, :gap_classes
|
|
245
|
+
private :container_classes, :mobile_dialog_attributes, :mobile_title_id
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
249
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Sidebar
|
|
6
|
+
# The Sidebar preview: the app shell in the icon-collapsible and
|
|
7
|
+
# offcanvas modes (the sidecar template composes the full nav + inset,
|
|
8
|
+
# since it is a helper-heavy structure).
|
|
9
|
+
class Preview < Poetry::Core::Preview::Base
|
|
10
|
+
def default
|
|
11
|
+
render_with_template(template: "poetry/ui/sidebar/shell_preview", locals: { collapsible: :icon })
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def offcanvas_collapsed
|
|
15
|
+
render_with_template(template: "poetry/ui/sidebar/shell_preview",
|
|
16
|
+
locals: { collapsible: :offcanvas, open: false })
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
<%# The app shell: a grouped nav column + a page inset with the trigger. %>
|
|
2
|
+
<% open = local_assigns.fetch(:open, true) %>
|
|
3
|
+
<div class="h-96 overflow-hidden rounded-lg border">
|
|
4
|
+
<%= poetry_sidebar(collapsible: collapsible, open: open) do |shell| %>
|
|
5
|
+
<% shell.with_nav do %>
|
|
6
|
+
<%= poetry_sidebar_header do %>
|
|
7
|
+
<div class="flex items-center gap-2 px-2 py-1 text-sm font-semibold">Acme Inc</div>
|
|
8
|
+
<% end %>
|
|
9
|
+
<%= poetry_sidebar_content do %>
|
|
10
|
+
<%= poetry_sidebar_group do %>
|
|
11
|
+
<%= poetry_sidebar_group_label { "Platform" } %>
|
|
12
|
+
<%= poetry_sidebar_menu do %>
|
|
13
|
+
<%= poetry_sidebar_menu_item do %>
|
|
14
|
+
<%= poetry_sidebar_menu_button(href: "#", active: true) do %>
|
|
15
|
+
<%= poetry_icon(name: :"layout-dashboard") %><span>Dashboard</span>
|
|
16
|
+
<% end %>
|
|
17
|
+
<% end %>
|
|
18
|
+
<%= poetry_sidebar_menu_item do %>
|
|
19
|
+
<%= poetry_sidebar_menu_button(href: "#") do %>
|
|
20
|
+
<%= poetry_icon(name: :inbox) %><span>Inbox</span>
|
|
21
|
+
<% end %>
|
|
22
|
+
<%= poetry_sidebar_menu_badge do %>12<% end %>
|
|
23
|
+
<% end %>
|
|
24
|
+
<%= poetry_sidebar_menu_item do %>
|
|
25
|
+
<%= poetry_sidebar_menu_button(href: "#") do %>
|
|
26
|
+
<%= poetry_icon(name: :settings) %><span>Settings</span>
|
|
27
|
+
<% end %>
|
|
28
|
+
<%= poetry_sidebar_menu_action(label: "Settings options") do %>
|
|
29
|
+
<%= poetry_icon(name: :"ellipsis") %>
|
|
30
|
+
<% end %>
|
|
31
|
+
<% end %>
|
|
32
|
+
<% end %>
|
|
33
|
+
<% end %>
|
|
34
|
+
<% end %>
|
|
35
|
+
<%= poetry_sidebar_footer do %>
|
|
36
|
+
<div class="px-2 py-1 text-xs text-muted-foreground">v1.0.0</div>
|
|
37
|
+
<% end %>
|
|
38
|
+
<% end %>
|
|
39
|
+
<% shell.with_inset do %>
|
|
40
|
+
<div class="flex items-center gap-2 border-b p-3">
|
|
41
|
+
<%= poetry_sidebar_trigger %>
|
|
42
|
+
<span class="text-sm font-medium">Dashboard</span>
|
|
43
|
+
</div>
|
|
44
|
+
<div class="p-4 text-sm text-muted-foreground">Main content area.</div>
|
|
45
|
+
<% end %>
|
|
46
|
+
<% end %>
|
|
47
|
+
</div>
|