diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,28 @@
 Brick changelog
 ---------------
 
+0.34
+----
+
+API changes:
+ * Core: vLimit and hLimit now *bound* sizes rather than setting them.
+   This was the original intention of these combinators. The change in
+   behavior means that now `vLimit N` means that *at most* `N` rows will
+   be available; if the context has less, then the smaller constraint in
+   the context is used instead. Programs affected by this behavior will
+   be those that assume that `vLimit` doesn't do this, but that should
+   be very few or zero.
+
+Other changes:
+ * Dialog: now arrow keys no longer wrap around available buttons but
+   stop at rightmost or leftmost button to avoid confusion when
+   attempting to tell which button is selected in two-button dialogs
+   (thanks to Karl Ostmo for this change)
+
+Documentation changes:
+ * Updated Haddocks for str/txt in Core to mention tab character
+   considerations
+
 0.33
 ----
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -66,6 +66,7 @@
  * `herms`, a command-line tool for managing kitchen recipes: https://github.com/jackkiefer/herms
  * `purebred`, a mail user agent: https://github.com/purebred-mua/purebred
  * `2048Haskell`, an implementation of the 2048 game: https://github.com/8Gitbrix/2048Haskell
+ * `bhoogle`, a [Hoogle](https://www.haskell.org/hoogle/) client: https://github.com/andrevdm/bhoogle
 
 Getting Started
 ---------------
diff --git a/brick.cabal b/brick.cabal
--- a/brick.cabal
+++ b/brick.cabal
@@ -1,5 +1,5 @@
 name:                brick
-version:             0.33
+version:             0.34
 synopsis:            A declarative terminal user interface library
 description:
   Write terminal applications painlessly with 'brick'! You write an
diff --git a/src/Brick/Widgets/Core.hs b/src/Brick/Widgets/Core.hs
--- a/src/Brick/Widgets/Core.hs
+++ b/src/Brick/Widgets/Core.hs
@@ -244,6 +244,11 @@
 
 -- | Build a widget from a 'String'. Breaks newlines up and space-pads
 -- short lines out to the length of the longest line.
+--
+-- The input string must not contain tab characters. If it does,
+-- interface corruption will result since the terminal will likely
+-- render it as taking up more than a single column. The caller should
+-- replace tabs with the appropriate number of spaces as desired.
 str :: String -> Widget n
 str s =
     Widget Fixed Fixed $ do
@@ -264,6 +269,11 @@
 
 -- | Build a widget from a 'T.Text' value. Behaves the same as 'str'
 -- when the input contains multiple lines.
+--
+-- The input string must not contain tab characters. If it does,
+-- interface corruption will result since the terminal will likely
+-- render it as taking up more than a single column. The caller should
+-- replace tabs with the appropriate number of spaces as desired.
 txt :: T.Text -> Widget n
 txt = str . T.unpack
 
@@ -555,7 +565,7 @@
 hLimit :: Int -> Widget n -> Widget n
 hLimit w p =
     Widget Fixed (vSize p) $
-      withReaderT (& availWidthL .~ w) $ render $ cropToContext p
+      withReaderT (& availWidthL %~ (min w)) $ render $ cropToContext p
 
 -- | Limit the space available to the specified widget to the specified
 -- number of rows. This is important for constraining the vertical
@@ -564,7 +574,7 @@
 vLimit :: Int -> Widget n -> Widget n
 vLimit h p =
     Widget (hSize p) Fixed $
-      withReaderT (& availHeightL .~ h) $ render $ cropToContext p
+      withReaderT (& availHeightL %~ (min h)) $ render $ cropToContext p
 
 -- | Set the rendering context height and width for this widget. This
 -- is useful for relaxing the rendering size constraints on e.g. layer
diff --git a/src/Brick/Widgets/Dialog.hs b/src/Brick/Widgets/Dialog.hs
--- a/src/Brick/Widgets/Dialog.hs
+++ b/src/Brick/Widgets/Dialog.hs
@@ -76,10 +76,10 @@
 handleDialogEvent :: Event -> Dialog a -> EventM n (Dialog a)
 handleDialogEvent ev d =
     return $ case ev of
-        EvKey (KChar '\t') [] -> nextButtonBy 1 d
-        EvKey KBackTab [] -> nextButtonBy (-1) d
-        EvKey KRight [] -> nextButtonBy 1 d
-        EvKey KLeft [] -> nextButtonBy (-1) d
+        EvKey (KChar '\t') [] -> nextButtonBy 1 True d
+        EvKey KBackTab [] -> nextButtonBy (-1) True d
+        EvKey KRight [] -> nextButtonBy 1 False d
+        EvKey KLeft [] -> nextButtonBy (-1) False d
         _ -> d
 
 -- | Create a dialog.
@@ -133,13 +133,18 @@
             , hCenter buttons
             ]
 
-nextButtonBy :: Int -> Dialog a -> Dialog a
-nextButtonBy amt d =
+nextButtonBy :: Int -> Bool -> Dialog a -> Dialog a
+nextButtonBy amt wrapCycle d =
     let numButtons = length $ d^.dialogButtonsL
     in if numButtons == 0 then d
        else case d^.dialogSelectedIndexL of
            Nothing -> d & dialogSelectedIndexL .~ (Just 0)
-           Just i -> d & dialogSelectedIndexL .~ (Just $ (i + amt) `mod` numButtons)
+           Just i -> d & dialogSelectedIndexL .~ (Just newIndex)
+               where
+                   addedIndex = i + amt
+                   newIndex = if wrapCycle
+                              then addedIndex `mod` numButtons
+                              else max 0 $ min addedIndex $ numButtons - 1
 
 -- | Obtain the value associated with the dialog's currently-selected
 -- button, if any. This function is probably what you want when someone
