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,47 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Bubble
|
|
6
|
+
# Re-expressed through the cn-* theme layer. The variant rules
|
|
7
|
+
# (root classes styling the content child via *:data-[slot] selectors,
|
|
8
|
+
# incl. the tinted relative-color math flagged to the contrast gate)
|
|
9
|
+
# ride the theme; the align choreography and the reactions' side/align
|
|
10
|
+
# translate positioning stay inline (mechanism).
|
|
11
|
+
class Style < Poetry::Core::Style
|
|
12
|
+
base "cn-bubble group/bubble relative flex w-fit min-w-0 flex-col " \
|
|
13
|
+
"group-data-[align=end]/message:self-end data-[align=end]:self-end"
|
|
14
|
+
|
|
15
|
+
variant :variant, {
|
|
16
|
+
default: "cn-bubble-variant-default",
|
|
17
|
+
secondary: "cn-bubble-variant-secondary",
|
|
18
|
+
muted: "cn-bubble-variant-muted",
|
|
19
|
+
tinted: "cn-bubble-variant-tinted",
|
|
20
|
+
outline: "cn-bubble-variant-outline",
|
|
21
|
+
ghost: "cn-bubble-variant-ghost",
|
|
22
|
+
destructive: "cn-bubble-variant-destructive"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
element :group, "cn-bubble-group flex min-w-0 flex-col"
|
|
26
|
+
|
|
27
|
+
element :content, "cn-bubble-content w-fit max-w-full min-w-0 overflow-hidden wrap-break-word " \
|
|
28
|
+
"group-data-[align=end]/bubble:self-end " \
|
|
29
|
+
"[button]:text-left [button,a]:transition-colors [button,a]:outline-none"
|
|
30
|
+
|
|
31
|
+
# The side x align positioning stays inline (mechanism); the pill
|
|
32
|
+
# treatment rides .cn-bubble-reactions. Fixed offsets, NOT translate:
|
|
33
|
+
# translate makes the pill the CONTAINING BLOCK for fixed-position
|
|
34
|
+
# descendants, so a tooltip or popover composed into the reactions
|
|
35
|
+
# slot anchored to the pill and clamped to its width (libraries that
|
|
36
|
+
# portal overlay content to <body> survive this; poetry positions in
|
|
37
|
+
# place). -4.5 = 18px = 75% of the one-line pill height the themes
|
|
38
|
+
# pin - pixel-identical to a 3/4 translate for every pill poetry
|
|
39
|
+
# renders.
|
|
40
|
+
element :reactions, "cn-bubble-reactions absolute z-10 flex w-fit shrink-0 items-center " \
|
|
41
|
+
"justify-center data-[side=top]:-top-4.5 " \
|
|
42
|
+
"data-[side=bottom]:-bottom-4.5 " \
|
|
43
|
+
"data-[align=start]:left-3 data-[align=end]:right-3"
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<%= content_tag(root_tag, **root_attributes.to_attributes) do %>
|
|
2
|
+
<% if loading %>
|
|
3
|
+
<span data-slot="spinner" aria-hidden="true"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" class="animate-spin"><path d="M21 12a9 9 0 1 1-6.219-8.56" /></svg></span>
|
|
4
|
+
<% end %>
|
|
5
|
+
<% if leading? %><span data-slot="icon" aria-hidden="true"><%= leading %></span><% end %>
|
|
6
|
+
<%# contents: the label span must not create an inline box - a block-level
|
|
7
|
+
svg passed IN the content (icon + text + kbd) would force a line break
|
|
8
|
+
inside it (Tailwind preflight makes svg display:block). display:contents
|
|
9
|
+
promotes the content to flex items of the button, so items-center and
|
|
10
|
+
gap apply exactly as upstream (where children are direct flex items). %>
|
|
11
|
+
<% if icon_only? %><%= content %><% else %><span data-slot="label" class="contents"><%= content %></span><% end %>
|
|
12
|
+
<% if trailing? %><span data-slot="icon" aria-hidden="true"><%= trailing %></span><% end %>
|
|
13
|
+
<% if loading %><span class="sr-only"><%= t("poetry.button.loading") %></span><% end %>
|
|
14
|
+
<% end %>
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# Action buttons and button-styled links.
|
|
6
|
+
module Button
|
|
7
|
+
# A button. Variants carry semantic intent (one default-variant
|
|
8
|
+
# action per view); size covers text and icon-only forms. Renders a
|
|
9
|
+
# real <a> when href: is given, and a no-JS loading state
|
|
10
|
+
# (aria-busy + spinner) via loading:.
|
|
11
|
+
#
|
|
12
|
+
# Icon-only sizes require label: - an icon button without an
|
|
13
|
+
# accessible name raises.
|
|
14
|
+
#
|
|
15
|
+
# @example
|
|
16
|
+
# render Poetry::Ui::Button::Component.new(variant: :default) { "Save" }
|
|
17
|
+
class Component < Poetry::Core::Component
|
|
18
|
+
# The closed vocabulary for the variant axis.
|
|
19
|
+
VARIANTS = %i[default destructive outline secondary ghost link].freeze
|
|
20
|
+
# The closed vocabulary for the size axis; icon* are the square icon-only forms.
|
|
21
|
+
SIZES = %i[default xs sm lg icon icon-xs icon-sm icon-lg].freeze
|
|
22
|
+
# The closed vocabulary for the native type: attribute.
|
|
23
|
+
TYPES = %i[button submit reset].freeze
|
|
24
|
+
|
|
25
|
+
# The contract's agent-rules section (projected into the registry,
|
|
26
|
+
# llms.txt, and the generated agent-rules.md).
|
|
27
|
+
AGENT_RULES = [
|
|
28
|
+
"Use poetry_button - never a raw <button> with hand-written Tailwind.",
|
|
29
|
+
"The visible text is the content block: poetry_button { \"Save\" }. label: is ONLY the accessible name.",
|
|
30
|
+
"Icon-only buttons (size: :icon*) MUST pass label: (the accessible name).",
|
|
31
|
+
"Link-styled actions use variant: :link - not <a> with button classes.",
|
|
32
|
+
"Navigation wearing button styling: pass href: (renders a real <a>; tag: :a is implied) - " \
|
|
33
|
+
"never onclick navigation.",
|
|
34
|
+
"Loading via loading: - never a manual disabled + spinner.",
|
|
35
|
+
"Never nest an interactive element inside a Button.",
|
|
36
|
+
"Pick the variant by intent; one primary (default) action per view."
|
|
37
|
+
].freeze
|
|
38
|
+
|
|
39
|
+
# At least one of these must be present or nothing visible renders;
|
|
40
|
+
# static checks read this without rendering.
|
|
41
|
+
REQUIRES_ANY = [
|
|
42
|
+
{ hint: "nothing visible renders without one - label: is only the accessible name",
|
|
43
|
+
content: true, slots: %w[leading trailing], options: %w[loading] }
|
|
44
|
+
].freeze
|
|
45
|
+
|
|
46
|
+
renders_one :leading, doc: "Optional leading visual, rendered inside the icon span."
|
|
47
|
+
renders_one :trailing, doc: "Optional trailing visual, rendered inside the icon span."
|
|
48
|
+
|
|
49
|
+
style :variant, default: :default, required: true, variants: VARIANTS,
|
|
50
|
+
doc: "The visual intent axis; :destructive marks irreversible actions."
|
|
51
|
+
style :size, default: :default, required: true, variants: SIZES,
|
|
52
|
+
doc: "The size axis; the icon* sizes are square icon-only forms (label: required)."
|
|
53
|
+
|
|
54
|
+
option :type, :symbol, default: :button,
|
|
55
|
+
doc: "The native button type; ignored when the button renders as an anchor."
|
|
56
|
+
option :tag, :symbol, default: :button,
|
|
57
|
+
doc: "Renders the same styling on an <a> when :a - navigation wearing button clothes."
|
|
58
|
+
option :disabled, :boolean, default: false,
|
|
59
|
+
doc: "Disables the control (native disabled; aria-disabled on the anchor form)."
|
|
60
|
+
option :loading, :boolean, default: false,
|
|
61
|
+
doc: "The no-JS loading state: aria-busy, a spinner, and the control disabled."
|
|
62
|
+
option :label, :string, doc: "The accessible name for icon-only usage - not visible text."
|
|
63
|
+
option :href, :string, doc: "The link target; implies the anchor form."
|
|
64
|
+
|
|
65
|
+
validates :type, inclusion: { in: TYPES }
|
|
66
|
+
validates :tag, inclusion: { in: %i[button a] }
|
|
67
|
+
|
|
68
|
+
part "button", "The rendered control itself (<button>, or <a> when tag: :a) - " \
|
|
69
|
+
"every visual state rides here",
|
|
70
|
+
states: {
|
|
71
|
+
"data-variant" => { condition: "always - the resolved variant",
|
|
72
|
+
values: VARIANTS.map(&:to_s) },
|
|
73
|
+
"data-size" => { condition: "always - the resolved size", values: SIZES.map(&:to_s) },
|
|
74
|
+
"data-loading" => "loading: is set (aria-busy rides along)"
|
|
75
|
+
}
|
|
76
|
+
part "icon", "Wrapper span around leading/trailing slot content - sizes and centers " \
|
|
77
|
+
"whatever it holds"
|
|
78
|
+
part "label", "The content block's span (display: contents - children join the root's " \
|
|
79
|
+
"flex row directly)"
|
|
80
|
+
part "spinner", "The loading indicator, swapped in for the leading icon while loading:"
|
|
81
|
+
|
|
82
|
+
# Raises when an icon-only size lacks label:.
|
|
83
|
+
# @api private
|
|
84
|
+
def initialize(...)
|
|
85
|
+
super
|
|
86
|
+
return unless icon_only? && label.blank?
|
|
87
|
+
|
|
88
|
+
# The accessible-icon rule: an icon-only control without an
|
|
89
|
+
# accessible name never ships.
|
|
90
|
+
raise ArgumentError, "icon-only Button requires label: (the accessible name)"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Enforces that something visible renders.
|
|
94
|
+
# @api private
|
|
95
|
+
def before_render
|
|
96
|
+
return if content? || leading? || trailing? || loading
|
|
97
|
+
|
|
98
|
+
raise ArgumentError,
|
|
99
|
+
"Button renders nothing visible: pass a content block (the visible text), " \
|
|
100
|
+
"an icon slot (with_leading/with_trailing), or loading: - label: is only the accessible name"
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Whether size: is one of the square icon-only forms.
|
|
104
|
+
# @api private
|
|
105
|
+
def icon_only?
|
|
106
|
+
size.to_s.start_with?("icon")
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# href: implies the anchor: an href on a native <button> would be
|
|
110
|
+
# silently dropped, leaving a dead control.
|
|
111
|
+
# @api private
|
|
112
|
+
def link_tag?
|
|
113
|
+
tag == :a || href.present?
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# @api private
|
|
117
|
+
def root_tag
|
|
118
|
+
link_tag? ? :a : :button
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# @api private
|
|
122
|
+
def root_attributes
|
|
123
|
+
html_attributes.merge_if_not_set(base_attributes.merge(tag_attributes))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
private
|
|
127
|
+
|
|
128
|
+
def base_attributes
|
|
129
|
+
attrs = { "data-slot" => "button", "data-variant" => variant, "data-size" => size }
|
|
130
|
+
.merge(component_data_attributes)
|
|
131
|
+
attrs["aria-label"] = label if label.present?
|
|
132
|
+
if loading
|
|
133
|
+
attrs["data-loading"] = true
|
|
134
|
+
attrs["aria-busy"] = true
|
|
135
|
+
end
|
|
136
|
+
attrs
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Native <button> gets native semantics (type, real disabled);
|
|
140
|
+
# `tag: :a` is navigation-styled-as-button: role="button" + the
|
|
141
|
+
# faux-disabled convention (aria-disabled, href withheld).
|
|
142
|
+
def tag_attributes
|
|
143
|
+
link_tag? ? link_attributes : button_attributes
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def link_attributes
|
|
147
|
+
attrs = { "role" => "button" }
|
|
148
|
+
if disabled || loading
|
|
149
|
+
attrs["aria-disabled"] = true
|
|
150
|
+
elsif href.present?
|
|
151
|
+
attrs["href"] = href
|
|
152
|
+
end
|
|
153
|
+
attrs
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def button_attributes
|
|
157
|
+
attrs = { "type" => type }
|
|
158
|
+
attrs["disabled"] = true if disabled || loading
|
|
159
|
+
attrs
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
private :icon_only?, :link_tag?, :root_tag, :root_attributes
|
|
163
|
+
|
|
164
|
+
private :icon_only?, :link_tag?, :root_tag, :root_attributes
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
end
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Button
|
|
6
|
+
# The Button preview matrix - one corpus, three uses: Lookbook docs,
|
|
7
|
+
# test fixtures (smoke-rendered in CI), and the agent visual loop.
|
|
8
|
+
class Preview < Poetry::Core::Preview::Base
|
|
9
|
+
# @!group Variants
|
|
10
|
+
|
|
11
|
+
def default
|
|
12
|
+
render_component(variant: :default) { "Save changes" }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def destructive
|
|
16
|
+
render_component(variant: :destructive) { "Delete account" }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def outline
|
|
20
|
+
render_component(variant: :outline) { "Cancel" }
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def secondary
|
|
24
|
+
render_component(variant: :secondary) { "Duplicate" }
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def ghost
|
|
28
|
+
render_component(variant: :ghost) { "Dismiss" }
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def link
|
|
32
|
+
render_component(variant: :link) { "Learn more" }
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# @!endgroup
|
|
36
|
+
|
|
37
|
+
# @!group Sizes
|
|
38
|
+
|
|
39
|
+
def size_xs
|
|
40
|
+
render_component(size: :xs) { "Tag" }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def size_sm
|
|
44
|
+
render_component(size: :sm) { "Small" }
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def size_lg
|
|
48
|
+
render_component(size: :lg) { "Continue" }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def icon_only
|
|
52
|
+
render_component(size: :icon, label: "Add item") do |component|
|
|
53
|
+
component.with_leading { embed(Icon::Component.new(name: :plus)) }
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def icon_large
|
|
58
|
+
render_component(size: :"icon-lg", label: "Open settings") do |component|
|
|
59
|
+
component.with_leading { embed(Icon::Component.new(name: :settings)) }
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
# @!endgroup
|
|
64
|
+
|
|
65
|
+
# @!group States
|
|
66
|
+
|
|
67
|
+
def disabled
|
|
68
|
+
render_component(disabled: true) { "Unavailable" }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def loading
|
|
72
|
+
render_component(loading: true) { "Saving" }
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# @!endgroup
|
|
76
|
+
|
|
77
|
+
# @!group Composition
|
|
78
|
+
|
|
79
|
+
def with_icons
|
|
80
|
+
render_component(variant: :destructive) do |component|
|
|
81
|
+
component.with_leading { embed(Icon::Component.new(name: :trash)) }
|
|
82
|
+
"Delete"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def as_link
|
|
87
|
+
render_component(tag: :a, href: "#", variant: :outline) { "View pricing" }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
# @!endgroup
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module Button
|
|
6
|
+
# The Button dictionary, re-expressed through the cn-* theme layer:
|
|
7
|
+
# entries carry the stable `cn-button*` names plus the
|
|
8
|
+
# structural/behavioral inline set; the visual classes live in
|
|
9
|
+
# themes/default.css. NOTE dark destructive: the dark treatment
|
|
10
|
+
# paints bg-destructive/60 - the composite the contrast gate
|
|
11
|
+
# measures (6.5:1); solid dark destructive is 2.9:1 and must never
|
|
12
|
+
# carry white text undiluted (the rule lives in the theme file's
|
|
13
|
+
# .cn-button-variant-destructive).
|
|
14
|
+
class Style < Poetry::Core::Style
|
|
15
|
+
base "cn-button inline-flex shrink-0 items-center justify-center whitespace-nowrap " \
|
|
16
|
+
"transition-all outline-none disabled:pointer-events-none disabled:opacity-50 " \
|
|
17
|
+
"[&_svg]:pointer-events-none [&_svg]:shrink-0 group/button select-none"
|
|
18
|
+
|
|
19
|
+
variant :variant, {
|
|
20
|
+
default: "cn-button-variant-default",
|
|
21
|
+
destructive: "cn-button-variant-destructive",
|
|
22
|
+
outline: "cn-button-variant-outline",
|
|
23
|
+
secondary: "cn-button-variant-secondary",
|
|
24
|
+
ghost: "cn-button-variant-ghost",
|
|
25
|
+
link: "cn-button-variant-link"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
variant :size, {
|
|
29
|
+
default: "cn-button-size-default",
|
|
30
|
+
xs: "cn-button-size-xs",
|
|
31
|
+
sm: "cn-button-size-sm",
|
|
32
|
+
lg: "cn-button-size-lg",
|
|
33
|
+
icon: "cn-button-size-icon",
|
|
34
|
+
"icon-xs": "cn-button-size-icon-xs",
|
|
35
|
+
"icon-sm": "cn-button-size-icon-sm",
|
|
36
|
+
"icon-lg": "cn-button-size-icon-lg"
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
# Segmented groups of adjacent controls.
|
|
6
|
+
module ButtonGroup
|
|
7
|
+
# Visually joins adjacent controls (buttons, inputs, select
|
|
8
|
+
# triggers) into one segmented unit: outer corners stay rounded,
|
|
9
|
+
# inner corners and doubled borders collapse. Compose the members in
|
|
10
|
+
# the content block; poetry_button_group_text and
|
|
11
|
+
# poetry_button_group_separator are the non-button parts.
|
|
12
|
+
#
|
|
13
|
+
# @example A segmented pair
|
|
14
|
+
# render Poetry::Ui::ButtonGroup::Component.new("aria-label": "Alignment") do
|
|
15
|
+
# safe_join([
|
|
16
|
+
# render(Poetry::Ui::Button::Component.new(variant: :outline).with_content("Left")),
|
|
17
|
+
# render(Poetry::Ui::Button::Component.new(variant: :outline).with_content("Right"))
|
|
18
|
+
# ])
|
|
19
|
+
# end
|
|
20
|
+
class Component < Poetry::Core::Component
|
|
21
|
+
requires_content "its member controls"
|
|
22
|
+
|
|
23
|
+
# The closed vocabulary for the orientation axis.
|
|
24
|
+
ORIENTATIONS = %i[horizontal vertical].freeze
|
|
25
|
+
|
|
26
|
+
# Projected into the registry, llms.txt, and the agent surface.
|
|
27
|
+
AGENT_RULES = [
|
|
28
|
+
"Members go in the content block - the group's selectors join ANY data-slot children " \
|
|
29
|
+
"(buttons, inputs, select triggers); never hand-round the inner corners.",
|
|
30
|
+
"Give the group an aria-label when the page has more than one (role=group is unnamed by default).",
|
|
31
|
+
"A visual divider between members is poetry_button_group_separator, not a styled border."
|
|
32
|
+
].freeze
|
|
33
|
+
|
|
34
|
+
style :orientation, default: :horizontal, required: true, variants: ORIENTATIONS,
|
|
35
|
+
doc: "The join axis - a horizontal row or a vertical stack."
|
|
36
|
+
|
|
37
|
+
part "button-group", "The role=group root - its selectors join ANY data-slot children into " \
|
|
38
|
+
"the segmented unit",
|
|
39
|
+
states: {
|
|
40
|
+
"data-orientation" => { condition: "the join axis", values: ORIENTATIONS.map(&:to_s) }
|
|
41
|
+
}
|
|
42
|
+
part "button-group-text", "A non-button member (the poetry_button_group_text helper's div) - " \
|
|
43
|
+
"a text affix joined like a button"
|
|
44
|
+
|
|
45
|
+
# Enforces the member-controls content block.
|
|
46
|
+
# @api private
|
|
47
|
+
def before_render
|
|
48
|
+
ensure_content!
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# @api private
|
|
52
|
+
def call
|
|
53
|
+
content_tag(:div, content, **root_attributes.to_attributes)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# @api private
|
|
57
|
+
def root_attributes
|
|
58
|
+
html_attributes.merge_if_not_set(
|
|
59
|
+
{
|
|
60
|
+
"role" => "group", "data-slot" => "button-group",
|
|
61
|
+
"data-orientation" => orientation
|
|
62
|
+
}.merge(component_data_attributes)
|
|
63
|
+
)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
private :root_attributes
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
<%# Popup wrappers at every group position: select FIRST (rounded left,
|
|
2
|
+
square right), dropdown-menu MIDDLE (square both, collapsed border),
|
|
3
|
+
popover LAST (square left, rounded right). %>
|
|
4
|
+
<%= poetry_button_group("aria-label": "Popup trigger corners") do %>
|
|
5
|
+
<%= poetry_select(placeholder: "USD", "aria-label": "Currency") do |select| %>
|
|
6
|
+
<% select.with_item(value: "usd") { "USD" } %>
|
|
7
|
+
<% select.with_item(value: "eur") { "EUR" } %>
|
|
8
|
+
<% end %>
|
|
9
|
+
<%= poetry_dropdown_menu do |menu| %>
|
|
10
|
+
<% menu.with_trigger(variant: :outline) { "Actions" } %>
|
|
11
|
+
<% menu.with_item { "Duplicate" } %>
|
|
12
|
+
<% menu.with_item { "Archive" } %>
|
|
13
|
+
<% end %>
|
|
14
|
+
<%= poetry_popover do |popover| %>
|
|
15
|
+
<% popover.with_trigger(variant: :outline, size: :icon, label: "Open details") do %>
|
|
16
|
+
<%= poetry_icon(name: :"chevron-down") %>
|
|
17
|
+
<% end %>
|
|
18
|
+
<% popover.with_title { "Details" } %>
|
|
19
|
+
<% popover.with_description { "The popover trigger sits last in the group." } %>
|
|
20
|
+
<% end %>
|
|
21
|
+
<% end %>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module ButtonGroup
|
|
6
|
+
# The ButtonGroup preview: a segmented pair, a prefix text member,
|
|
7
|
+
# and the vertical orientation.
|
|
8
|
+
class Preview < Poetry::Core::Preview::Base
|
|
9
|
+
def default
|
|
10
|
+
render_component("aria-label": "Text alignment") do
|
|
11
|
+
embed(button("Left", variant: :outline)) +
|
|
12
|
+
embed(button("Center", variant: :outline)) +
|
|
13
|
+
embed(button("Right", variant: :outline))
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def with_text_prefix
|
|
18
|
+
# Part helpers need a real view context - a per-example template
|
|
19
|
+
# (a class-level preview.html.erb would hijack every example).
|
|
20
|
+
render_with_template(template: "poetry/ui/button_group/text_prefix_preview")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def vertical
|
|
24
|
+
render_component(orientation: :vertical, "aria-label": "Vertical actions") do
|
|
25
|
+
embed(button("Top", variant: :outline)) +
|
|
26
|
+
embed(button("Bottom", variant: :outline))
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# The corner rig for popup wrappers (select / dropdown-menu /
|
|
31
|
+
# popover render a Stimulus wrapper around their trigger, unlike
|
|
32
|
+
# upstream fragments): first, middle, and last positions each
|
|
33
|
+
# prove the theme chains reach the trigger THROUGH its wrapper.
|
|
34
|
+
def popup_triggers
|
|
35
|
+
render_with_template(template: "poetry/ui/button_group/popup_triggers_preview")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def button(text, **)
|
|
41
|
+
Poetry::Ui::Button::Component.new(**).with_content(text)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Poetry
|
|
4
|
+
module Ui
|
|
5
|
+
module ButtonGroup
|
|
6
|
+
# Re-expressed through the cn-* theme layer. One documented
|
|
7
|
+
# deviation from upstream's literal split: upstream ships the
|
|
8
|
+
# orientation corner-chains inline AND under cn names; poetry puts
|
|
9
|
+
# them theme-side only (pure radius/border design - the theme owns
|
|
10
|
+
# them, nothing is emitted twice).
|
|
11
|
+
class Style < Poetry::Core::Style
|
|
12
|
+
base "cn-button-group flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 " \
|
|
13
|
+
"[&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1"
|
|
14
|
+
|
|
15
|
+
variant :orientation, {
|
|
16
|
+
horizontal: "cn-button-group-orientation-horizontal",
|
|
17
|
+
vertical: "cn-button-group-orientation-vertical"
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
element :text, "cn-button-group-text flex items-center [&_svg]:pointer-events-none"
|
|
21
|
+
element :separator, "cn-button-group-separator relative self-stretch " \
|
|
22
|
+
"data-horizontal:mx-px data-horizontal:w-auto " \
|
|
23
|
+
"data-vertical:my-px data-vertical:h-auto"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
<%# A text member joined to an input: the group collapses the seam. %>
|
|
2
|
+
<div class="p-4">
|
|
3
|
+
<%= poetry_button_group("aria-label": "Site address") do %>
|
|
4
|
+
<%= poetry_button_group_text { "https://" } %>
|
|
5
|
+
<%= poetry_input(name: "domain", placeholder: "example.com") %>
|
|
6
|
+
<% end %>
|
|
7
|
+
</div>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
<%= content_tag(:div, **root_attributes.to_attributes) do %>
|
|
2
|
+
<div data-slot="calendar-nav" class="<%= css(:nav) %>">
|
|
3
|
+
<%= render Poetry::Ui::Button::Component.new(**previous_options) do |button| %>
|
|
4
|
+
<% button.with_leading { render Poetry::Ui::Icon::Component.new(name: :"chevron-left") } %>
|
|
5
|
+
<% end %>
|
|
6
|
+
<% if dropdown_caption? %>
|
|
7
|
+
<%# No caption target here: the controller reflects navigation into
|
|
8
|
+
the selects and their visible labels (data-calendar-unit).
|
|
9
|
+
Upstream's overlay pattern: the label span
|
|
10
|
+
is what you SEE (aria-hidden - the select carries the value);
|
|
11
|
+
the real select sits invisibly on top. %>
|
|
12
|
+
<div data-slot="calendar-caption" class="<%= css(:caption_dropdowns) %>">
|
|
13
|
+
<% { "month" => [month_options, @month.month, t("poetry.calendar.month"), month_names_list[@month.month - 1]],
|
|
14
|
+
"year" => [year_options, @month.year, t("poetry.calendar.year"), @month.year.to_s] }.each do |unit, (options, current, label, text)| %>
|
|
15
|
+
<span data-slot="calendar-dropdown" data-calendar-unit="<%= unit %>" class="<%= css(:dropdown_root) %>"
|
|
16
|
+
<%= tag.attributes(**stimulus_attributes_for(:dropdown)) %>>
|
|
17
|
+
<span data-slot="calendar-caption-label" aria-hidden="true" class="<%= css(:dropdown_label) %>">
|
|
18
|
+
<span data-slot="calendar-dropdown-value"><%= text %></span>
|
|
19
|
+
<%= render Poetry::Ui::Icon::Component.new(name: :"chevron-down") %>
|
|
20
|
+
</span>
|
|
21
|
+
<select aria-label="<%= label %>" class="<%= css(:dropdown_select) %>">
|
|
22
|
+
<% options.each do |(option_label, value)| %>
|
|
23
|
+
<option value="<%= value %>" <% if value == current %>selected<% end %>><%= option_label %></option>
|
|
24
|
+
<% end %>
|
|
25
|
+
</select>
|
|
26
|
+
</span>
|
|
27
|
+
<% end %>
|
|
28
|
+
</div>
|
|
29
|
+
<% else %>
|
|
30
|
+
<div data-slot="calendar-caption" class="<%= css(:caption) %>" <%= tag.attributes(**stimulus_attributes_for(:caption)) %>><%= caption %></div>
|
|
31
|
+
<% end %>
|
|
32
|
+
<%= render Poetry::Ui::Button::Component.new(**next_options) do |button| %>
|
|
33
|
+
<% button.with_leading { render Poetry::Ui::Icon::Component.new(name: :"chevron-right") } %>
|
|
34
|
+
<% end %>
|
|
35
|
+
</div>
|
|
36
|
+
<div role="grid" data-slot="calendar-grid" class="<%= css(:grid) %>"
|
|
37
|
+
<%= tag.attributes(**stimulus_attributes_for(:grid)) %>>
|
|
38
|
+
<div role="row" data-slot="calendar-weekdays" class="<%= css(:weekdays) %>">
|
|
39
|
+
<% if week_numbers %>
|
|
40
|
+
<div role="columnheader" data-slot="calendar-week-number" class="<%= css(:weekday) %>"><span class="sr-only">Week</span></div>
|
|
41
|
+
<% end %>
|
|
42
|
+
<% weekday_labels.each do |label| %>
|
|
43
|
+
<div role="columnheader" data-slot="calendar-weekday" class="<%= css(:weekday) %>"><%= label %></div>
|
|
44
|
+
<% end %>
|
|
45
|
+
</div>
|
|
46
|
+
<% cells.each_slice(7) do |week| %>
|
|
47
|
+
<div role="row" data-slot="calendar-week" class="<%= css(:week) %>">
|
|
48
|
+
<% if week_numbers %>
|
|
49
|
+
<div role="rowheader" data-slot="calendar-week-number" class="<%= css(:weekday) %>"><%= iso_week(week) %></div>
|
|
50
|
+
<% end %>
|
|
51
|
+
<% week.each do |date| %>
|
|
52
|
+
<%= content_tag(:div, cell_attributes(date)) do %>
|
|
53
|
+
<%= content_tag(:button, day_attributes(date)) do %>
|
|
54
|
+
<span data-slot="calendar-day-label"><%= date.day %></span>
|
|
55
|
+
<% end %>
|
|
56
|
+
<% end %>
|
|
57
|
+
<% end %>
|
|
58
|
+
</div>
|
|
59
|
+
<% end %>
|
|
60
|
+
</div>
|
|
61
|
+
<% if name.present? %>
|
|
62
|
+
<% if range? %>
|
|
63
|
+
<input type="hidden" name="<%= name %>[start]" value="<%= range_start&.iso8601 %>"
|
|
64
|
+
<%= tag.attributes(**stimulus_attributes_for(:start_input)) %>>
|
|
65
|
+
<input type="hidden" name="<%= name %>[end]" value="<%= range_end&.iso8601 %>"
|
|
66
|
+
<%= tag.attributes(**stimulus_attributes_for(:end_input)) %>>
|
|
67
|
+
<% else %>
|
|
68
|
+
<input type="hidden" name="<%= name %>" value="<%= selected&.iso8601 %>"
|
|
69
|
+
<%= tag.attributes(**stimulus_attributes_for(:hidden_input)) %>>
|
|
70
|
+
<% end %>
|
|
71
|
+
<% end %>
|
|
72
|
+
<% end %>
|