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,50 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Avatar
|
|
6
|
+
# The Avatar preview: the initials fallback (the deterministic base
|
|
7
|
+
# state), the image layer actually covering it (a data-URI svg, so the
|
|
8
|
+
# browser rig loads it without a network), sizes, a badge, and the
|
|
9
|
+
# stacked group via the sidecar template.
|
|
10
|
+
class Preview < Poetry::Core::Preview::Base
|
|
11
|
+
# A gradient + head-and-shoulders silhouette - unlike the 1x1 solid
|
|
12
|
+
# pixel it replaced, this is visibly an image, so the screenshot can
|
|
13
|
+
# tell "image loaded" apart from a tinted fallback.
|
|
14
|
+
IMAGE = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2NC" \
|
|
15
|
+
"A2NCI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJnIiB4MT0iMCIgeTE9IjAiIHgyPSIxIiB5Mj0iMSI+PHN0b3Agb2Zmc2V0PS" \
|
|
16
|
+
"IwIiBzdG9wLWNvbG9yPSIjNjM2NmYxIi8+PHN0b3Agb2Zmc2V0PSIuNTUiIHN0b3AtY29sb3I9IiM4YjVjZjYiLz48c3RvcCBvZm" \
|
|
17
|
+
"ZzZXQ9IjEiIHN0b3AtY29sb3I9IiNlYzQ4OTkiLz48L2xpbmVhckdyYWRpZW50PjwvZGVmcz48cmVjdCB3aWR0aD0iNjQiIGhlaW" \
|
|
18
|
+
"dodD0iNjQiIGZpbGw9InVybCgjZykiLz48Y2lyY2xlIGN4PSIzMiIgY3k9IjI1IiByPSIxMCIgZmlsbD0iI2ZmZiIgb3BhY2l0eT" \
|
|
19
|
+
"0iLjkiLz48cGF0aCBkPSJNMTIgNjRjMi0xMyAxMC0xOSAyMC0xOXMxOCA2IDIwIDE5eiIgZmlsbD0iI2ZmZiIgb3BhY2l0eT0iLj" \
|
|
20
|
+
"kiLz48L3N2Zz4="
|
|
21
|
+
|
|
22
|
+
def default
|
|
23
|
+
render_component(label: "Matt Solt") { "MS" }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def with_image
|
|
27
|
+
render_component(src: IMAGE, label: "Grace Hopper") { "GH" }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def small_with_badge
|
|
31
|
+
render_component(size: :sm, label: "Ada Lovelace (online)") do |avatar|
|
|
32
|
+
avatar.with_badge { "" }
|
|
33
|
+
"AL"
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def large
|
|
38
|
+
render_component(size: :lg, label: "Annie Easley") { "AE" }
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def group
|
|
42
|
+
# An explicit per-example template: a CLASS-level preview.html.erb
|
|
43
|
+
# would shadow the shared default for EVERY example (the contrib
|
|
44
|
+
# sidecar contract), silently replacing the other previews.
|
|
45
|
+
render_with_template(template: "poetry/ui/avatar/group_preview")
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Avatar
|
|
6
|
+
# Re-expressed through the cn-* theme layer.
|
|
7
|
+
# :image keeps the "absolute inset-0" rule inline (the
|
|
8
|
+
# server-native layered fallback keeps BOTH fallback and image in the
|
|
9
|
+
# DOM, so the image must cover the initials); the after:* ring
|
|
10
|
+
# machinery stays inline as a structural rule.
|
|
11
|
+
class Style < Poetry::Core::Style
|
|
12
|
+
base "cn-avatar group/avatar relative flex shrink-0 select-none " \
|
|
13
|
+
"after:absolute after:inset-0 after:border after:border-border " \
|
|
14
|
+
"after:mix-blend-darken dark:after:mix-blend-lighten"
|
|
15
|
+
|
|
16
|
+
element :image, "cn-avatar-image absolute inset-0 aspect-square size-full object-cover"
|
|
17
|
+
element :fallback, "cn-avatar-fallback flex size-full items-center justify-center " \
|
|
18
|
+
"text-sm group-data-[size=sm]/avatar:text-xs"
|
|
19
|
+
element :badge, "cn-avatar-badge absolute right-0 bottom-0 z-10 inline-flex items-center " \
|
|
20
|
+
"justify-center rounded-full bg-blend-color ring-2 select-none " \
|
|
21
|
+
"group-data-[size=default]/avatar:[&>svg]:size-2 " \
|
|
22
|
+
"group-data-[size=default]/avatar:size-2.5 group-data-[size=lg]/avatar:[&>svg]:size-2 " \
|
|
23
|
+
"group-data-[size=lg]/avatar:size-3 group-data-[size=sm]/avatar:[&>svg]:hidden " \
|
|
24
|
+
"group-data-[size=sm]/avatar:size-2"
|
|
25
|
+
|
|
26
|
+
# The stack (poetry_avatar_group) + its overflow count.
|
|
27
|
+
element :group, "group/avatar-group flex -space-x-2 " \
|
|
28
|
+
"*:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background"
|
|
29
|
+
element :group_count, "cn-avatar-group-count relative flex shrink-0 items-center " \
|
|
30
|
+
"justify-center ring-2 ring-background"
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# Non-interactive status pills.
|
|
6
|
+
module Badge
|
|
7
|
+
# A small status pill. Variants carry semantic intent: the solid
|
|
8
|
+
# set (default/secondary/destructive/outline/ghost/link) for labels
|
|
9
|
+
# and emphasis, plus the soft status trio (success/warning/info) -
|
|
10
|
+
# the muted color-coded pills record-status columns need.
|
|
11
|
+
#
|
|
12
|
+
# Badges are non-interactive; the one interactive form is href:,
|
|
13
|
+
# which renders the pill as a real link.
|
|
14
|
+
#
|
|
15
|
+
# @example A soft status pill
|
|
16
|
+
# render Poetry::Ui::Badge::Component.new(variant: :success) { "Fulfilled" }
|
|
17
|
+
class Component < Poetry::Core::Component
|
|
18
|
+
# A status label with no text is an invisible sliver.
|
|
19
|
+
requires_content "the visible status text"
|
|
20
|
+
|
|
21
|
+
# The closed vocabulary for the variant axis.
|
|
22
|
+
VARIANTS = %i[default secondary destructive outline ghost link success warning info].freeze
|
|
23
|
+
|
|
24
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
25
|
+
AGENT_RULES = [
|
|
26
|
+
"Badges are non-interactive status labels - never attach click handlers; use Button for " \
|
|
27
|
+
"actions. The one interactive form is href:, which renders the badge AS a real link " \
|
|
28
|
+
"(a navigational chip - the themes' [a&]:hover treatments activate).",
|
|
29
|
+
"The visible text is the content block: render ... { \"beta\" } - there is no label: option.",
|
|
30
|
+
"Pick the variant by intent (destructive = error states; success/warning/info = record " \
|
|
31
|
+
"status, e.g. Fulfilled/Processing/Syncing), never by color preference.",
|
|
32
|
+
"Status badges on one surface read as a SET: keep one treatment family per table/list - " \
|
|
33
|
+
"the soft trio (+ outline for neutral) together, or the solid pair together; never a " \
|
|
34
|
+
"solid destructive pill inside a soft status column (design lint flags the mix)."
|
|
35
|
+
].freeze
|
|
36
|
+
|
|
37
|
+
style :variant, default: :default, required: true, variants: VARIANTS,
|
|
38
|
+
doc: "The intent axis; success/warning/info are the soft record-status treatments."
|
|
39
|
+
|
|
40
|
+
option :href, :string,
|
|
41
|
+
doc: "Renders the pill as a real <a> - a navigational chip; the theme's link hover treatments " \
|
|
42
|
+
"activate on exactly this element."
|
|
43
|
+
|
|
44
|
+
part "badge", "The status pill itself (a <span>; a real <a> when href: is given) - " \
|
|
45
|
+
"the whole component is this one element",
|
|
46
|
+
states: {
|
|
47
|
+
"data-variant" => { condition: "always - the resolved variant",
|
|
48
|
+
values: VARIANTS.map(&:to_s) }
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
# Enforces the visible-text content block.
|
|
52
|
+
# @api private
|
|
53
|
+
def before_render
|
|
54
|
+
ensure_content!
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# @api private
|
|
58
|
+
def call
|
|
59
|
+
content_tag(href.present? ? :a : :span, content, **root_attributes.to_attributes)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @api private
|
|
63
|
+
def root_attributes
|
|
64
|
+
attrs = { "data-slot" => "badge", "data-variant" => variant }
|
|
65
|
+
attrs["href"] = href if href.present?
|
|
66
|
+
html_attributes.merge_if_not_set(attrs.merge(component_data_attributes))
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
private :root_attributes
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Badge
|
|
6
|
+
class Preview < Poetry::Core::Preview::Base
|
|
7
|
+
def default
|
|
8
|
+
render_component(variant: :default) { "New" }
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def secondary
|
|
12
|
+
render_component(variant: :secondary) { "Draft" }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def destructive
|
|
16
|
+
render_component(variant: :destructive) { "Failed" }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def outline
|
|
20
|
+
render_component(variant: :outline) { "Beta" }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def ghost
|
|
24
|
+
render_component(variant: :ghost) { "Muted on hover" }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# The link VARIANT (distinct from the badge-as-anchor example below).
|
|
28
|
+
def link_variant
|
|
29
|
+
render_component(variant: :link) { "Reference" }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Badge-as-link (upstream badge#link parity): a real <a>, so the
|
|
33
|
+
# axe walk covers the anchor treatment and its contrast.
|
|
34
|
+
def link
|
|
35
|
+
render_component(href: "#changelog") { "v2.0 release notes" }
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# The status vocabulary: soft tints on the status
|
|
39
|
+
# tokens - the axe walk holds every theme's treatment to AA here.
|
|
40
|
+
def success
|
|
41
|
+
render_component(variant: :success) { "Fulfilled" }
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def warning
|
|
45
|
+
render_component(variant: :warning) { "Processing" }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def info
|
|
49
|
+
render_component(variant: :info) { "Syncing" }
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Badge
|
|
6
|
+
# Re-expressed through the cn-* theme layer. The focus/invalid
|
|
7
|
+
# ring chain deviates from upstream's inline split DELIBERATELY: the
|
|
8
|
+
# destructive variant re-colors focus-visible:ring-* in the theme and
|
|
9
|
+
# can only beat the base treatment from the same layer (the
|
|
10
|
+
# split-side conflict rule).
|
|
11
|
+
class Style < Poetry::Core::Style
|
|
12
|
+
base "cn-badge inline-flex w-fit shrink-0 items-center justify-center overflow-hidden " \
|
|
13
|
+
"whitespace-nowrap [&>svg]:pointer-events-none aria-invalid:border-destructive " \
|
|
14
|
+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 " \
|
|
15
|
+
"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 " \
|
|
16
|
+
"group/badge"
|
|
17
|
+
|
|
18
|
+
# success/warning/info: the poetry-original soft status vocabulary
|
|
19
|
+
# (upstream Badge has no status variants); every theme carries the
|
|
20
|
+
# soft treatment on the new status tokens.
|
|
21
|
+
variant :variant, {
|
|
22
|
+
ghost: "cn-badge-variant-ghost",
|
|
23
|
+
link: "cn-badge-variant-link",
|
|
24
|
+
default: "cn-badge-variant-default",
|
|
25
|
+
secondary: "cn-badge-variant-secondary",
|
|
26
|
+
destructive: "cn-badge-variant-destructive",
|
|
27
|
+
outline: "cn-badge-variant-outline",
|
|
28
|
+
success: "cn-badge-variant-success",
|
|
29
|
+
warning: "cn-badge-variant-warning",
|
|
30
|
+
info: "cn-badge-variant-info"
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<%= content_tag(:nav, **root_attributes.to_attributes) do %>
|
|
2
|
+
<ol data-slot="breadcrumb-list" class="<%= css(:list) %>">
|
|
3
|
+
<% entries.each_with_index do |entry, index| %>
|
|
4
|
+
<li data-slot="breadcrumb-item" class="<%= css(:item) %>">
|
|
5
|
+
<% if entry.ellipsis %>
|
|
6
|
+
<span data-slot="breadcrumb-ellipsis" role="presentation" aria-hidden="true" class="<%= css(:ellipsis) %>">
|
|
7
|
+
<%= render Poetry::Ui::Icon::Component.new(name: :ellipsis) %>
|
|
8
|
+
</span>
|
|
9
|
+
<span class="sr-only">More</span>
|
|
10
|
+
<% else %>
|
|
11
|
+
<% if entry.block %>
|
|
12
|
+
<%= capture(&entry.block) %>
|
|
13
|
+
<% elsif entry.href.present? %>
|
|
14
|
+
<a data-slot="breadcrumb-link" href="<%= entry.href %>" class="<%= css(:link) %>"><%= entry.label %></a>
|
|
15
|
+
<% else %>
|
|
16
|
+
<span data-slot="breadcrumb-page" role="link" aria-disabled="true" aria-current="page"
|
|
17
|
+
class="<%= css(:page) %>"><%= entry.label %></span>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% end %>
|
|
20
|
+
</li>
|
|
21
|
+
<% unless index == entries.size - 1 %>
|
|
22
|
+
<li data-slot="breadcrumb-separator" role="presentation" aria-hidden="true" class="<%= css(:separator) %>">
|
|
23
|
+
<% if separator_block %>
|
|
24
|
+
<%= capture(&separator_block) %>
|
|
25
|
+
<% else %>
|
|
26
|
+
<%= render Poetry::Ui::Icon::Component.new(name: :"chevron-right", class: "cn-rtl-flip") %>
|
|
27
|
+
<% end %>
|
|
28
|
+
</li>
|
|
29
|
+
<% end %>
|
|
30
|
+
<% end %>
|
|
31
|
+
</ol>
|
|
32
|
+
<% end %>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# Ancestor-trail navigation.
|
|
6
|
+
module Breadcrumb
|
|
7
|
+
# A navigation trail of ancestor links. Declare the trail (with_item
|
|
8
|
+
# per crumb, with_ellipsis for a collapsed middle) and the component
|
|
9
|
+
# owns the <nav>/<ol> chrome, the separators, and the current-page
|
|
10
|
+
# semantics. An item with href: is a link; an item without href:
|
|
11
|
+
# is the current page (aria-current="page").
|
|
12
|
+
#
|
|
13
|
+
# @example
|
|
14
|
+
# <%= poetry_breadcrumb do |crumb| %>
|
|
15
|
+
# <% crumb.with_item("Home", href: "/") %>
|
|
16
|
+
# <% crumb.with_ellipsis %>
|
|
17
|
+
# <% crumb.with_item("Breadcrumb") %>
|
|
18
|
+
# <% end %>
|
|
19
|
+
class Component < Poetry::Core::Component
|
|
20
|
+
# The caller's separator block, captured by with_separator.
|
|
21
|
+
# @api private
|
|
22
|
+
attr_reader :separator_block
|
|
23
|
+
|
|
24
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
25
|
+
AGENT_RULES = [
|
|
26
|
+
"Declare the trail with with_item(label, href:) - never hand-build the nav/ol/li chain.",
|
|
27
|
+
"The current page is the item WITHOUT href: (it renders aria-current=page, not a link).",
|
|
28
|
+
"Collapse a long middle with with_ellipsis - it announces 'More' to screen readers.",
|
|
29
|
+
"A BLOCK item (with_item { ... }) renders your content inside the <li> - the seat for a " \
|
|
30
|
+
"dropdown crumb or a custom-rendered link; you own its semantics (aria-current only " \
|
|
31
|
+
"applies to label items).",
|
|
32
|
+
"with_separator(icon: :dot) - or a block - replaces the chevron in EVERY gap; the default " \
|
|
33
|
+
"chevron RTL-flips, a custom glyph is used as given."
|
|
34
|
+
].freeze
|
|
35
|
+
|
|
36
|
+
# Slots the component cannot render without; static checks read this without rendering.
|
|
37
|
+
REQUIRED_SLOTS = { item: "at least one item" }.freeze
|
|
38
|
+
|
|
39
|
+
renders_many :items,
|
|
40
|
+
doc: "The crumbs, in declaration order. A label with href: renders a link; without one, the " \
|
|
41
|
+
"current page. A block makes the <li>'s content caller-owned (a dropdown crumb, a " \
|
|
42
|
+
"custom-rendered link).",
|
|
43
|
+
renders: lambda { |label = nil, href: nil, ellipsis: false, &block|
|
|
44
|
+
entries << Entry.new(label: label, href: href, ellipsis: ellipsis, block: block)
|
|
45
|
+
nil
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
renders_one :separator,
|
|
49
|
+
doc: "Replaces the separator glyph in EVERY gap: an icon name, or a block for arbitrary " \
|
|
50
|
+
"content. Absent, the default chevron renders (with its RTL flip - a custom glyph is used " \
|
|
51
|
+
"as given).",
|
|
52
|
+
renders: lambda { |icon: nil, &block|
|
|
53
|
+
@separator_block = icon ? proc { render Icon::Component.new(name: icon) } : block
|
|
54
|
+
nil
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
part "breadcrumb", "The <nav> landmark (aria-label=breadcrumb) around the trail"
|
|
58
|
+
part "breadcrumb-list", "The <ol> laying crumbs and separators out as one wrapping row"
|
|
59
|
+
part "breadcrumb-item", "One <li> of the trail - wraps a link, the current page, the ellipsis, " \
|
|
60
|
+
"or a block item's own content (a dropdown crumb, a custom link)"
|
|
61
|
+
part "breadcrumb-link", "A crumb with href: - a real <a> to an ancestor page"
|
|
62
|
+
part "breadcrumb-page", "The current page (the item without href:) - aria-current=page, not a link"
|
|
63
|
+
part "breadcrumb-separator", "The chevron <li> between crumbs - presentational, aria-hidden"
|
|
64
|
+
part "breadcrumb-ellipsis", "The collapsed-middle glyph (with_ellipsis) - aria-hidden; a sibling " \
|
|
65
|
+
"sr-only 'More' announces it"
|
|
66
|
+
|
|
67
|
+
# Enforces the required item slot.
|
|
68
|
+
# @api private
|
|
69
|
+
def before_render
|
|
70
|
+
# items? is the SLOT predicate: it forces the render block (which
|
|
71
|
+
# populates entries) - reading @entries directly here would run
|
|
72
|
+
# before the block ever executed.
|
|
73
|
+
raise ArgumentError, "Breadcrumb requires at least one with_item" unless items?
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Adds a collapsed-middle marker to the trail; screen readers hear "More".
|
|
77
|
+
def with_ellipsis
|
|
78
|
+
with_item(ellipsis: true)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# The declared crumbs in order.
|
|
82
|
+
# @api private
|
|
83
|
+
def entries
|
|
84
|
+
@entries ||= []
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @api private
|
|
88
|
+
def root_attributes
|
|
89
|
+
html_attributes.merge_if_not_set(
|
|
90
|
+
{ "aria-label" => "breadcrumb", "data-slot" => "breadcrumb" }.merge(component_data_attributes)
|
|
91
|
+
)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# One declared crumb.
|
|
95
|
+
# @api private
|
|
96
|
+
Entry = Data.define(:label, :href, :ellipsis, :block)
|
|
97
|
+
|
|
98
|
+
private :entries, :root_attributes
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%# A middle crumb IS a dropdown (upstream breadcrumb#dropdown): the block
|
|
2
|
+
item hands the <li> to caller content; the ghost trigger is restyled to
|
|
3
|
+
read as breadcrumb text. %>
|
|
4
|
+
<%= poetry_breadcrumb do |crumb| %>
|
|
5
|
+
<% crumb.with_item("Home", href: "#") %>
|
|
6
|
+
<% crumb.with_item do %>
|
|
7
|
+
<%= poetry_dropdown_menu(align: :start) do |menu| %>
|
|
8
|
+
<% menu.with_trigger(variant: :ghost, size: :sm,
|
|
9
|
+
class: "h-auto gap-1 p-0 font-normal text-muted-foreground hover:bg-transparent hover:text-foreground") do %>
|
|
10
|
+
Components
|
|
11
|
+
<%= poetry_icon(name: :"chevron-down", class: "size-3.5") %>
|
|
12
|
+
<% end %>
|
|
13
|
+
<% menu.with_group do |group| %>
|
|
14
|
+
<% group.with_item { "Documentation" } %>
|
|
15
|
+
<% group.with_item { "Themes" } %>
|
|
16
|
+
<% group.with_item { "GitHub" } %>
|
|
17
|
+
<% end %>
|
|
18
|
+
<% end %>
|
|
19
|
+
<% end %>
|
|
20
|
+
<% crumb.with_item("Breadcrumb") %>
|
|
21
|
+
<% end %>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Breadcrumb
|
|
6
|
+
# The Breadcrumb preview: a plain trail and a collapsed-middle trail.
|
|
7
|
+
class Preview < Poetry::Core::Preview::Base
|
|
8
|
+
def default
|
|
9
|
+
render_component do |crumb|
|
|
10
|
+
crumb.with_item("Home", href: "#")
|
|
11
|
+
crumb.with_item("Components", href: "#")
|
|
12
|
+
crumb.with_item("Breadcrumb")
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def collapsed
|
|
17
|
+
render_component do |crumb|
|
|
18
|
+
crumb.with_item("Home", href: "#")
|
|
19
|
+
crumb.with_ellipsis
|
|
20
|
+
crumb.with_item("Components", href: "#")
|
|
21
|
+
crumb.with_item("Breadcrumb")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# with_separator swaps the chevron in every gap (upstream
|
|
26
|
+
# breadcrumb#separator - the dot form).
|
|
27
|
+
def dot_separator
|
|
28
|
+
render_component do |crumb|
|
|
29
|
+
crumb.with_separator(icon: :dot)
|
|
30
|
+
crumb.with_item("Home", href: "#")
|
|
31
|
+
crumb.with_item("Components", href: "#")
|
|
32
|
+
crumb.with_item("Breadcrumb")
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# A block item seats a dropdown as a middle crumb (upstream
|
|
37
|
+
# breadcrumb#dropdown) - the axe walk holds the composed menu
|
|
38
|
+
# inside the nav landmark to the same bar as everything else.
|
|
39
|
+
def dropdown_crumb
|
|
40
|
+
render_with_template(template: "poetry/ui/breadcrumb/dropdown_crumb_preview")
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Breadcrumb
|
|
6
|
+
# Re-expressed through the cn-* theme layer. The separator
|
|
7
|
+
# chevron wears cn-rtl-flip (template-side): upstream ships that
|
|
8
|
+
# NAME with no rule anywhere - dead in source - so poetry authors the
|
|
9
|
+
# intended RTL mirror in the theme (rtl:-scale-x-100, LTR-neutral).
|
|
10
|
+
# No cn-breadcrumb root name: the root's poetry surface is empty and
|
|
11
|
+
# empty theme rules don't survive compilation (data-slot remains the
|
|
12
|
+
# restyle hook).
|
|
13
|
+
class Style < Poetry::Core::Style
|
|
14
|
+
base ""
|
|
15
|
+
|
|
16
|
+
element :list, "cn-breadcrumb-list flex flex-wrap items-center wrap-break-word"
|
|
17
|
+
element :item, "cn-breadcrumb-item inline-flex items-center"
|
|
18
|
+
element :link, "cn-breadcrumb-link"
|
|
19
|
+
element :page, "cn-breadcrumb-page"
|
|
20
|
+
element :separator, "cn-breadcrumb-separator"
|
|
21
|
+
element :ellipsis, "cn-breadcrumb-ellipsis flex items-center justify-center"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# Chat message bubbles.
|
|
6
|
+
module Bubble
|
|
7
|
+
# A chat message bubble - one per message, aligned to the sender's
|
|
8
|
+
# side. The content block is the message; tag: :button or :a (with
|
|
9
|
+
# href:) turns the bubble into a quick reply, and the reactions slot
|
|
10
|
+
# overlays a pill of reactions. Purely presentational - no
|
|
11
|
+
# JavaScript.
|
|
12
|
+
#
|
|
13
|
+
# @example An assistant reply
|
|
14
|
+
# render Poetry::Ui::Bubble::Component.new(variant: :secondary) { "Here's the summary." }
|
|
15
|
+
class Component < Poetry::Core::Component
|
|
16
|
+
# The closed vocabulary for the variant axis.
|
|
17
|
+
VARIANTS = %i[default secondary muted tinted outline ghost destructive].freeze
|
|
18
|
+
# The closed vocabulary for the align axis.
|
|
19
|
+
ALIGNS = %i[start end].freeze
|
|
20
|
+
# The closed vocabulary for the tag: axis.
|
|
21
|
+
CONTENT_TAGS = %i[div button a].freeze
|
|
22
|
+
|
|
23
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
24
|
+
AGENT_RULES = [
|
|
25
|
+
"One Bubble per message; stack a sender's run inside poetry_bubble_group.",
|
|
26
|
+
"Quick replies are tag: :button (with the caller's data-action) or tag: :a + " \
|
|
27
|
+
"href: - never a click handler on a div.",
|
|
28
|
+
"ghost is for tool output / system text flowing full-width - not a visual preference.",
|
|
29
|
+
"Reactions REQUIRE label: (the accessible name for the cluster).",
|
|
30
|
+
"Inside a Message, alignment follows the Message's align - do not set both."
|
|
31
|
+
].freeze
|
|
32
|
+
|
|
33
|
+
renders_one :reactions,
|
|
34
|
+
doc: "The reactions pill overlaid on an edge; label: names the cluster for assistive tech, " \
|
|
35
|
+
"side:/align: place it (default bottom end).",
|
|
36
|
+
renders: lambda { |label:, side: :bottom, align: :end, &block|
|
|
37
|
+
content_tag(:div,
|
|
38
|
+
class: css(:reactions), "data-slot" => "bubble-reactions",
|
|
39
|
+
"data-side" => side, "data-align" => align,
|
|
40
|
+
role: "group", "aria-label" => label, &block)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# The content block IS the message; an empty bubble is an empty pill.
|
|
44
|
+
requires_content "the message content"
|
|
45
|
+
|
|
46
|
+
style :variant, default: :default, required: true, variants: VARIANTS,
|
|
47
|
+
doc: "The intent axis; :ghost is for tool output / system text flowing full-width."
|
|
48
|
+
|
|
49
|
+
option :align, :symbol, default: :start,
|
|
50
|
+
doc: "Which side the bubble hugs; inside a Message, set the Message's align instead."
|
|
51
|
+
option :tag, :symbol, default: :div,
|
|
52
|
+
doc: "The content element: :div (default), or :button/:a for a quick reply."
|
|
53
|
+
option :href, :string, doc: "Renders the content as a real anchor; implies tag: :a."
|
|
54
|
+
|
|
55
|
+
validates :align, inclusion: { in: ALIGNS }
|
|
56
|
+
validates :tag, inclusion: { in: CONTENT_TAGS }
|
|
57
|
+
|
|
58
|
+
part "bubble", "The message surface root - variant and alignment ride here",
|
|
59
|
+
states: {
|
|
60
|
+
"data-variant" => { condition: "always - the resolved variant",
|
|
61
|
+
values: VARIANTS.map(&:to_s) },
|
|
62
|
+
"data-align" => { condition: "always - the resolved align",
|
|
63
|
+
values: ALIGNS.map(&:to_s) }
|
|
64
|
+
}
|
|
65
|
+
part "bubble-content", "The body (<div>, or a <button>/<a> quick reply via tag:) - " \
|
|
66
|
+
"the content block renders here"
|
|
67
|
+
part "bubble-reactions", "The reactions pill overlay (role=group, named by label:)",
|
|
68
|
+
states: {
|
|
69
|
+
"data-side" => "always - which edge the pill overlays (default bottom)",
|
|
70
|
+
"data-align" => "always - placement along that edge (default end)"
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
# Enforces the message content block.
|
|
74
|
+
# @api private
|
|
75
|
+
def before_render
|
|
76
|
+
ensure_content!
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# @api private
|
|
80
|
+
def root_attributes
|
|
81
|
+
html_attributes.merge_if_not_set(
|
|
82
|
+
{ "data-slot" => "bubble", "data-variant" => variant, "data-align" => align }
|
|
83
|
+
.merge(component_data_attributes)
|
|
84
|
+
)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# href: implies the anchor - an href on the default :div would
|
|
88
|
+
# otherwise be silently dropped, leaving a dead control.
|
|
89
|
+
# @api private
|
|
90
|
+
def content_tag_name
|
|
91
|
+
href.present? ? :a : tag
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# @api private
|
|
95
|
+
def content_attributes
|
|
96
|
+
attrs = { class: css(:content), "data-slot" => "bubble-content" }
|
|
97
|
+
attrs[:href] = href if content_tag_name == :a
|
|
98
|
+
attrs[:type] = "button" if content_tag_name == :button
|
|
99
|
+
attrs
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private :root_attributes, :content_tag_name, :content_attributes
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Bubble
|
|
6
|
+
# The Bubble preview matrix - one corpus for Lookbook, docs, and the
|
|
7
|
+
# agent visual loop.
|
|
8
|
+
class Preview < Poetry::Core::Preview::Base
|
|
9
|
+
# @!group Variants
|
|
10
|
+
|
|
11
|
+
def default
|
|
12
|
+
render_component { "Sounds good - see you at 10." }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def secondary
|
|
16
|
+
render_component(variant: :secondary) { "Here's the summary you asked for." }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def muted
|
|
20
|
+
render_component(variant: :muted) { "Typing indicator context." }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def tinted
|
|
24
|
+
render_component(variant: :tinted) { "A tinted assistant reply." }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def outline
|
|
28
|
+
render_component(variant: :outline) { "An outlined reply." }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def ghost
|
|
32
|
+
render_component(variant: :ghost) { "Tool output flows full-width without a surface." }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def destructive
|
|
36
|
+
render_component(variant: :destructive) { "That upload failed." }
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# @!endgroup
|
|
40
|
+
|
|
41
|
+
def align_end
|
|
42
|
+
render_component(align: :end) { "Sent by me." }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def quick_reply_button
|
|
46
|
+
render_component(variant: :outline, tag: :button) { "Yes, book it" }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def quick_reply_link
|
|
50
|
+
render_component(variant: :outline, tag: :a, href: "/details") { "View details" }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def with_reactions
|
|
54
|
+
render_component do |bubble|
|
|
55
|
+
bubble.with_reactions(label: "Reactions: thumbs up") { "👍" }
|
|
56
|
+
"Great idea!"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|