diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,3 @@
 .ghc.environment.*
 .ghcid
-.stack-work/
-dist/
 dist-newstyle/
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,60 +1,66 @@
 # Changelog
 
-All notable changes to this project will be documented in this file.
+## [1.2.0.4] - 2023-04-25
 
-The format is based on [Keep a Changelog](http://keepachangelog.com/)
-and this project adheres to the [Haskell Package Versioning Policy](https://pvp.haskell.org/).
+- Add support for `hspec-2.11`
+- Drop support for `hspec-2.10`
+- Drop support for GHC < 8.4
 
+## [1.2.0.3] - 2023-01-11
+
+- Drop support for `hspec < 2.10`, `hspec-core < 2.10`, `tasty < 1.3`, and `tasty-quickcheck < 0.9.1`. This was done to
+  eliminate CPP and reduce maintenance burden. Moving forward, this library will opt to tighten compatibility bounds
+  when dependencies make breaking changes, rather than reintroduce CPP.
+
+## [1.2.0.2] - 2023-01-10
+
+- Fix build when `tasty-quickcheck < 0.9.1`
+
+## [1.2.0.1] - 2022-05-14
+
+- Support hspec-2.10.0
+
+## [1.2] - 2021-05-28
+
+- No changes, but 1.1.7 should have been a major version bump due to dropping the `Test.Hspec` re-export.
+
 ## [1.1.7] - 2021-05-12
 
-### Changed
 - Support hspec-2.8.0
-
-### Removed
-- Don't re-export `Test.Hspec`
+- Remove re-export of `Test.Hspec`
 - Drop support for hspec < 2.5
 
 ## [1.1.6-r1] - 2021-03-13
 
-### Changed
 - Support base-4.15
 
 ## [1.1.6] - 2020-11-11
 
-### Changed
 - Rename `Success`/`Failure` to `TreatPendingAsSuccess`/`TreatPendingAsFailure`
 - Support tasty-1.4
 
 ## [1.1.5.1] - 2018-11-15
 
-### Changed
 - Support hspec-2.6.0
 
 ## [1.1.5] - 2018-06-27
 
-### Added
-- `TreatPendingAs` option, for allowing pending tests to be treated as successes
+- Add `TreatPendingAs` option, for allowing pending tests to be treated as successes
 
 ## [1.1.4] - 2018-3-18
 
-### Changed
 - Support hspec-2.5.0
-
-### Removed
-- Re-exports of QuickCheck and SmallCheck options
+- Remove re-exports of QuickCheck and SmallCheck options
 
 ## [1.1.3.3] - 2018-1-26
 
-### Removed
-- Redundant `random` dependency
+- Remove redundant `random` dependency
 
 ## [1.1.3.2] - 2017-6-20
 
-### Changed
 - Support tasty-0.9.1
 - More accurate dependency version bounds
 
 ## [1.1.3.1] - 2017-1-25
 
-### Changed
 - Support hspec-2.4.0
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2013, Mitchell Rosen
+Copyright (c) 2013-2022, Mitchell Rosen
 
 All rights reserved.
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # tasty-hspec
 
-[![Build Status](https://travis-ci.org/mitchellwrosen/tasty-hspec.svg?branch=master)](https://travis-ci.org/mitchellwrosen/tasty-hspec)
+[![GitHub CI](https://github.com/mitchellwrosen/tasty-hspec/workflows/CI/badge.svg)](https://github.com/mitchellwrosen/tasty-hspec/actions)
 [![Hackage](https://img.shields.io/hackage/v/tasty-hspec.svg)](https://hackage.haskell.org/package/tasty-hspec)
 [![Stackage LTS](https://stackage.org/package/tasty-hspec/badge/lts)](https://www.stackage.org/lts/package/tasty-hspec)
 [![Stackage Nightly](https://stackage.org/package/tasty-hspec/badge/nightly)](https://www.stackage.org/nightly/package/tasty-hspec)
diff --git a/cabal.project b/cabal.project
deleted file mode 100644
--- a/cabal.project
+++ /dev/null
@@ -1,1 +0,0 @@
-packages: .
diff --git a/examples/example.hs b/examples/example.hs
--- a/examples/example.hs
+++ b/examples/example.hs
@@ -1,3 +1,4 @@
+import Test.Hspec
 import Test.Tasty
 import Test.Tasty.Hspec
 
diff --git a/src/Test/Tasty/Hspec.hs b/src/Test/Tasty/Hspec.hs
--- a/src/Test/Tasty/Hspec.hs
+++ b/src/Test/Tasty/Hspec.hs
@@ -1,5 +1,3 @@
-{-# LANGUAGE CPP #-}
-
 -- | @hspec@ and @tasty@ serve similar purposes; consider using one or the
 -- other.
 --
@@ -18,26 +16,24 @@
   )
 where
 
-import Control.Applicative ((<$>))
 import Control.Monad (guard)
 import Data.Maybe (catMaybes, fromMaybe, mapMaybe)
 import Data.Proxy
 import Data.Typeable (Typeable)
-import qualified Test.Hspec as H
-import qualified Test.Hspec.Core.Formatters as H
-import qualified Test.Hspec.Core.Spec as H
-import qualified Test.Tasty as T
-import Test.Tasty.Hspec.Compat
-import qualified Test.Tasty.Options as T
-import qualified Test.Tasty.Providers as T
-import qualified Test.Tasty.QuickCheck as TQC
-import qualified Test.Tasty.Runners as T
-import qualified Test.Tasty.SmallCheck as TSC
+import qualified Test.Hspec as Hspec
+import qualified Test.Hspec.Api.Formatters.V1 as Hspec.Api.Formatters.V1
+import qualified Test.Hspec.Core.Spec as Hspec.Core.Spec
+import qualified Test.Tasty as Tasty
+import qualified Test.Tasty.Options as Tasty.Options
+import qualified Test.Tasty.Providers as Tasty.Providers
+import qualified Test.Tasty.QuickCheck as Tasty.QuickCheck
+import qualified Test.Tasty.Runners as Tasty.Runners
+import qualified Test.Tasty.SmallCheck as Tasty.SmallCheck
 
 -- $examples
 --
--- The simplest usage of this library involves first creating a 'T.TestTree' in
--- @IO@, then running it with 'T.defaultMain'.
+-- The simplest usage of this library involves first creating a 'T.TestTree' in @IO@, then running it with
+-- 'T.defaultMain'.
 --
 -- @
 -- main = do
@@ -61,7 +57,7 @@
 --     ]
 -- @
 --
--- However, if you don't do any @IO@ during 'Spec' creation, or the @IO@ need
+-- If you don't do any @IO@ during 'Spec' creation, or the @IO@ need
 -- not be performed at any particular time relative to other @IO@ actions, it's
 -- perfectly fine to use 'System.IO.unsafePerformIO'.
 --
@@ -75,87 +71,90 @@
 -- @
 
 -- | Create a <https://hackage.haskell.org/package/tasty tasty> 'T.TestTree' from an
--- <https://hackage.haskell.org/package/hspec Hspec> 'H.Spec'.
-testSpec :: T.TestName -> H.Spec -> IO T.TestTree
+-- <https://hackage.haskell.org/package/hspec hspec> 'H.Spec'.
+testSpec :: Tasty.TestName -> Hspec.Spec -> IO Tasty.TestTree
 testSpec name spec = do
   trees <- testSpecs spec
-  pure (T.testGroup name trees)
+  pure (Tasty.testGroup name trees)
 
 -- | Create a list of <https://hackage.haskell.org/package/tasty tasty> 'T.TestTree' from an
--- <https://hackage.haskell.org/package/hspec Hspec> 'H.Spec'. This returns the same tests as 'testSpec'
+-- <https://hackage.haskell.org/package/hspec hspec> 'H.Spec'. This returns the same tests as 'testSpec'
 -- but doesn't create a <https://hackage.haskell.org/package/tasty tasty> test group from them.
-testSpecs :: H.Spec -> IO [T.TestTree]
+testSpecs :: Hspec.Spec -> IO [Tasty.TestTree]
 testSpecs spec = do
   -- Here we do as hspec does, which is pre-process a spec by focusing the whole thing, which is a no-op if
   -- anything inside is already focused, but otherwise focuses every item. Then, when creating a tasty test tree,
   -- we just toss the unfocused items.
-  trees <- H.runSpecM (focus spec)
+  (_configBuilder, trees) <- Hspec.Core.Spec.runSpecM (Hspec.focus spec)
   pure (mapMaybe specTreeToTestTree trees)
 
-specTreeToTestTree :: H.SpecTree () -> Maybe T.TestTree
+specTreeToTestTree :: Hspec.Core.Spec.SpecTree () -> Maybe Tasty.TestTree
 specTreeToTestTree = \case
-  Node name trees -> pure (T.testGroup name (mapMaybe specTreeToTestTree trees))
-  NodeWithCleanup cleanup trees -> do
-    tree <- specTreeToTestTree (H.Node "(unnamed)" trees)
-    pure (T.WithResource (T.ResourceSpec (return ()) cleanup) (const tree))
-  Leaf item -> do
-    guard (itemIsFocused item)
-    pure (T.singleTest (H.itemRequirement item) (Item item))
+  Hspec.Core.Spec.Node name trees -> pure (Tasty.testGroup name (mapMaybe specTreeToTestTree trees))
+  Hspec.Core.Spec.NodeWithCleanup _loc cleanup trees -> do
+    tree <- specTreeToTestTree (Hspec.Core.Spec.Node "(unnamed)" trees)
+    pure (Tasty.Runners.WithResource (Tasty.Runners.ResourceSpec (pure ()) (const cleanup)) (const tree))
+  Hspec.Core.Spec.Leaf item -> do
+    guard (Hspec.Core.Spec.itemIsFocused item)
+    pure (Tasty.Providers.singleTest (Hspec.Core.Spec.itemRequirement item) (Item item))
 
 newtype Item
-  = Item (H.Item ())
+  = Item (Hspec.Core.Spec.Item ())
   deriving (Typeable)
 
-instance T.IsTest Item where
+instance Tasty.Providers.IsTest Item where
   run opts (Item item) progress = do
-    qcArgs <- optionSetToQuickCheckArgs opts
-    H.Result _ result <- itemExample item (params qcArgs) ($ ()) progress'
+    (_, qcArgs) <- Tasty.QuickCheck.optionSetToArgs opts
+    -- optionSetToQuickCheckArgs :: Tasty.OptionSet -> IO QuickCheck.Args
+    -- optionSetToQuickCheckArgs opts =
+    --   snd <$> Tasty.QuickCheck.optionSetToArgs opts
+    let params =
+          Hspec.Core.Spec.Params
+            { Hspec.Core.Spec.paramsQuickCheckArgs = qcArgs,
+              Hspec.Core.Spec.paramsSmallCheckDepth =
+                case Tasty.Options.lookupOption opts of
+                  Tasty.SmallCheck.SmallCheckDepth depth -> Just depth
+            }
+    Hspec.Core.Spec.Result _ result <- Hspec.Core.Spec.itemExample item params ($ ()) progress'
     pure
       ( case result of
-          H.Success -> T.testPassed ""
-          H.Pending _ reason ->
-            case T.lookupOption opts of
-              TreatPendingAsFailure -> T.testFailed reason'
-              TreatPendingAsSuccess -> T.testPassed reason'
+          Hspec.Core.Spec.Success -> Tasty.Providers.testPassed ""
+          Hspec.Core.Spec.Pending _ reason ->
+            case Tasty.Options.lookupOption opts of
+              TreatPendingAsFailure -> Tasty.Providers.testFailed reason'
+              TreatPendingAsSuccess -> Tasty.Providers.testPassed reason'
             where
               reason' = "# PENDING: " ++ fromMaybe "No reason given" reason
-          H.Failure _ reason ->
+          Hspec.Core.Spec.Failure _ reason ->
             case reason of
-              H.NoReason -> T.testFailed ""
-              H.Reason x -> T.testFailed x
-              H.ExpectedButGot preface expected actual ->
-                T.testFailed . unlines . catMaybes $
+              Hspec.Core.Spec.ColorizedReason x -> Tasty.Providers.testFailed x
+              Hspec.Core.Spec.NoReason -> Tasty.Providers.testFailed ""
+              Hspec.Core.Spec.Reason x -> Tasty.Providers.testFailed x
+              Hspec.Core.Spec.ExpectedButGot preface expected actual ->
+                Tasty.Providers.testFailed . unlines . catMaybes $
                   [ preface,
                     Just ("expected: " ++ expected),
                     Just (" but got: " ++ actual)
                   ]
-              H.Error _ exception -> T.testFailed ("uncaught exception: " ++ H.formatException exception)
+              Hspec.Core.Spec.Error _ exception ->
+                Tasty.Providers.testFailed ("uncaught exception: " ++ Hspec.Api.Formatters.V1.formatException exception)
       )
     where
-      params qcArgs =
-        H.Params
-          { H.paramsQuickCheckArgs = qcArgs,
-            H.paramsSmallCheckDepth =
-              case T.lookupOption opts of
-                TSC.SmallCheckDepth depth ->
-                  depth
-          }
-
       progress' (x, y) =
         progress
-          T.Progress
-            { T.progressText = "",
-              T.progressPercent = fromIntegral x / fromIntegral y
+          Tasty.Runners.Progress
+            { Tasty.Runners.progressText = "",
+              Tasty.Runners.progressPercent = fromIntegral x / fromIntegral y
             }
 
   testOptions =
     pure
-      [ T.Option (Proxy :: Proxy TreatPendingAs),
-        T.Option (Proxy :: Proxy TQC.QuickCheckTests),
-        T.Option (Proxy :: Proxy TQC.QuickCheckReplay),
-        T.Option (Proxy :: Proxy TQC.QuickCheckMaxSize),
-        T.Option (Proxy :: Proxy TQC.QuickCheckMaxRatio),
-        T.Option (Proxy :: Proxy TSC.SmallCheckDepth)
+      [ Tasty.Options.Option (Proxy :: Proxy TreatPendingAs),
+        Tasty.Options.Option (Proxy :: Proxy Tasty.QuickCheck.QuickCheckTests),
+        Tasty.Options.Option (Proxy :: Proxy Tasty.QuickCheck.QuickCheckReplay),
+        Tasty.Options.Option (Proxy :: Proxy Tasty.QuickCheck.QuickCheckMaxSize),
+        Tasty.Options.Option (Proxy :: Proxy Tasty.QuickCheck.QuickCheckMaxRatio),
+        Tasty.Options.Option (Proxy :: Proxy Tasty.SmallCheck.SmallCheckDepth)
       ]
 
 -- | How to treat @hspec@ pending tests.
@@ -165,10 +164,11 @@
 --
 -- Set via the command line flag @--treat-pending-as (success|failure)@.
 data TreatPendingAs
-  = TreatPendingAsFailure
+  = -- | Default.
+    TreatPendingAsFailure
   | TreatPendingAsSuccess
 
-instance T.IsOption TreatPendingAs where
+instance Tasty.Options.IsOption TreatPendingAs where
   defaultValue =
     TreatPendingAsFailure
 
@@ -183,7 +183,5 @@
   optionHelp =
     pure "How to treat pending hspec tests ('failure' or 'success')"
 
-#if MIN_VERSION_tasty(1,3,0)
   showDefaultValue _ =
     Just "failure"
-#endif
diff --git a/src/Test/Tasty/Hspec/Compat.hs b/src/Test/Tasty/Hspec/Compat.hs
deleted file mode 100644
--- a/src/Test/Tasty/Hspec/Compat.hs
+++ /dev/null
@@ -1,83 +0,0 @@
-{-# LANGUAGE CPP #-}
-
-module Test.Tasty.Hspec.Compat
-  ( itemExample,
-    itemIsFocused,
-    focus,
-    optionSetToQuickCheckArgs,
-
-    pattern Leaf,
-    pattern Node,
-    pattern NodeWithCleanup,
-  )
-where
-
-import qualified Test.Hspec as Hspec
-import qualified Test.Hspec.Core.Spec as Hspec
-import qualified Test.QuickCheck as QuickCheck
-import qualified Test.Tasty.Options as Tasty
-import qualified Test.Tasty.QuickCheck as Tasty.QuickCheck
-
-{-# COMPLETE Leaf, Node, NodeWithCleanup #-}
-
-pattern Leaf :: a -> Hspec.Tree c a
-pattern Leaf item <-
-  Hspec.Leaf item
-
-pattern Node :: String -> [Hspec.Tree c a] -> Hspec.Tree c a
-pattern Node name trees <-
-  Hspec.Node name trees
-
-pattern NodeWithCleanup :: c -> [Hspec.Tree c a] -> Hspec.Tree c a
-pattern NodeWithCleanup cleanup trees <-
-#if MIN_VERSION_hspec(2,8,0)
-  Hspec.NodeWithCleanup _loc cleanup trees
-#else
-  Hspec.NodeWithCleanup cleanup trees
-#endif
-
-itemExample :: Hspec.Item a -> Hspec.Params -> (Hspec.ActionWith a -> IO ()) -> Hspec.ProgressCallback -> IO Hspec.Result
-itemExample item =
-  case item of
-#if MIN_VERSION_hspec(2,6,0)
-    Hspec.Item _ _ _ _ example -> example
-#else
-    Hspec.Item _ _ _ example -> example
-#endif
-
-itemIsFocused :: Hspec.Item a -> Bool
-itemIsFocused =
-#if MIN_VERSION_hspec(2,6,0)
-  Hspec.itemIsFocused
-#else
-  const True
-#endif
-
-focus :: Hspec.Spec -> Hspec.Spec
-focus =
-#if MIN_VERSION_hspec(2,6,0)
-  Hspec.focus
-#else
-  id
-#endif
-
-optionSetToQuickCheckArgs :: Tasty.OptionSet -> IO QuickCheck.Args
-optionSetToQuickCheckArgs opts =
-#if MIN_VERSION_tasty_quickcheck(0,9,1)
-  snd <$> Tasty.QuickCheck.optionSetToArgs opts
-#else
-  pure
-    QuickCheck.stdArgs
-      { QuickCheck.chatty = False,
-        QuickCheck.maxDiscardRatio = max_ratio,
-        QuickCheck.maxSize = max_size,
-        QuickCheck.maxSuccess = num_tests,
-        QuickCheck.replay = replay
-      }
-  where
-    Tasty.QuickCheck.QuickCheckTests num_tests = T.lookupOption opts
-    Tasty.QuickCheck.QuickCheckReplay replay = T.lookupOption opts
-    Tasty.QuickCheck.QuickCheckMaxSize max_size = T.lookupOption opts
-    Tasty.QuickCheck.QuickCheckMaxRatio max_ratio = T.lookupOption opts
-#endif
-
diff --git a/tasty-hspec.cabal b/tasty-hspec.cabal
--- a/tasty-hspec.cabal
+++ b/tasty-hspec.cabal
@@ -1,48 +1,47 @@
-cabal-version:       2.0
+cabal-version:       2.2
 name:                tasty-hspec
-version:             1.1.7
+version:             1.2.0.4
 synopsis:            Hspec support for the Tasty test framework.
 description:         This package provides a Tasty provider for Hspec test
                      suites.
 
 homepage:            https://github.com/mitchellwrosen/tasty-hspec
-license:             BSD3
+license:             BSD-3-Clause
 license-file:        LICENSE
 author:              Mitchell Rosen
 maintainer:          mitchellwrosen@gmail.com
 category:            Testing
 build-type:          Simple
+tested-with:         GHC == 9.2.7, GHC == 9.4.4, GHC == 9.6.1
 
-extra-source-files:
+extra-doc-files:
   .gitignore
-  cabal.project
   CHANGELOG.md
-  examples/example.hs
   README.md
 
+extra-source-files:
+  examples/example.hs
+
 source-repository head
   type:     git
   location: https://github.com/mitchellwrosen/tasty-hspec.git
 
 library
   build-depends:
-    base ^>= 4.9 || ^>= 4.10 || ^>= 4.11 || ^>= 4.12 || ^>= 4.13 || ^>= 4.14 || ^>= 4.15,
-    hspec >= 2.5 && < 2.9,
-    hspec-core >= 2.5 && < 2.9,
+    base ^>= 4.11 || ^>= 4.12 || ^>= 4.13 || ^>= 4.14 || ^>= 4.15 || ^>= 4.16 || ^>= 4.17 || ^>= 4.18,
+    hspec ^>= 2.11.0,
+    hspec-api ^>= 2.11.0,
+    hspec-core ^>= 2.11.0,
     QuickCheck ^>= 2.7 || ^>= 2.8 || ^>= 2.9 || ^>= 2.10 || ^>= 2.11 || ^>= 2.12 || ^>= 2.13 || ^>= 2.14,
-    tasty ^>= 0.8 || ^>= 0.9 || ^>= 0.10 || ^>= 0.11 || ^>= 0.12 || ^>= 1.0 || ^>= 1.1 || ^>= 1.2 || ^>= 1.3 || ^>= 1.4,
+    tasty ^>= 1.3 || ^>= 1.4,
     tasty-smallcheck >= 0.1 && < 0.9,
-    -- 0.9 is missing 'optionSetToArgs'
-    tasty-quickcheck >=0.3 && <0.9 || ^>=0.9.1 || ^>= 0.10
-  if impl(ghc < 7.8)
-    build-depends:     tagged >= 0.2
+    tasty-quickcheck ^>= 0.9.1 || ^>= 0.10,
   default-extensions:
     LambdaCase
-    PatternSynonyms
+    ScopedTypeVariables
   default-language: Haskell2010
   exposed-modules: Test.Tasty.Hspec
   ghc-options: -Wall
   if impl(ghc >= 8.0)
     ghc-options: -Wcompat
   hs-source-dirs: src
-  other-modules: Test.Tasty.Hspec.Compat
