diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,3 +1,7 @@
+## 0.3.1.1
+### Fixed
+- Fixed a bug where row background color was determined by the original row index rather than the sorted index.
+
 ## 0.3.1.0
 ### Changed
 - Remove ilist package dependency, since it is not in the latest Stackage LTS and is easily replaced.
diff --git a/example-basic/Main.hs b/example-basic/Main.hs
deleted file mode 100644
--- a/example-basic/Main.hs
+++ /dev/null
@@ -1,213 +0,0 @@
-{-# LANGUAGE TemplateHaskell #-}
-{-# OPTIONS_GHC -Wno-name-shadowing #-}
-
-module Main (main) where
-
-import Control.Lens (Ixed (ix), makeLensesFor, singular)
-import Data.Sequence (Seq ((:|>)))
-import qualified Data.Sequence as S
-import Data.Text (Text, pack)
-import qualified Data.Text as T
-import Data.Time (Day, addDays, defaultTimeLocale, formatTime, fromGregorian)
-import Monomer
-import Monomer.Hagrid (Column (..), ColumnAlign (..), ColumnFooterWidget (..), ColumnSortKey (..), SortDirection (..), hagrid_, initialSort, scrollToRow, showOrdColumn, textColumn, widgetColumn)
-import Text.Printf (printf)
-
-data AppModel = AppModel
-  { theme :: Theme,
-    spiders :: Seq Spider,
-    columns :: [AppColumn],
-    rowToScrollTo :: Int
-  }
-  deriving (Eq, Show)
-
-newtype AppColumn = AppColumn
-  {enabled :: Bool}
-  deriving (Eq, Show)
-
-data AppEvent
-  = FeedSpider Int
-  | AddSpider
-  | NameColumnResized Int
-  | NameColumnSorted SortDirection
-  | ScrollToOriginalIndex
-
-data Spider = Spider
-  { index :: Int,
-    species :: Text,
-    name :: Text,
-    dateOfBirth :: Day,
-    weightKilos :: Double
-  }
-  deriving (Eq, Show)
-
-makeLensesFor [("enabled", "_enabled")] ''AppColumn
-makeLensesFor [("columns", "_columns"), ("theme", "_theme"), ("rowToScrollTo", "_rowToScrollTo")] ''AppModel
-
-main :: IO ()
-main = startApp model handleEvent buildUI config
-  where
-    config =
-      [ appWindowTitle "Hagrid Basic Example",
-        appFontDef "Bold" "./assets/fonts/Cantarell/Cantarell-Bold.ttf",
-        appFontDef "Regular" "./assets/fonts/Cantarell/Cantarell-Regular.ttf",
-        appDisableAutoScale True,
-        appWindowState (MainWindowNormal (1200, 1000))
-      ]
-    model =
-      AppModel
-        { theme = darkTheme,
-          spiders = spiders,
-          columns = AppColumn True <$ gridColumns,
-          rowToScrollTo = 0
-        }
-    spiders = S.fromFunction numSpiders spider
-    spider i =
-      Spider
-        { index = i,
-          species = "Acromantula",
-          name = T.pack (printf "Son of Aragog %d" (i + 1)),
-          dateOfBirth = addDays (fromIntegral i) (fromGregorian 1942 3 1),
-          weightKilos = fromIntegral (numSpiders + 2 - i) * 2.3
-        }
-    numSpiders = 100
-
-buildUI :: UIBuilder AppModel AppEvent
-buildUI _wenv model = tree
-  where
-    tree =
-      themeSwitch_ model.theme [themeClearBg] $
-        vstack
-          [ grid `nodeKey` hagridKey,
-            vstack_
-              [childSpacing]
-              (themeConfigurer : columnConfigurers <> actionButtons)
-              `styleBasic` [padding 8]
-          ]
-
-    grid =
-      hagrid_
-        [initialSort 1 SortDescending]
-        (mconcat (zipWith column model.columns gridColumns))
-        model.spiders
-
-    column (AppColumn enabled) columnDef =
-      [columnDef | enabled]
-
-    themeConfigurer =
-      hstack_
-        [childSpacing]
-        [ labeledRadio_ "Dark Theme" darkTheme _theme [textRight],
-          labeledRadio_ "Light Theme" lightTheme _theme [textRight]
-        ]
-
-    columnConfigurers =
-      zipWith columnConfigurer [0 .. length model.columns - 1] gridColumns
-
-    columnConfigurer :: Int -> Column AppEvent Spider -> WidgetNode AppModel AppEvent
-    columnConfigurer idx columnDef =
-      labeledCheckbox_
-        columnDef.name
-        (_columns . singular (ix idx) . _enabled)
-        [textRight]
-
-    actionButtons =
-      [ hstack_
-          [childSpacing]
-          [ label "Scroll to index of unsorted list",
-            numericField _rowToScrollTo,
-            button "Go!" ScrollToOriginalIndex
-          ],
-        hstack_
-          [childSpacing]
-          [button "Add spider" AddSpider]
-      ]
-
-handleEvent :: EventHandler AppModel AppEvent sp ep
-handleEvent _wenv _node model = \case
-  FeedSpider idx
-    | Just spdr <- S.lookup idx model.spiders ->
-        [ Producer (const (putStrLn ("Feeding spider " <> T.unpack spdr.name))),
-          Model model {spiders = S.update idx spdr {weightKilos = spdr.weightKilos + 1} model.spiders}
-        ]
-  FeedSpider _ ->
-    []
-  AddSpider ->
-    [Model model {spiders = model.spiders :|> newSpider model}]
-  NameColumnResized colWidth ->
-    [Producer (const (putStrLn ("Name column was resized: " <> show colWidth)))]
-  NameColumnSorted direction ->
-    [Producer (const (putStrLn ("Name column was sorted: " <> show direction)))]
-  ScrollToOriginalIndex ->
-    [scrollToRow (WidgetKey hagridKey) (rowScrollIndex model)]
-
-newSpider :: AppModel -> Spider
-newSpider model =
-  Spider
-    { index = fromIntegral (length model.spiders),
-      name = "Extra Spider " <> pack (show (length model.spiders)),
-      species = "Spider plant",
-      dateOfBirth = fromGregorian 2022 6 26,
-      weightKilos = 0.01
-    }
-
-rowScrollIndex :: AppModel -> Seq (Spider, Int) -> Maybe Int
-rowScrollIndex model items =
-  snd <$> S.lookup model.rowToScrollTo items
-
-gridColumns :: [Column AppEvent Spider]
-gridColumns = cols
-  where
-    cols =
-      [ (showOrdColumn "Index" (.index))
-          { initialWidth = 120,
-            align = ColumnAlignRight,
-            footerWidget = CustomFooterWidget countFooter
-          },
-        (textColumn "Name" (.name))
-          { initialWidth = 300,
-            resizeHandler = Just NameColumnResized,
-            sortHandler = Just NameColumnSorted
-          },
-        (textColumn "Species" (.species))
-          { initialWidth = 200
-          },
-        (textColumn "Date of Birth" (T.pack . formatTime defaultTimeLocale "%Y-%m-%d" . (.dateOfBirth)))
-          { initialWidth = 200
-          },
-        (textColumn "Weight (Kg)" (T.pack . printf "%.2f" . (.weightKilos)))
-          { sortKey = SortWith (.weightKilos),
-            initialWidth = 200,
-            align = ColumnAlignRight,
-            footerWidget = CustomFooterWidget sumWeightFooter
-          },
-        (widgetColumn "Actions" actionsColumn)
-          { initialWidth = 100,
-            paddingW = 5,
-            paddingH = 5
-          }
-      ]
-
-    countFooter spiders =
-      labelledFooter "Count" (T.pack . show . length $ spiders)
-
-    sumWeightFooter spiders = tree
-      where
-        tree = labelledFooter "Sum" (T.pack (printf "%.2f" totalWeightKilos))
-        totalWeightKilos = sum ((.weightKilos) . fst <$> spiders)
-
-    labelledFooter labelText text =
-      hstack
-        [ label labelText,
-          filler,
-          label text
-            `styleBasic` [textFont "Bold"]
-        ]
-        `styleBasic` [padding 10]
-
-    actionsColumn :: Int -> Spider -> WidgetNode s AppEvent
-    actionsColumn idx _spdr =
-      button "Feed" (FeedSpider idx)
-
-hagridKey :: Text
-hagridKey = "SpiderHagrid"
diff --git a/example-big-grid/Main.hs b/example-big-grid/Main.hs
deleted file mode 100644
--- a/example-big-grid/Main.hs
+++ /dev/null
@@ -1,58 +0,0 @@
-module Main (main) where
-
-import Data.Function ((&))
-import Data.Sequence (Seq)
-import qualified Data.Sequence as S
-import Data.Text (Text, dropWhile, dropWhileEnd, pack, splitOn, strip)
-import Data.Text.IO (readFile)
-import Monomer
-import Monomer.Hagrid (estimatedItemHeight, hagrid_, initialWidth, textColumn, widgetColumn)
-import Prelude hiding (dropWhile, readFile)
-
-newtype AppModel = AppModel
-  { paragraphs :: Seq Text
-  }
-  deriving (Eq, Show)
-
-data AppEvent
-
-main :: IO ()
-main = do
-  paragraphs <- splitParagraphs <$> readFile "./assets/etc/war-and-peace.txt"
-  startApp (model paragraphs) handleEvent buildUI config
-  where
-    config =
-      [ appWindowTitle "Hagrid Big Grid Example",
-        appFontDef "Bold" "./assets/fonts/Cantarell/Cantarell-Bold.ttf",
-        appFontDef "Regular" "./assets/fonts/Cantarell/Cantarell-Regular.ttf",
-        appTheme darkTheme,
-        appDisableAutoScale True,
-        appWindowState (MainWindowNormal (1200, 1000))
-      ]
-    model paragraphs =
-      AppModel
-        { paragraphs
-        }
-
-buildUI :: UIBuilder AppModel AppEvent
-buildUI _wenv model = tree
-  where
-    tree =
-      hagrid_
-        [estimatedItemHeight 100]
-        [ (textColumn "Author" (const "Leo Tolstoy")) {initialWidth = 180},
-          (textColumn "Title" (const "War and Peace")) {initialWidth = 160},
-          widgetColumn "Line Index" (\i _ -> label (pack (show i))),
-          (widgetColumn "Line" (\_ para -> label_ para [multiline, ellipsis])) {initialWidth = 760}
-        ]
-        model.paragraphs
-
-handleEvent :: EventHandler AppModel AppEvent sp ep
-handleEvent _wenv _node _model = \case {}
-
-splitParagraphs :: Text -> Seq Text
-splitParagraphs s =
-  splitOn "\n\n" s
-    & S.fromList
-    & fmap (dropWhile (== '\n') . dropWhileEnd (== '\n'))
-    & S.filter ((/= mempty) . strip)
diff --git a/example-resizing-cells/Main.hs b/example-resizing-cells/Main.hs
deleted file mode 100644
--- a/example-resizing-cells/Main.hs
+++ /dev/null
@@ -1,111 +0,0 @@
-module Main (main) where
-
-import Control.Concurrent (threadDelay)
-import Control.Monad (forM, forever)
-import Data.Default.Class (def)
-import Data.Sequence (Seq)
-import qualified Data.Sequence as S
-import Data.Text (Text, pack, words)
-import Monomer
-import Monomer.Hagrid (estimatedItemHeight, hagrid_, initialWidth, minWidth, showOrdColumn, textColumn, widgetColumn)
-import Monomer.Widgets.Single
-import System.Random.Stateful (globalStdGen, uniformRM)
-import Prelude hiding (words)
-
-newtype AppModel = AppModel
-  { cellModels :: Seq CellModel
-  }
-  deriving (Eq, Show)
-
-data CellModel = CellModel
-  { info :: Text,
-    dotColor :: Color,
-    dotSize :: Double,
-    dotSpeed :: Int,
-    dotPhase :: Int
-  }
-  deriving (Eq, Show)
-
-data AppEvent = AppInit | UpdatePhase
-
-main :: IO ()
-main = do
-  cellModels <- forM (take 1_000 (zip infos colors)) $ \(info, dotColor) -> do
-    dotSize <- uniformRM (30, 200) globalStdGen
-    dotPhase <- uniformRM (0, 180) globalStdGen
-    dotSpeed <- uniformRM (1, 4) globalStdGen
-    pure CellModel {info, dotColor, dotSize, dotPhase, dotSpeed}
-  startApp (model cellModels) handleEvent buildUI config
-  where
-    config =
-      [ appWindowTitle "Hagrid Resizing Cells Example",
-        appFontDef "Bold" "./assets/fonts/Cantarell/Cantarell-Bold.ttf",
-        appFontDef "Regular" "./assets/fonts/Cantarell/Cantarell-Regular.ttf",
-        appTheme darkTheme,
-        appDisableAutoScale True,
-        appWindowState (MainWindowNormal (1_200, 1_000)),
-        appInitEvent AppInit
-      ]
-    model cellModels =
-      AppModel {cellModels = S.fromList cellModels}
-    colors =
-      cycle [red, green, blue, yellow]
-    infos =
-      cycle . words $
-        "This demo shows how hagrid behaves when cells are dynamically changing size."
-
-buildUI :: UIBuilder AppModel AppEvent
-buildUI _wenv model = tree
-  where
-    tree =
-      hagrid_
-        [estimatedItemHeight 60]
-        [ widgetColumn "Line Index" (\i _ -> label (pack (show i))),
-          (textColumn "Info" (.info)) {initialWidth = 200},
-          (showOrdColumn "Phase" (.dotPhase)) {initialWidth = 300},
-          (widgetColumn "Dot" dotWidget) {minWidth = 220}
-        ]
-        model.cellModels
-
-handleEvent :: EventHandler AppModel AppEvent sp ep
-handleEvent _wenv _node model = \case
-  AppInit ->
-    [ Producer $ \emit -> do
-        forever $ do
-          emit UpdatePhase
-          threadDelay (1_000_000 `div` 30)
-    ]
-  UpdatePhase ->
-    [Model model {cellModels = updatePhase <$> model.cellModels}]
-    where
-      updatePhase cellModel =
-        cellModel {dotPhase = cellModel.dotPhase + cellModel.dotSpeed}
-
-dotWidget :: Int -> CellModel -> WidgetNode s AppEvent
-dotWidget _idx cellModel = tree
-  where
-    tree =
-      defaultWidgetNode "DotWidget" $
-        createSingle
-          cellModel
-          def
-            { singleGetSizeReq = getSizeReq,
-              singleMerge = merge,
-              singleRender = render
-            }
-
-    size = cellModel.dotSize * abs (sin (fromIntegral cellModel.dotPhase / 100))
-
-    merge _wenv node _oldNode oldState = resultReqs node [resizeReq | needResize]
-      where
-        resizeReq = ResizeWidgets node._wnInfo._wniWidgetId
-        needResize = oldState /= cellModel
-
-    getSizeReq _wenv _node =
-      (fixedSize size, fixedSize size)
-
-    render wenv node renderer =
-      drawEllipse renderer carea {_rW = size, _rH = size} (Just cellModel.dotColor)
-      where
-        style = currentStyle wenv node
-        carea = getContentArea node style
diff --git a/examples/basic/Main.hs b/examples/basic/Main.hs
new file mode 100644
--- /dev/null
+++ b/examples/basic/Main.hs
@@ -0,0 +1,213 @@
+{-# LANGUAGE TemplateHaskell #-}
+{-# OPTIONS_GHC -Wno-name-shadowing #-}
+
+module Main (main) where
+
+import Control.Lens (Ixed (ix), makeLensesFor, singular)
+import Data.Sequence (Seq ((:|>)))
+import qualified Data.Sequence as S
+import Data.Text (Text, pack)
+import qualified Data.Text as T
+import Data.Time (Day, addDays, defaultTimeLocale, formatTime, fromGregorian)
+import Monomer
+import Monomer.Hagrid (Column (..), ColumnAlign (..), ColumnFooterWidget (..), ColumnSortKey (..), SortDirection (..), hagrid_, initialSort, scrollToRow, showOrdColumn, textColumn, widgetColumn)
+import Text.Printf (printf)
+
+data AppModel = AppModel
+  { theme :: Theme,
+    spiders :: Seq Spider,
+    columns :: [AppColumn],
+    rowToScrollTo :: Int
+  }
+  deriving (Eq, Show)
+
+newtype AppColumn = AppColumn
+  {enabled :: Bool}
+  deriving (Eq, Show)
+
+data AppEvent
+  = FeedSpider Int
+  | AddSpider
+  | NameColumnResized Int
+  | NameColumnSorted SortDirection
+  | ScrollToOriginalIndex
+
+data Spider = Spider
+  { index :: Int,
+    species :: Text,
+    name :: Text,
+    dateOfBirth :: Day,
+    weightKilos :: Double
+  }
+  deriving (Eq, Show)
+
+makeLensesFor [("enabled", "_enabled")] ''AppColumn
+makeLensesFor [("columns", "_columns"), ("theme", "_theme"), ("rowToScrollTo", "_rowToScrollTo")] ''AppModel
+
+main :: IO ()
+main = startApp model handleEvent buildUI config
+  where
+    config =
+      [ appWindowTitle "Hagrid Basic Example",
+        appFontDef "Bold" "./assets/fonts/Cantarell/Cantarell-Bold.ttf",
+        appFontDef "Regular" "./assets/fonts/Cantarell/Cantarell-Regular.ttf",
+        appDisableAutoScale True,
+        appWindowState (MainWindowNormal (1200, 1000))
+      ]
+    model =
+      AppModel
+        { theme = darkTheme,
+          spiders = spiders,
+          columns = AppColumn True <$ gridColumns,
+          rowToScrollTo = 0
+        }
+    spiders = S.fromFunction numSpiders spider
+    spider i =
+      Spider
+        { index = i,
+          species = "Acromantula",
+          name = T.pack (printf "Son of Aragog %d" (i + 1)),
+          dateOfBirth = addDays (fromIntegral i) (fromGregorian 1942 3 1),
+          weightKilos = fromIntegral (numSpiders + 2 - i) * 2.3
+        }
+    numSpiders = 100
+
+buildUI :: UIBuilder AppModel AppEvent
+buildUI _wenv model = tree
+  where
+    tree =
+      themeSwitch_ model.theme [themeClearBg] $
+        vstack
+          [ grid `nodeKey` hagridKey,
+            vstack_
+              [childSpacing]
+              (themeConfigurer : columnConfigurers <> actionButtons)
+              `styleBasic` [padding 8]
+          ]
+
+    grid =
+      hagrid_
+        [initialSort 1 SortDescending]
+        (mconcat (zipWith column model.columns gridColumns))
+        model.spiders
+
+    column (AppColumn enabled) columnDef =
+      [columnDef | enabled]
+
+    themeConfigurer =
+      hstack_
+        [childSpacing]
+        [ labeledRadio_ "Dark Theme" darkTheme _theme [textRight],
+          labeledRadio_ "Light Theme" lightTheme _theme [textRight]
+        ]
+
+    columnConfigurers =
+      zipWith columnConfigurer [0 .. length model.columns - 1] gridColumns
+
+    columnConfigurer :: Int -> Column AppEvent Spider -> WidgetNode AppModel AppEvent
+    columnConfigurer idx columnDef =
+      labeledCheckbox_
+        columnDef.name
+        (_columns . singular (ix idx) . _enabled)
+        [textRight]
+
+    actionButtons =
+      [ hstack_
+          [childSpacing]
+          [ label "Scroll to index of unsorted list",
+            numericField _rowToScrollTo,
+            button "Go!" ScrollToOriginalIndex
+          ],
+        hstack_
+          [childSpacing]
+          [button "Add spider" AddSpider]
+      ]
+
+handleEvent :: EventHandler AppModel AppEvent sp ep
+handleEvent _wenv _node model = \case
+  FeedSpider idx
+    | Just spdr <- S.lookup idx model.spiders ->
+        [ Producer (const (putStrLn ("Feeding spider " <> T.unpack spdr.name))),
+          Model model {spiders = S.update idx spdr {weightKilos = spdr.weightKilos + 1} model.spiders}
+        ]
+  FeedSpider _ ->
+    []
+  AddSpider ->
+    [Model model {spiders = model.spiders :|> newSpider model}]
+  NameColumnResized colWidth ->
+    [Producer (const (putStrLn ("Name column was resized: " <> show colWidth)))]
+  NameColumnSorted direction ->
+    [Producer (const (putStrLn ("Name column was sorted: " <> show direction)))]
+  ScrollToOriginalIndex ->
+    [scrollToRow (WidgetKey hagridKey) (rowScrollIndex model)]
+
+newSpider :: AppModel -> Spider
+newSpider model =
+  Spider
+    { index = fromIntegral (length model.spiders),
+      name = "Extra Spider " <> pack (show (length model.spiders)),
+      species = "Spider plant",
+      dateOfBirth = fromGregorian 2022 6 26,
+      weightKilos = 0.01
+    }
+
+rowScrollIndex :: AppModel -> Seq (Spider, Int) -> Maybe Int
+rowScrollIndex model items =
+  snd <$> S.lookup model.rowToScrollTo items
+
+gridColumns :: [Column AppEvent Spider]
+gridColumns = cols
+  where
+    cols =
+      [ (showOrdColumn "Index" (.index))
+          { initialWidth = 120,
+            align = ColumnAlignRight,
+            footerWidget = CustomFooterWidget countFooter
+          },
+        (textColumn "Name" (.name))
+          { initialWidth = 300,
+            resizeHandler = Just NameColumnResized,
+            sortHandler = Just NameColumnSorted
+          },
+        (textColumn "Species" (.species))
+          { initialWidth = 200
+          },
+        (textColumn "Date of Birth" (T.pack . formatTime defaultTimeLocale "%Y-%m-%d" . (.dateOfBirth)))
+          { initialWidth = 200
+          },
+        (textColumn "Weight (Kg)" (T.pack . printf "%.2f" . (.weightKilos)))
+          { sortKey = SortWith (.weightKilos),
+            initialWidth = 200,
+            align = ColumnAlignRight,
+            footerWidget = CustomFooterWidget sumWeightFooter
+          },
+        (widgetColumn "Actions" actionsColumn)
+          { initialWidth = 100,
+            paddingW = 5,
+            paddingH = 5
+          }
+      ]
+
+    countFooter spiders =
+      labelledFooter "Count" (T.pack . show . length $ spiders)
+
+    sumWeightFooter spiders = tree
+      where
+        tree = labelledFooter "Sum" (T.pack (printf "%.2f" totalWeightKilos))
+        totalWeightKilos = sum ((.weightKilos) . fst <$> spiders)
+
+    labelledFooter labelText text =
+      hstack
+        [ label labelText,
+          filler,
+          label text
+            `styleBasic` [textFont "Bold"]
+        ]
+        `styleBasic` [padding 10]
+
+    actionsColumn :: Int -> Spider -> WidgetNode s AppEvent
+    actionsColumn idx _spdr =
+      button "Feed" (FeedSpider idx)
+
+hagridKey :: Text
+hagridKey = "SpiderHagrid"
diff --git a/examples/big-grid/Main.hs b/examples/big-grid/Main.hs
new file mode 100644
--- /dev/null
+++ b/examples/big-grid/Main.hs
@@ -0,0 +1,58 @@
+module Main (main) where
+
+import Data.Function ((&))
+import Data.Sequence (Seq)
+import qualified Data.Sequence as S
+import Data.Text (Text, dropWhile, dropWhileEnd, pack, splitOn, strip)
+import Data.Text.IO (readFile)
+import Monomer
+import Monomer.Hagrid (estimatedItemHeight, hagrid_, initialWidth, textColumn, widgetColumn)
+import Prelude hiding (dropWhile, readFile)
+
+newtype AppModel = AppModel
+  { paragraphs :: Seq Text
+  }
+  deriving (Eq, Show)
+
+data AppEvent
+
+main :: IO ()
+main = do
+  paragraphs <- splitParagraphs <$> readFile "./assets/etc/war-and-peace.txt"
+  startApp (model paragraphs) handleEvent buildUI config
+  where
+    config =
+      [ appWindowTitle "Hagrid Big Grid Example",
+        appFontDef "Bold" "./assets/fonts/Cantarell/Cantarell-Bold.ttf",
+        appFontDef "Regular" "./assets/fonts/Cantarell/Cantarell-Regular.ttf",
+        appTheme darkTheme,
+        appDisableAutoScale True,
+        appWindowState (MainWindowNormal (1200, 1000))
+      ]
+    model paragraphs =
+      AppModel
+        { paragraphs
+        }
+
+buildUI :: UIBuilder AppModel AppEvent
+buildUI _wenv model = tree
+  where
+    tree =
+      hagrid_
+        [estimatedItemHeight 100]
+        [ (textColumn "Author" (const "Leo Tolstoy")) {initialWidth = 180},
+          (textColumn "Title" (const "War and Peace")) {initialWidth = 160},
+          widgetColumn "Line Index" (\i _ -> label (pack (show i))),
+          (widgetColumn "Line" (\_ para -> label_ para [multiline, ellipsis])) {initialWidth = 760}
+        ]
+        model.paragraphs
+
+handleEvent :: EventHandler AppModel AppEvent sp ep
+handleEvent _wenv _node _model = \case {}
+
+splitParagraphs :: Text -> Seq Text
+splitParagraphs s =
+  splitOn "\n\n" s
+    & S.fromList
+    & fmap (dropWhile (== '\n') . dropWhileEnd (== '\n'))
+    & S.filter ((/= mempty) . strip)
diff --git a/examples/resizing-cells/Main.hs b/examples/resizing-cells/Main.hs
new file mode 100644
--- /dev/null
+++ b/examples/resizing-cells/Main.hs
@@ -0,0 +1,111 @@
+module Main (main) where
+
+import Control.Concurrent (threadDelay)
+import Control.Monad (forM, forever)
+import Data.Default.Class (def)
+import Data.Sequence (Seq)
+import qualified Data.Sequence as S
+import Data.Text (Text, pack, words)
+import Monomer
+import Monomer.Hagrid (estimatedItemHeight, hagrid_, initialWidth, minWidth, showOrdColumn, textColumn, widgetColumn)
+import Monomer.Widgets.Single
+import System.Random.Stateful (globalStdGen, uniformRM)
+import Prelude hiding (words)
+
+newtype AppModel = AppModel
+  { cellModels :: Seq CellModel
+  }
+  deriving (Eq, Show)
+
+data CellModel = CellModel
+  { info :: Text,
+    dotColor :: Color,
+    dotSize :: Double,
+    dotSpeed :: Int,
+    dotPhase :: Int
+  }
+  deriving (Eq, Show)
+
+data AppEvent = AppInit | UpdatePhase
+
+main :: IO ()
+main = do
+  cellModels <- forM (take 1_000 (zip infos colors)) $ \(info, dotColor) -> do
+    dotSize <- uniformRM (30, 200) globalStdGen
+    dotPhase <- uniformRM (0, 180) globalStdGen
+    dotSpeed <- uniformRM (1, 4) globalStdGen
+    pure CellModel {info, dotColor, dotSize, dotPhase, dotSpeed}
+  startApp (model cellModels) handleEvent buildUI config
+  where
+    config =
+      [ appWindowTitle "Hagrid Resizing Cells Example",
+        appFontDef "Bold" "./assets/fonts/Cantarell/Cantarell-Bold.ttf",
+        appFontDef "Regular" "./assets/fonts/Cantarell/Cantarell-Regular.ttf",
+        appTheme darkTheme,
+        appDisableAutoScale True,
+        appWindowState (MainWindowNormal (1_200, 1_000)),
+        appInitEvent AppInit
+      ]
+    model cellModels =
+      AppModel {cellModels = S.fromList cellModels}
+    colors =
+      cycle [red, green, blue, yellow]
+    infos =
+      cycle . words $
+        "This demo shows how hagrid behaves when cells are dynamically changing size."
+
+buildUI :: UIBuilder AppModel AppEvent
+buildUI _wenv model = tree
+  where
+    tree =
+      hagrid_
+        [estimatedItemHeight 60]
+        [ widgetColumn "Line Index" (\i _ -> label (pack (show i))),
+          (textColumn "Info" (.info)) {initialWidth = 200},
+          (showOrdColumn "Phase" (.dotPhase)) {initialWidth = 300},
+          (widgetColumn "Dot" dotWidget) {minWidth = 220}
+        ]
+        model.cellModels
+
+handleEvent :: EventHandler AppModel AppEvent sp ep
+handleEvent _wenv _node model = \case
+  AppInit ->
+    [ Producer $ \emit -> do
+        forever $ do
+          emit UpdatePhase
+          threadDelay (1_000_000 `div` 30)
+    ]
+  UpdatePhase ->
+    [Model model {cellModels = updatePhase <$> model.cellModels}]
+    where
+      updatePhase cellModel =
+        cellModel {dotPhase = cellModel.dotPhase + cellModel.dotSpeed}
+
+dotWidget :: Int -> CellModel -> WidgetNode s AppEvent
+dotWidget _idx cellModel = tree
+  where
+    tree =
+      defaultWidgetNode "DotWidget" $
+        createSingle
+          cellModel
+          def
+            { singleGetSizeReq = getSizeReq,
+              singleMerge = merge,
+              singleRender = render
+            }
+
+    size = cellModel.dotSize * abs (sin (fromIntegral cellModel.dotPhase / 100))
+
+    merge _wenv node _oldNode oldState = resultReqs node [resizeReq | needResize]
+      where
+        resizeReq = ResizeWidgets node._wnInfo._wniWidgetId
+        needResize = oldState /= cellModel
+
+    getSizeReq _wenv _node =
+      (fixedSize size, fixedSize size)
+
+    render wenv node renderer =
+      drawEllipse renderer carea {_rW = size, _rH = size} (Just cellModel.dotColor)
+      where
+        style = currentStyle wenv node
+        carea = getContentArea node style
diff --git a/monomer-hagrid.cabal b/monomer-hagrid.cabal
--- a/monomer-hagrid.cabal
+++ b/monomer-hagrid.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.0
 name:               monomer-hagrid
-version:            0.3.1.0
+version:            0.3.1.1
 license:            MIT
 license-file:       LICENSE
 maintainer:         garethdanielsmith@gmail.com
@@ -53,7 +53,7 @@
 
 executable example-basic
     main-is:            Main.hs
-    hs-source-dirs:     example-basic
+    hs-source-dirs:     examples/basic
     other-modules:      Paths_monomer_hagrid
     autogen-modules:    Paths_monomer_hagrid
     default-language:   Haskell2010
@@ -85,7 +85,7 @@
 
 executable example-big-grid
     main-is:            Main.hs
-    hs-source-dirs:     example-big-grid
+    hs-source-dirs:     examples/big-grid
     other-modules:      Paths_monomer_hagrid
     autogen-modules:    Paths_monomer_hagrid
     default-language:   Haskell2010
@@ -116,7 +116,7 @@
 
 executable example-resizing-cells
     main-is:            Main.hs
-    hs-source-dirs:     example-resizing-cells
+    hs-source-dirs:     examples/resizing-cells
     other-modules:      Paths_monomer_hagrid
     autogen-modules:    Paths_monomer_hagrid
     default-language:   Haskell2010
diff --git a/src/Monomer/Hagrid.hs b/src/Monomer/Hagrid.hs
--- a/src/Monomer/Hagrid.hs
+++ b/src/Monomer/Hagrid.hs
@@ -131,7 +131,7 @@
     LabelWidget (Int -> a -> Text)
   | -- | Create a widget of arbitrary type. The function receives the original item
     -- index (i.e. not the index in the sorted list) and the item itself.
-    CustomWidget (forall s. WidgetModel s => Int -> a -> WidgetNode s e)
+    CustomWidget (forall s. (WidgetModel s) => Int -> a -> WidgetNode s e)
 
 -- | How to create the footer widget for a column.
 data ColumnFooterWidget e a
@@ -139,7 +139,7 @@
     NoFooterWidget
   | -- | Create a footer widget. The function receives the items in their current sort
     -- order, and also along with each item it's original (unsorted) index.
-    CustomFooterWidget (forall s. WidgetModel s => Seq (ItemWithIndex a) -> WidgetNode s e)
+    CustomFooterWidget (forall s. (WidgetModel s) => Seq (ItemWithIndex a) -> WidgetNode s e)
 
 -- | How to align the widget within each cell of a column.
 data ColumnAlign
@@ -152,7 +152,7 @@
   = -- | Means that a column can't be sorted.
     DontSort
   | -- | Means that a column can be sorted, using the specified sort key function.
-    forall b. Ord b => SortWith (a -> b)
+    forall b. (Ord b) => SortWith (a -> b)
 
 -- | Whether a column is being sorted in ascending or descending order.
 data SortDirection
@@ -177,7 +177,7 @@
   | OrderByColumn Int
   | ResizeColumn Int Int
   | ResizeColumnFinished Int
-  | forall a. Typeable a => ScrollToRow (ScrollToRowCallback a)
+  | forall a. (Typeable a) => ScrollToRow (ScrollToRowCallback a)
   | ScrollToRect Rect
   | ParentEvent e
 
@@ -242,7 +242,7 @@
   = SetVisibleArea {visibleArea :: Rect}
   | InnerResizeComplete
   | ContentPaneParentEvent e
-  | forall a. Typeable a => ContentPaneScrollToRow (ScrollToRowCallback a)
+  | forall a. (Typeable a) => ContentPaneScrollToRow (ScrollToRowCallback a)
 
 -- | Creates a hagrid widget, using the default configuration.
 hagrid ::
@@ -377,7 +377,7 @@
     color = fromMaybe (rgb 255 255 255) (_sstText style >>= _txsFontColor)
     transColor = color {_colorA = 0.7}
 
-headerPane :: forall e a. WidgetEvent e => [Column e a] -> HagridModel a -> WidgetNode (HagridModel a) (HagridEvent e)
+headerPane :: forall e a. (WidgetEvent e) => [Column e a] -> HagridModel a -> WidgetNode (HagridModel a) (HagridEvent e)
 headerPane columnDefs model = makeNode (initialHeaderFooterState model)
   where
     makeNode :: HeaderFooterState -> WidgetNode (HagridModel a) (HagridEvent e)
@@ -437,7 +437,7 @@
             indL = l + w + state.offsetX - indW - pad
             indRect = Rect indL indT indW indW
 
-headerButton :: WidgetEvent e => Int -> Column e a -> WidgetNode (HagridModel a) (HagridEvent e)
+headerButton :: (WidgetEvent e) => Int -> Column e a -> WidgetNode (HagridModel a) (HagridEvent e)
 headerButton colIndex columnDef =
   button_ columnDef.name (OrderByColumn colIndex) [ellipsis]
     `styleBasic` [radius 0]
@@ -533,7 +533,7 @@
                 node & L.widget .~ makeWidget state {offsetX}
         result = cast msg >>= handleTypedMessage
 
-headerDragHandle :: WidgetEvent e => Int -> Column e a -> ModelColumn -> WidgetNode s (HagridEvent e)
+headerDragHandle :: (WidgetEvent e) => Int -> Column e a -> ModelColumn -> WidgetNode s (HagridEvent e)
 headerDragHandle colIndex columnDef column = tree
   where
     tree = defaultWidgetNode "Hagrid.HeaderDragHandle" (headerDragHandleWidget Nothing)
@@ -757,7 +757,7 @@
             containerResize = resize
           }
 
-    rowWidgets = contentPaneRow columnDefs cpModel <$> cpModel.inflatedItems
+    rowWidgets = S.mapWithIndex (contentPaneRow columnDefs cpModel) cpModel.inflatedItems
 
     merge _wenv newNode _oldNode oldState = resultReqs newNode reqs
       where
@@ -799,9 +799,10 @@
   (CompositeModel a, WidgetEvent e) =>
   Seq (Column e a) ->
   ContentPaneModel a ->
-  (a, Int) ->
+  Int ->
+  ItemWithIndex a ->
   WidgetNode (ContentPaneModel a) (ContentPaneEvent e)
-contentPaneRow columnDefs cpModel (item, rowIdx) = tree
+contentPaneRow columnDefs cpModel sortedIdx item = tree
   where
     tree =
       defaultWidgetNode "Hagrid.Row" widget
@@ -809,7 +810,7 @@
 
     widget =
       createContainer
-        (cpModel.columnWidths, item, rowIdx)
+        (cpModel.columnWidths, item, sortedIdx)
         def
           { containerGetSizeReq = getSizeReq,
             containerResize = resize,
@@ -818,7 +819,7 @@
 
     cellWidgets = do
       Column {widget} <- columnDefs
-      pure (cellWidget rowIdx item widget)
+      pure (cellWidget item widget)
 
     getSizeReq _wenv _node children = (w, h)
       where
@@ -864,7 +865,7 @@
         colXs = scanl (+) 0 (fromIntegral <$> cpModel.columnWidths)
         bgColor
           | mouseover = Just mouseOverColor
-          | rowIdx `mod` 2 == 1 = Just oddRowBgColor
+          | sortedIdx `mod` 2 == 1 = Just oddRowBgColor
           | otherwise = Nothing
         vp = node ^. L.info . L.viewport
         mouseover = pointInRect mouse vp
@@ -1052,11 +1053,10 @@
 
 cellWidget ::
   (CompositeModel a, WidgetEvent e) =>
-  Int ->
-  a ->
+  ItemWithIndex a ->
   ColumnWidget e a ->
   WidgetNode (ContentPaneModel a) (ContentPaneEvent e)
-cellWidget idx item = \case
+cellWidget (item, idx) = \case
   LabelWidget get -> label_ (get idx item) [ellipsis]
   CustomWidget get -> widget
     where
