alchemy_cms 8.0.6 → 8.1.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.
Files changed (292) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +14 -10
  3. data/app/assets/builds/alchemy/admin.css +1 -1
  4. data/app/assets/builds/alchemy/dark-theme.css +1 -1
  5. data/app/assets/builds/alchemy/light-theme.css +1 -1
  6. data/app/assets/builds/alchemy/preview.min.js +1 -1
  7. data/app/assets/builds/alchemy/theme.css +1 -1
  8. data/app/assets/builds/alchemy/welcome.css +1 -1
  9. data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css +1 -1
  10. data/app/assets/builds/tinymce/skins/content/alchemy-dark/content.min.css +1 -1
  11. data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css +1 -1
  12. data/app/assets/builds/tinymce/skins/ui/alchemy-dark/skin.min.css +1 -1
  13. data/app/{views/alchemy/admin/elements/_element.html.erb → components/alchemy/admin/element_editor.html.erb} +34 -29
  14. data/app/components/alchemy/admin/element_editor.rb +115 -0
  15. data/app/components/alchemy/admin/element_select.rb +12 -9
  16. data/app/components/alchemy/admin/ingredient_editor.rb +54 -0
  17. data/app/components/alchemy/admin/list_filter.rb +16 -5
  18. data/app/components/alchemy/admin/page_node.html.erb +214 -0
  19. data/app/components/alchemy/admin/page_node.rb +70 -0
  20. data/app/components/alchemy/admin/picture_thumbnail.rb +36 -0
  21. data/app/components/alchemy/admin/publish_page_button.html.erb +15 -0
  22. data/app/components/alchemy/admin/publish_page_button.rb +54 -0
  23. data/app/{helpers/alchemy/admin/tags_helper.rb → components/alchemy/admin/tags_list.rb} +19 -11
  24. data/app/components/alchemy/admin/toolbar_button.rb +16 -12
  25. data/app/components/alchemy/ingredients/audio_editor.rb +8 -0
  26. data/app/components/alchemy/ingredients/base_editor.rb +222 -0
  27. data/app/components/alchemy/ingredients/boolean_editor.rb +21 -0
  28. data/app/components/alchemy/ingredients/color_editor.rb +80 -0
  29. data/app/components/alchemy/ingredients/color_view.rb +13 -0
  30. data/app/components/alchemy/ingredients/datetime_editor.rb +28 -0
  31. data/app/components/alchemy/ingredients/file_editor.rb +69 -0
  32. data/app/components/alchemy/ingredients/headline_editor.rb +88 -0
  33. data/app/components/alchemy/ingredients/html_editor.rb +11 -0
  34. data/app/components/alchemy/ingredients/link_editor.rb +29 -0
  35. data/app/components/alchemy/ingredients/node_editor.rb +23 -0
  36. data/app/components/alchemy/ingredients/number_editor.rb +28 -0
  37. data/app/components/alchemy/ingredients/page_editor.rb +19 -0
  38. data/app/components/alchemy/ingredients/picture_editor.rb +81 -0
  39. data/app/components/alchemy/ingredients/richtext_editor.rb +31 -0
  40. data/app/components/alchemy/ingredients/select_editor.rb +37 -0
  41. data/app/components/alchemy/ingredients/select_view.rb +7 -0
  42. data/app/components/alchemy/ingredients/text_editor.rb +41 -0
  43. data/app/components/alchemy/ingredients/video_editor.rb +8 -0
  44. data/app/controllers/alchemy/admin/attachments_controller.rb +8 -6
  45. data/app/controllers/alchemy/admin/base_controller.rb +7 -18
  46. data/app/controllers/alchemy/admin/clipboard_controller.rb +15 -11
  47. data/app/controllers/alchemy/admin/dashboard_controller.rb +2 -2
  48. data/app/controllers/alchemy/admin/elements_controller.rb +34 -32
  49. data/app/controllers/alchemy/admin/ingredients_controller.rb +1 -0
  50. data/app/controllers/alchemy/admin/layoutpages_controller.rb +2 -1
  51. data/app/controllers/alchemy/admin/legacy_page_urls_controller.rb +1 -1
  52. data/app/controllers/alchemy/admin/nodes_controller.rb +24 -1
  53. data/app/controllers/alchemy/admin/pages_controller.rb +31 -41
  54. data/app/controllers/alchemy/admin/pictures_controller.rb +2 -5
  55. data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
  56. data/app/controllers/alchemy/api/ingredients_controller.rb +1 -1
  57. data/app/controllers/alchemy/api/pages_controller.rb +5 -3
  58. data/app/controllers/alchemy/base_controller.rb +6 -6
  59. data/app/controllers/alchemy/pages_controller.rb +12 -6
  60. data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +0 -1
  61. data/app/controllers/concerns/alchemy/admin/clipboard.rb +57 -0
  62. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +2 -2
  63. data/app/controllers/concerns/alchemy/site_redirects.rb +1 -1
  64. data/app/decorators/alchemy/ingredient_editor.rb +37 -4
  65. data/app/helpers/alchemy/admin/base_helper.rb +12 -7
  66. data/app/helpers/alchemy/admin/ingredients_helper.rb +6 -3
  67. data/app/helpers/alchemy/base_helper.rb +1 -1
  68. data/app/helpers/alchemy/pages_helper.rb +1 -1
  69. data/app/javascript/alchemy_admin/components/action.js +5 -1
  70. data/app/javascript/alchemy_admin/components/color_select.js +73 -0
  71. data/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js +11 -3
  72. data/app/javascript/alchemy_admin/components/element_editor/publish_element_button.js +7 -2
  73. data/app/javascript/alchemy_admin/components/element_editor.js +11 -12
  74. data/app/javascript/alchemy_admin/components/element_select.js +39 -17
  75. data/app/javascript/alchemy_admin/components/elements_window.js +0 -2
  76. data/app/javascript/alchemy_admin/components/file_editor.js +26 -0
  77. data/app/javascript/alchemy_admin/components/index.js +9 -0
  78. data/app/javascript/alchemy_admin/components/list_filter.js +57 -8
  79. data/app/javascript/alchemy_admin/components/message.js +9 -3
  80. data/app/javascript/alchemy_admin/components/page_node.js +119 -0
  81. data/app/javascript/alchemy_admin/{page_publication_fields.js → components/page_publication_fields.js} +9 -8
  82. data/app/javascript/alchemy_admin/{picture_editors.js → components/picture_editor.js} +30 -45
  83. data/app/javascript/alchemy_admin/components/picture_thumbnail.js +107 -0
  84. data/app/javascript/alchemy_admin/components/publish_page_button.js +41 -0
  85. data/app/javascript/alchemy_admin/components/select.js +3 -1
  86. data/app/javascript/alchemy_admin/components/sitemap.js +210 -0
  87. data/app/javascript/alchemy_admin/{sortable_elements.js → components/sortable_elements.js} +22 -25
  88. data/app/javascript/alchemy_admin/components/tinymce.js +10 -5
  89. data/app/javascript/alchemy_admin/components/update_check.js +1 -1
  90. data/app/javascript/alchemy_admin/components/uploader.js +30 -0
  91. data/app/javascript/alchemy_admin/image_overlay.js +0 -2
  92. data/app/javascript/alchemy_admin/initializer.js +0 -3
  93. data/app/javascript/alchemy_admin/templates/compiled.js +1 -1
  94. data/app/javascript/alchemy_admin/utils/ajax.js +15 -3
  95. data/app/javascript/alchemy_admin.js +0 -6
  96. data/app/models/alchemy/attachment.rb +4 -4
  97. data/app/models/alchemy/element/definitions.rb +1 -2
  98. data/app/models/alchemy/element/element_ingredients.rb +6 -2
  99. data/app/models/alchemy/element.rb +55 -13
  100. data/app/models/alchemy/element_definition.rb +5 -1
  101. data/app/models/alchemy/elements_repository.rb +6 -0
  102. data/app/models/alchemy/folded_page.rb +2 -2
  103. data/app/models/alchemy/ingredient.rb +38 -1
  104. data/app/models/alchemy/ingredient_definition.rb +5 -1
  105. data/app/models/alchemy/ingredient_validator.rb +6 -2
  106. data/app/models/alchemy/ingredients/color.rb +10 -0
  107. data/app/models/alchemy/ingredients/headline.rb +2 -17
  108. data/app/models/alchemy/ingredients/picture.rb +4 -4
  109. data/app/models/alchemy/ingredients/select.rb +19 -0
  110. data/app/models/alchemy/node.rb +28 -1
  111. data/app/models/alchemy/page/page_naming.rb +0 -7
  112. data/app/models/alchemy/page/page_natures.rb +7 -3
  113. data/app/models/alchemy/page/page_scopes.rb +1 -1
  114. data/app/models/alchemy/page/publisher.rb +14 -2
  115. data/app/models/alchemy/page.rb +102 -23
  116. data/app/models/alchemy/page_definition.rb +4 -1
  117. data/app/models/alchemy/page_version.rb +22 -6
  118. data/app/models/alchemy/picture.rb +10 -11
  119. data/app/models/alchemy/picture_variant.rb +1 -3
  120. data/app/models/alchemy/resource.rb +1 -1
  121. data/app/models/alchemy/storage_adapter/active_storage.rb +14 -2
  122. data/app/models/alchemy/storage_adapter/dragonfly.rb +12 -0
  123. data/app/models/alchemy/storage_adapter.rb +2 -0
  124. data/app/models/concerns/alchemy/picture_thumbnails.rb +4 -4
  125. data/app/models/concerns/alchemy/publishable.rb +54 -0
  126. data/app/serializers/alchemy/page_tree_serializer.rb +11 -31
  127. data/app/services/alchemy/copy_page.rb +17 -0
  128. data/app/services/alchemy/duplicate_element.rb +1 -1
  129. data/app/services/alchemy/page_tree_preloader.rb +105 -0
  130. data/app/stylesheets/alchemy/_custom-properties.scss +1 -0
  131. data/app/stylesheets/alchemy/_extends.scss +3 -9
  132. data/app/stylesheets/alchemy/_mixins.scss +3 -1
  133. data/app/stylesheets/alchemy/_themes.scss +19 -10
  134. data/app/stylesheets/alchemy/admin/archive.scss +1 -0
  135. data/app/stylesheets/alchemy/admin/base.scss +13 -4
  136. data/app/stylesheets/alchemy/admin/buttons.scss +3 -3
  137. data/app/stylesheets/alchemy/admin/dialogs.scss +11 -5
  138. data/app/stylesheets/alchemy/admin/element-select.scss +18 -0
  139. data/app/stylesheets/alchemy/admin/elements.scss +127 -25
  140. data/app/stylesheets/alchemy/admin/errors.scss +1 -1
  141. data/app/stylesheets/alchemy/admin/flash.scss +6 -4
  142. data/app/stylesheets/alchemy/admin/images.scss +9 -5
  143. data/app/stylesheets/alchemy/admin/list_filter.scss +4 -4
  144. data/app/stylesheets/alchemy/admin/notices.scss +1 -2
  145. data/app/stylesheets/alchemy/admin/preview_window.scss +1 -1
  146. data/app/stylesheets/alchemy/admin/resource_info.scss +7 -0
  147. data/app/stylesheets/alchemy/admin/selects.scss +36 -21
  148. data/app/stylesheets/alchemy/admin/shoelace.scss +14 -1
  149. data/app/stylesheets/alchemy/admin/sitemap.scss +11 -3
  150. data/app/stylesheets/alchemy/admin/tags.scss +3 -1
  151. data/app/stylesheets/alchemy/admin/toolbar.scss +1 -1
  152. data/app/stylesheets/tinymce/skins/ui/alchemy/skin.scss +2 -2
  153. data/app/stylesheets/tinymce/skins/ui/alchemy-dark/skin.scss +2 -2
  154. data/app/views/alchemy/_edit_mode.html.erb +1 -1
  155. data/app/views/alchemy/_menubar.html.erb +1 -1
  156. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +35 -31
  157. data/app/views/alchemy/admin/attachments/_library_sidebar.html.erb +6 -0
  158. data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +1 -1
  159. data/app/views/alchemy/admin/attachments/_replace_button.html.erb +1 -8
  160. data/app/views/alchemy/admin/attachments/_sorting_select.html.erb +13 -0
  161. data/app/views/alchemy/admin/attachments/_tag_list.html.erb +2 -3
  162. data/app/views/alchemy/admin/attachments/index.html.erb +5 -11
  163. data/app/views/alchemy/admin/attachments/show.html.erb +1 -1
  164. data/app/views/alchemy/admin/clipboard/_button.html.erb +1 -0
  165. data/app/views/alchemy/admin/clipboard/index.html.erb +4 -5
  166. data/app/views/alchemy/admin/clipboard/insert.turbo_stream.erb +1 -1
  167. data/app/views/alchemy/admin/crop.html.erb +5 -7
  168. data/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb +6 -6
  169. data/app/views/alchemy/admin/elements/_fixed_element.html.erb +1 -1
  170. data/app/views/alchemy/admin/elements/_footer.html.erb +7 -1
  171. data/app/views/alchemy/admin/elements/_header.html.erb +5 -5
  172. data/app/views/alchemy/admin/elements/_toolbar.html.erb +33 -8
  173. data/app/views/alchemy/admin/elements/create.turbo_stream.erb +10 -10
  174. data/app/views/alchemy/admin/elements/index.html.erb +29 -16
  175. data/app/views/alchemy/admin/elements/new.html.erb +2 -2
  176. data/app/views/alchemy/admin/ingredients/update.turbo_stream.erb +3 -5
  177. data/app/views/alchemy/admin/leave.html.erb +9 -9
  178. data/app/views/alchemy/admin/nodes/_node.html.erb +19 -0
  179. data/app/views/alchemy/admin/nodes/edit.html.erb +1 -1
  180. data/app/views/alchemy/admin/nodes/index.html.erb +3 -1
  181. data/app/views/alchemy/admin/nodes/new.html.erb +14 -1
  182. data/app/views/alchemy/admin/pages/_current_page.html.erb +3 -1
  183. data/app/views/alchemy/admin/pages/_form.html.erb +21 -9
  184. data/app/views/alchemy/admin/pages/_page_status.html.erb +1 -1
  185. data/app/views/alchemy/admin/pages/_publication_fields.html.erb +28 -26
  186. data/app/views/alchemy/admin/pages/_table.html.erb +0 -7
  187. data/app/views/alchemy/admin/pages/_toolbar.html.erb +3 -5
  188. data/app/views/alchemy/admin/pages/edit.html.erb +5 -13
  189. data/app/views/alchemy/admin/pages/flush.turbo_stream.erb +2 -0
  190. data/app/views/alchemy/admin/pages/fold.turbo_stream.erb +5 -0
  191. data/app/views/alchemy/admin/pages/index.html.erb +5 -3
  192. data/app/views/alchemy/admin/pages/new.html.erb +2 -12
  193. data/app/views/alchemy/admin/pages/publish.turbo_stream.erb +12 -0
  194. data/app/views/alchemy/admin/pages/tree.html.erb +13 -0
  195. data/app/views/alchemy/admin/pages/update.turbo_stream.erb +5 -16
  196. data/app/views/alchemy/admin/partials/_flash_notices.html.erb +1 -1
  197. data/app/views/alchemy/admin/partials/{_remote_search_form.html.erb → _overlay_search_form.html.erb} +1 -2
  198. data/app/views/alchemy/admin/partials/_paste_from_clipboard_form.html.erb +12 -0
  199. data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +24 -21
  200. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +18 -26
  201. data/app/views/alchemy/admin/pictures/_picture.html.erb +11 -15
  202. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +3 -6
  203. data/app/views/alchemy/admin/pictures/_tag_list.html.erb +2 -3
  204. data/app/views/alchemy/admin/pictures/index.html.erb +0 -1
  205. data/app/views/alchemy/admin/pictures/update.turbo_stream.erb +1 -1
  206. data/app/views/alchemy/admin/resources/_resource_usage_info.html.erb +1 -1
  207. data/app/views/alchemy/admin/resources/_tag_list.html.erb +2 -3
  208. data/app/views/alchemy/admin/styleguide/index.html.erb +25 -20
  209. data/app/views/alchemy/admin/tags/edit.html.erb +1 -1
  210. data/app/views/alchemy/admin/tinymce/_setup.html.erb +2 -2
  211. data/app/views/alchemy/admin/uploader/_button.html.erb +1 -15
  212. data/app/views/alchemy/attachments/show.html.erb +1 -1
  213. data/app/views/alchemy/base/permission_denied.js.erb +1 -1
  214. data/app/views/alchemy/ingredients/shared/_anchor.html.erb +9 -7
  215. data/app/views/alchemy/ingredients/shared/_link_tools.html.erb +12 -5
  216. data/app/views/alchemy/ingredients/shared/_picture_tools.html.erb +10 -11
  217. data/app/views/alchemy/language_links/_spacer.html.erb +1 -1
  218. data/app/views/alchemy/messages_mailer/new.html.erb +1 -1
  219. data/app/views/alchemy/welcome.html.erb +1 -1
  220. data/app/views/layouts/alchemy/admin.html.erb +1 -1
  221. data/config/locales/alchemy.en.yml +12 -2
  222. data/config/routes.rb +2 -2
  223. data/db/migrate/20230123112425_add_searchable_to_alchemy_pages.rb +1 -1
  224. data/db/migrate/20230505132743_add_indexes_to_alchemy_pictures.rb +1 -1
  225. data/db/migrate/20231113104432_create_page_mutexes.rb +1 -1
  226. data/db/migrate/20240314105244_create_alchemy_picture_descriptions.rb +1 -1
  227. data/db/migrate/20250626160259_add_unique_index_to_picture_descriptions.rb +1 -1
  228. data/db/migrate/20250905140323_add_created_at_index_to_pictures_and_attachments.rb +1 -1
  229. data/db/migrate/20251106150010_convert_select_value_for_multiple.rb +11 -0
  230. data/db/migrate/20260102121232_add_metadata_to_page_versions.rb +9 -0
  231. data/db/migrate/20260115164704_add_publication_timestamps_to_alchemy_elements.rb +30 -0
  232. data/db/migrate/20260115164705_add_index_to_element_publication_timestamps.rb +13 -0
  233. data/lib/alchemy/ability_helper.rb +1 -3
  234. data/lib/alchemy/auth_accessors.rb +51 -117
  235. data/lib/alchemy/configuration.rb +1 -0
  236. data/lib/alchemy/configurations/main.rb +63 -0
  237. data/lib/alchemy/controller_actions.rb +1 -1
  238. data/lib/alchemy/engine.rb +9 -12
  239. data/lib/alchemy/error_tracking/error_logger.rb +1 -1
  240. data/lib/alchemy/errors.rb +1 -1
  241. data/lib/alchemy/logger.rb +34 -4
  242. data/lib/alchemy/name_conversions.rb +0 -6
  243. data/lib/alchemy/seeder.rb +2 -2
  244. data/lib/alchemy/tasks/usage.rb +4 -4
  245. data/lib/alchemy/test_support/factories/page_version_factory.rb +3 -0
  246. data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +30 -0
  247. data/lib/alchemy/test_support/shared_ingredient_editor_examples.rb +26 -6
  248. data/lib/alchemy/test_support/shared_publishable_examples.rb +114 -0
  249. data/lib/alchemy/upgrader/eight_one.rb +56 -0
  250. data/lib/alchemy/upgrader.rb +9 -1
  251. data/lib/alchemy/version.rb +1 -1
  252. data/lib/alchemy.rb +1 -4
  253. data/lib/alchemy_cms.rb +0 -1
  254. data/lib/generators/alchemy/elements/templates/view.html.erb +3 -3
  255. data/lib/generators/alchemy/ingredient/ingredient_generator.rb +6 -8
  256. data/lib/generators/alchemy/ingredient/templates/editor_component.rb.tt +22 -0
  257. data/lib/generators/alchemy/page_layouts/templates/layout.html.erb +1 -1
  258. data/lib/generators/alchemy/site_layouts/templates/layout.html.erb +1 -1
  259. data/lib/tasks/alchemy/upgrade.rake +21 -7
  260. data/vendor/javascript/shoelace.min.js +713 -31
  261. data/vendor/javascript/tinymce.min.js +1 -1
  262. metadata +103 -83
  263. data/app/decorators/alchemy/element_editor.rb +0 -90
  264. data/app/helpers/alchemy/admin/pictures_helper.rb +0 -14
  265. data/app/javascript/alchemy_admin/file_editors.js +0 -28
  266. data/app/javascript/alchemy_admin/image_loader.js +0 -54
  267. data/app/javascript/alchemy_admin/page_sorter.js +0 -71
  268. data/app/javascript/alchemy_admin/sitemap.js +0 -154
  269. data/app/javascript/alchemy_admin/templates/page_folder.hbs +0 -3
  270. data/app/views/alchemy/admin/attachments/archive_overlay.js.erb +0 -4
  271. data/app/views/alchemy/admin/pages/_page.html.erb +0 -163
  272. data/app/views/alchemy/admin/pages/_sitemap.html.erb +0 -30
  273. data/app/views/alchemy/admin/pages/flush.js.erb +0 -2
  274. data/app/views/alchemy/admin/pictures/archive_overlay.js.erb +0 -5
  275. data/app/views/alchemy/admin/pictures/index.js.erb +0 -2
  276. data/app/views/alchemy/ingredients/_audio_editor.html.erb +0 -5
  277. data/app/views/alchemy/ingredients/_boolean_editor.html.erb +0 -11
  278. data/app/views/alchemy/ingredients/_datetime_editor.html.erb +0 -20
  279. data/app/views/alchemy/ingredients/_file_editor.html.erb +0 -52
  280. data/app/views/alchemy/ingredients/_headline_editor.html.erb +0 -44
  281. data/app/views/alchemy/ingredients/_html_editor.html.erb +0 -8
  282. data/app/views/alchemy/ingredients/_link_editor.html.erb +0 -30
  283. data/app/views/alchemy/ingredients/_node_editor.html.erb +0 -13
  284. data/app/views/alchemy/ingredients/_number_editor.html.erb +0 -24
  285. data/app/views/alchemy/ingredients/_page_editor.html.erb +0 -13
  286. data/app/views/alchemy/ingredients/_picture_editor.html.erb +0 -59
  287. data/app/views/alchemy/ingredients/_richtext_editor.html.erb +0 -15
  288. data/app/views/alchemy/ingredients/_select_editor.html.erb +0 -31
  289. data/app/views/alchemy/ingredients/_text_editor.html.erb +0 -29
  290. data/app/views/alchemy/ingredients/_video_editor.html.erb +0 -5
  291. data/lib/generators/alchemy/ingredient/templates/editor.html.erb +0 -14
  292. /data/{lib → app/models}/alchemy/permissions.rb +0 -0
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Alchemy
4
+ # Preloads page trees with all associations and children
5
+ #
6
+ # This service efficiently loads page trees to avoid N+1 queries.
7
+ # It handles folded pages and preloads all necessary associations.
8
+ #
9
+ # @example Preload subtree from a specific page
10
+ # preloader = Alchemy::PageTreePreloader.new(page: page, user: current_user)
11
+ # page_with_descendants = preloader.call
12
+ #
13
+ class PageTreePreloader
14
+ # @param page [Page] Starting page for loading descendants
15
+ # @param user [User, nil] User for folding support
16
+ # @param admin_includes [Boolean] Whether to include admin-only associations like :locker
17
+ def initialize(page:, user: nil, admin_includes: false)
18
+ @page = page
19
+ @user = user
20
+ @admin_includes = admin_includes
21
+ end
22
+
23
+ # Preloads and returns the page tree
24
+ #
25
+ # @return [Array<Page>] Pages with preloaded children, or array with single page when using from:
26
+ def call
27
+ pages = page.self_and_descendants
28
+ folded_page_ids = load_folded_page_ids
29
+ if folded_page_ids.any?
30
+ pages = pages.where(
31
+ "parent_id IS NULL OR parent_id NOT IN (?)",
32
+ folded_page_ids
33
+ )
34
+ end
35
+ pages = pages.preload(*preload_associations)
36
+ pages = pages.map { PageTreePage.new(_1) }
37
+
38
+ preload_children_associations(pages, folded_page_ids:)
39
+
40
+ # Return the starting page, which now has preloaded descendants
41
+ # We need to return the actual instance from the pages array, not the @page instance
42
+ # because the children associations were set on the pages array instances
43
+ pages.find { |p| p.id == page.id }
44
+ end
45
+
46
+ private
47
+
48
+ attr_reader :page, :user, :admin_includes
49
+
50
+ # Load folded page IDs for the user
51
+ def load_folded_page_ids
52
+ if user && Alchemy.config.user_class < ActiveRecord::Base
53
+ FoldedPage.folded_for_user(user).pluck(:page_id).to_set
54
+ else
55
+ Set.new
56
+ end
57
+ end
58
+
59
+ # Preload children associations for a collection of pages
60
+ # This manually populates the children association to prevent N+1 queries
61
+ #
62
+ # @param pages [Array<Page>] The pages to preload children for
63
+ # @param folded_page_ids [Set] Optional set of page IDs that should have empty children
64
+ # @return [void]
65
+ def preload_children_associations(pages, folded_page_ids: Set.new)
66
+ # Group pages by parent_id for efficient lookup
67
+ pages_by_parent = pages.group_by(&:parent_id)
68
+
69
+ # Manually populate the children association for each page
70
+ pages.each do |page|
71
+ children_records = pages_by_parent[page.id] || []
72
+
73
+ # If page is folded, set children to empty array
74
+ collection = if folded_page_ids.include?(page.id)
75
+ page.folded = true
76
+ []
77
+ else
78
+ page.folded = false
79
+ children_records.sort_by(&:lft)
80
+ end
81
+ page.association(:children).target = collection
82
+ page.association(:children).loaded!
83
+ end
84
+ end
85
+
86
+ # Associations to preload for sitemap rendering
87
+ def preload_associations
88
+ associations = [
89
+ {
90
+ language: {
91
+ site: :languages
92
+ }
93
+ },
94
+ :public_version
95
+ ]
96
+ associations.push(:locker) if admin_includes
97
+ associations
98
+ end
99
+ end
100
+
101
+ class PageTreePage < SimpleDelegator
102
+ attr_accessor :folded
103
+ alias_method :folded?, :folded
104
+ end
105
+ end
@@ -108,6 +108,7 @@
108
108
  /* Elements */
109
109
  --elements-window-width: 0px;
110
110
  --elements-window-min-width: 400px;
111
+ --elements-window-transition-easing: ease-in-out;
111
112
 
112
113
  /* Form */
113
114
  --form-left-column-width: 35%;
@@ -34,16 +34,15 @@
34
34
  line-height: var(--form-field-line-height);
35
35
  transition: var(--transition-duration);
36
36
 
37
- &:focus:not(.readonly) {
37
+ &:focus:not(.readonly),
38
+ &:focus:not([readonly]) {
38
39
  @include mixins.default-focus-style(
39
40
  $box-shadow: 0 0 0 1px var(--focus-color)
40
41
  );
41
42
  }
42
43
 
43
44
  &[disabled],
44
- &.disabled,
45
- &:not(.flatpickr-input)[readonly],
46
- &:not(.flatpickr-input).readonly {
45
+ &.disabled {
47
46
  color: var(--form-field-disabled-text-color);
48
47
  background-color: var(--form-field-disabled-bg-color);
49
48
  cursor: default;
@@ -53,11 +52,6 @@
53
52
  &.disabled {
54
53
  cursor: not-allowed;
55
54
  }
56
-
57
- &:not(.flatpickr-input)[readonly],
58
- &:not(.flatpickr-input).readonly {
59
- pointer-events: none;
60
- }
61
55
  }
62
56
 
63
57
  %gradiated-toolbar {
@@ -16,6 +16,7 @@
16
16
 
17
17
  @mixin button-defaults(
18
18
  $background-color: var(--button-bg-color),
19
+ $disabled-background-color: var(--button-disabled-bg-color),
19
20
  $hover-color: var(--button-hover-bg-color),
20
21
  $hover-border-color: var(--button-hover-border-color),
21
22
  $border-radius: var(--button-border-radius),
@@ -68,8 +69,9 @@
68
69
 
69
70
  &.disabled,
70
71
  &[disabled] {
71
- background-color: var(--button-disabled-bg-color);
72
+ background-color: $disabled-background-color;
72
73
  border-color: var(--button-disabled-border-color);
74
+ color: var(--text-color-muted);
73
75
  cursor: not-allowed;
74
76
  box-shadow: none;
75
77
  outline: none;
@@ -83,8 +83,8 @@
83
83
  --form-field-box-shadow: inset 0 0 1px var(--a-dark-grey);
84
84
  --form-field-label-color: var(--text-color-muted);
85
85
  --form-field-text-color: var(--text-color);
86
- --form-field-disabled-text-color: hsl(0deg, 0%, 53%);
87
- --form-field-disabled-bg-color: hsla(0deg, 0%, 20%, 0.5);
86
+ --form-field-disabled-text-color: var(--form-field-text-color);
87
+ --form-field-disabled-bg-color: transparent;
88
88
  --form-field-error-bg-color: hsl(0deg, 47%, 10%);
89
89
  --form-field-error-box-shadow: inset 0 0 1px hsla(0deg, 25%, 30%, 0.5);
90
90
 
@@ -153,6 +153,9 @@
153
153
  --picture-tool-background-color: var(--a-darker-grey);
154
154
  --picture-tool-hover-background-color: var(--a-darkest-grey);
155
155
 
156
+ --scrollbar-thumb-color: var(--a-dark-grey);
157
+ --scrollbar-track-color: var(--a-darkest-grey);
158
+
156
159
  --search-field-background-color: var(--a-dark-grey);
157
160
 
158
161
  /* Selects */
@@ -161,12 +164,12 @@
161
164
  --select-text-color: var(--text-color);
162
165
  --select-hover-bg-color: var(--color-blue_dark);
163
166
  --select-hover-border-color: var(--form-field-border-color);
164
- --select-hover-text-color: var(--color-white);
167
+ --select-hover-text-color: var(--text-color);
165
168
  --select-background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" fill="hsl(200deg, 5%, 70%)" viewBox="0 0 24 24"><path d="M11.9997 13.1714L16.9495 8.22168L18.3637 9.63589L11.9997 15.9999L5.63574 9.63589L7.04996 8.22168L11.9997 13.1714Z"></path></svg>');
166
169
  --select-close-icon: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="hsl(200deg, 5%, 70%)"><path d="M11.9997 10.5865L16.9495 5.63672L18.3637 7.05093L13.4139 12.0007L18.3637 16.9504L16.9495 18.3646L11.9997 13.4149L7.04996 18.3646L5.63574 16.9504L10.5855 12.0007L5.63574 7.05093L7.04996 5.63672L11.9997 10.5865Z"></path></svg>');
167
- --select-disabled-background-color: var(--a-darker-grey);
170
+ --select-disabled-background-color: transparent;
168
171
  --select-disabled-border-color: var(--a-grey);
169
- --select-disabled-text-color: var(--a-lighter-grey);
172
+ --select-disabled-text-color: var(--select-text-color);
170
173
  --select-dropdown-background-color: var(--a-darker-grey);
171
174
  --select-dropdown-box-shadow: 0 var(--spacing-2) var(--spacing-2)
172
175
  hsla(0deg, 0%, 0%, 0.75);
@@ -213,6 +216,7 @@
213
216
  /* Toolbar */
214
217
  --toolbar-bg-color: var(--a-darker-grey);
215
218
  --toolbar-border-bottom: 1px solid var(--a-darkest-grey);
219
+ --toolbar-spacer-color: var(--a-grey);
216
220
 
217
221
  /* Tooltips */
218
222
  --tooltip-background-color: var(--color-blue_dark);
@@ -327,7 +331,7 @@
327
331
  --dialog-header-color: var(--color-blue_dark);
328
332
  --dialog-header-text-color: var(--color-white);
329
333
  --dialog-box-shadow: 0 var(--spacing-2) var(--spacing-4)
330
- hsla(0deg, 0%, 14%, 0.5);
334
+ hsla(0deg, 0%, 14%, 0.15);
331
335
  --dialog-overlay-color: hsla(0deg, 0%, 39%, 0.4);
332
336
  --dialog-background-color: var(--color-grey_very_light);
333
337
 
@@ -354,8 +358,8 @@
354
358
  --form-field-box-shadow: inset 0 0 1px var(--color-grey_light);
355
359
  --form-field-label-color: var(--text-color);
356
360
  --form-field-text-color: var(--text-color);
357
- --form-field-disabled-text-color: hsl(0deg, 0%, 53%);
358
- --form-field-disabled-bg-color: hsla(0deg, 0%, 100%, 0.5);
361
+ --form-field-disabled-text-color: var(--form-field-text-color);
362
+ --form-field-disabled-bg-color: transparent;
359
363
  --form-field-error-bg-color: hsl(0deg, 47%, 96%);
360
364
  --form-field-error-box-shadow: inset 0 0 1px hsla(0deg, 25%, 69%, 0.5);
361
365
 
@@ -422,6 +426,9 @@
422
426
  --picture-tool-background-color: var(--color-white);
423
427
  --picture-tool-hover-background-color: var(--color-grey_very_light);
424
428
 
429
+ --scrollbar-thumb-color: var(--color-white);
430
+ --scrollbar-track-color: var(--color-grey_light);
431
+
425
432
  --search-field-background-color: var(--color-grey_very_light);
426
433
 
427
434
  /* Selects */
@@ -433,8 +440,9 @@
433
440
  --select-hover-text-color: var(--color-white);
434
441
  --select-background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="hsla(224deg, 23%, 26%, 0.75)"><path d="M11.9999 13.1714L16.9497 8.22168L18.3639 9.63589L11.9999 15.9999L5.63599 9.63589L7.0502 8.22168L11.9999 13.1714Z"></path></svg>');
435
442
  --select-close-icon: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="hsla(224deg, 23%, 26%, 0.75)"><path d="M11.9997 10.5865L16.9495 5.63672L18.3637 7.05093L13.4139 12.0007L18.3637 16.9504L16.9495 18.3646L11.9997 13.4149L7.04996 18.3646L5.63574 16.9504L10.5855 12.0007L5.63574 7.05093L7.04996 5.63672L11.9997 10.5865Z"></path></svg>');
436
- --select-disabled-background-color: var(--color-grey_very_light);
443
+ --select-disabled-background-color: transparent;
437
444
  --select-disabled-border-color: var(--border-inset-color);
445
+ --select-disabled-text-color: var(--select-text-color);
438
446
  --select-dropdown-background-color: var(--color-white);
439
447
  --select-dropdown-box-shadow: 0 var(--spacing-2) var(--spacing-2)
440
448
  hsla(0deg, 0%, 0%, 0.15);
@@ -465,7 +473,7 @@
465
473
 
466
474
  /* Text */
467
475
  --text-color: hsla(224deg, 23%, 26%, 0.8);
468
- --text-color-muted: hsla(224deg, 23%, 26%, 0.5);
476
+ --text-color-muted: hsla(224deg, 23%, 26%, 0.6);
469
477
  --text-link-color: var(--color-orange_very_dark);
470
478
  --text-shadow-light: 0 0 var(--spacing-1) hsla(0deg, 0%, 100%, 0.5);
471
479
 
@@ -483,6 +491,7 @@
483
491
  /* Toolbar */
484
492
  --toolbar-bg-color: var(--color-grey_light);
485
493
  --toolbar-border-bottom: var(--border-default);
494
+ --toolbar-spacer-color: var(--border-color);
486
495
 
487
496
  /* Tooltips */
488
497
  --tooltip-background-color: var(--color-blue_dark);
@@ -184,6 +184,7 @@ div.assign_image_list_image {
184
184
  z-index: 10;
185
185
  border-radius: var(--border-radius_medium);
186
186
  box-shadow: 0 0 1px var(--color-grey_dark);
187
+ border: 0;
187
188
 
188
189
  &:hover {
189
190
  text-decoration: none;
@@ -1,9 +1,17 @@
1
1
  @use "../mixins";
2
2
 
3
+ @property --custom-elements-loaded {
4
+ syntax: "<number>";
5
+ inherits: true;
6
+ initial-value: 0;
7
+ }
8
+
3
9
  html {
4
10
  box-sizing: border-box;
5
11
  height: 100%;
6
12
  font-size: var(--font-size_medium);
13
+ scrollbar-width: thin;
14
+ scrollbar-color: var(--scrollbar-thumb-color) var(--scrollbar-track-color);
7
15
 
8
16
  &.turbo-progress-bar::before,
9
17
  .turbo-progress-bar {
@@ -15,6 +23,7 @@ html {
15
23
  *,
16
24
  *::before,
17
25
  *::after {
26
+ scrollbar-width: inherit;
18
27
  box-sizing: inherit;
19
28
  }
20
29
 
@@ -46,6 +55,7 @@ body {
46
55
  cursor: default;
47
56
  opacity: 1;
48
57
  transition: opacity var(--transition-duration);
58
+ animation: custom-elements-loaded 0 linear 250ms forwards;
49
59
 
50
60
  // Fix for strange element window offset
51
61
  &.pages.edit {
@@ -56,9 +66,8 @@ body {
56
66
  overflow: hidden;
57
67
  }
58
68
 
59
- &:has(:not(:defined)) {
69
+ &:has(alchemy-spinner:not(:defined)) {
60
70
  opacity: var(--custom-elements-loaded, 0);
61
- animation: custom-elements-loaded 0 linear 250ms forwards;
62
71
  }
63
72
  }
64
73
 
@@ -85,8 +94,8 @@ a {
85
94
  }
86
95
  }
87
96
 
88
- a:focus,
89
- [tabindex]:focus {
97
+ a:focus:not(.disabled),
98
+ [tabindex]:focus:not(.disabled) {
90
99
  @include mixins.default-focus-style;
91
100
  }
92
101
 
@@ -84,21 +84,21 @@ input.button {
84
84
 
85
85
  &.disabled,
86
86
  &[disabled] {
87
- pointer-events: none;
88
-
89
87
  svg {
90
88
  opacity: 0.3;
91
89
  }
92
90
 
93
91
  &:hover {
94
92
  text-decoration: none;
95
- cursor: default;
93
+ cursor: not-allowed;
94
+ border-color: initial;
96
95
  }
97
96
  }
98
97
 
99
98
  &.linked {
100
99
  @include mixins.button-defaults(
101
100
  $background-color: var(--icon-button-linked-color),
101
+ $disabled-background-color: var(--icon-button-linked-color),
102
102
  $hover-color: var(--icon-button-linked-hover-color),
103
103
  $border: 1px solid var(--icon-button-linked-border-color),
104
104
  $hover-border-color: var(--icon-button-linked-hover-border-color),
@@ -192,11 +192,17 @@
192
192
  }
193
193
 
194
194
  .buttons {
195
- text-align: right;
196
-
197
- label {
198
- float: left;
199
- margin-top: var(--spacing-3);
195
+ display: grid;
196
+ grid-template-columns: 1fr 1fr;
197
+ grid-auto-rows: auto;
198
+ gap: var(--spacing-3);
199
+ align-items: center;
200
+ margin-top: 2em;
201
+ margin-bottom: 0;
202
+
203
+ > .button {
204
+ width: 100%;
205
+ white-space: nowrap;
200
206
  }
201
207
  }
202
208
  }
@@ -1,11 +1,29 @@
1
1
  .element-select-item {
2
+ display: flex;
3
+ flex-direction: column;
4
+ }
5
+
6
+ .element-select-name {
2
7
  display: flex;
3
8
  align-items: center;
4
9
 
5
10
  > svg {
11
+ flex-shrink: 0;
6
12
  width: auto;
7
13
  height: var(--spacing-4);
8
14
  fill: currentColor;
9
15
  padding-right: var(--spacing-2);
10
16
  }
11
17
  }
18
+
19
+ .element-select-description {
20
+ margin-top: var(--spacing-0);
21
+ padding-left: var(--spacing-6);
22
+ font-size: var(--font-size_small);
23
+ color: var(--text-color-muted);
24
+ max-width: 270px;
25
+
26
+ .select2-highlighted & {
27
+ color: var(--select-hover-text-color);
28
+ }
29
+ }
@@ -5,10 +5,9 @@
5
5
 
6
6
  #alchemy_elements_window {
7
7
  --width: var(--elements-window-width, 100vw);
8
- position: absolute;
8
+ position: fixed;
9
9
  right: 0;
10
10
  top: var(--top-menu-height);
11
- z-index: 20;
12
11
  display: block;
13
12
  width: var(--width);
14
13
  min-width: var(--elements-window-min-width);
@@ -21,7 +20,8 @@
21
20
  --elements-window-background-color,
22
21
  var(--dialog-background-color)
23
22
  );
24
- transition: var(--transition-duration) ease-in-out;
23
+ transition: var(--transition-duration)
24
+ var(--elements-window-transition-easing);
25
25
  transform: translate3d(100%, 0, 0);
26
26
 
27
27
  .elements-window-visible & {
@@ -73,16 +73,37 @@ alchemy-elements-window-handle {
73
73
  padding: var(--spacing-2);
74
74
 
75
75
  .right {
76
- display: inline-block;
76
+ display: inline-flex;
77
+ gap: var(--spacing-2);
77
78
  margin-left: auto;
78
79
  }
79
- }
80
80
 
81
- #element_area {
82
- .sortable-elements {
83
- min-height: 100%;
81
+ alchemy-list-filter {
82
+ width: 58px;
83
+ transition: var(--transition-duration);
84
+
85
+ &:focus-within,
86
+ &:has(input:not(:placeholder-shown)) {
87
+ width: 180px;
88
+
89
+ input {
90
+ background-color: var(--form-field-background-color);
91
+ }
92
+ }
93
+
94
+ input {
95
+ height: 100%;
96
+ background-color: var(--toolbar-bg-color);
97
+ }
84
98
  }
99
+ }
85
100
 
101
+ alchemy-sortable-elements {
102
+ display: block;
103
+ min-height: 100%;
104
+ }
105
+
106
+ #element_area {
86
107
  textarea {
87
108
  width: 100%;
88
109
  }
@@ -97,6 +118,7 @@ alchemy-elements-window {
97
118
  --scrollable-elements-offset: calc(
98
119
  var(--top-menu-height) + var(--toolbar-height)
99
120
  );
121
+ display: block;
100
122
  }
101
123
 
102
124
  #main-content-elements {
@@ -147,7 +169,10 @@ alchemy-elements-window {
147
169
  flex-shrink: 0;
148
170
  width: var(--spacing-4);
149
171
  height: var(--spacing-4);
150
- cursor: move;
172
+
173
+ &.draggable {
174
+ cursor: move;
175
+ }
151
176
  }
152
177
 
153
178
  button.element-toggle {
@@ -186,14 +211,10 @@ button.element-toggle {
186
211
  --element-editor-background-color,
187
212
  --dialog-background-color
188
213
  );
189
- margin: var(--spacing-2) 0;
214
+ margin-bottom: var(--spacing-2);
190
215
  transition: box-shadow var(--transition-duration);
191
216
  scroll-margin: var(--spacing-2);
192
217
 
193
- &:first-child {
194
- margin-top: 0;
195
- }
196
-
197
218
  &.element-hidden {
198
219
  border-style: dashed;
199
220
 
@@ -483,35 +504,35 @@ button.element-toggle {
483
504
  border-bottom-right-radius: 0;
484
505
  }
485
506
 
486
- .icon {
507
+ .element-icon {
487
508
  fill: currentColor;
488
509
  transition: fill var(--transition-duration);
489
510
  }
490
511
 
491
512
  > .element-handle {
492
- alchemy-icon,
493
- .icon {
513
+ .handle-icon,
514
+ .element-icon {
494
515
  position: absolute;
495
516
  width: var(--spacing-4);
496
517
  height: var(--spacing-4);
497
518
  transition: opacity var(--transition-duration);
498
519
  }
499
520
 
500
- alchemy-icon {
521
+ .handle-icon {
501
522
  opacity: 0;
502
523
  }
503
524
 
504
- .icon {
525
+ .element-icon {
505
526
  opacity: 1;
506
527
  }
507
528
  }
508
529
 
509
530
  &:hover {
510
- > .element-handle alchemy-icon {
531
+ > .element-handle .handle-icon {
511
532
  opacity: 1;
512
533
  }
513
534
 
514
- > .element-handle .icon.element {
535
+ > .element-handle .element-icon {
515
536
  opacity: 0;
516
537
  }
517
538
  }
@@ -602,6 +623,68 @@ alchemy-publish-element-button {
602
623
  min-height: 100px;
603
624
  }
604
625
 
626
+ alchemy-color-select {
627
+ display: flex;
628
+ justify-content: space-between;
629
+ align-items: center;
630
+
631
+ > input[type="text"],
632
+ > .select2-container {
633
+ width: 100%;
634
+ }
635
+
636
+ > input[type="color"] {
637
+ border-width: var(--form-field-border-width);
638
+ border-style: var(--form-field-border-style);
639
+ border-color: var(--form-field-border-color);
640
+ border-radius: var(--border-radius_medium);
641
+ height: var(--form-field-height);
642
+ background: var(--form-field-background-color);
643
+ padding: var(--spacing-1);
644
+ width: 100%;
645
+
646
+ &[disabled] {
647
+ display: none;
648
+ }
649
+ }
650
+
651
+ &:has(input[type="color"]:not([disabled])) {
652
+ input[type="text"],
653
+ .select2-container,
654
+ .select2-choice {
655
+ border-top-right-radius: 0;
656
+ border-bottom-right-radius: 0;
657
+ }
658
+ }
659
+
660
+ input[type="text"] + input[type="color"],
661
+ select + input[type="color"] {
662
+ width: calc(2 * var(--form-field-addon-width));
663
+ flex-shrink: 0;
664
+ border-top-left-radius: 0;
665
+ border-bottom-left-radius: 0;
666
+ border-left-width: 0;
667
+ }
668
+ }
669
+
670
+ // place the select color options outside, because Select2
671
+ // is opening the selection container outside the `alchemy-color-select`
672
+ // component
673
+ .select-color-option {
674
+ .color-indicator {
675
+ background: var(--color) 100% 100% no-repeat;
676
+ border: var(--border-default);
677
+ border-radius: var(--border-radius_medium);
678
+ display: inline-block;
679
+ height: var(--icon-size-md);
680
+ width: var(--icon-size-md);
681
+ }
682
+
683
+ display: flex;
684
+ align-items: center;
685
+ gap: var(--spacing-2);
686
+ }
687
+
605
688
  .ingredient_link_buttons {
606
689
  display: flex;
607
690
  position: absolute;
@@ -621,8 +704,8 @@ alchemy-publish-element-button {
621
704
  width: var(--form-field-addon-width);
622
705
  height: var(--form-field-height);
623
706
 
624
- &:hover {
625
- border-color: #c0c0c0;
707
+ &:hover:not([disabled]):not(.disabled) {
708
+ border-color: var(--button-hover-border-color);
626
709
  }
627
710
 
628
711
  &:focus {
@@ -686,6 +769,14 @@ alchemy-publish-element-button {
686
769
  }
687
770
  }
688
771
 
772
+ .ingredient-editor.boolean {
773
+ label {
774
+ display: inline-flex;
775
+ align-items: center;
776
+ gap: var(--spacing-0);
777
+ }
778
+ }
779
+
689
780
  .ingredient-editor.picture {
690
781
  position: relative;
691
782
  width: 50%;
@@ -763,6 +854,12 @@ alchemy-publish-element-button {
763
854
  }
764
855
  }
765
856
 
857
+ .ingredient-editor.richtext {
858
+ alchemy-tinymce {
859
+ margin: var(--spacing-2) 0;
860
+ }
861
+ }
862
+
766
863
  .ingredient-editor.headline {
767
864
  &.with-level-select {
768
865
  input[type="text"] {
@@ -1034,14 +1131,19 @@ select.long {
1034
1131
  text-indent: 1px;
1035
1132
  color: var(--form-field-label-color);
1036
1133
 
1134
+ > sl-tooltip {
1135
+ display: inline-flex;
1136
+ margin-left: var(--spacing-1);
1137
+ }
1138
+
1037
1139
  span.warning.icon {
1038
1140
  position: relative;
1039
1141
  top: 2px;
1040
1142
  }
1041
1143
 
1042
1144
  &.inline {
1043
- display: inline-block;
1044
- vertical-align: middle;
1145
+ display: inline-flex;
1146
+ align-items: center;
1045
1147
  min-width: 90px;
1046
1148
  margin-right: var(--spacing-1);
1047
1149
  }
@@ -8,7 +8,7 @@
8
8
  border-radius: var(--border-radius_medium);
9
9
 
10
10
  h2 {
11
- font-size: 1.2em;
11
+ font-size: var(--font-size_medium);
12
12
  }
13
13
 
14
14
  ul {