diff --git a/Text/Reform/HSP/Common.hs b/Text/Reform/HSP/Common.hs
--- a/Text/Reform/HSP/Common.hs
+++ b/Text/Reform/HSP/Common.hs
@@ -2,6 +2,8 @@
 {-# OPTIONS_GHC -F -pgmFhsx2hs #-}
 module Text.Reform.HSP.Common where
 
+import Data.List      (intercalate)
+import Data.Monoid    ((<>), mconcat)
 import Data.Text.Lazy (Text, pack)
 import qualified Data.Text as T
 import Text.Reform.Backend
@@ -161,6 +163,55 @@
              [ <input type="radio" id=i name=nm value=(pack $ show val) (if checked then [("checked" := "checked") :: Attr Text Text] else []) />
              , <label for=i><% lbl %></label>
              , <br />
+             ]
+
+inputRadioForms :: forall m x error input lbl proof a. (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, XMLGenerator x, StringType x ~ Text, EmbedAsChild x lbl, EmbedAsAttr x (Attr Text FormId)) =>
+                   [(Form m input error [XMLGenT x (XMLType x)] proof a, lbl)]  -- ^ value, label, initially checked
+                 -> a -- ^ default
+                 -> Form m input error [XMLGenT x (XMLType x)] proof a
+inputRadioForms choices def =
+    inputRadioForms' onclick choices def
+    where
+      formIdsJS :: [FormId] -> Text
+      formIdsJS [] = "[]"
+      formIdsJS ids =
+          "['" <> (pack $ intercalate "', '" $ map show ids) <> "']"
+
+      onclick :: FormId -> FormId -> [FormId] -> Text
+      onclick nm iview iviews = mconcat
+                [ "var views = " <> formIdsJS iviews <> ";"
+                , "var iview = '" <> (pack $ show iview) <> "';"
+                , "for (var i = 0; i < views.length; i++) {"
+                , "  if (iview == views[i]) {"
+                , "    document.getElementById(iview).style.display='block';"
+                , "  } else {"
+                , "    document.getElementById(views[i]).style.display='none';"
+                , "  }"
+                , "}"
+                ]
+
+inputRadioForms' :: forall m x error input lbl proof a. (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, XMLGenerator x, StringType x ~ Text, EmbedAsChild x lbl, EmbedAsAttr x (Attr Text FormId)) =>
+                    (FormId -> FormId -> [FormId] -> Text)
+                 -> [(Form m input error [XMLGenT x (XMLType x)] proof a, lbl)]  -- ^ value, label, initially checked
+                 -> a -- ^ default
+                 -> Form m input error [XMLGenT x (XMLType x)] proof a
+inputRadioForms' onclick choices def =
+    G.inputChoiceForms def choices mkRadios
+    where
+      iviewsExtract :: [(FormId, Int, FormId, [XMLGenT x (XMLType x)], lbl, Bool)] -> [FormId]
+      iviewsExtract = map (\(_,_, iv, _, _, _) -> iv)
+
+      mkRadios :: FormId -> [(FormId, Int, FormId, [XMLGenT x (XMLType x)], lbl, Bool)] -> [XMLGenT x (XMLType x)]
+      mkRadios nm choices' =
+          let iviews = iviewsExtract choices' in
+          (concatMap (mkRadio nm iviews) choices')
+
+      mkRadio nm iviews (i, val, iview, view, lbl, checked) =
+             [ <div>
+                <input type="radio" onclick=(onclick nm iview iviews) id=i name=nm value=(pack $ show val) (if checked then [("checked" := "checked") :: Attr Text Text] else []) />
+               <label for=i><% lbl %></label>
+               <div id=iview (if checked then [] else [("style" := "display:none;") :: Attr Text Text])><% view %></div>
+              </div>
              ]
 
 select :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, XMLGenerator x, StringType x ~ Text, EmbedAsChild x lbl, EmbedAsAttr x (Attr Text FormId)) =>
diff --git a/Text/Reform/HSP/String.hs b/Text/Reform/HSP/String.hs
--- a/Text/Reform/HSP/String.hs
+++ b/Text/Reform/HSP/String.hs
@@ -16,6 +16,7 @@
     , inputCheckbox
     , inputCheckboxes
     , inputRadio
+    , inputRadioForms
     , inputFile
       -- * \<textarea\> element
     , textarea
@@ -136,6 +137,13 @@
            -> (a -> Bool) -- ^ predicate which returns @True@ if @a@ should be initially checked. Must match exactly one value in the previous argument.
            -> Form m input error [XMLGenT x (XMLType x)] () a
 inputRadio = C.inputRadio
+
+-- | Create a group of radio buttons that select between sub-forms
+inputRadioForms :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, XMLGenerator x, StringType x ~ Text, EmbedAsChild x lbl, EmbedAsAttr x (Attr Text FormId)) =>
+              [(Form m input error [XMLGenT x (XMLType x)] proof a, lbl)]  -- ^ value, label, initially checked
+           -> a -- ^ default
+           -> Form m input error [XMLGenT x (XMLType x)] proof a
+inputRadioForms = C.inputRadioForms
 
 -- | Create an @\<input type=\"file\"\>@ element
 --
diff --git a/Text/Reform/HSP/Text.hs b/Text/Reform/HSP/Text.hs
--- a/Text/Reform/HSP/Text.hs
+++ b/Text/Reform/HSP/Text.hs
@@ -15,6 +15,7 @@
     , inputCheckbox
     , inputCheckboxes
     , inputRadio
+    , inputRadioForms
     , inputFile
       -- * \<textarea\> element
     , textarea
@@ -138,6 +139,13 @@
            -> (a -> Bool) -- ^ predicate which returns @True@ if @a@ should be initially checked. Must match exactly one value in the previous argument.
            -> Form m input error [XMLGenT x (XMLType x)] () a
 inputRadio = C.inputRadio
+
+-- | Create a group of radio buttons that select between sub-forms
+inputRadioForms :: (Functor m, Monad m, FormError error, ErrorInputType error ~ input, FormInput input, XMLGenerator x, StringType x ~ Text, EmbedAsChild x lbl, EmbedAsAttr x (Attr Text FormId)) =>
+              [(Form m input error [XMLGenT x (XMLType x)] proof a, lbl)]  -- ^ value, label, initially checked
+           -> a -- ^ default
+           -> Form m input error [XMLGenT x (XMLType x)] proof a
+inputRadioForms = C.inputRadioForms
 
 -- | Create an @\<input type=\"file\"\>@ element
 --
diff --git a/reform-hsp.cabal b/reform-hsp.cabal
--- a/reform-hsp.cabal
+++ b/reform-hsp.cabal
@@ -1,5 +1,5 @@
 Name:                reform-hsp
-Version:             0.2.0
+Version:             0.2.1
 Synopsis:            Add support for using HSP with Reform
 Description:         Reform is a library for building and validating forms using applicative functors. This package add support for using reform with HSP.
 Homepage:            http://www.happstack.com/
@@ -21,7 +21,7 @@
   Exposed-modules:     Text.Reform.HSP.Common
                        Text.Reform.HSP.String
                        Text.Reform.HSP.Text
-  Build-depends:       base > 4 && <5,
-                       hsp    == 0.9.*,
+  Build-depends:       base   > 4    && <5,
+                       hsp    >= 0.9 && < 0.11,
                        reform == 0.2.*,
                        text   == 0.11.*
