unmagic-components 0.3.0 → 0.4.0
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 +4 -4
- data/CHANGELOG.md +98 -1
- data/README.md +506 -1
- data/app/assets/icons/lucide/LICENSE +43 -0
- data/app/assets/icons/lucide/arrow-down.svg +1 -0
- data/app/assets/icons/lucide/arrow-left.svg +1 -0
- data/app/assets/icons/lucide/arrow-up.svg +1 -0
- data/app/assets/icons/lucide/ban.svg +1 -0
- data/app/assets/icons/lucide/brain.svg +1 -0
- data/app/assets/icons/lucide/check.svg +1 -0
- data/app/assets/icons/lucide/chevron-down.svg +1 -0
- data/app/assets/icons/lucide/chevron-left.svg +1 -0
- data/app/assets/icons/lucide/chevron-right.svg +1 -0
- data/app/assets/icons/lucide/circle-check.svg +1 -0
- data/app/assets/icons/lucide/circle-dashed.svg +1 -0
- data/app/assets/icons/lucide/circle-question-mark.svg +1 -0
- data/app/assets/icons/lucide/circle-stop.svg +1 -0
- data/app/assets/icons/lucide/circle-x.svg +1 -0
- data/app/assets/icons/lucide/clock.svg +1 -0
- data/app/assets/icons/lucide/copy.svg +1 -0
- data/app/assets/icons/lucide/ellipsis-vertical.svg +1 -0
- data/app/assets/icons/lucide/file.svg +1 -0
- data/app/assets/icons/lucide/folder.svg +1 -0
- data/app/assets/icons/lucide/grip-vertical.svg +1 -0
- data/app/assets/icons/lucide/info.svg +1 -0
- data/app/assets/icons/lucide/lightbulb.svg +1 -0
- data/app/assets/icons/lucide/list-checks.svg +1 -0
- data/app/assets/icons/lucide/loader-circle.svg +1 -0
- data/app/assets/icons/lucide/messages-square.svg +1 -0
- data/app/assets/icons/lucide/paperclip.svg +1 -0
- data/app/assets/icons/lucide/pencil.svg +1 -0
- data/app/assets/icons/lucide/plus.svg +1 -0
- data/app/assets/icons/lucide/rotate-cw.svg +1 -0
- data/app/assets/icons/lucide/shield-alert.svg +1 -0
- data/app/assets/icons/lucide/timer.svg +1 -0
- data/app/assets/icons/lucide/triangle-alert.svg +1 -0
- data/app/assets/icons/lucide/wrench.svg +1 -0
- data/app/assets/icons/lucide/x.svg +1 -0
- data/app/assets/javascripts/unmagic/components/ai_chat.js +142 -0
- data/app/assets/javascripts/unmagic/components/autoscroll.js +103 -0
- data/app/assets/javascripts/unmagic/components/board.js +65 -0
- data/app/assets/javascripts/unmagic/components/dropzone.js +206 -0
- data/app/assets/javascripts/unmagic/components/elapsed.js +64 -0
- data/app/assets/javascripts/unmagic/components/optimistic.js +71 -0
- data/app/assets/javascripts/unmagic/components/placement.js +30 -0
- data/app/assets/javascripts/unmagic/components/slash_menu.js +186 -0
- data/app/assets/javascripts/unmagic/components/sortable.js +6 -0
- data/app/assets/javascripts/unmagic/components/sortable_item.js +122 -0
- data/app/assets/javascripts/unmagic/components/sortable_list.js +135 -0
- data/app/assets/javascripts/unmagic/components/sortable_param.js +14 -0
- data/app/assets/javascripts/unmagic/components/sortable_session.js +502 -0
- data/app/assets/javascripts/unmagic/components/streaming_markdown.js +269 -0
- data/app/assets/javascripts/unmagic/components/toasts.js +14 -4
- data/app/assets/javascripts/unmagic/components/toolbar.js +76 -0
- data/app/assets/javascripts/unmagic/components/upsert.js +4 -20
- data/app/assets/javascripts/unmagic/components.js +10 -0
- data/app/assets/tailwind/unmagic_components/engine.css +1515 -0
- data/lib/unmagic/components/action_view_helpers.rb +558 -3
- data/lib/unmagic/components/ai_chat/action_bar.rb +70 -0
- data/lib/unmagic/components/ai_chat/attachments.rb +119 -0
- data/lib/unmagic/components/ai_chat/branch_picker.rb +65 -0
- data/lib/unmagic/components/ai_chat/citation.rb +89 -0
- data/lib/unmagic/components/ai_chat/composer.rb +160 -0
- data/lib/unmagic/components/ai_chat/failure.rb +80 -0
- data/lib/unmagic/components/ai_chat/message.rb +142 -0
- data/lib/unmagic/components/ai_chat/payload.rb +93 -0
- data/lib/unmagic/components/ai_chat/permission.rb +143 -0
- data/lib/unmagic/components/ai_chat/plan.rb +91 -0
- data/lib/unmagic/components/ai_chat/proposal.rb +102 -0
- data/lib/unmagic/components/ai_chat/reasoning.rb +75 -0
- data/lib/unmagic/components/ai_chat/request.rb +206 -0
- data/lib/unmagic/components/ai_chat/section.rb +53 -0
- data/lib/unmagic/components/ai_chat/slash_menu.rb +68 -0
- data/lib/unmagic/components/ai_chat/tool_call.rb +181 -0
- data/lib/unmagic/components/ai_chat/transcript.rb +68 -0
- data/lib/unmagic/components/ai_chat/welcome.rb +73 -0
- data/lib/unmagic/components/ai_chat/workspace.rb +74 -0
- data/lib/unmagic/components/ai_chat.rb +31 -0
- data/lib/unmagic/components/avatar.rb +134 -0
- data/lib/unmagic/components/board.rb +182 -0
- data/lib/unmagic/components/browser/app/controllers/unmagic/components/browser/application_controller.rb +80 -0
- data/lib/unmagic/components/browser/app/controllers/unmagic/components/browser/demos_controller.rb +137 -0
- data/lib/unmagic/components/browser/app/controllers/unmagic/components/browser/pages_controller.rb +40 -0
- data/lib/unmagic/components/browser/app/helpers/unmagic/components/browser/application_helper.rb +52 -0
- data/lib/unmagic/components/browser/app/models/unmagic/components/browser/board_store.rb +88 -0
- data/lib/unmagic/components/browser/app/models/unmagic/components/browser/catalog.rb +65 -0
- data/lib/unmagic/components/browser/app/models/unmagic/components/browser/pager.rb +11 -0
- data/lib/unmagic/components/browser/app/models/unmagic/components/browser/profile.rb +25 -0
- data/lib/unmagic/components/browser/app/models/unmagic/components/browser/reply.rb +72 -0
- data/lib/unmagic/components/browser/app/models/unmagic/components/browser/thing.rb +31 -0
- data/lib/unmagic/components/browser/app/views/layouts/unmagic/components/browser/application.html.erb +65 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/application/_code.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/application/_crumb.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/application/_example.html.erb +37 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/application/_nav.html.erb +17 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/demos/edit_profile.html.erb +9 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat/_conversation.html.erb +101 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat/_live.html.erb +53 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat/_thumbnail.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat/_welcome.html.erb +12 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_action_bar/_always.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_action_bar/_hover.html.erb +12 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_action_bar/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_attachments/_dropzone.html.erb +17 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_attachments/_sent.html.erb +11 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_attachments/_thumbnail.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_branch_picker/_positions.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_branch_picker/_thumbnail.html.erb +3 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_citation/_compact.html.erb +10 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_citation/_quote.html.erb +11 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_citation/_thumbnail.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_composer/_parts.html.erb +14 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_composer/_states.html.erb +8 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_composer/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_failure/_full.html.erb +11 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_failure/_plain.html.erb +3 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_failure/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_message/_parts.html.erb +23 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_message/_states.html.erb +9 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_message/_thumbnail.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_message/_turns.html.erb +16 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_payload/_json.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_payload/_text.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_payload/_thumbnail.html.erb +3 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_permission/_answered.html.erb +12 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_permission/_thumbnail.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_permission/_waiting.html.erb +12 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_plan/_empty.html.erb +3 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_plan/_states.html.erb +9 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_plan/_thumbnail.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_proposal/_decided.html.erb +11 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_proposal/_inline.html.erb +18 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_proposal/_thumbnail.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_reasoning/_settled.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_reasoning/_thinking.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_reasoning/_thumbnail.html.erb +3 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_request/_answered.html.erb +10 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_request/_choices.html.erb +13 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_request/_form.html.erb +9 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_request/_thumbnail.html.erb +8 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_slash_menu/_composer.html.erb +15 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_slash_menu/_thumbnail.html.erb +9 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_tool_call/_made.html.erb +12 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_tool_call/_run.html.erb +25 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_tool_call/_states.html.erb +22 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_tool_call/_thumbnail.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_welcome/_suggestions.html.erb +11 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_welcome/_thumbnail.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_workspace/_files.html.erb +12 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/ai_chat_workspace/_thumbnail.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/avatar/_group.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/avatar/_sizes.html.erb +8 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/avatar/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/avatar/_tints.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/badge/_in_context.html.erb +14 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/badge/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/badge/_tones.html.erb +8 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/board/_handles.html.erb +13 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/board/_live.html.erb +34 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/board/_thumbnail.html.erb +10 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/button/_sizes.html.erb +12 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/button/_thumbnail.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/button/_variants.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/callout/_neutral.html.erb +3 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/callout/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/callout/_tones.html.erb +14 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/card/_actions_and_footer.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/card/_flush_table.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/card/_link.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/card/_thumbnail.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/confirm/_danger.html.erb +3 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/confirm/_plain.html.erb +2 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/confirm/_thumbnail.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/copy_button/_from_element.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/copy_button/_thumbnail.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/copy_button/_with_label.html.erb +3 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/detail_list/_inline.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/detail_list/_stacked.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/detail_list/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/dialog/_dialog_tag.html.erb +8 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/dialog/_modal.html.erb +10 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/dialog/_thumbnail.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/elapsed/_countdown.html.erb +3 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/elapsed/_running.html.erb +8 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/elapsed/_thumbnail.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/empty_state/_default.html.erb +1 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/empty_state/_thumbnail.html.erb +3 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/forms/_autogrow.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/forms/_control_classes.html.erb +54 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/forms/_fields.html.erb +28 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/forms/_states.html.erb +11 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/forms/_thumbnail.html.erb +8 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/forms/_uuid_field.html.erb +9 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/local_time/_absolute.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/local_time/_relative.html.erb +14 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/local_time/_thumbnail.html.erb +14 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/menu/_actions.html.erb +10 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/menu/_labelled.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/menu/_thumbnail.html.erb +14 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/page_header/_default.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/page_header/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/page_header/_with_leading.html.erb +14 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/skeleton/_blocking_out.html.erb +25 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/skeleton/_card.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/skeleton/_detail_list.html.erb +15 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/skeleton/_page_header.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/skeleton/_text_and_button.html.erb +17 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/skeleton/_thumbnail.html.erb +10 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/sortable_list/_connected.html.erb +17 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/sortable_list/_grid.html.erb +20 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/sortable_list/_handles.html.erb +22 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/sortable_list/_thumbnail.html.erb +7 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/streaming_markdown/_reveal.html.erb +19 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/streaming_markdown/_stopped.html.erb +31 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/streaming_markdown/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/table/_deferred.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/table/_empty.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/table/_sortable.html.erb +8 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/table/_table_tag.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/table/_thumbnail.html.erb +4 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/tabs/_links.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/tabs/_panels.html.erb +18 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/tabs/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/toast/_above_dialog.html.erb +10 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/toast/_flash.html.erb +13 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/toast/_stream.html.erb +6 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/toast/_thumbnail.html.erb +10 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/tooltip/_placement.html.erb +8 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/tooltip/_term.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/examples/tooltip/_thumbnail.html.erb +5 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/pages/component.html.erb +58 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/pages/installation.html.erb +47 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/pages/overview.html.erb +49 -0
- data/lib/unmagic/components/browser/app/views/unmagic/components/browser/pages/theming.html.erb +52 -0
- data/lib/unmagic/components/browser/assets/browser.css +2 -0
- data/lib/unmagic/components/browser/catalog/ai_chat.rb +21 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_action_bar.rb +15 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_attachments.rb +15 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_branch_picker.rb +12 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_citation.rb +15 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_composer.rb +16 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_failure.rb +15 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_message.rb +17 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_payload.rb +16 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_permission.rb +15 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_plan.rb +14 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_proposal.rb +15 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_reasoning.rb +14 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_request.rb +17 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_slash_menu.rb +14 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_tool_call.rb +17 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_welcome.rb +13 -0
- data/lib/unmagic/components/browser/catalog/ai_chat_workspace.rb +12 -0
- data/lib/unmagic/components/browser/catalog/avatar.rb +15 -0
- data/lib/unmagic/components/browser/catalog/badge.rb +11 -0
- data/lib/unmagic/components/browser/catalog/board.rb +18 -0
- data/lib/unmagic/components/browser/catalog/button.rb +14 -0
- data/lib/unmagic/components/browser/catalog/callout.rb +13 -0
- data/lib/unmagic/components/browser/catalog/card.rb +16 -0
- data/lib/unmagic/components/browser/catalog/confirm.rb +14 -0
- data/lib/unmagic/components/browser/catalog/copy_button.rb +15 -0
- data/lib/unmagic/components/browser/catalog/detail_list.rb +14 -0
- data/lib/unmagic/components/browser/catalog/dialog.rb +15 -0
- data/lib/unmagic/components/browser/catalog/elapsed.rb +14 -0
- data/lib/unmagic/components/browser/catalog/empty_state.rb +11 -0
- data/lib/unmagic/components/browser/catalog/forms.rb +21 -0
- data/lib/unmagic/components/browser/catalog/local_time.rb +13 -0
- data/lib/unmagic/components/browser/catalog/menu.rb +15 -0
- data/lib/unmagic/components/browser/catalog/page_header.rb +13 -0
- data/lib/unmagic/components/browser/catalog/skeleton.rb +18 -0
- data/lib/unmagic/components/browser/catalog/sortable_list.rb +17 -0
- data/lib/unmagic/components/browser/catalog/streaming_markdown.rb +17 -0
- data/lib/unmagic/components/browser/catalog/table.rb +17 -0
- data/lib/unmagic/components/browser/catalog/tabs.rb +15 -0
- data/lib/unmagic/components/browser/catalog/toast.rb +17 -0
- data/lib/unmagic/components/browser/catalog/tooltip.rb +14 -0
- data/lib/unmagic/components/browser/config/routes.rb +41 -0
- data/lib/unmagic/components/browser/tailwind/browser.css +33 -0
- data/lib/unmagic/components/browser.rb +39 -0
- data/lib/unmagic/components/configuration.rb +31 -1
- data/lib/unmagic/components/duration.rb +35 -0
- data/lib/unmagic/components/elapsed.rb +46 -0
- data/lib/unmagic/components/engine.rb +9 -0
- data/lib/unmagic/components/icons.rb +34 -26
- data/lib/unmagic/components/modal.rb +1 -1
- data/lib/unmagic/components/page_header.rb +8 -0
- data/lib/unmagic/components/sortable.rb +104 -0
- data/lib/unmagic/components/streaming_markdown.rb +34 -0
- data/lib/unmagic/components/turbo_stream_actions.rb +16 -0
- data/lib/unmagic/components/version.rb +1 -1
- data/lib/unmagic/components.rb +30 -1
- metadata +308 -4
|
@@ -26,6 +26,23 @@
|
|
|
26
26
|
* @custom-variant keyed to a class or attribute.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
+
/* Variants for a sortable item's drag states, so markup can decorate them with
|
|
30
|
+
* utilities (sortable-dragging:rotate-2, sortable-over:bg-neutral-100). Every
|
|
31
|
+
* name is prefixed, so none collides with a variant of the host's.
|
|
32
|
+
*
|
|
33
|
+
* sortable-dragging the copy following the pointer, or anything in it
|
|
34
|
+
* sortable-placeholder the item left in the list while a pointer drags it
|
|
35
|
+
* sortable-lifted the item a keyboard is holding
|
|
36
|
+
* sortable-active a list that can take the item being dragged, or its
|
|
37
|
+
* ancestor
|
|
38
|
+
* sortable-over the list under the pointer, or its ancestor
|
|
39
|
+
*/
|
|
40
|
+
@custom-variant sortable-dragging (&[data-sortable-dragging], [data-sortable-dragging] &);
|
|
41
|
+
@custom-variant sortable-placeholder (&[data-sortable-placeholder], [data-sortable-placeholder] &);
|
|
42
|
+
@custom-variant sortable-lifted (&[data-sortable-lifted], [data-sortable-lifted] &);
|
|
43
|
+
@custom-variant sortable-active (&[data-sortable-active], &:has([data-sortable-active]));
|
|
44
|
+
@custom-variant sortable-over (&[data-sortable-over], &:has([data-sortable-over]));
|
|
45
|
+
|
|
29
46
|
@layer components {
|
|
30
47
|
/* ------------------------------------------------------------------ Table */
|
|
31
48
|
|
|
@@ -1161,4 +1178,1502 @@
|
|
|
1161
1178
|
.UnmagicAutogrow textarea {
|
|
1162
1179
|
@apply resize-none overflow-y-hidden;
|
|
1163
1180
|
}
|
|
1181
|
+
|
|
1182
|
+
/* ---------------------------------------------------------------- Avatars */
|
|
1183
|
+
|
|
1184
|
+
/* The initials always render; the image sits in the same grid cell on top, so a
|
|
1185
|
+
broken image (alt="" draws nothing) shows the initials through it. */
|
|
1186
|
+
.UnmagicAvatar {
|
|
1187
|
+
@apply relative inline-grid shrink-0 place-items-center overflow-hidden rounded-full bg-neutral-100 align-middle font-medium text-neutral-600 select-none;
|
|
1188
|
+
@apply dark:bg-neutral-800 dark:text-neutral-400;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
.UnmagicAvatar > * {
|
|
1192
|
+
grid-area: 1 / 1;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
.UnmagicAvatar__image {
|
|
1196
|
+
@apply size-full object-cover;
|
|
1197
|
+
border-radius: inherit;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
.UnmagicAvatar--small {
|
|
1201
|
+
@apply size-6 text-[0.625rem];
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
.UnmagicAvatar--medium {
|
|
1205
|
+
@apply size-8 text-xs;
|
|
1206
|
+
}
|
|
1207
|
+
|
|
1208
|
+
.UnmagicAvatar--large {
|
|
1209
|
+
@apply size-10 text-sm;
|
|
1210
|
+
}
|
|
1211
|
+
|
|
1212
|
+
.UnmagicAvatar--square {
|
|
1213
|
+
@apply rounded-md;
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
/* Six palette tints, picked from the name. A host recolours them through its
|
|
1217
|
+
palette, or by overriding these classes. */
|
|
1218
|
+
.UnmagicAvatar--tint-1 {
|
|
1219
|
+
@apply bg-sky-100 text-sky-700 dark:bg-sky-400/15 dark:text-sky-300;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
.UnmagicAvatar--tint-2 {
|
|
1223
|
+
@apply bg-emerald-100 text-emerald-700 dark:bg-emerald-400/15 dark:text-emerald-300;
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
.UnmagicAvatar--tint-3 {
|
|
1227
|
+
@apply bg-amber-100 text-amber-700 dark:bg-amber-400/15 dark:text-amber-300;
|
|
1228
|
+
}
|
|
1229
|
+
|
|
1230
|
+
.UnmagicAvatar--tint-4 {
|
|
1231
|
+
@apply bg-rose-100 text-rose-700 dark:bg-rose-400/15 dark:text-rose-300;
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
.UnmagicAvatar--tint-5 {
|
|
1235
|
+
@apply bg-violet-100 text-violet-700 dark:bg-violet-400/15 dark:text-violet-300;
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
.UnmagicAvatar--tint-6 {
|
|
1239
|
+
@apply bg-teal-100 text-teal-700 dark:bg-teal-400/15 dark:text-teal-300;
|
|
1240
|
+
}
|
|
1241
|
+
|
|
1242
|
+
.UnmagicAvatarGroup {
|
|
1243
|
+
@apply inline-flex items-center;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
/* A ring the colour of the surface separates the overlapping faces. */
|
|
1247
|
+
.UnmagicAvatarGroup > * {
|
|
1248
|
+
box-shadow: 0 0 0 2px var(--color-white);
|
|
1249
|
+
|
|
1250
|
+
@variant dark {
|
|
1251
|
+
box-shadow: 0 0 0 2px var(--color-neutral-900);
|
|
1252
|
+
}
|
|
1253
|
+
}
|
|
1254
|
+
|
|
1255
|
+
.UnmagicAvatarGroup > * + * {
|
|
1256
|
+
@apply -ml-2;
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
.UnmagicAvatarGroup--small > * + * {
|
|
1260
|
+
@apply -ml-1.5;
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
.UnmagicAvatarGroup__more {
|
|
1264
|
+
@apply inline-grid shrink-0 place-items-center rounded-full bg-neutral-50 font-medium text-neutral-500 tabular-nums;
|
|
1265
|
+
@apply dark:bg-neutral-800 dark:text-neutral-400;
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
.UnmagicAvatarGroup--small .UnmagicAvatarGroup__more {
|
|
1269
|
+
@apply size-6 text-[0.625rem];
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
.UnmagicAvatarGroup--medium .UnmagicAvatarGroup__more {
|
|
1273
|
+
@apply size-8 text-xs;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
.UnmagicAvatarGroup--large .UnmagicAvatarGroup__more {
|
|
1277
|
+
@apply size-10 text-sm;
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
/* ---------------------------------------------------------------- Elapsed */
|
|
1281
|
+
|
|
1282
|
+
/* tabular-nums is the reason for styling it at all: without it the reading
|
|
1283
|
+
shifts sideways each time a digit changes width. */
|
|
1284
|
+
.UnmagicElapsed {
|
|
1285
|
+
@apply font-mono text-xs tabular-nums;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1288
|
+
/* ------------------------------------------------------------------ Prose */
|
|
1289
|
+
|
|
1290
|
+
/* Server-rendered Markdown: the host renders and sanitises it, and this gives it
|
|
1291
|
+
a look. :where() keeps every rule at the specificity of .UnmagicProse alone, so
|
|
1292
|
+
a component placed inside prose (marked not-prose) wins with its own class. */
|
|
1293
|
+
.UnmagicProse {
|
|
1294
|
+
@apply block text-sm leading-relaxed text-neutral-900 dark:text-neutral-100;
|
|
1295
|
+
overflow-wrap: break-word;
|
|
1296
|
+
}
|
|
1297
|
+
|
|
1298
|
+
.UnmagicProse > :first-child {
|
|
1299
|
+
@apply mt-0;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
.UnmagicProse > :last-child {
|
|
1303
|
+
@apply mb-0;
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
.UnmagicProse :where(p, ul, ol, pre, blockquote, table, hr):not(:where(.not-prose *)) {
|
|
1307
|
+
margin-block: 0.75em;
|
|
1308
|
+
}
|
|
1309
|
+
|
|
1310
|
+
.UnmagicProse :where(h1, h2, h3, h4, h5, h6):not(:where(.not-prose *)) {
|
|
1311
|
+
@apply font-semibold text-neutral-900 dark:text-neutral-100;
|
|
1312
|
+
line-height: 1.3;
|
|
1313
|
+
margin-block: 1.25em 0.5em;
|
|
1314
|
+
}
|
|
1315
|
+
|
|
1316
|
+
.UnmagicProse :where(h1):not(:where(.not-prose *)) {
|
|
1317
|
+
@apply text-xl;
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
.UnmagicProse :where(h2):not(:where(.not-prose *)) {
|
|
1321
|
+
@apply text-lg;
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1324
|
+
.UnmagicProse :where(h3):not(:where(.not-prose *)) {
|
|
1325
|
+
@apply text-base;
|
|
1326
|
+
}
|
|
1327
|
+
|
|
1328
|
+
.UnmagicProse :where(h4, h5, h6):not(:where(.not-prose *)) {
|
|
1329
|
+
@apply text-sm;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
.UnmagicProse :where(ul):not(:where(.not-prose *)) {
|
|
1333
|
+
@apply list-disc;
|
|
1334
|
+
padding-inline-start: 1.5em;
|
|
1335
|
+
}
|
|
1336
|
+
|
|
1337
|
+
.UnmagicProse :where(ol):not(:where(.not-prose *)) {
|
|
1338
|
+
@apply list-decimal;
|
|
1339
|
+
padding-inline-start: 1.5em;
|
|
1340
|
+
}
|
|
1341
|
+
|
|
1342
|
+
.UnmagicProse :where(li):not(:where(.not-prose *)) {
|
|
1343
|
+
margin-block: 0.25em;
|
|
1344
|
+
}
|
|
1345
|
+
|
|
1346
|
+
.UnmagicProse :where(li > ul, li > ol):not(:where(.not-prose *)) {
|
|
1347
|
+
margin-block: 0.25em;
|
|
1348
|
+
}
|
|
1349
|
+
|
|
1350
|
+
.UnmagicProse :where(strong):not(:where(.not-prose *)) {
|
|
1351
|
+
@apply font-semibold;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
.UnmagicProse :where(a):not(:where(.not-prose *)) {
|
|
1355
|
+
@apply font-medium text-neutral-900 underline decoration-neutral-400 underline-offset-2 dark:text-neutral-100 dark:decoration-neutral-500;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
.UnmagicProse :where(blockquote):not(:where(.not-prose *)) {
|
|
1359
|
+
@apply border-l-2 border-neutral-300 pl-3 text-neutral-600 dark:border-neutral-700 dark:text-neutral-400;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
.UnmagicProse :where(hr):not(:where(.not-prose *)) {
|
|
1363
|
+
@apply border-0 border-t border-neutral-200 dark:border-neutral-800;
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
.UnmagicProse :where(:not(pre) > code):not(:where(.not-prose *)) {
|
|
1367
|
+
@apply rounded bg-neutral-100 px-1 py-0.5 font-mono text-[0.9em] dark:bg-neutral-800;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
/* The block's chrome only: the tokens are the host's highlighter's, through the
|
|
1371
|
+
same code_block seam a tool payload uses. */
|
|
1372
|
+
.UnmagicProse :where(pre):not(:where(.not-prose *)) {
|
|
1373
|
+
@apply overflow-x-auto rounded-lg border border-neutral-200 bg-neutral-50 p-3 font-mono text-xs leading-relaxed;
|
|
1374
|
+
@apply dark:border-neutral-800 dark:bg-neutral-900;
|
|
1375
|
+
}
|
|
1376
|
+
|
|
1377
|
+
.UnmagicProse :where(pre code):not(:where(.not-prose *)) {
|
|
1378
|
+
@apply bg-transparent p-0;
|
|
1379
|
+
font-size: inherit;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
.UnmagicProse :where(table):not(:where(.not-prose *)) {
|
|
1383
|
+
@apply block w-max max-w-full border-collapse overflow-x-auto text-left;
|
|
1384
|
+
}
|
|
1385
|
+
|
|
1386
|
+
.UnmagicProse :where(th, td):not(:where(.not-prose *)) {
|
|
1387
|
+
@apply border-b border-neutral-200 py-1.5 pr-4 align-top dark:border-neutral-800;
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
.UnmagicProse :where(th):not(:where(.not-prose *)) {
|
|
1391
|
+
@apply font-semibold;
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
.UnmagicProse :where(ul:has(> li > input[type="checkbox"])):not(:where(.not-prose *)) {
|
|
1395
|
+
@apply list-none pl-1;
|
|
1396
|
+
}
|
|
1397
|
+
|
|
1398
|
+
/* -------------------------------------------------------- Custom elements */
|
|
1399
|
+
|
|
1400
|
+
/* Elements that only add behaviour, and must not take part in their parent's
|
|
1401
|
+
layout. */
|
|
1402
|
+
.UnmagicAutoscroll,
|
|
1403
|
+
.UnmagicOptimistic {
|
|
1404
|
+
display: contents;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
.UnmagicStreamingMarkdown {
|
|
1408
|
+
@apply block;
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
/* ---------------------------------------------------------------- AI chat */
|
|
1412
|
+
|
|
1413
|
+
/* The gap between turns is margin-top on each *following* visible turn, not a
|
|
1414
|
+
space-y utility: Tailwind's space-y puts it on the preceding element, which
|
|
1415
|
+
can't be tightened by what follows. Hidden entries (a tool result's anchor, a
|
|
1416
|
+
turn that said nothing) never earn a gap. A run of tool calls sits closer,
|
|
1417
|
+
counting the gap markers between them as part of the run. */
|
|
1418
|
+
.UnmagicAIChat {
|
|
1419
|
+
@apply block;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
.UnmagicAIChat > :not([hidden]) ~ :not([hidden]) {
|
|
1423
|
+
margin-top: calc(var(--spacing) * 6);
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
.UnmagicAIChat > [data-ai-chat-timeline] + [data-ai-chat-timeline]:not([hidden]) {
|
|
1427
|
+
margin-top: calc(var(--spacing) * 3);
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
/* The welcome stands in for an empty conversation, and steps aside for the first
|
|
1431
|
+
entry streamed in. */
|
|
1432
|
+
.UnmagicAIChat:has(> :not(.UnmagicAIChat__welcome, [hidden])) > .UnmagicAIChat__welcome {
|
|
1433
|
+
@apply hidden;
|
|
1434
|
+
}
|
|
1435
|
+
|
|
1436
|
+
/* A zero-height sticky dock, so the button floats over the transcript's foot
|
|
1437
|
+
without taking room in it. A host with a sticky composer lifts it with bottom. */
|
|
1438
|
+
.UnmagicAIChat__latest {
|
|
1439
|
+
@apply pointer-events-none sticky bottom-4 z-10 flex h-0 justify-center;
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1442
|
+
.UnmagicAIChat__latestButton {
|
|
1443
|
+
font: inherit;
|
|
1444
|
+
@apply pointer-events-auto inline-flex size-9 -translate-y-full cursor-pointer items-center justify-center rounded-full border border-neutral-200 bg-white text-neutral-600 shadow-md;
|
|
1445
|
+
@apply dark:border-neutral-700 dark:bg-neutral-900 dark:text-neutral-300;
|
|
1446
|
+
transition: opacity 150ms ease;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1449
|
+
.UnmagicAIChat__latestButton[hidden] {
|
|
1450
|
+
@apply hidden;
|
|
1451
|
+
}
|
|
1452
|
+
|
|
1453
|
+
.UnmagicAIChat__latestButton:hover {
|
|
1454
|
+
@apply text-neutral-900 dark:text-white;
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
.UnmagicAIChat__latestButton:focus-visible {
|
|
1458
|
+
@apply outline-2 outline-offset-2 outline-neutral-400 dark:outline-neutral-500;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
/* A spinner that pulses rather than turning under reduced motion, since a
|
|
1462
|
+
frozen one reads as a hang. */
|
|
1463
|
+
.UnmagicAIChatSpinner {
|
|
1464
|
+
animation: unmagic-ai-chat-spin 1s linear infinite;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
@keyframes unmagic-ai-chat-spin {
|
|
1468
|
+
to {
|
|
1469
|
+
transform: rotate(360deg);
|
|
1470
|
+
}
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
@keyframes unmagic-ai-chat-pulse {
|
|
1474
|
+
50% {
|
|
1475
|
+
opacity: 0.35;
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
|
|
1479
|
+
/* A disclosure's chevron points right when shut and down when open. */
|
|
1480
|
+
.UnmagicAIChatChevron {
|
|
1481
|
+
@apply size-3.5 shrink-0;
|
|
1482
|
+
transition: rotate 150ms ease;
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
details[open] > summary .UnmagicAIChatChevron {
|
|
1486
|
+
rotate: 90deg;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
@media (prefers-reduced-motion: reduce) {
|
|
1490
|
+
.UnmagicAIChatSpinner {
|
|
1491
|
+
animation: unmagic-ai-chat-pulse 2s ease-in-out infinite;
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
.UnmagicAIChatChevron,
|
|
1495
|
+
.UnmagicAIChat__latestButton {
|
|
1496
|
+
transition: none;
|
|
1497
|
+
}
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
/* The family's disclosures are rows, not buttons: no marker, a pointer, and the
|
|
1501
|
+
shared focus ring. */
|
|
1502
|
+
:is(.UnmagicAIChatToolCall, .UnmagicAIChatReasoning, .UnmagicAIChatFailure, .UnmagicAIChatPlan, .UnmagicAIChatWorkspace) summary {
|
|
1503
|
+
@apply cursor-pointer list-none select-none;
|
|
1504
|
+
}
|
|
1505
|
+
|
|
1506
|
+
:is(.UnmagicAIChatToolCall, .UnmagicAIChatReasoning, .UnmagicAIChatFailure, .UnmagicAIChatPlan, .UnmagicAIChatWorkspace) summary::-webkit-details-marker {
|
|
1507
|
+
@apply hidden;
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
:is(.UnmagicAIChatToolCall, .UnmagicAIChatReasoning, .UnmagicAIChatFailure, .UnmagicAIChatPlan, .UnmagicAIChatWorkspace) summary:focus-visible {
|
|
1511
|
+
@apply rounded-xs outline-2 outline-offset-2 outline-neutral-400 dark:outline-neutral-500;
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
/* ------------------------------------------------------- AI chat messages */
|
|
1515
|
+
|
|
1516
|
+
.UnmagicAIChatMessage {
|
|
1517
|
+
@apply flex flex-col items-start gap-1.5;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
.UnmagicAIChatMessage--user {
|
|
1521
|
+
@apply items-end;
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
.UnmagicAIChatMessage--assistant > .UnmagicAIChatMessage__body {
|
|
1525
|
+
@apply w-full;
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
/* A user's turn was typed into a box, never written as Markdown, so the line
|
|
1529
|
+
breaks they typed are the only formatting it has. */
|
|
1530
|
+
.UnmagicAIChatMessage__bubble {
|
|
1531
|
+
@apply max-w-[85%] rounded-2xl rounded-br-sm bg-neutral-900 px-4 py-2.5 text-sm leading-relaxed whitespace-pre-wrap text-white;
|
|
1532
|
+
@apply dark:bg-neutral-100 dark:text-neutral-900;
|
|
1533
|
+
overflow-wrap: anywhere;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
.UnmagicAIChatMessage[data-optimistic] .UnmagicAIChatMessage__bubble {
|
|
1537
|
+
@apply opacity-60;
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
.UnmagicAIChatMessage__attachments {
|
|
1541
|
+
@apply max-w-[85%];
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
.UnmagicAIChatMessage__thinking {
|
|
1545
|
+
@apply inline-flex py-0.5 text-neutral-400 dark:text-neutral-500;
|
|
1546
|
+
}
|
|
1547
|
+
|
|
1548
|
+
.UnmagicAIChatMessage__footer {
|
|
1549
|
+
@apply flex min-h-7 items-center gap-1;
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
/* ------------------------------------------------------ AI chat reasoning */
|
|
1553
|
+
|
|
1554
|
+
.UnmagicAIChatReasoning {
|
|
1555
|
+
@apply max-w-[85%] rounded-xl border border-neutral-200 bg-neutral-50 px-3 py-2 text-xs text-neutral-500;
|
|
1556
|
+
@apply dark:border-neutral-800 dark:bg-neutral-900 dark:text-neutral-400;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
.UnmagicAIChatReasoning__head {
|
|
1560
|
+
@apply flex items-center gap-1.5;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
.UnmagicAIChatReasoning__head:hover {
|
|
1564
|
+
@apply text-neutral-900 dark:text-neutral-100;
|
|
1565
|
+
}
|
|
1566
|
+
|
|
1567
|
+
.UnmagicAIChatReasoning__head .UnmagicIcon {
|
|
1568
|
+
@apply size-3.5;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1571
|
+
.UnmagicAIChatReasoning__block {
|
|
1572
|
+
@apply mt-2 text-xs text-neutral-600 dark:text-neutral-400;
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
/* ----------------------------------------------------- AI chat tool calls */
|
|
1576
|
+
|
|
1577
|
+
.UnmagicAIChatToolCall {
|
|
1578
|
+
@apply relative text-sm text-neutral-500 dark:text-neutral-400;
|
|
1579
|
+
}
|
|
1580
|
+
|
|
1581
|
+
/* The line joining a run: every row draws it, and only a row following another
|
|
1582
|
+
shows it. It reaches up into the gap above, centred on the glyph's column,
|
|
1583
|
+
rather than taking room of its own. */
|
|
1584
|
+
.UnmagicAIChatToolCall__join {
|
|
1585
|
+
@apply absolute hidden w-px -translate-x-1/2 bg-neutral-200 dark:bg-neutral-700;
|
|
1586
|
+
left: 0.4375rem;
|
|
1587
|
+
top: calc(var(--spacing) * -2.5);
|
|
1588
|
+
height: calc(var(--spacing) * 2);
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
[data-ai-chat-timeline] + [data-ai-chat-timeline] > .UnmagicAIChatToolCall__join {
|
|
1592
|
+
@apply block;
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
.UnmagicAIChatToolCall__row {
|
|
1596
|
+
@apply flex min-w-0 flex-wrap items-center gap-x-2 gap-y-0.5;
|
|
1597
|
+
}
|
|
1598
|
+
|
|
1599
|
+
summary.UnmagicAIChatToolCall__row:hover {
|
|
1600
|
+
@apply text-neutral-900 dark:text-neutral-100;
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
.UnmagicAIChatToolCall__glyph {
|
|
1604
|
+
@apply inline-flex shrink-0;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
.UnmagicAIChatToolCall__glyph .UnmagicIcon {
|
|
1608
|
+
@apply size-3.5;
|
|
1609
|
+
}
|
|
1610
|
+
|
|
1611
|
+
.UnmagicAIChatToolCall--done .UnmagicAIChatToolCall__glyph,
|
|
1612
|
+
.UnmagicAIChatToolCall--queued .UnmagicAIChatToolCall__glyph {
|
|
1613
|
+
@apply text-neutral-400 dark:text-neutral-500;
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
.UnmagicAIChatToolCall--waiting .UnmagicAIChatToolCall__glyph {
|
|
1617
|
+
@apply text-amber-600 dark:text-amber-500;
|
|
1618
|
+
}
|
|
1619
|
+
|
|
1620
|
+
.UnmagicAIChatToolCall--failed .UnmagicAIChatToolCall__glyph,
|
|
1621
|
+
.UnmagicAIChatToolCall--failed .UnmagicAIChatToolCall__name {
|
|
1622
|
+
@apply text-red-600 dark:text-red-400;
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
.UnmagicAIChatToolCall__name {
|
|
1626
|
+
@apply font-mono text-xs;
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
.UnmagicAIChatToolCall__summary {
|
|
1630
|
+
@apply min-w-0 truncate font-medium text-neutral-700 dark:text-neutral-300;
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
/* Beside the name rather than hard right: there's no box edge to flush them to,
|
|
1634
|
+
and a clock alone at the far side of a wide column belongs to nothing. */
|
|
1635
|
+
.UnmagicAIChatToolCall__readings {
|
|
1636
|
+
@apply inline-flex shrink-0 items-center gap-2.5;
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
.UnmagicAIChatToolCall__reading {
|
|
1640
|
+
@apply inline-flex items-center gap-1 font-mono text-xs text-neutral-400 tabular-nums dark:text-neutral-500;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
.UnmagicAIChatToolCall__reading .UnmagicIcon {
|
|
1644
|
+
@apply size-3.5;
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
.UnmagicAIChatToolCall__reading--warn {
|
|
1648
|
+
@apply text-amber-600 dark:text-amber-500;
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
.UnmagicAIChatToolCall__progress {
|
|
1652
|
+
@apply basis-full pl-5.5 text-xs text-neutral-400 dark:text-neutral-500;
|
|
1653
|
+
}
|
|
1654
|
+
|
|
1655
|
+
/* An open call keeps the line running down its own body, so it's a stretch of
|
|
1656
|
+
the run rather than a hole in it. Anything under a row hangs off the glyph's
|
|
1657
|
+
column. */
|
|
1658
|
+
.UnmagicAIChatToolCall__body {
|
|
1659
|
+
@apply relative mt-2 flex flex-col gap-3 pb-1 pl-5.5;
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1662
|
+
.UnmagicAIChatToolCall__made {
|
|
1663
|
+
@apply relative mt-2 flex flex-wrap gap-2 pl-5.5;
|
|
1664
|
+
}
|
|
1665
|
+
|
|
1666
|
+
.UnmagicAIChatToolCall__rail {
|
|
1667
|
+
@apply absolute bottom-0 w-px -translate-x-1/2 bg-neutral-200 dark:bg-neutral-700;
|
|
1668
|
+
left: 0.4375rem;
|
|
1669
|
+
top: calc(var(--spacing) * -1.5);
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
/* ------------------------------------------------------- AI chat payloads */
|
|
1673
|
+
|
|
1674
|
+
.UnmagicAIChatPayload {
|
|
1675
|
+
@apply flex min-w-0 flex-col gap-1.5;
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
.UnmagicAIChatPayload__head {
|
|
1679
|
+
@apply flex items-center gap-2;
|
|
1680
|
+
}
|
|
1681
|
+
|
|
1682
|
+
.UnmagicAIChatPayload__label {
|
|
1683
|
+
@apply flex-1 text-[10px] font-medium tracking-wide text-neutral-500 uppercase;
|
|
1684
|
+
}
|
|
1685
|
+
|
|
1686
|
+
.UnmagicAIChatPayload__timing {
|
|
1687
|
+
@apply inline-flex items-center gap-1 font-mono text-xs text-neutral-400 tabular-nums;
|
|
1688
|
+
}
|
|
1689
|
+
|
|
1690
|
+
.UnmagicAIChatPayload__timing .UnmagicIcon {
|
|
1691
|
+
@apply size-3.5;
|
|
1692
|
+
}
|
|
1693
|
+
|
|
1694
|
+
/* The box itself scrolls, so a keyboard user focusing it can scroll it; long
|
|
1695
|
+
lines wrap, since one line of a payload can be a whole page. It deliberately
|
|
1696
|
+
doesn't contain overscroll: Chrome would apply that to a short payload too,
|
|
1697
|
+
and a finger swiping over one couldn't scroll the page. */
|
|
1698
|
+
.UnmagicAIChatPayload__code {
|
|
1699
|
+
@apply max-h-64 overflow-auto rounded-md border border-neutral-200 bg-white text-neutral-800;
|
|
1700
|
+
@apply dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-200;
|
|
1701
|
+
}
|
|
1702
|
+
|
|
1703
|
+
.UnmagicAIChatPayload__code:focus-visible {
|
|
1704
|
+
@apply outline-2 outline-offset-2 outline-neutral-400 dark:outline-neutral-500;
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1707
|
+
.UnmagicAIChatPayload__code > pre {
|
|
1708
|
+
@apply m-0 bg-transparent p-2.5 font-mono text-xs leading-relaxed break-words whitespace-pre-wrap;
|
|
1709
|
+
}
|
|
1710
|
+
|
|
1711
|
+
/* ------------------------------------------------------- AI chat failures */
|
|
1712
|
+
|
|
1713
|
+
.UnmagicAIChatFailure {
|
|
1714
|
+
@apply rounded-lg border border-red-200 bg-red-50 px-3 py-2 text-sm dark:border-red-400/30 dark:bg-red-400/10;
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
.UnmagicAIChatFailure__head {
|
|
1718
|
+
@apply flex items-start gap-2;
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
.UnmagicAIChatFailure__icon {
|
|
1722
|
+
@apply mt-0.5 text-red-600 dark:text-red-400;
|
|
1723
|
+
}
|
|
1724
|
+
|
|
1725
|
+
.UnmagicAIChatFailure__text {
|
|
1726
|
+
@apply min-w-0 flex-1;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
.UnmagicAIChatFailure__message {
|
|
1730
|
+
@apply m-0 text-red-800 dark:text-red-300;
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1733
|
+
/* A provider's message runs long and usually holds a URL. */
|
|
1734
|
+
.UnmagicAIChatFailure__cause {
|
|
1735
|
+
@apply mt-1 mb-0 font-mono text-xs break-words text-red-700/90 dark:text-red-400/90;
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
.UnmagicAIChatFailure__details {
|
|
1739
|
+
@apply mt-2;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
.UnmagicAIChatFailure__summary {
|
|
1743
|
+
@apply inline-flex items-center gap-1.5 text-xs text-red-700/80 dark:text-red-400/80;
|
|
1744
|
+
}
|
|
1745
|
+
|
|
1746
|
+
.UnmagicAIChatFailure__body {
|
|
1747
|
+
@apply mt-2 flex flex-col gap-3;
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
.UnmagicAIChatFailure__retry {
|
|
1751
|
+
@apply mt-2;
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
/* ---------------------------------------------------------- AI chat plans */
|
|
1755
|
+
|
|
1756
|
+
/* A plan and a workspace are two sections of one panel, so they share a shape,
|
|
1757
|
+
and a divider when one follows the other. */
|
|
1758
|
+
.UnmagicAIChatPlan,
|
|
1759
|
+
.UnmagicAIChatWorkspace {
|
|
1760
|
+
@apply block p-4 text-sm text-neutral-900 dark:text-neutral-100;
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
.UnmagicAIChatPlan + .UnmagicAIChatWorkspace {
|
|
1764
|
+
@apply border-t border-neutral-200 dark:border-neutral-800;
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
.UnmagicAIChatPlan__head,
|
|
1768
|
+
.UnmagicAIChatWorkspace__head {
|
|
1769
|
+
@apply flex items-center gap-2 text-neutral-400 dark:text-neutral-500;
|
|
1770
|
+
}
|
|
1771
|
+
|
|
1772
|
+
.UnmagicAIChatPlan__title,
|
|
1773
|
+
.UnmagicAIChatWorkspace__title {
|
|
1774
|
+
@apply m-0 text-sm font-medium text-neutral-900 dark:text-neutral-100;
|
|
1775
|
+
}
|
|
1776
|
+
|
|
1777
|
+
.UnmagicAIChatPlan__count,
|
|
1778
|
+
.UnmagicAIChatWorkspace__count {
|
|
1779
|
+
@apply ml-auto shrink-0 text-xs text-neutral-400 tabular-nums;
|
|
1780
|
+
}
|
|
1781
|
+
|
|
1782
|
+
.UnmagicAIChatPlan__empty,
|
|
1783
|
+
.UnmagicAIChatWorkspace__empty {
|
|
1784
|
+
@apply mt-2 mb-0 text-neutral-400 dark:text-neutral-500;
|
|
1785
|
+
}
|
|
1786
|
+
|
|
1787
|
+
.UnmagicAIChatPlan__steps {
|
|
1788
|
+
@apply mx-0 mt-3 mb-0 flex list-none flex-col gap-1.5 p-0;
|
|
1789
|
+
}
|
|
1790
|
+
|
|
1791
|
+
.UnmagicAIChatPlan__step {
|
|
1792
|
+
@apply flex items-start gap-2;
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
.UnmagicAIChatPlan__glyph {
|
|
1796
|
+
@apply mt-0.5 inline-flex shrink-0;
|
|
1797
|
+
}
|
|
1798
|
+
|
|
1799
|
+
.UnmagicAIChatPlan__glyph .UnmagicIcon {
|
|
1800
|
+
@apply size-3.5;
|
|
1801
|
+
}
|
|
1802
|
+
|
|
1803
|
+
.UnmagicAIChatPlan__text {
|
|
1804
|
+
@apply min-w-0;
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
.UnmagicAIChatPlan__detail {
|
|
1808
|
+
@apply mt-1 text-xs text-neutral-500;
|
|
1809
|
+
}
|
|
1810
|
+
|
|
1811
|
+
/* A done step recedes and the one being worked stands up, so a long plan reads as
|
|
1812
|
+
a position. Waiting is the one in colour: the only state that won't move on
|
|
1813
|
+
its own. */
|
|
1814
|
+
.UnmagicAIChatPlan__step[data-state="completed"] .UnmagicAIChatPlan__glyph {
|
|
1815
|
+
@apply text-green-600 dark:text-green-500;
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
.UnmagicAIChatPlan__step[data-state="completed"] .UnmagicAIChatPlan__label {
|
|
1819
|
+
@apply text-neutral-400 line-through dark:text-neutral-500;
|
|
1820
|
+
}
|
|
1821
|
+
|
|
1822
|
+
.UnmagicAIChatPlan__step[data-state="in_progress"] .UnmagicAIChatPlan__glyph {
|
|
1823
|
+
@apply text-neutral-900 dark:text-neutral-100;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
.UnmagicAIChatPlan__step[data-state="waiting"] .UnmagicAIChatPlan__glyph {
|
|
1827
|
+
@apply text-amber-600 dark:text-amber-500;
|
|
1828
|
+
}
|
|
1829
|
+
|
|
1830
|
+
.UnmagicAIChatPlan__step[data-state="in_progress"] .UnmagicAIChatPlan__label,
|
|
1831
|
+
.UnmagicAIChatPlan__step[data-state="waiting"] .UnmagicAIChatPlan__label {
|
|
1832
|
+
@apply font-medium text-neutral-900 dark:text-neutral-100;
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
.UnmagicAIChatPlan__step[data-state="pending"] .UnmagicAIChatPlan__glyph {
|
|
1836
|
+
@apply text-neutral-300 dark:text-neutral-600;
|
|
1837
|
+
}
|
|
1838
|
+
|
|
1839
|
+
.UnmagicAIChatPlan__step[data-state="pending"] .UnmagicAIChatPlan__label {
|
|
1840
|
+
@apply text-neutral-600 dark:text-neutral-400;
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
/* ------------------------------------------------------ AI chat workspace */
|
|
1844
|
+
|
|
1845
|
+
.UnmagicAIChatWorkspace__files {
|
|
1846
|
+
@apply mx-0 mt-3 mb-0 flex list-none flex-col p-0;
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
.UnmagicAIChatWorkspace__file,
|
|
1850
|
+
.UnmagicAIChatWorkspace__link {
|
|
1851
|
+
@apply flex min-w-0 items-center gap-1.5;
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1854
|
+
.UnmagicAIChatWorkspace__file {
|
|
1855
|
+
@apply rounded-md px-1 py-1 text-neutral-700 dark:text-neutral-300;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
.UnmagicAIChatWorkspace__link {
|
|
1859
|
+
@apply flex-1 text-inherit no-underline;
|
|
1860
|
+
}
|
|
1861
|
+
|
|
1862
|
+
.UnmagicAIChatWorkspace__file:has(> .UnmagicAIChatWorkspace__link):hover {
|
|
1863
|
+
@apply bg-neutral-100 dark:bg-neutral-800;
|
|
1864
|
+
}
|
|
1865
|
+
|
|
1866
|
+
.UnmagicAIChatWorkspace__link:focus-visible {
|
|
1867
|
+
@apply rounded-xs outline-2 outline-offset-2 outline-neutral-400 dark:outline-neutral-500;
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
.UnmagicAIChatWorkspace__icon {
|
|
1871
|
+
@apply text-neutral-400 dark:text-neutral-500;
|
|
1872
|
+
}
|
|
1873
|
+
|
|
1874
|
+
.UnmagicAIChatWorkspace__name {
|
|
1875
|
+
@apply min-w-0 truncate;
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
.UnmagicAIChatWorkspace__directory {
|
|
1879
|
+
@apply text-neutral-400 dark:text-neutral-500;
|
|
1880
|
+
}
|
|
1881
|
+
|
|
1882
|
+
.UnmagicAIChatWorkspace__size {
|
|
1883
|
+
@apply ml-auto shrink-0 pl-2 text-xs text-neutral-400 tabular-nums;
|
|
1884
|
+
}
|
|
1885
|
+
|
|
1886
|
+
/* ------------------------------------------------------- AI chat composer */
|
|
1887
|
+
|
|
1888
|
+
/* A container, so the hint below can give way to the field in a narrow column
|
|
1889
|
+
however wide the page is. */
|
|
1890
|
+
.UnmagicAIChatComposer {
|
|
1891
|
+
@apply relative flex flex-col gap-2;
|
|
1892
|
+
container-type: inline-size;
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
.UnmagicAIChatComposer__chips:empty {
|
|
1896
|
+
@apply hidden;
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
.UnmagicAIChatComposer__chips {
|
|
1900
|
+
@apply flex flex-wrap gap-1.5;
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
/* The box is the control, so it takes the focus ring; the textarea inside it is
|
|
1904
|
+
bare. */
|
|
1905
|
+
.UnmagicAIChatComposer__box {
|
|
1906
|
+
@apply flex items-end gap-2 rounded-xl border border-neutral-300 bg-white p-2 shadow-xs;
|
|
1907
|
+
@apply dark:border-neutral-700 dark:bg-neutral-900;
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
.UnmagicAIChatComposer__box:focus-within {
|
|
1911
|
+
@apply border-neutral-500 dark:border-neutral-500;
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
.UnmagicAIChatComposer__box:has(.UnmagicAIChatComposer__field:focus-visible) {
|
|
1915
|
+
@apply outline-2 outline-offset-2 outline-neutral-400 dark:outline-neutral-500;
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
.UnmagicAIChatComposer__box > .UnmagicAutogrow {
|
|
1919
|
+
@apply min-w-0 flex-1 self-center;
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
.UnmagicAIChatComposer__field {
|
|
1923
|
+
font: inherit;
|
|
1924
|
+
@apply block max-h-60 w-full border-0 bg-transparent px-2 py-1.5 text-sm text-neutral-900 shadow-none outline-none placeholder:text-neutral-400;
|
|
1925
|
+
@apply dark:text-neutral-100 dark:placeholder:text-neutral-500;
|
|
1926
|
+
}
|
|
1927
|
+
|
|
1928
|
+
.UnmagicAIChatComposer__attach,
|
|
1929
|
+
.UnmagicAIChatComposer__actions,
|
|
1930
|
+
.UnmagicAIChatComposer__action {
|
|
1931
|
+
@apply flex shrink-0 items-center gap-1;
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
.UnmagicAIChatComposer__action {
|
|
1935
|
+
@apply gap-2;
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1938
|
+
/* Hidden only visually when the box is narrow: it's in the action region's live
|
|
1939
|
+
region, and a screen reader should still hear that the turn is waiting. */
|
|
1940
|
+
.UnmagicAIChatComposer__hint {
|
|
1941
|
+
@apply sr-only text-sm whitespace-nowrap text-neutral-500;
|
|
1942
|
+
}
|
|
1943
|
+
|
|
1944
|
+
@container (min-width: 36rem) {
|
|
1945
|
+
.UnmagicAIChatComposer__hint {
|
|
1946
|
+
@apply not-sr-only;
|
|
1947
|
+
}
|
|
1948
|
+
}
|
|
1949
|
+
|
|
1950
|
+
.UnmagicAIChatComposer__stop:hover {
|
|
1951
|
+
@apply border-red-300 bg-red-50 text-red-700 dark:border-red-400/40 dark:bg-red-400/10 dark:text-red-400;
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
/* Empty: Stop reaches it by id, and asks nothing of the person. */
|
|
1955
|
+
.UnmagicAIChatStopForm {
|
|
1956
|
+
@apply hidden;
|
|
1957
|
+
}
|
|
1958
|
+
|
|
1959
|
+
/* ----------------------------------------------------- AI chat slash menu */
|
|
1960
|
+
|
|
1961
|
+
/* Floats over the page rather than pushing it about, opening towards the room
|
|
1962
|
+
there is: upwards from a composer at the foot of a page. */
|
|
1963
|
+
.UnmagicAIChatSlashMenu {
|
|
1964
|
+
@apply absolute inset-x-0 top-full z-20 mt-2 block max-h-64 overflow-y-auto rounded-xl border border-neutral-200 bg-white p-1 shadow-lg;
|
|
1965
|
+
@apply dark:border-neutral-700 dark:bg-neutral-900;
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
.UnmagicAIChatSlashMenu[hidden] {
|
|
1969
|
+
@apply hidden;
|
|
1970
|
+
}
|
|
1971
|
+
|
|
1972
|
+
.UnmagicAIChatSlashMenu--above {
|
|
1973
|
+
@apply top-auto bottom-full mt-0 mb-2;
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1976
|
+
.UnmagicAIChatSlashMenu__list {
|
|
1977
|
+
@apply m-0 list-none p-0;
|
|
1978
|
+
}
|
|
1979
|
+
|
|
1980
|
+
.UnmagicAIChatSlashMenu__item {
|
|
1981
|
+
@apply flex cursor-pointer items-baseline gap-2 rounded-lg px-2 py-1.5 text-sm;
|
|
1982
|
+
}
|
|
1983
|
+
|
|
1984
|
+
.UnmagicAIChatSlashMenu__item[hidden] {
|
|
1985
|
+
@apply hidden;
|
|
1986
|
+
}
|
|
1987
|
+
|
|
1988
|
+
.UnmagicAIChatSlashMenu__item[aria-selected="true"] {
|
|
1989
|
+
@apply bg-neutral-100 dark:bg-neutral-800;
|
|
1990
|
+
}
|
|
1991
|
+
|
|
1992
|
+
.UnmagicAIChatSlashMenu__name {
|
|
1993
|
+
@apply shrink-0 font-mono text-xs text-neutral-900 dark:text-neutral-100;
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
.UnmagicAIChatSlashMenu__argument {
|
|
1997
|
+
@apply text-neutral-400;
|
|
1998
|
+
}
|
|
1999
|
+
|
|
2000
|
+
.UnmagicAIChatSlashMenu__description {
|
|
2001
|
+
@apply min-w-0 truncate text-xs text-neutral-500;
|
|
2002
|
+
}
|
|
2003
|
+
|
|
2004
|
+
/* ---------------------------------------------------- AI chat attachments */
|
|
2005
|
+
|
|
2006
|
+
.UnmagicAIChatAttachments {
|
|
2007
|
+
@apply m-0 flex list-none flex-wrap gap-2 p-0;
|
|
2008
|
+
}
|
|
2009
|
+
|
|
2010
|
+
.UnmagicAIChatAttachments--end {
|
|
2011
|
+
@apply justify-end;
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
.UnmagicAIChatAttachments__file,
|
|
2015
|
+
.UnmagicAIChatAttachments__link {
|
|
2016
|
+
@apply flex min-w-0 items-center gap-2;
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
.UnmagicAIChatAttachments__file {
|
|
2020
|
+
@apply max-w-64 rounded-lg border border-neutral-200 bg-white py-1 pr-2.5 pl-1 text-xs text-neutral-700;
|
|
2021
|
+
@apply dark:border-neutral-800 dark:bg-neutral-900 dark:text-neutral-300;
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
.UnmagicAIChatAttachments__link {
|
|
2025
|
+
@apply text-inherit no-underline;
|
|
2026
|
+
}
|
|
2027
|
+
|
|
2028
|
+
.UnmagicAIChatAttachments__thumb {
|
|
2029
|
+
@apply size-8 shrink-0 rounded-md object-cover;
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
.UnmagicAIChatAttachments__glyph {
|
|
2033
|
+
@apply ml-1.5 text-neutral-400;
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
.UnmagicAIChatAttachments__name {
|
|
2037
|
+
@apply min-w-0 truncate font-medium;
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
.UnmagicAIChatAttachments__size {
|
|
2041
|
+
@apply shrink-0 text-neutral-400 tabular-nums;
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
.UnmagicAIChatAttachments__remove {
|
|
2045
|
+
font: inherit;
|
|
2046
|
+
@apply -mr-1 inline-flex shrink-0 cursor-pointer rounded border-0 bg-transparent p-0.5 text-neutral-400;
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2049
|
+
.UnmagicAIChatAttachments__remove:hover {
|
|
2050
|
+
@apply text-neutral-900 dark:text-neutral-100;
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
.UnmagicAIChatAttachments__remove:focus-visible {
|
|
2054
|
+
@apply outline-2 outline-offset-2 outline-neutral-400 dark:outline-neutral-500;
|
|
2055
|
+
}
|
|
2056
|
+
|
|
2057
|
+
.UnmagicAIChatAttachments__remove .UnmagicIcon {
|
|
2058
|
+
@apply size-3.5;
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
.UnmagicAIChatDropzone {
|
|
2062
|
+
@apply relative block;
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
/* Outside the flow and pointer-transparent: it can't take the drop it's
|
|
2066
|
+
advertising, and it mustn't move the page when it appears. */
|
|
2067
|
+
.UnmagicAIChatDropzone__overlay {
|
|
2068
|
+
@apply pointer-events-none absolute inset-0 z-30 hidden place-items-center rounded-2xl border-2 border-dashed border-neutral-400 bg-white/85;
|
|
2069
|
+
@apply dark:border-neutral-500 dark:bg-neutral-950/85;
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
.UnmagicAIChatDropzone[data-dragging] > .UnmagicAIChatDropzone__overlay {
|
|
2073
|
+
@apply grid;
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
.UnmagicAIChatDropzone__overlay p {
|
|
2077
|
+
@apply m-0 inline-flex items-center gap-2 text-sm font-medium text-neutral-600 dark:text-neutral-300;
|
|
2078
|
+
}
|
|
2079
|
+
|
|
2080
|
+
/* -------------------------------------------------------- AI chat welcome */
|
|
2081
|
+
|
|
2082
|
+
.UnmagicAIChatWelcome {
|
|
2083
|
+
@apply flex flex-col items-center py-10 text-center;
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
.UnmagicAIChatWelcome__heading {
|
|
2087
|
+
@apply m-0 text-xl font-semibold text-neutral-900 dark:text-neutral-100;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
.UnmagicAIChatWelcome__body {
|
|
2091
|
+
@apply mx-0 mt-2 mb-0 max-w-md text-sm text-neutral-500 dark:text-neutral-400;
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
.UnmagicAIChatWelcome__suggestions {
|
|
2095
|
+
@apply mx-0 mt-6 mb-0 flex list-none flex-wrap justify-center gap-2 p-0;
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
.UnmagicAIChatWelcome__suggestion {
|
|
2099
|
+
font: inherit;
|
|
2100
|
+
@apply inline-flex cursor-pointer items-center gap-1.5 rounded-full border border-neutral-200 bg-white px-3 py-1.5 text-sm text-neutral-600;
|
|
2101
|
+
@apply dark:border-neutral-700 dark:bg-neutral-900 dark:text-neutral-300;
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
.UnmagicAIChatWelcome__suggestion:hover {
|
|
2105
|
+
@apply bg-neutral-50 text-neutral-900 dark:bg-neutral-800 dark:text-neutral-100;
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
.UnmagicAIChatWelcome__suggestion:focus-visible {
|
|
2109
|
+
@apply outline-2 outline-offset-2 outline-neutral-400 dark:outline-neutral-500;
|
|
2110
|
+
}
|
|
2111
|
+
|
|
2112
|
+
.UnmagicAIChatWelcome__suggestion .UnmagicIcon {
|
|
2113
|
+
@apply text-neutral-400;
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
/* ------------------------------------------------------- AI chat requests */
|
|
2117
|
+
|
|
2118
|
+
/* Amber is the family's colour for waiting on a person — the one state that
|
|
2119
|
+
won't move on its own. Answered, a card recedes to neutral, and one declined
|
|
2120
|
+
or dropped dims further. */
|
|
2121
|
+
.UnmagicAIChatRequest,
|
|
2122
|
+
.UnmagicAIChatPermission {
|
|
2123
|
+
@apply rounded-xl border border-neutral-200 bg-white p-4 text-sm text-neutral-700;
|
|
2124
|
+
@apply dark:border-neutral-800 dark:bg-neutral-900 dark:text-neutral-300;
|
|
2125
|
+
}
|
|
2126
|
+
|
|
2127
|
+
.UnmagicAIChatRequest--waiting,
|
|
2128
|
+
.UnmagicAIChatPermission--waiting {
|
|
2129
|
+
@apply border-amber-300 bg-amber-50 dark:border-amber-400/30 dark:bg-amber-400/10;
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
.UnmagicAIChatRequest--declined,
|
|
2133
|
+
.UnmagicAIChatRequest--cancelled,
|
|
2134
|
+
.UnmagicAIChatRequest--timed_out {
|
|
2135
|
+
@apply opacity-60;
|
|
2136
|
+
}
|
|
2137
|
+
|
|
2138
|
+
.UnmagicAIChatRequest__head,
|
|
2139
|
+
.UnmagicAIChatPermission__head {
|
|
2140
|
+
@apply flex items-center gap-2 font-medium;
|
|
2141
|
+
}
|
|
2142
|
+
|
|
2143
|
+
.UnmagicAIChatRequest--waiting .UnmagicAIChatRequest__head,
|
|
2144
|
+
.UnmagicAIChatPermission--waiting .UnmagicAIChatPermission__head {
|
|
2145
|
+
@apply text-amber-900 dark:text-amber-200;
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
.UnmagicAIChatRequest__outcome {
|
|
2149
|
+
@apply ml-auto inline-flex items-center gap-1 text-xs text-neutral-500;
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
.UnmagicAIChatRequest__outcome .UnmagicIcon {
|
|
2153
|
+
@apply size-3.5;
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
.UnmagicAIChatRequest__prompt {
|
|
2157
|
+
@apply mt-2 mb-0 text-neutral-900 dark:text-neutral-100;
|
|
2158
|
+
}
|
|
2159
|
+
|
|
2160
|
+
.UnmagicAIChatRequest__form {
|
|
2161
|
+
@apply m-0;
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
.UnmagicAIChatRequest__form > .UnmagicField {
|
|
2165
|
+
@apply mt-4;
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
.UnmagicAIChatRequest__question {
|
|
2169
|
+
@apply mx-0 mt-4 mb-0 min-w-0 border-0 p-0;
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
.UnmagicAIChatRequest__legend {
|
|
2173
|
+
@apply flex w-full flex-col gap-0.5 p-0;
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
.UnmagicAIChatRequest__header {
|
|
2177
|
+
@apply text-[10px] font-medium tracking-wide text-neutral-500 uppercase;
|
|
2178
|
+
}
|
|
2179
|
+
|
|
2180
|
+
.UnmagicAIChatRequest--waiting .UnmagicAIChatRequest__header {
|
|
2181
|
+
@apply text-amber-800 dark:text-amber-400;
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
.UnmagicAIChatRequest__label {
|
|
2185
|
+
@apply text-neutral-900 dark:text-neutral-100;
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
.UnmagicAIChatRequest__options {
|
|
2189
|
+
@apply mt-2 flex flex-col gap-1.5;
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
.UnmagicAIChatRequest__option {
|
|
2193
|
+
@apply flex cursor-pointer items-start gap-3 rounded-lg border border-neutral-200 bg-white p-2.5;
|
|
2194
|
+
@apply dark:border-neutral-800 dark:bg-neutral-900;
|
|
2195
|
+
}
|
|
2196
|
+
|
|
2197
|
+
.UnmagicAIChatRequest__option:hover {
|
|
2198
|
+
@apply border-neutral-300 dark:border-neutral-700;
|
|
2199
|
+
}
|
|
2200
|
+
|
|
2201
|
+
.UnmagicAIChatRequest__option:has(:checked) {
|
|
2202
|
+
@apply border-amber-400 bg-amber-100/60 dark:border-amber-400/50 dark:bg-amber-400/15;
|
|
2203
|
+
}
|
|
2204
|
+
|
|
2205
|
+
.UnmagicAIChatRequest__option > input {
|
|
2206
|
+
@apply mt-0.5 shrink-0;
|
|
2207
|
+
}
|
|
2208
|
+
|
|
2209
|
+
.UnmagicAIChatRequest__choice {
|
|
2210
|
+
@apply flex min-w-0 flex-col;
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
.UnmagicAIChatRequest__choiceLabel {
|
|
2214
|
+
@apply font-medium text-neutral-900 dark:text-neutral-100;
|
|
2215
|
+
}
|
|
2216
|
+
|
|
2217
|
+
.UnmagicAIChatRequest__choiceDescription {
|
|
2218
|
+
@apply text-xs text-neutral-500;
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
.UnmagicAIChatRequest__picked {
|
|
2222
|
+
@apply mt-1.5 mb-0 font-medium text-amber-800 dark:text-amber-400;
|
|
2223
|
+
}
|
|
2224
|
+
|
|
2225
|
+
.UnmagicAIChatRequest__picked--none {
|
|
2226
|
+
@apply font-normal text-neutral-500;
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
.UnmagicAIChatRequest__answers {
|
|
2230
|
+
@apply mt-3 mb-0 flex flex-col gap-1.5;
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
.UnmagicAIChatRequest__answer {
|
|
2234
|
+
@apply flex gap-2;
|
|
2235
|
+
}
|
|
2236
|
+
|
|
2237
|
+
.UnmagicAIChatRequest__answer dt {
|
|
2238
|
+
@apply shrink-0 text-neutral-500;
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
.UnmagicAIChatRequest__answer dd {
|
|
2242
|
+
@apply m-0 text-neutral-900 dark:text-neutral-100;
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
.UnmagicAIChatRequest__actions,
|
|
2246
|
+
.UnmagicAIChatPermission__actions {
|
|
2247
|
+
@apply mt-4 flex flex-wrap items-center gap-2;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
.UnmagicAIChatRequest__aside {
|
|
2251
|
+
@apply m-0 text-xs text-neutral-500;
|
|
2252
|
+
}
|
|
2253
|
+
|
|
2254
|
+
/* ---------------------------------------------------- AI chat permissions */
|
|
2255
|
+
|
|
2256
|
+
/* Focus lands on the card when one arrives, so it needs a ring of its own. */
|
|
2257
|
+
.UnmagicAIChatPermission:focus-visible {
|
|
2258
|
+
@apply outline-2 outline-offset-2 outline-amber-500;
|
|
2259
|
+
}
|
|
2260
|
+
|
|
2261
|
+
.UnmagicAIChatPermission__ask {
|
|
2262
|
+
@apply mt-2 mb-0 flex flex-wrap gap-x-2 font-mono text-xs text-neutral-500;
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
.UnmagicAIChatPermission--waiting .UnmagicAIChatPermission__ask {
|
|
2266
|
+
@apply text-amber-900/70 dark:text-amber-200/70;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
.UnmagicAIChatPermission__tool {
|
|
2270
|
+
@apply font-semibold;
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
.UnmagicAIChatPermission--waiting .UnmagicAIChatPermission__argument {
|
|
2274
|
+
@apply text-amber-900 dark:text-amber-200;
|
|
2275
|
+
}
|
|
2276
|
+
|
|
2277
|
+
.UnmagicAIChatPermission__summary {
|
|
2278
|
+
@apply mt-2;
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
.UnmagicAIChatPermission__reason {
|
|
2282
|
+
@apply mt-1 text-neutral-600 dark:text-neutral-400;
|
|
2283
|
+
}
|
|
2284
|
+
|
|
2285
|
+
.UnmagicAIChatPermission__examples {
|
|
2286
|
+
@apply mt-2 mb-0 list-disc pl-5 text-neutral-500;
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
.UnmagicAIChatPermission__actions > form,
|
|
2290
|
+
.UnmagicAIChatProposal__actions > form,
|
|
2291
|
+
.UnmagicAIChatActionBar > form,
|
|
2292
|
+
.UnmagicAIChatBranchPicker > form {
|
|
2293
|
+
@apply m-0 inline-flex;
|
|
2294
|
+
}
|
|
2295
|
+
|
|
2296
|
+
/* Red for the affirmative, deliberately: this is the consequential choice, not
|
|
2297
|
+
an error, and it is the one control in the family that should give pause. */
|
|
2298
|
+
.UnmagicAIChatPermission__allow {
|
|
2299
|
+
@apply border-transparent bg-red-600 text-white dark:border-transparent dark:bg-red-600 dark:text-white;
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
.UnmagicAIChatPermission__allow:hover {
|
|
2303
|
+
@apply bg-red-500 dark:bg-red-500;
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
.UnmagicAIChatPermission__widen {
|
|
2307
|
+
@apply border-red-300 text-red-700 dark:border-red-400/40 dark:text-red-400;
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
.UnmagicAIChatPermission__widen:hover {
|
|
2311
|
+
@apply bg-red-50 dark:bg-red-400/10;
|
|
2312
|
+
}
|
|
2313
|
+
|
|
2314
|
+
.UnmagicAIChatPermission__outcome {
|
|
2315
|
+
@apply mt-3 mb-0 text-xs font-medium text-neutral-500;
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
/* A grant is the outcome worth spotting later. */
|
|
2319
|
+
.UnmagicAIChatPermission--granted .UnmagicAIChatPermission__outcome {
|
|
2320
|
+
@apply text-red-700 dark:text-red-400;
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
/* ------------------------------------------------------ AI chat proposals */
|
|
2324
|
+
|
|
2325
|
+
/* Quieter than a card: it sits inside a reply, and a card-weight box mid-paragraph
|
|
2326
|
+
reads as the end of the reply. */
|
|
2327
|
+
.UnmagicAIChatProposal {
|
|
2328
|
+
@apply my-2 flex flex-wrap items-center justify-between gap-2 rounded-lg border border-neutral-200 bg-neutral-50 px-3 py-2 text-sm;
|
|
2329
|
+
@apply dark:border-neutral-800 dark:bg-neutral-900;
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
.UnmagicAIChatProposal--rejected {
|
|
2333
|
+
@apply opacity-55;
|
|
2334
|
+
}
|
|
2335
|
+
|
|
2336
|
+
.UnmagicAIChatProposal__body {
|
|
2337
|
+
@apply flex min-w-0 items-start gap-2;
|
|
2338
|
+
}
|
|
2339
|
+
|
|
2340
|
+
.UnmagicAIChatProposal__glyph {
|
|
2341
|
+
@apply mt-0.5 text-blue-600 dark:text-blue-400;
|
|
2342
|
+
}
|
|
2343
|
+
|
|
2344
|
+
.UnmagicAIChatProposal__claim {
|
|
2345
|
+
@apply m-0 text-neutral-900 dark:text-neutral-100;
|
|
2346
|
+
}
|
|
2347
|
+
|
|
2348
|
+
.UnmagicAIChatProposal__meta {
|
|
2349
|
+
@apply m-0 text-xs text-neutral-500;
|
|
2350
|
+
}
|
|
2351
|
+
|
|
2352
|
+
.UnmagicAIChatProposal__actions {
|
|
2353
|
+
@apply flex items-center gap-1.5;
|
|
2354
|
+
}
|
|
2355
|
+
|
|
2356
|
+
.UnmagicAIChatProposal__outcome {
|
|
2357
|
+
@apply inline-flex items-center gap-1 text-xs text-neutral-500;
|
|
2358
|
+
}
|
|
2359
|
+
|
|
2360
|
+
.UnmagicAIChatProposal__outcome .UnmagicIcon {
|
|
2361
|
+
@apply size-3.5;
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
/* ------------------------------------------------------ AI chat citations */
|
|
2365
|
+
|
|
2366
|
+
/* The left rule is what sets a quotation apart from the prose around it. */
|
|
2367
|
+
.UnmagicAIChatCitation {
|
|
2368
|
+
@apply mx-0 my-2 flex items-start gap-2 rounded-md border-l-[3px] border-blue-300 bg-neutral-50 px-3 py-2 text-sm;
|
|
2369
|
+
@apply dark:border-blue-400/50 dark:bg-neutral-900;
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
.UnmagicAIChatCitation__main {
|
|
2373
|
+
@apply min-w-0 flex-1;
|
|
2374
|
+
}
|
|
2375
|
+
|
|
2376
|
+
.UnmagicAIChatCitation__caption {
|
|
2377
|
+
@apply mb-0.5 flex flex-wrap items-baseline gap-x-2 text-xs text-neutral-500;
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
.UnmagicAIChatCitation__who {
|
|
2381
|
+
@apply font-semibold text-neutral-700 dark:text-neutral-300;
|
|
2382
|
+
}
|
|
2383
|
+
|
|
2384
|
+
.UnmagicAIChatCitation__when {
|
|
2385
|
+
@apply text-inherit no-underline;
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2388
|
+
a.UnmagicAIChatCitation__when:hover {
|
|
2389
|
+
@apply underline;
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
.UnmagicAIChatCitation__quote {
|
|
2393
|
+
@apply m-0 border-0 p-0 whitespace-pre-wrap text-neutral-900 dark:text-neutral-100;
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
.UnmagicAIChatCitation--compact {
|
|
2397
|
+
@apply items-baseline py-1;
|
|
2398
|
+
}
|
|
2399
|
+
|
|
2400
|
+
.UnmagicAIChatCitation--compact .UnmagicAIChatCitation__main {
|
|
2401
|
+
@apply flex items-baseline gap-2;
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
.UnmagicAIChatCitation--compact .UnmagicAIChatCitation__caption {
|
|
2405
|
+
@apply mb-0 shrink-0 flex-nowrap;
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2408
|
+
.UnmagicAIChatCitation--compact .UnmagicAIChatCitation__quote {
|
|
2409
|
+
@apply min-w-0 truncate whitespace-nowrap;
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
/* ---------------------------------------------------- AI chat action bars */
|
|
2413
|
+
|
|
2414
|
+
.UnmagicAIChatActionBar {
|
|
2415
|
+
@apply inline-flex items-center gap-0.5;
|
|
2416
|
+
}
|
|
2417
|
+
|
|
2418
|
+
/* Hidden with opacity, never display: none, so the bar stays in the tab order and
|
|
2419
|
+
shows the moment it takes focus. There is no hover on a touch screen, so it is
|
|
2420
|
+
always shown there. */
|
|
2421
|
+
.UnmagicAIChatActionBar[data-reveal="hover"] {
|
|
2422
|
+
@apply opacity-0;
|
|
2423
|
+
transition: opacity 150ms ease;
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
.UnmagicAIChatMessage:hover .UnmagicAIChatActionBar[data-reveal="hover"],
|
|
2427
|
+
.UnmagicAIChatActionBar[data-reveal="hover"]:focus-within {
|
|
2428
|
+
@apply opacity-100;
|
|
2429
|
+
}
|
|
2430
|
+
|
|
2431
|
+
@media (hover: none) {
|
|
2432
|
+
.UnmagicAIChatActionBar[data-reveal="hover"] {
|
|
2433
|
+
@apply opacity-100;
|
|
2434
|
+
}
|
|
2435
|
+
}
|
|
2436
|
+
|
|
2437
|
+
@media (prefers-reduced-motion: reduce) {
|
|
2438
|
+
.UnmagicAIChatActionBar[data-reveal="hover"] {
|
|
2439
|
+
transition: none;
|
|
2440
|
+
}
|
|
2441
|
+
}
|
|
2442
|
+
|
|
2443
|
+
.UnmagicAIChatActionBar .UnmagicButton--icon {
|
|
2444
|
+
@apply p-1;
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2447
|
+
.UnmagicAIChatActionBar .UnmagicIcon {
|
|
2448
|
+
@apply size-3.5;
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
/* ------------------------------------------------- AI chat branch pickers */
|
|
2452
|
+
|
|
2453
|
+
.UnmagicAIChatBranchPicker {
|
|
2454
|
+
@apply inline-flex items-center gap-0.5 text-xs text-neutral-500;
|
|
2455
|
+
}
|
|
2456
|
+
|
|
2457
|
+
/* Tabular, so 9/10 and 10/10 don't jitter. */
|
|
2458
|
+
.UnmagicAIChatBranchPicker__count {
|
|
2459
|
+
@apply px-0.5 tabular-nums;
|
|
2460
|
+
}
|
|
2461
|
+
|
|
2462
|
+
.UnmagicAIChatBranchPicker__step {
|
|
2463
|
+
font: inherit;
|
|
2464
|
+
@apply inline-flex cursor-pointer items-center justify-center rounded-md border-0 bg-transparent p-1 text-neutral-500 no-underline;
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
.UnmagicAIChatBranchPicker__step:hover {
|
|
2468
|
+
@apply bg-neutral-100 text-neutral-900 dark:bg-neutral-800 dark:text-neutral-100;
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
.UnmagicAIChatBranchPicker__step:focus-visible {
|
|
2472
|
+
@apply outline-2 outline-offset-2 outline-neutral-400 dark:outline-neutral-500;
|
|
2473
|
+
}
|
|
2474
|
+
|
|
2475
|
+
.UnmagicAIChatBranchPicker__step[aria-disabled="true"] {
|
|
2476
|
+
@apply pointer-events-none cursor-default opacity-40;
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
.UnmagicAIChatBranchPicker__step .UnmagicIcon {
|
|
2480
|
+
@apply size-3.5;
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
/* --------------------------------------------------------------- Sortable */
|
|
2484
|
+
|
|
2485
|
+
.UnmagicSortableList,
|
|
2486
|
+
.UnmagicSortableItem {
|
|
2487
|
+
@apply block;
|
|
2488
|
+
}
|
|
2489
|
+
|
|
2490
|
+
unmagic-sortable-param {
|
|
2491
|
+
@apply hidden;
|
|
2492
|
+
}
|
|
2493
|
+
|
|
2494
|
+
/* A handle is where a pointer picks an item up. The grip button is also
|
|
2495
|
+
touch-action: none, so a finger drags it at once rather than scrolling. A
|
|
2496
|
+
larger handle (a board column's header) leaves scrolling alone, and a finger
|
|
2497
|
+
lifts it with a long press instead; the element reads which from touch-action. */
|
|
2498
|
+
[data-sortable-handle] {
|
|
2499
|
+
@apply cursor-grab;
|
|
2500
|
+
}
|
|
2501
|
+
|
|
2502
|
+
.UnmagicSortableHandle {
|
|
2503
|
+
touch-action: none;
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2506
|
+
[data-sortable-handle]:active {
|
|
2507
|
+
@apply cursor-grabbing;
|
|
2508
|
+
}
|
|
2509
|
+
|
|
2510
|
+
/* Nothing is selected while dragging, and the grab shows wherever the pointer is. */
|
|
2511
|
+
html:has([data-sortable-placeholder]) {
|
|
2512
|
+
@apply cursor-grabbing select-none;
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
/* The copy following the pointer, placed by the element. drop-shadow rather than
|
|
2516
|
+
box-shadow, so the shadow follows a rounded card rather than its square box. */
|
|
2517
|
+
[data-sortable-dragging] {
|
|
2518
|
+
@apply pointer-events-none fixed top-0 left-0 z-50 m-0 opacity-95;
|
|
2519
|
+
filter: drop-shadow(0 8px 12px rgb(0 0 0 / 0.2));
|
|
2520
|
+
}
|
|
2521
|
+
|
|
2522
|
+
/* The item left in the list, showing where it will land. */
|
|
2523
|
+
[data-sortable-placeholder] {
|
|
2524
|
+
@apply opacity-40;
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
/* The item a keyboard is holding. */
|
|
2528
|
+
[data-sortable-lifted] {
|
|
2529
|
+
@apply rounded-lg outline-2 outline-offset-2 outline-neutral-900 dark:outline-neutral-100;
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
/* A long press lifts an item on a touch screen, so it mustn't also select text
|
|
2533
|
+
or open the system's link menu. */
|
|
2534
|
+
@media (pointer: coarse) {
|
|
2535
|
+
.UnmagicSortableItem {
|
|
2536
|
+
@apply select-none;
|
|
2537
|
+
-webkit-touch-callout: none;
|
|
2538
|
+
}
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
.UnmagicSortableItem:focus-visible {
|
|
2542
|
+
@apply rounded-lg outline-2 outline-offset-2 outline-neutral-400 dark:outline-neutral-500;
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
.UnmagicSortableList--horizontal {
|
|
2546
|
+
@apply flex;
|
|
2547
|
+
}
|
|
2548
|
+
|
|
2549
|
+
.UnmagicSortableList--grid {
|
|
2550
|
+
@apply flex flex-wrap;
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
/* ----------------------------------------------------------------- Boards */
|
|
2554
|
+
|
|
2555
|
+
/* Columns sit side by side and the board scrolls sideways; a column's cards
|
|
2556
|
+
scroll inside it past --unmagic-board-column-height. */
|
|
2557
|
+
.UnmagicBoard {
|
|
2558
|
+
@apply relative;
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
/* relative, like the card list below: anything absolute inside a scroller (a
|
|
2562
|
+
visually hidden label) must be placed within it. Placed by an ancestor
|
|
2563
|
+
outside, it escapes the scroller's clipping and widens the whole page. */
|
|
2564
|
+
.UnmagicBoard__columns {
|
|
2565
|
+
@apply relative flex items-start gap-3 overflow-x-auto pb-2;
|
|
2566
|
+
overscroll-behavior-x: contain;
|
|
2567
|
+
}
|
|
2568
|
+
|
|
2569
|
+
.UnmagicBoard__column,
|
|
2570
|
+
.UnmagicBoard__tail {
|
|
2571
|
+
@apply w-72 shrink-0;
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2574
|
+
.UnmagicBoard__panel {
|
|
2575
|
+
@apply flex flex-col rounded-xl border border-neutral-200 bg-neutral-100 dark:border-neutral-800 dark:bg-neutral-900;
|
|
2576
|
+
max-height: var(--unmagic-board-column-height, 75dvh);
|
|
2577
|
+
}
|
|
2578
|
+
|
|
2579
|
+
.UnmagicBoard__head {
|
|
2580
|
+
@apply flex min-w-0 items-center gap-1 px-2 pt-2 pb-1;
|
|
2581
|
+
}
|
|
2582
|
+
|
|
2583
|
+
.UnmagicBoard__grip {
|
|
2584
|
+
@apply p-1 text-neutral-400;
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
.UnmagicBoard__title {
|
|
2588
|
+
@apply m-0 min-w-0 flex-1 truncate text-sm font-semibold text-neutral-900 dark:text-neutral-100;
|
|
2589
|
+
}
|
|
2590
|
+
|
|
2591
|
+
.UnmagicBoard__count {
|
|
2592
|
+
@apply shrink-0 rounded-full bg-neutral-200 px-1.5 text-xs text-neutral-500 tabular-nums dark:bg-neutral-800 dark:text-neutral-400;
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
.UnmagicBoard__actions {
|
|
2596
|
+
@apply flex shrink-0 items-center gap-0.5;
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
/* The cards take the column's height and scroll within it. min-height keeps an
|
|
2600
|
+
empty column a target to drop into. No overscroll containment: Chrome applies
|
|
2601
|
+
it to a list that isn't even overflowing, and a finger swiping over a short
|
|
2602
|
+
column then can't scroll the page. */
|
|
2603
|
+
.UnmagicBoard__cards {
|
|
2604
|
+
@apply relative flex min-h-12 flex-1 flex-col gap-2 overflow-y-auto rounded-lg px-2 py-1;
|
|
2605
|
+
}
|
|
2606
|
+
|
|
2607
|
+
.UnmagicBoard__cards[data-sortable-over] {
|
|
2608
|
+
@apply bg-neutral-200/70 dark:bg-neutral-800/70;
|
|
2609
|
+
}
|
|
2610
|
+
|
|
2611
|
+
.UnmagicBoard__card {
|
|
2612
|
+
@apply cursor-grab rounded-lg border border-neutral-200 bg-white p-3 text-sm text-neutral-900 shadow-xs;
|
|
2613
|
+
@apply dark:border-neutral-700 dark:bg-neutral-950 dark:text-neutral-100;
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
.UnmagicBoard__card:hover {
|
|
2617
|
+
@apply border-neutral-300 dark:border-neutral-600;
|
|
2618
|
+
}
|
|
2619
|
+
|
|
2620
|
+
.UnmagicBoard__card[data-sortable-dragging] {
|
|
2621
|
+
rotate: 2deg;
|
|
2622
|
+
}
|
|
2623
|
+
|
|
2624
|
+
/* The whole column is lifted by keyboard, so its panel shows it rather than the
|
|
2625
|
+
item's box. */
|
|
2626
|
+
.UnmagicBoard__column[data-sortable-lifted] {
|
|
2627
|
+
@apply rounded-xl;
|
|
2628
|
+
}
|
|
2629
|
+
|
|
2630
|
+
.UnmagicBoard__add {
|
|
2631
|
+
@apply px-2 pt-1 pb-2;
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2634
|
+
.UnmagicBoard__addToggle {
|
|
2635
|
+
@apply flex cursor-pointer list-none items-center gap-1.5 rounded-lg px-2 py-1.5 text-sm text-neutral-500 select-none;
|
|
2636
|
+
}
|
|
2637
|
+
|
|
2638
|
+
.UnmagicBoard__addToggle::-webkit-details-marker {
|
|
2639
|
+
@apply hidden;
|
|
2640
|
+
}
|
|
2641
|
+
|
|
2642
|
+
.UnmagicBoard__addToggle:hover {
|
|
2643
|
+
@apply bg-neutral-200 text-neutral-900 dark:bg-neutral-800 dark:text-neutral-100;
|
|
2644
|
+
}
|
|
2645
|
+
|
|
2646
|
+
.UnmagicBoard__addToggle:focus-visible {
|
|
2647
|
+
@apply outline-2 outline-offset-2 outline-neutral-400 dark:outline-neutral-500;
|
|
2648
|
+
}
|
|
2649
|
+
|
|
2650
|
+
/* Open, the form stands in for the toggle; Escape or × closes it. */
|
|
2651
|
+
.UnmagicBoard__add[open] > .UnmagicBoard__addToggle {
|
|
2652
|
+
@apply hidden;
|
|
2653
|
+
}
|
|
2654
|
+
|
|
2655
|
+
.UnmagicBoard__addForm {
|
|
2656
|
+
@apply m-0 flex flex-col gap-2;
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
.UnmagicBoard__addField {
|
|
2660
|
+
@apply max-h-40 w-full;
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
.UnmagicBoard__addActions {
|
|
2664
|
+
@apply flex items-center gap-1;
|
|
2665
|
+
}
|
|
2666
|
+
|
|
2667
|
+
/* The "Add a list" tile at the end of the board. */
|
|
2668
|
+
.UnmagicBoard__addColumn {
|
|
2669
|
+
@apply rounded-xl border border-dashed border-neutral-300 bg-neutral-50 p-0 dark:border-neutral-700 dark:bg-neutral-900/50;
|
|
2670
|
+
}
|
|
2671
|
+
|
|
2672
|
+
.UnmagicBoard__addColumn[open] {
|
|
2673
|
+
@apply border-solid bg-neutral-100 p-2 dark:bg-neutral-900;
|
|
2674
|
+
}
|
|
2675
|
+
|
|
2676
|
+
.UnmagicBoard__addColumn > .UnmagicBoard__addToggle {
|
|
2677
|
+
@apply px-3 py-2.5;
|
|
2678
|
+
}
|
|
1164
2679
|
}
|