diff --git a/src/Hook/TermReferenceTreeHooks.php b/src/Hook/TermReferenceTreeHooks.php
new file mode 100644
index 0000000..765296c
--- /dev/null
+++ b/src/Hook/TermReferenceTreeHooks.php
@@ -0,0 +1,130 @@
+<?php
+
+namespace Drupal\term_reference_tree\Hook;
+
+use Drupal\Core\Routing\RouteMatchInterface;
+use Drupal\Core\Hook\Attribute\Hook;
+use Drupal\Core\StringTranslation\StringTranslationTrait;
+
+/**
+ * Hook implementations for term_reference_tree.
+ */
+class TermReferenceTreeHooks {
+  use StringTranslationTrait;
+
+  /**
+   * Implements hook_help().
+   */
+  #[Hook('help')]
+  public function help($route_name, RouteMatchInterface $route_match) {
+    switch ($route_name) {
+      // Main module help for the term_reference_tree module.
+      case 'help.page.term_reference_tree':
+        $output = '';
+        $output .= '<h3>' . $this->t('About') . '</h3>';
+        $output .= '<p>' . $this->t('This module provides an expandable tree widget for
+      the Taxonomy Term Reference field in Drupal. This widget is intended to
+      serve as a replacement for Drupal core Taxonomy Term Reference widget,
+      which is a flat list of radio buttons or checkboxes and not necessarily
+      fit for medium to large taxonomy trees.') . '</p>';
+        $output .= '<p>' . $this->t('This widget has the following features:') . '</p>';
+        $output .= '<ul>' . $this->t('<li>Expand/minimize buttons</li>') . '</ul>';
+        $output .= '<ul>' . $this->t('<li>Fully theme-able</li>') . '</ul>';
+        $output .= '<ul>' . $this->t('<li>Filter and sort available options with a view
+      (if views is installed)</li>') . '</ul>';
+        $output .= '<ul>' . $this->t('<li>The ability to start with the tree either
+      minimized or maximized</li>') . '</ul>';
+        $output .= '<ul>' . $this->t('<li>If you limit the number of selectable options,
+      client-side javascript limits the number of terms that can be selected by
+      disabling the other remaining options when the limit has been reached
+      (this is enforced on the server side too).</li>') . '</ul>';
+        $output .= '<ul>' . $this->t('<li>For large trees, this widget now optionally
+      keeps a list of selected items below the tree.</li>') . '</ul>';
+        $output .= '<ul>' . $this->t('<li>You can use tokens to alter the widget label
+      (good for adding icons, turning the options into links, etc).</li>') . '</ul>';
+        $output .= '<p>' . $this->t('This module now comes with a display formatter with
+      the following features:') . '</p>';
+        $output .= '<ul>' . $this->t('<li>Display taxonomy terms as a nested list by
+      hierarchy.</li>') . '</ul>';
+        $output .= '<ul>' . $this->t('<li>Displayed terms can be altered with tokens or
+      themed using a custom theme function.</li>') . '</ul>';
+        $output .= '<p>' . $this->t('Future features include:') . '</p>';
+        $output .= '<ul>' . $this->t('<li>Dynamic loading of the tree as it is expanded
+      (for very large trees)</li>') . '</ul>';
+        return $output;
+    }
+  }
+
+  /**
+   * Implements hook_theme().
+   */
+  #[Hook('theme')]
+  public static function theme() {
+    return [
+      'checkbox_tree' => [
+        'render element' => 'element',
+      ],
+      'checkbox_tree_level' => [
+        'render element' => 'element',
+      ],
+      'checkbox_tree_item' => [
+        'render element' => 'element',
+      ],
+      'checkbox_tree_label' => [
+        'render element' => 'element',
+      ],
+      'term_tree_list' => [
+        'render element' => 'element',
+      ],
+    ];
+  }
+
+  /**
+   * Implements hook_preprocess_HOOK() for term tree display templates.
+   *
+   * Themes the term tree display (as opposed to the select widget).
+   * Prepares variables for the term_tree_list template.
+   *
+   * Themes the term tree display (as opposed to the select widget).
+   *
+   * Default template: term-tree-list.html.twig.
+   */
+  #[Hook('preprocess_term_tree_list', module: 'template')]
+  public static function templatePreprocessTermTreeList(array &$variables) {
+    $element =& $variables['element'];
+    $data =& $element['#data'];
+    $tree = [];
+    // For each selected term.
+    foreach ($data as $item) {
+      // Loop if the term ID is not zero.
+      $values = [];
+      $tid = $item['target_id'];
+      $original_tid = $tid;
+      while ($tid != 0) {
+        // Unshift the term onto an array.
+        array_unshift($values, $tid);
+        // Repeat with parent term.
+        $tid = _term_reference_tree_get_parent($tid);
+      }
+      $current =& $tree;
+      // For each term in the above array.
+      foreach ($values as $tid) {
+        // current[children][term_id] = new array.
+        if (!isset($current['children'][$tid])) {
+          $current['children'][$tid] = [
+            'selected' => FALSE,
+          ];
+        }
+        // If this is the last value in the array,
+        // tree[children][term_id][selected] = true.
+        if ($tid == $original_tid) {
+          $current['children'][$tid]['selected'] = TRUE;
+        }
+        $current['children'][$tid]['tid'] = $tid;
+        $current =& $current['children'][$tid];
+      }
+    }
+    $variables['children'] = _term_reference_tree_output_list_level($element, $tree);
+  }
+
+}
diff --git a/term_reference_tree.module b/term_reference_tree.module
index d3e1abd..b722a11 100644
--- a/term_reference_tree.module
+++ b/term_reference_tree.module
@@ -5,6 +5,8 @@
  * Term reference tree module.
  */
 
+use Drupal\Core\Hook\Attribute\LegacyHook;
+use Drupal\term_reference_tree\Hook\TermReferenceTreeHooks;
 use Drupal\Component\Utility\Html;
 use Drupal\Core\Render\Element;
 use Drupal\Core\Routing\RouteMatchInterface;
@@ -16,66 +18,17 @@ use Drupal\term_reference_tree\Plugin\Field\FieldWidget\TermReferenceTree;
 /**
  * Implements hook_help().
  */
+#[LegacyHook]
 function term_reference_tree_help($route_name, RouteMatchInterface $route_match) {
-  switch ($route_name) {
-    // Main module help for the term_reference_tree module.
-    case 'help.page.term_reference_tree':
-      $output = '';
-      $output .= '<h3>' . t('About') . '</h3>';
-      $output .= '<p>' . t('This module provides an expandable tree widget for
-      the Taxonomy Term Reference field in Drupal. This widget is intended to
-      serve as a replacement for Drupal core Taxonomy Term Reference widget,
-      which is a flat list of radio buttons or checkboxes and not necessarily
-      fit for medium to large taxonomy trees.') . '</p>';
-      $output .= '<p>' . t('This widget has the following features:') . '</p>';
-      $output .= '<ul>' . t('<li>Expand/minimize buttons</li>') . '</ul>';
-      $output .= '<ul>' . t('<li>Fully theme-able</li>') . '</ul>';
-      $output .= '<ul>' . t('<li>Filter and sort available options with a view
-      (if views is installed)</li>') . '</ul>';
-      $output .= '<ul>' . t('<li>The ability to start with the tree either
-      minimized or maximized</li>') . '</ul>';
-      $output .= '<ul>' . t('<li>If you limit the number of selectable options,
-      client-side javascript limits the number of terms that can be selected by
-      disabling the other remaining options when the limit has been reached
-      (this is enforced on the server side too).</li>') . '</ul>';
-      $output .= '<ul>' . t('<li>For large trees, this widget now optionally
-      keeps a list of selected items below the tree.</li>') . '</ul>';
-      $output .= '<ul>' . t('<li>You can use tokens to alter the widget label
-      (good for adding icons, turning the options into links, etc).</li>') . '</ul>';
-      $output .= '<p>' . t('This module now comes with a display formatter with
-      the following features:') . '</p>';
-      $output .= '<ul>' . t('<li>Display taxonomy terms as a nested list by
-      hierarchy.</li>') . '</ul>';
-      $output .= '<ul>' . t('<li>Displayed terms can be altered with tokens or
-      themed using a custom theme function.</li>') . '</ul>';
-      $output .= '<p>' . t('Future features include:') . '</p>';
-      $output .= '<ul>' . t('<li>Dynamic loading of the tree as it is expanded
-      (for very large trees)</li>') . '</ul>';
-      return $output;
-  }
+  return \Drupal::service(TermReferenceTreeHooks::class)->help($route_name, $route_match);
 }
 
 /**
  * Implements hook_theme().
  */
+#[LegacyHook]
 function term_reference_tree_theme() {
-  return [
-    'checkbox_tree' => [
-      'render element' => 'element',
-    ],
-    'checkbox_tree_level' => [
-      'render element' => 'element',
-    ],
-    'checkbox_tree_item' => [
-      'render element' => 'element',
-    ],
-    'checkbox_tree_label' => [
-      'render element' => 'element',
-    ],
-    'term_tree_list' => [
-      'render element' => 'element',
-    ],
-  ];
+  return \Drupal::service(TermReferenceTreeHooks::class)->theme();
 }
 
 /**
@@ -520,45 +473,9 @@ function _term_reference_tree_build_item($element, $term, $form_state, $value, $
  *
  * Default template: term-tree-list.html.twig.
  */
+#[LegacyHook]
 function template_preprocess_term_tree_list(array &$variables) {
-  $element = &$variables['element'];
-  $data = &$element['#data'];
-
-  $tree = [];
-
-  // For each selected term.
-  foreach ($data as $item) {
-    // Loop if the term ID is not zero.
-    $values = [];
-    $tid = $item['target_id'];
-    $original_tid = $tid;
-    while ($tid != 0) {
-      // Unshift the term onto an array.
-      array_unshift($values, $tid);
-
-      // Repeat with parent term.
-      $tid = _term_reference_tree_get_parent($tid);
-    }
-
-    $current = &$tree;
-    // For each term in the above array.
-    foreach ($values as $tid) {
-      // current[children][term_id] = new array.
-      if (!isset($current['children'][$tid])) {
-        $current['children'][$tid] = ['selected' => FALSE];
-      }
-
-      // If this is the last value in the array,
-      // tree[children][term_id][selected] = true.
-      if ($tid == $original_tid) {
-        $current['children'][$tid]['selected'] = TRUE;
-      }
-
-      $current['children'][$tid]['tid'] = $tid;
-      $current = &$current['children'][$tid];
-    }
-  }
-  $variables['children'] = _term_reference_tree_output_list_level($element, $tree);
+  \Drupal::service(TermReferenceTreeHooks::class)->templatePreprocessTermTreeList($variables);
 }
 
 /**
diff --git a/term_reference_tree.services.yml b/term_reference_tree.services.yml
new file mode 100644
index 0000000..57d8c23
--- /dev/null
+++ b/term_reference_tree.services.yml
@@ -0,0 +1,5 @@
+
+services:
+  Drupal\term_reference_tree\Hook\TermReferenceTreeHooks:
+    class: Drupal\term_reference_tree\Hook\TermReferenceTreeHooks
+    autowire: true
