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,152 @@
|
|
|
1
|
+
# Component anatomy - the canonical section order
|
|
2
|
+
|
|
3
|
+
Every poetry component class reads top to bottom in the same order.
|
|
4
|
+
The order is chosen so a reader meets the component the way an agent
|
|
5
|
+
consumes its contract: identity, vocabulary, surface, behavior,
|
|
6
|
+
arguments, structure, then implementation.
|
|
7
|
+
|
|
8
|
+
## The order
|
|
9
|
+
|
|
10
|
+
| # | Section | Declares |
|
|
11
|
+
|---|---------|----------|
|
|
12
|
+
| 1 | Includes & class config | `include` / `extend`, `internal_component!`, `requires_content`, `delegate`, `with_collection_parameter` |
|
|
13
|
+
| 2 | Constants | vocabularies first (`VARIANTS`, `SIZES`, ...), then the agent contract (`AGENT_RULES`, `REQUIRES_ANY`, `SLOT_RENDERS`) |
|
|
14
|
+
| 3 | Slots | `renders_one` / `renders_many` |
|
|
15
|
+
| 4 | Stimulus | `use_stimulus do ... end` |
|
|
16
|
+
| 4b | Agent tools | `tool :name, executes:, ...` (interactive components; optional) |
|
|
17
|
+
| 5 | Styles & options | `style` declarations, then `option` declarations |
|
|
18
|
+
| 6 | Validations | `validates` / `validate` |
|
|
19
|
+
| 7 | Parts | `part` declarations |
|
|
20
|
+
| 8 | Lifecycle | `initialize`, `before_render`, `call` - in that order |
|
|
21
|
+
| 9 | Public methods | everything else callable from templates or callers |
|
|
22
|
+
| 10 | Private methods | under a single `private` |
|
|
23
|
+
| 11 | Nested classes | builder / internal classes, last |
|
|
24
|
+
|
|
25
|
+
## Why this order
|
|
26
|
+
|
|
27
|
+
- **Constants come before the DSL calls that read them.** Ruby
|
|
28
|
+
evaluates the class body top to bottom; `style :variant, variants:
|
|
29
|
+
VARIANTS` needs `VARIANTS` already defined. Putting every constant in
|
|
30
|
+
one early section satisfies this everywhere at once.
|
|
31
|
+
- **The agent contract lives with the constants.** `AGENT_RULES`,
|
|
32
|
+
`REQUIRES_ANY`, and `SLOT_RENDERS` are data the machine surfaces
|
|
33
|
+
project; grouping them right after the vocabularies keeps the whole
|
|
34
|
+
published contract readable in one screen.
|
|
35
|
+
- **Slots before behavior, behavior before arguments.** What the
|
|
36
|
+
component holds (slots), how it acts (Stimulus), what it accepts
|
|
37
|
+
(styles, options, validations), what it renders (parts). Each section
|
|
38
|
+
answers the next question a reader has.
|
|
39
|
+
- **Lifecycle heads the public methods.** `initialize` is the first
|
|
40
|
+
public method anyone looks for; `before_render` and `call` follow it
|
|
41
|
+
so the render path reads as one block.
|
|
42
|
+
|
|
43
|
+
## Hard rules
|
|
44
|
+
|
|
45
|
+
1. **Never reorder declarations within a section.** Option, part, and
|
|
46
|
+
slot order is projected into the registry and the agent surface in
|
|
47
|
+
declaration order. Moving a whole section preserves it; shuffling
|
|
48
|
+
inside a section changes a machine surface.
|
|
49
|
+
2. **One `private` keyword.** Everything below it is private; no
|
|
50
|
+
interleaving public and private methods.
|
|
51
|
+
3. **Inner classes declare `internal_component!`** when they inherit
|
|
52
|
+
the component machinery but are not published components in their
|
|
53
|
+
own right.
|
|
54
|
+
4. **Nested classes sit at the end of the class but above the
|
|
55
|
+
`private` divider.** A constant is never private-scoped, so placing
|
|
56
|
+
one below `private` is misleading (and linters flag it). A nested
|
|
57
|
+
class a class-body DSL call evaluates must stay above that call
|
|
58
|
+
instead.
|
|
59
|
+
5. **`frozen_string_literal: true`** heads every file.
|
|
60
|
+
|
|
61
|
+
## Skeleton
|
|
62
|
+
|
|
63
|
+
```ruby
|
|
64
|
+
# frozen_string_literal: true
|
|
65
|
+
|
|
66
|
+
module MyApp
|
|
67
|
+
module Callout
|
|
68
|
+
# A bordered notice that frames one message and an optional action.
|
|
69
|
+
# Reaches for the semantic-role tokens, so every theme styles it
|
|
70
|
+
# without per-instance CSS.
|
|
71
|
+
#
|
|
72
|
+
# @example Basic usage
|
|
73
|
+
# render MyApp::Callout::Component.new(variant: :info) { "Saved." }
|
|
74
|
+
class Component < Poetry::Core::Component
|
|
75
|
+
requires_content "the message body"
|
|
76
|
+
|
|
77
|
+
VARIANTS = %i[info success warning danger].freeze
|
|
78
|
+
|
|
79
|
+
AGENT_RULES = [
|
|
80
|
+
"Use Callout for inline notices - never a hand-styled div.",
|
|
81
|
+
"Pick the variant by intent; danger is reserved for destructive outcomes."
|
|
82
|
+
].freeze
|
|
83
|
+
|
|
84
|
+
renders_one :action
|
|
85
|
+
|
|
86
|
+
use_stimulus do
|
|
87
|
+
controller :callout do
|
|
88
|
+
target :dismiss
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
style :variant, default: :info, required: true, variants: VARIANTS
|
|
93
|
+
|
|
94
|
+
option :dismissible, :boolean, default: false
|
|
95
|
+
|
|
96
|
+
validates :variant, inclusion: { in: VARIANTS }
|
|
97
|
+
|
|
98
|
+
part "root", "The bordered container - variant state rides here",
|
|
99
|
+
states: { "data-variant" => { condition: "always", values: VARIANTS.map(&:to_s) } }
|
|
100
|
+
part "action", "Wrapper around the action slot"
|
|
101
|
+
|
|
102
|
+
def initialize(...)
|
|
103
|
+
super
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def before_render
|
|
107
|
+
ensure_content!
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def dismiss_label
|
|
111
|
+
t(".dismiss")
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
private
|
|
115
|
+
|
|
116
|
+
def css
|
|
117
|
+
# section-level styles resolved by the style DSL
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Agent tools (the operate surface)
|
|
125
|
+
|
|
126
|
+
Beside `use_stimulus`, an interactive component may declare the tools an
|
|
127
|
+
in-page agent (WebMCP, `document.modelContext`) can invoke on a rendered
|
|
128
|
+
instance. Each tool is MCP `Tool`-shaped and dispatches to one of the
|
|
129
|
+
component's OWN Stimulus actions, positionally in declared parameter order:
|
|
130
|
+
|
|
131
|
+
```ruby
|
|
132
|
+
tool :set_value,
|
|
133
|
+
description: "Activate the tab whose value matches and show its panel.",
|
|
134
|
+
params: { value: { type: "string", required: true, description: "The tab's value." } },
|
|
135
|
+
executes: :set_value, # a declared controller action - validated at class load
|
|
136
|
+
mutating: true # read-only by default; the annotation says which
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Rules: declare `use_stimulus` first; keep `executes:` bare (`:open`) when a
|
|
140
|
+
subclass may re-controller the root (Sheet over Dialog) - it re-resolves per
|
|
141
|
+
class; descriptions are positive, single-purpose, at most 500 characters.
|
|
142
|
+
Override `webmcp_tool_definition(definition)` to refine a schema with what
|
|
143
|
+
only the rendered instance knows (Tabs adds its tab values as the enum).
|
|
144
|
+
Nothing registers until a call opts in: `poetry_tabs(webmcp: "sections")`.
|
|
145
|
+
The registry projects tools to llms-full.txt, `describe_component`, and the
|
|
146
|
+
docs page; `poetry:check` gates the opt-ins (`webmcp-without-tools`,
|
|
147
|
+
`webmcp-name`, `webmcp-duplicate-name`).
|
|
148
|
+
|
|
149
|
+
A component may not need every section - Button has no `use_stimulus`,
|
|
150
|
+
static components have no validations. Skip absent sections entirely;
|
|
151
|
+
never leave placeholder comments for them. The sections that are
|
|
152
|
+
present appear in this order.
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Component audit checklist
|
|
2
|
+
|
|
3
|
+
Run this against one component file at a time, top to bottom - the
|
|
4
|
+
checks are ordered so violations surface in file order. The audit has
|
|
5
|
+
two passes: structure, then documentation. It never changes behavior:
|
|
6
|
+
rendered output, projected surfaces, and test results are identical
|
|
7
|
+
before and after an audit fix, except where a projected string was
|
|
8
|
+
itself the finding.
|
|
9
|
+
|
|
10
|
+
## Pass 1 - structure
|
|
11
|
+
|
|
12
|
+
- [ ] `# frozen_string_literal: true` heads the file.
|
|
13
|
+
- [ ] Sections present appear in canonical order: includes & class
|
|
14
|
+
config → constants → slots → stimulus → styles & options →
|
|
15
|
+
validations → parts → lifecycle → public methods → private
|
|
16
|
+
methods → nested classes. (Absent sections are skipped, not
|
|
17
|
+
stubbed.)
|
|
18
|
+
- [ ] Constants: vocabularies before the agent contract
|
|
19
|
+
(`AGENT_RULES`, `REQUIRES_ANY`, `SLOT_RENDERS`); every constant
|
|
20
|
+
above the first DSL call that reads it; all `.freeze`d.
|
|
21
|
+
- [ ] No declaration was reordered *within* its section - option,
|
|
22
|
+
part, and slot order projects in declaration order. Verify with
|
|
23
|
+
the diff, not by eye.
|
|
24
|
+
- [ ] Lifecycle methods (`initialize`, `before_render`, `call`) lead
|
|
25
|
+
the public methods, in that order.
|
|
26
|
+
- [ ] Exactly one `private` keyword; nothing public below it.
|
|
27
|
+
- [ ] Inner machinery classes declare `internal_component!`.
|
|
28
|
+
- [ ] Nested classes sit last in the class body, above the `private`
|
|
29
|
+
divider (constants are never private-scoped).
|
|
30
|
+
|
|
31
|
+
## Pass 2 - documentation
|
|
32
|
+
|
|
33
|
+
- [ ] Class docblock: purpose in 1-3 sentences + at least one
|
|
34
|
+
`@example` (published components); `@api private` one-liner
|
|
35
|
+
(internal components).
|
|
36
|
+
- [ ] Public methods with non-obvious signatures carry `@param` /
|
|
37
|
+
`@return`; examples where usage isn't clear from the signature.
|
|
38
|
+
- [ ] Projected strings (part descriptions, agent rules, option
|
|
39
|
+
descriptions, `requires_content` hints) read consumer-facing:
|
|
40
|
+
concrete DOM reality, explicit conditions, imperative rules.
|
|
41
|
+
- [ ] No internal references anywhere in comments: no planning-doc or
|
|
42
|
+
decision-index citations, no milestone names, no links to
|
|
43
|
+
private notes. Reasoning is stated inline or removed.
|
|
44
|
+
- [ ] No other library named in any comment or string (notices file
|
|
45
|
+
excepted).
|
|
46
|
+
- [ ] No narration comments (restating the next line) and no
|
|
47
|
+
reviewer-addressed comments.
|
|
48
|
+
- [ ] Comment prose is complete sentences; abbreviations only if a
|
|
49
|
+
newcomer reads them cold.
|
|
50
|
+
|
|
51
|
+
## Verification
|
|
52
|
+
|
|
53
|
+
- [ ] Full suite green.
|
|
54
|
+
- [ ] `git diff` shows only: comment changes, section moves, doc
|
|
55
|
+
strings intentionally rewritten. No logic lines changed.
|
|
56
|
+
- [ ] If a projected string changed: the registry / agent-surface /
|
|
57
|
+
check tests that assert on it were updated in the same change,
|
|
58
|
+
and the new text is an improvement for the consumer, not a
|
|
59
|
+
paraphrase.
|
|
60
|
+
- [ ] `yard doc` (or the gem's docs build) runs warning-clean on the
|
|
61
|
+
touched files.
|
|
62
|
+
|
|
63
|
+
## Recording findings that are out of scope
|
|
64
|
+
|
|
65
|
+
Anything discovered that is *not* structure or documentation - a bug, a
|
|
66
|
+
missing validation, a contract gap - does not get fixed in an audit
|
|
67
|
+
pass. Record it separately and keep the audit diff clean.
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Documentation standard
|
|
2
|
+
|
|
3
|
+
poetry components carry two kinds of documentation, and they have
|
|
4
|
+
different readers. YARD comments serve the person or agent reading the
|
|
5
|
+
source; projected strings (part descriptions, agent rules, option
|
|
6
|
+
metadata) are published verbatim through the registry, the agent
|
|
7
|
+
surface, and the docs. Write each for its consumer.
|
|
8
|
+
|
|
9
|
+
## The class docblock
|
|
10
|
+
|
|
11
|
+
Every published component class opens with a YARD docblock:
|
|
12
|
+
|
|
13
|
+
- **One to three sentences** on what it renders and when to reach for
|
|
14
|
+
it. Present tense, no history. This is the *reference lead* - a public
|
|
15
|
+
reader with zero codebase context must parse every word.
|
|
16
|
+
- Optionally ONE short paragraph of load-bearing behavior facts a USER
|
|
17
|
+
needs (keyboard behavior, required slots, form participation), written
|
|
18
|
+
to stand alone. Maintainer rationale is a different register: it lives
|
|
19
|
+
as a plain comment above the method it concerns, never in the class
|
|
20
|
+
docblock. Whole docblock ≤ 15 lines.
|
|
21
|
+
- **One `@example`** showing minimal usage through the helper or
|
|
22
|
+
`render`. Add a second example only when the primary axis (variant,
|
|
23
|
+
size, slots) isn't obvious from the first.
|
|
24
|
+
- Internal component classes (`internal_component!`) get a one-line
|
|
25
|
+
comment and `@api private` instead.
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
# Renders a dismissible inline notice with an optional action slot.
|
|
29
|
+
# Variants map to semantic intent, so themes restyle it wholesale.
|
|
30
|
+
#
|
|
31
|
+
# @example
|
|
32
|
+
# render MyApp::Callout::Component.new(variant: :success) { "Saved." }
|
|
33
|
+
class Component < Poetry::Core::Component
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## Public methods
|
|
37
|
+
|
|
38
|
+
- YARD tags (`@param`, `@return`, `@example`) on every public method
|
|
39
|
+
whose signature or return isn't obvious from the name.
|
|
40
|
+
- Template-facing methods (`*_attributes`, `*_id`, `*_classes`, part
|
|
41
|
+
builders) and lifecycle overrides (`initialize`, `before_render`,
|
|
42
|
+
`call`) carry a one-line comment ending in `@api private` - they are
|
|
43
|
+
public for the template's sake, not the consumer's, and the doc set
|
|
44
|
+
hides them.
|
|
45
|
+
- Hand-written slot writers a caller uses (`with_*`) are real public
|
|
46
|
+
API: full docs, never `@api private`.
|
|
47
|
+
- Markdown markup; full sentences; wrap at the file's prevailing width.
|
|
48
|
+
|
|
49
|
+
## Declaration docs
|
|
50
|
+
|
|
51
|
+
Every `option` and `style` carries a `doc:` string, and every
|
|
52
|
+
`renders_one`/`renders_many` carries one too - with `renders:` passing
|
|
53
|
+
the slot's lambda as a keyword so the doc reads first. (`slot_doc` is
|
|
54
|
+
the fallback for a doc declared away from its declaration, e.g. in a
|
|
55
|
+
different module.) That string is the declared surface's documentation everywhere at
|
|
56
|
+
once - the registry (option/style/slot descriptions), llms.txt and the
|
|
57
|
+
agent surface, the component page's API section, and the generated API
|
|
58
|
+
reference - with the machine facts (type, default, variants)
|
|
59
|
+
auto-appended, so the prose adds MEANING only:
|
|
60
|
+
|
|
61
|
+
- One sentence, two at most: the caller-visible effect and its
|
|
62
|
+
interactions ("Ignored unless `tag: :a`."), never the implementation
|
|
63
|
+
("sets @foo").
|
|
64
|
+
- Never repeat the type, default, or variant list - the projections
|
|
65
|
+
carry those already.
|
|
66
|
+
|
|
67
|
+
```ruby
|
|
68
|
+
option :loading, :boolean, default: false,
|
|
69
|
+
doc: "The no-JS loading state: aria-busy, a spinner, and the control disabled."
|
|
70
|
+
|
|
71
|
+
renders_one :leading, doc: "Optional leading visual, rendered inside the icon span."
|
|
72
|
+
|
|
73
|
+
renders_one :trigger,
|
|
74
|
+
doc: "The button that opens the dialog.",
|
|
75
|
+
renders: lambda { |**options, &block| ... }
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Constants that define the surface get one-liners too: vocabulary arrays
|
|
79
|
+
("The closed vocabulary for the variant axis."), `AGENT_RULES`
|
|
80
|
+
("Projected into the registry, llms.txt, and the agent surface.").
|
|
81
|
+
|
|
82
|
+
## Private methods
|
|
83
|
+
|
|
84
|
+
Plain comments, and only where the *why* isn't visible in the code. A
|
|
85
|
+
private method whose name states its job needs no comment.
|
|
86
|
+
|
|
87
|
+
## Projected strings
|
|
88
|
+
|
|
89
|
+
Part descriptions, agent rules, option and slot descriptions, and
|
|
90
|
+
`requires_content` hints are machine-published documentation:
|
|
91
|
+
|
|
92
|
+
- Write for the consumer who has never seen the source: name the DOM
|
|
93
|
+
reality ("the rendered control itself"), the condition ("loading: is
|
|
94
|
+
set"), the rule ("icon-only buttons MUST pass label:").
|
|
95
|
+
- No abbreviations that only make sense inside this codebase.
|
|
96
|
+
- Agent rules are imperatives: what to do, what never to do, one rule
|
|
97
|
+
per entry.
|
|
98
|
+
|
|
99
|
+
## What comments never contain
|
|
100
|
+
|
|
101
|
+
Comments explain the component to its next reader. Reasoning stands on
|
|
102
|
+
its own - state the constraint, not where it came from:
|
|
103
|
+
|
|
104
|
+
- **No internal references**: planning documents, decision indexes,
|
|
105
|
+
milestone names, issue numbers, links into private notes. If the
|
|
106
|
+
reasoning matters, write the reasoning; the citation is noise to
|
|
107
|
+
every reader who isn't the author.
|
|
108
|
+
- **No other libraries**: naming another library belongs in
|
|
109
|
+
`THIRD_PARTY_NOTICES.md` when code was adapted, and nowhere
|
|
110
|
+
otherwise. "The base-contract rule: an icon-only control without an
|
|
111
|
+
accessible name never ships" carries the rule; attribution lives in
|
|
112
|
+
the notices file.
|
|
113
|
+
- **No narration**: nothing that restates what the next line does, and
|
|
114
|
+
nothing addressed to a reviewer ("this is correct because..."). A
|
|
115
|
+
comment earns its place by stating a constraint the code can't show.
|
|
116
|
+
|
|
117
|
+
## YARD setup
|
|
118
|
+
|
|
119
|
+
Each gem carries a `.yardopts` (markdown markup, README as the index,
|
|
120
|
+
`--hide-api private`, previews and generator templates excluded,
|
|
121
|
+
CHANGELOG and notices as extra files) and loads the shared handler kit
|
|
122
|
+
(`poetry-core/yard/poetry_yard.rb`), which makes the declarative
|
|
123
|
+
surfaces - `class_methods do`, `option`/`style` readers, slot writers,
|
|
124
|
+
`part` anatomy - visible to the doc build.
|
|
125
|
+
|
|
126
|
+
Gates, from the gem root:
|
|
127
|
+
|
|
128
|
+
- `rake yard:verify` - fails on any warning (an unresolvable reference
|
|
129
|
+
or malformed tag is a review finding; structural warnings are
|
|
130
|
+
allowlisted in the task).
|
|
131
|
+
- `rake yard:coverage` - the ratchet: fails when the undocumented-object
|
|
132
|
+
count exceeds the committed `.yard_coverage` floor. After a
|
|
133
|
+
documentation pass, lower the floor with `rake yard:coverage:record`.
|
|
134
|
+
|
|
135
|
+
Previews are OUTSIDE the doc set: preview.rb comments are for gallery
|
|
136
|
+
authors (Lookbook tags like `@label`/`@!group` live there) and are never
|
|
137
|
+
published.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: poetry-design
|
|
3
|
+
description: >-
|
|
4
|
+
Design guidance for building poetry UIs: theme selection, page
|
|
5
|
+
composition (macrostructure, hierarchy, containment, status color),
|
|
6
|
+
the visual audit of a finished screen, and studying a brand into a
|
|
7
|
+
DESIGN.md. Load this WHENEVER building, composing, or restyling a
|
|
8
|
+
page, screen, dashboard, or view with poetry - alongside the poetry
|
|
9
|
+
usage skill, before composing - not only when the task mentions
|
|
10
|
+
design.
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# poetry-design - the taste layer
|
|
14
|
+
|
|
15
|
+
poetry's catalog guarantees valid, accessible components; this skill covers
|
|
16
|
+
the decisions the catalog cannot make for you: which theme, what
|
|
17
|
+
macrostructure, whether the finished page reads well. Any task that builds
|
|
18
|
+
a PAGE is a design task - load this before composing, not after something
|
|
19
|
+
looks wrong. It works through tokens, variants, themes, and DESIGN.md -
|
|
20
|
+
**never per-instance CSS** (that reintroduces the drift the system exists
|
|
21
|
+
to prevent).
|
|
22
|
+
|
|
23
|
+
## Verbs
|
|
24
|
+
|
|
25
|
+
- **theme** (`references/theme.md`) - pick or adapt one of the nine shipped
|
|
26
|
+
themes; wire a brand in through the DESIGN.md import door.
|
|
27
|
+
- **compose** (`references/compose.md`) - shape a page BEFORE building it:
|
|
28
|
+
macrostructure, hierarchy, framing, content realism. The checklist here
|
|
29
|
+
is distilled from judged head-to-head runs.
|
|
30
|
+
- **audit** (`references/audit.md`) - review a finished screen: run the
|
|
31
|
+
deterministic design-lint tier first, then the critique checklist for
|
|
32
|
+
what detectors cannot see.
|
|
33
|
+
- **study** (`references/study.md`) - extract a brand's design DNA into a
|
|
34
|
+
DESIGN.md poetry can import; `redesign` = keep the content, swap the
|
|
35
|
+
fingerprint.
|
|
36
|
+
- **figma** (`references/figma.md`) - bring a Figma design into poetry:
|
|
37
|
+
import its variables as an AA-gated theme, or translate a selection into
|
|
38
|
+
components across the Figma + poetry MCPs.
|
|
39
|
+
- **paper** (`references/paper.md`) - bring a paper.design canvas into
|
|
40
|
+
poetry: import its theme, or translate the canvas across the Paper +
|
|
41
|
+
poetry MCPs.
|
|
42
|
+
|
|
43
|
+
## Working rules
|
|
44
|
+
|
|
45
|
+
- Deterministic first: run the linters before offering opinions - most slop
|
|
46
|
+
is mechanically detectable, and every rule names its fix.
|
|
47
|
+
- Express every fix through a token, variant, option, theme, or DESIGN.md
|
|
48
|
+
override. If a fix seems to need hand-written CSS, the real fix is a
|
|
49
|
+
different composition (or an upstream gap worth reporting). The one
|
|
50
|
+
sanctioned exception: a DECLARED `cn-*` override - host CSS restyling a
|
|
51
|
+
theme-owned class, recorded with a reason under `overrides:` in
|
|
52
|
+
config/poetry_components.yml after the user confirms intent
|
|
53
|
+
(`bin/rails poetry:design:overrides` reports drift). Never declare an
|
|
54
|
+
override to skip a fix.
|
|
55
|
+
- For component contracts (options, slots, variants), load the `poetry`
|
|
56
|
+
usage skill; this skill assumes you compose through it.
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# audit - review a finished screen
|
|
2
|
+
|
|
3
|
+
Deterministic first, judgment second. Most AI-UI slop is mechanically
|
|
4
|
+
detectable; run the machines before offering opinions. And the machines
|
|
5
|
+
also run LAST: any edit the audit produces re-opens the gate - finish
|
|
6
|
+
with a clean `poetry:check` run AFTER the final edit, never before it.
|
|
7
|
+
|
|
8
|
+
## Run the linters
|
|
9
|
+
|
|
10
|
+
- `bin/rails poetry:check` - the hard gate: unknown components, options,
|
|
11
|
+
variants, icon names, arity, wiring. Errors block; fix them first.
|
|
12
|
+
- `POETRY_CHECK_DESIGN=1 bin/rails poetry:check` - adds the design-slop
|
|
13
|
+
tier (warnings; the taste tier). `POETRY_CHECK_JSON=1` for machine
|
|
14
|
+
output; both accept a glob argument for one file.
|
|
15
|
+
- `bin/rails poetry:verify` - classes vs the compiled CSS (catches classes
|
|
16
|
+
that never compiled, i.e. styles silently not applying).
|
|
17
|
+
|
|
18
|
+
## The design-lint rules (what each catches)
|
|
19
|
+
|
|
20
|
+
Every finding names its fix in the message. The 23 rules:
|
|
21
|
+
|
|
22
|
+
- `card-in-card` - a Card nested in a Card; flatten to one containment level.
|
|
23
|
+
- `icon-tile-over-heading` - the decorative icon-in-a-tile stacked above
|
|
24
|
+
every heading; the stock AI-UI tell.
|
|
25
|
+
- `wall-of-cards` - everything boxed identically; vary the surface or merge
|
|
26
|
+
regions.
|
|
27
|
+
- `off-scale-arbitrary` - `w-[347px]`-style values that sit off the scale;
|
|
28
|
+
use the scale spelling.
|
|
29
|
+
- `gradient-off-token` - gradients built from palette utilities instead of
|
|
30
|
+
tokens.
|
|
31
|
+
- `heading-skip` - h1 -> h3 ladder skips (remember Card titles default h3;
|
|
32
|
+
pass `title_tag:`).
|
|
33
|
+
- `mixed-status-weight` - solid and soft status pills mixed in one table;
|
|
34
|
+
keep one treatment family per surface.
|
|
35
|
+
- `center-everything` - body copy and controls center-aligned page-wide;
|
|
36
|
+
center is for empty states and heroes.
|
|
37
|
+
- `shadow-stack` - stacked/oversized shadows on nested surfaces.
|
|
38
|
+
- `type-scale-monotony` - all content text at one size; hierarchy needs a
|
|
39
|
+
scale (DOM tier - reads computed styles).
|
|
40
|
+
- `adjacent-same-surface` - sibling regions with identical surfaces and no
|
|
41
|
+
separation (DOM tier).
|
|
42
|
+
- `contrast-adjacent` - adjacent text failing contrast against its own
|
|
43
|
+
surface (DOM tier).
|
|
44
|
+
- `stock-theme-nudge` - the app still wears the stock look while a foreign
|
|
45
|
+
DESIGN.md is present (DOM tier).
|
|
46
|
+
- `em-dash-overuse` - five or more em dashes in the page copy; the LLM
|
|
47
|
+
prose tell. Rewrite most as periods, commas, or parentheses.
|
|
48
|
+
- `marketing-buzzword` - stock SaaS phrases ("streamline your",
|
|
49
|
+
"enterprise-grade"); say what the product concretely does.
|
|
50
|
+
- `aphoristic-cadence` - "Not a X. Y." / "No X. Just Y." constructions;
|
|
51
|
+
one lands, three read as generated copy.
|
|
52
|
+
- `numbered-section-markers` - sequential 01/02/03 editorial markers; cut
|
|
53
|
+
the numbers or vary the section anatomy.
|
|
54
|
+
- `repeated-section-kickers` - a tracked-caps kicker above every section
|
|
55
|
+
heading; keep at most one.
|
|
56
|
+
- `hero-eyebrow-chip` - a text eyebrow directly above the h1; fold it into
|
|
57
|
+
the heading or cut it (badge announcement pills are fine).
|
|
58
|
+
- `oversized-h1` - display-size type (text-7xl+) carrying 40+ characters;
|
|
59
|
+
shorten the headline or step the size down.
|
|
60
|
+
|
|
61
|
+
Motion floor (perception physics, theme-independent - they read the motion
|
|
62
|
+
utilities an element carries):
|
|
63
|
+
|
|
64
|
+
- `motion-ease-in` - a bare `ease-in` on a transition; ease-in decelerates
|
|
65
|
+
into rest, wrong for UI. Use `ease-out` for enters, `ease-in-out` for
|
|
66
|
+
moves (a state-scoped `data-closed:ease-in` exit is fine).
|
|
67
|
+
- `motion-duration-ceiling` - a UI transition over ~500ms (`duration-700`,
|
|
68
|
+
`duration-1000`, `duration-[800ms]`); past ~300ms UI reads as laggy.
|
|
69
|
+
- `motion-scale-from-zero` - an animated element resting at `scale-0`; it
|
|
70
|
+
erupts from nothing. Start from `scale-95` with opacity, not zero.
|
|
71
|
+
|
|
72
|
+
`transition-all` is a REPORT-ONLY advisory (`bin/rake design:motion`), not a
|
|
73
|
+
gate: it animates every property including layout, so prefer the specific
|
|
74
|
+
transition (`transition-colors`, `transition-[color,box-shadow]`,
|
|
75
|
+
`transition-transform`). poetry ships the upstream default, so re-timing it
|
|
76
|
+
is a design decision, surfaced rather than enforced.
|
|
77
|
+
|
|
78
|
+
## Score it (deterministic)
|
|
79
|
+
|
|
80
|
+
When the audit needs a NUMBER - a PR gate, a before/after, a fleet
|
|
81
|
+
sweep - compute the adherence score from findings, never from a
|
|
82
|
+
subjective sense of overall quality (the spectrum-audit rule).
|
|
83
|
+
|
|
84
|
+
Severity weights, fixed:
|
|
85
|
+
|
|
86
|
+
- **Critical 10** - each `poetry:check` ERROR (unknown component/option/
|
|
87
|
+
variant/icon, arity, wiring, slot misuse). These also block outright.
|
|
88
|
+
- **High 5** - each `poetry:verify` failure (a class that never
|
|
89
|
+
compiled: styling silently not applying).
|
|
90
|
+
- **Medium 2** - each design-slop WARNING (`POETRY_CHECK_DESIGN=1`, the
|
|
91
|
+
twenty rules above).
|
|
92
|
+
- **Low 1** - each critique-checklist finding (the judgment items; name
|
|
93
|
+
the surface for every one you count).
|
|
94
|
+
|
|
95
|
+
Per category: `score = 100 - min(100, sum_of_weights)`. Overall
|
|
96
|
+
adherence = the weighted mean: contracts 40%, compiled styling 25%,
|
|
97
|
+
design slop 25%, critique 10%. Report all four category scores plus the
|
|
98
|
+
overall, each with its finding count - a score with no finding list is
|
|
99
|
+
not a score.
|
|
100
|
+
|
|
101
|
+
## The critique checklist (what detectors cannot see)
|
|
102
|
+
|
|
103
|
+
Work the rendered page, not the source:
|
|
104
|
+
|
|
105
|
+
1. **Squint test** - blur your eyes (or shrink the screenshot): does the
|
|
106
|
+
page still have a shape - regions, a focal point, a reading order? If
|
|
107
|
+
it goes uniform gray, hierarchy is missing.
|
|
108
|
+
2. **One-decision test** - can you say in one sentence what this page most
|
|
109
|
+
wants the user to do? Is that the one filled-primary element?
|
|
110
|
+
3. **Consistency sweep** - same state, same treatment; same gap rhythm per
|
|
111
|
+
region; aligned edges (one container width, not three).
|
|
112
|
+
4. **Content honesty** - would a real user's data look like this? Plausible
|
|
113
|
+
distributions, realistic names/dates/amounts, an empty state where the
|
|
114
|
+
data could be empty.
|
|
115
|
+
5. **Framing** - does the page's subject have breathing room? Does anything
|
|
116
|
+
sit naked at the viewport origin?
|
|
117
|
+
|
|
118
|
+
Report findings in the linters' voice: name the surface, name the fix, and
|
|
119
|
+
express every fix through a token, variant, option, theme, or DESIGN.md
|
|
120
|
+
override - never per-instance CSS. Host CSS already touching `cn-*` classes
|
|
121
|
+
is either a DECLARED override (listed by `bin/rails poetry:design:overrides`;
|
|
122
|
+
respect it - it is recorded design intent) or drift to flag, never silently
|
|
123
|
+
extend.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# compose - shape the page before building it
|
|
2
|
+
|
|
3
|
+
Write the shape down first (a sentence per region), then build. Screens
|
|
4
|
+
composed region-by-region from a stated shape consistently beat screens
|
|
5
|
+
grown element-by-element. The five mechanics below are distilled from
|
|
6
|
+
judged head-to-head runs - they are where composed pages win.
|
|
7
|
+
|
|
8
|
+
## Step 1 is a tool call, not a decision
|
|
9
|
+
|
|
10
|
+
Route the brief through the poetry MCP `compose` tool FIRST (no MCP:
|
|
11
|
+
`bin/rails g poetry:block --list` + the `poetry` skill's
|
|
12
|
+
`references/blocks.md`). If it returns a block, START FROM THAT SOURCE and
|
|
13
|
+
edit in place - do not re-derive the layout from the checklist below.
|
|
14
|
+
Blocks arrive with the five mechanics already composed; a blank file
|
|
15
|
+
arrives with none of them, and reading this checklist does not transfer
|
|
16
|
+
them (measured: screens built from scratch after reading it composed no
|
|
17
|
+
better than screens built without it).
|
|
18
|
+
|
|
19
|
+
For a whole SCREEN, prefer the `build_page` tool over `compose`: it runs
|
|
20
|
+
the guided workflow (probe -> plan -> direct -> snippets -> verify), so the
|
|
21
|
+
page architecture (section order, the states a real screen handles, the
|
|
22
|
+
edge cases), the theme-derived direction, and the source all arrive in
|
|
23
|
+
order, and it finishes on the executable `check` gate. `compose` is the
|
|
24
|
+
single-step router build_page calls at its snippets step; reach for it
|
|
25
|
+
directly for a quick route or a lone component.
|
|
26
|
+
|
|
27
|
+
## The five mechanics
|
|
28
|
+
|
|
29
|
+
1. **Containment.** Give each functional region a boundary the eye can
|
|
30
|
+
find: a Card, a bordered `section`, a `bg-muted/50` band. A page of
|
|
31
|
+
floating fragments reads unfinished; a page of nested-cards-in-cards
|
|
32
|
+
reads like slop (the lint catches that direction). One level of
|
|
33
|
+
containment, used consistently.
|
|
34
|
+
2. **Status color-coding.** Encode state with the status vocabulary
|
|
35
|
+
(Badge `success` / `warning` / `info` / `destructive`), consistently:
|
|
36
|
+
the same state always gets the same variant, and one treatment family
|
|
37
|
+
per surface - solid and soft pills never mix in one table.
|
|
38
|
+
3. **Contextual framing.** A section that IS the page's subject keeps its
|
|
39
|
+
container and breathing room (`mx-auto max-w-* p-6`); a bare component
|
|
40
|
+
at the viewport origin reads cramped. Drop the wrapper only when
|
|
41
|
+
composing into an already-padded frame (an app shell's content area).
|
|
42
|
+
4. **Page furniture.** Real screens have a header (title + description +
|
|
43
|
+
primary action), section headings, and end-of-list affordances
|
|
44
|
+
(pagination, a "view all" link). A component demo has none of them; a
|
|
45
|
+
page needs them.
|
|
46
|
+
5. **Content realism.** Realistic data - names, amounts, dates, statuses in
|
|
47
|
+
plausible distributions (mostly-fulfilled with a few exceptions, not
|
|
48
|
+
one of each) - is part of the design. Lorem ipsum and ALL-states-once
|
|
49
|
+
both read as unfinished.
|
|
50
|
+
|
|
51
|
+
## Hierarchy and density
|
|
52
|
+
|
|
53
|
+
- One primary action per view; everything else is `outline`, `ghost`, or a
|
|
54
|
+
link. Two filled primary buttons side-by-side is a hierarchy bug.
|
|
55
|
+
- Secondary copy goes `text-muted-foreground` at `text-sm` - contrast
|
|
56
|
+
carries hierarchy more cheaply than size.
|
|
57
|
+
- Respect the heading ladder (h1 -> h2 -> h3, no skips) - note Card titles
|
|
58
|
+
default to h3; pass `title_tag:` when the card sits higher in the page.
|
|
59
|
+
- Space on the built-in scale, consistently: one gap rhythm per region
|
|
60
|
+
(`space-y-4` / `gap-4` family), padding steps from the same scale.
|
|
61
|
+
- Destructive flows: tinted boundary + plain-language consequences in
|
|
62
|
+
AA-clean muted copy; the alert carries icon + title only (description
|
|
63
|
+
copy on the destructive tint fails AA).
|
|
64
|
+
- Rich navigation panels (title + description grids) want
|
|
65
|
+
`poetry_navigation_menu(viewport: true)` - the morphing-card mode that
|
|
66
|
+
keeps panel content contained.
|
|
67
|
+
|
|
68
|
+
## Iterate against the render
|
|
69
|
+
|
|
70
|
+
Screenshot or render what you built and look at it before calling it done
|
|
71
|
+
- then run the audit pass (`references/audit.md`). The linters read both
|
|
72
|
+
ERB source and rendered HTML; what they can't see, the critique checklist
|
|
73
|
+
covers.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# figma - bring a Figma design into poetry
|
|
2
|
+
|
|
3
|
+
Two doors, independent. Take the first for a palette/theme handoff; the
|
|
4
|
+
second when a whole frame must become working components. Both translate
|
|
5
|
+
INTO poetry primitives and tokens - never transcribe Figma's absolute
|
|
6
|
+
positions, raw hex, or pixel gaps into markup.
|
|
7
|
+
|
|
8
|
+
## Door 1: variables -> an AA-gated theme (no paywall, no MCP)
|
|
9
|
+
|
|
10
|
+
Figma variables become poetry token overrides through the same importer a
|
|
11
|
+
DESIGN.md uses, so imported swatches inherit poetry's contrast law.
|
|
12
|
+
|
|
13
|
+
1. In Figma, export the variables as JSON with a free plugin - **Tokens
|
|
14
|
+
Studio** or **Design Tokens** (six7). These use the Plugin API, which
|
|
15
|
+
reads variables on every plan; the REST Variables API is Enterprise-only,
|
|
16
|
+
so do not rely on it.
|
|
17
|
+
2. Run `bin/rails poetry:figma:import[variables.json]` (or
|
|
18
|
+
`poetry:design:import` - it detects `.json`).
|
|
19
|
+
3. **Read the report.** The importer walks DTCG groups and modes, resolves
|
|
20
|
+
`{aliases}`, flattens `primary/DEFAULT` and `primary/foreground`, converts
|
|
21
|
+
hex / rgb / DTCG-object / oklch into poetry's OKLCH model, then measures
|
|
22
|
+
every touched pair against WCAG AA. A swatch that fails AA is **dropped
|
|
23
|
+
and reported with the nearest passing value** - never shipped. Anything
|
|
24
|
+
with no poetry role is dropped and listed too; the importer never guesses.
|
|
25
|
+
4. It writes `app/assets/tailwind/poetry/design-overrides.css` and wires the
|
|
26
|
+
import. Rebuild CSS. `POETRY_DESIGN_FORCE=1` ships failing pairs on
|
|
27
|
+
purpose (rarely right); `POETRY_DESIGN_JSON=1` prints a machine report.
|
|
28
|
+
|
|
29
|
+
Names that do not match a poetry role (`color/brand/600`, say) are dropped,
|
|
30
|
+
not invented. Rename in Figma toward poetry's semantic roles (`background`,
|
|
31
|
+
`foreground`, `primary`, `muted-foreground`, `border`, ...) and re-run.
|
|
32
|
+
|
|
33
|
+
## Door 2: a selection -> components (dual-MCP)
|
|
34
|
+
|
|
35
|
+
Needs the **Figma MCP** connected alongside the poetry MCP in one agent. The
|
|
36
|
+
remote server (`https://mcp.figma.com/mcp`) reads files by node id on all
|
|
37
|
+
plans; the live current-selection path (`get_variable_defs` in context)
|
|
38
|
+
wants the desktop app plus a Dev or Full seat. The server is in beta.
|
|
39
|
+
|
|
40
|
+
Flow:
|
|
41
|
+
|
|
42
|
+
1. Read the design - `get_design_context` (React + Tailwind by default),
|
|
43
|
+
`get_variable_defs` (the tokens a selection uses), `get_screenshot` (keep
|
|
44
|
+
layout fidelity).
|
|
45
|
+
2. Land the tokens first via Door 1 so Figma's variables line up with poetry
|
|
46
|
+
theme tokens; reconcile, do not duplicate.
|
|
47
|
+
3. Translate, do not copy. Map each Figma node to the nearest poetry
|
|
48
|
+
primitive - consult `list_components` / `describe_component`; assemble
|
|
49
|
+
with `compose` / `build_page`, never hand-authored markup.
|
|
50
|
+
4. Run poetry `check` LAST - a PASS verdict, not an eyeball.
|
|
51
|
+
|
|
52
|
+
Mapping guide:
|
|
53
|
+
|
|
54
|
+
- Auto-layout frame -> a poetry block or a page section (`compose` routes it).
|
|
55
|
+
- Component instance -> the nearest poetry component; its variant property ->
|
|
56
|
+
the poetry `variant` option, not a new class.
|
|
57
|
+
- Text -> component content / slots.
|
|
58
|
+
- Color, spacing, radius tokens -> poetry theme tokens (Door 1), never
|
|
59
|
+
per-instance CSS.
|
|
60
|
+
|
|
61
|
+
Optional: the Figma `create_design_system_rules` prompt writes a rule file
|
|
62
|
+
that teaches Figma's codegen agent poetry's conventions - point it here so
|
|
63
|
+
token names and helper calls come out right.
|
|
64
|
+
|
|
65
|
+
Code Connect (Dev Mode showing `poetry_button(...)` ERB) is possible through
|
|
66
|
+
`*.figma.ts` template files, but it needs an Org/Enterprise plan, a Dev/Full
|
|
67
|
+
seat, and a Figma UI kit poetry does not ship yet. Treat it as a later,
|
|
68
|
+
enterprise-tier path, not a prerequisite.
|