diff --git a/stdlib/source/library/lux/web/html/attribute/type/button.lux b/stdlib/source/library/lux/web/html/attribute/type/button.lux
new file mode 100644
index 0000000000..f308ff2669
--- /dev/null
+++ b/stdlib/source/library/lux/web/html/attribute/type/button.lux
@@ -0,0 +1,23 @@
+... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+(.require
+ [library
+ [lux (.except Type)
+ [meta
+ [macro
+ ["[0]" template]]]]])
+
+... https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#attributes
+(every .public Type
+ Text)
+
+(with_template []
+ [(the .public
+ Type
+ (template.text []))]
+
+ [submit]
+ [reset]
+ [button]
+ )
diff --git a/stdlib/source/library/lux/web/html/attribute/type/input.lux b/stdlib/source/library/lux/web/html/attribute/type/input.lux
new file mode 100644
index 0000000000..54226aee72
--- /dev/null
+++ b/stdlib/source/library/lux/web/html/attribute/type/input.lux
@@ -0,0 +1,47 @@
+... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+(.require
+ [library
+ [lux (.except Type)
+ [data
+ ["[0]" text]]
+ [meta
+ [macro
+ ["[0]" template]]]]])
+
+... https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#input_types
+(every .public Type
+ Text)
+
+(with_template []
+ [(the .public
+ Type
+ (|> (template.text [])
+ (text.replaced "local_date_time" "datetime-local")
+ (text.replaced "telephone" "tel")
+ (text.replaced "_" "")))]
+
+ [button]
+ [check_box]
+ [color]
+ [date]
+ [local_date_time]
+ [email]
+ [file]
+ [hidden]
+ [image]
+ [month]
+ [number]
+ [password]
+ [radio]
+ [range]
+ [reset]
+ [search]
+ [submit]
+ [telephone]
+ [text]
+ [time]
+ [url]
+ [week]
+ )
diff --git a/stdlib/source/test/lux/web/html/attribute/type/button.lux b/stdlib/source/test/lux/web/html/attribute/type/button.lux
new file mode 100644
index 0000000000..35c31b9ffb
--- /dev/null
+++ b/stdlib/source/test/lux/web/html/attribute/type/button.lux
@@ -0,0 +1,43 @@
+... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+(.require
+ [library
+ [lux (.except)
+ [abstract
+ [monad (.only do)]]
+ [data
+ ["[0]" text]
+ [collection
+ ["[0]" list]
+ ["[0]" set]]]
+ [math
+ ["[0]" random (.only Random)]
+ [number
+ ["n" nat]]]
+ [test
+ ["_" property (.only Test)]]]]
+ [\\library
+ ["[0]" /]])
+
+(with_expansions [ (with_template []
+ []
+
+ [/.submit]
+ [/.reset]
+ [/.button]
+ )]
+ (the .public test
+ Test
+ (<| (_.covering /._)
+ (do [! random.monad]
+ [])
+ (_.for [/.Type])
+ (all _.and
+ (_.coverage []
+ (let [all (is (List /.Type)
+ (list ))
+ uniques (set.of_list text.hash all)]
+ (n.= (list.size all)
+ (set.size uniques))))
+ ))))
diff --git a/stdlib/source/test/lux/web/html/attribute/type/input.lux b/stdlib/source/test/lux/web/html/attribute/type/input.lux
new file mode 100644
index 0000000000..27770f9d1a
--- /dev/null
+++ b/stdlib/source/test/lux/web/html/attribute/type/input.lux
@@ -0,0 +1,62 @@
+... This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+... If a copy of the MPL was not distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
+
+(.require
+ [library
+ [lux (.except)
+ [abstract
+ [monad (.only do)]]
+ [data
+ ["[0]" text]
+ [collection
+ ["[0]" list]
+ ["[0]" set]]]
+ [math
+ ["[0]" random (.only Random)]
+ [number
+ ["n" nat]]]
+ [test
+ ["_" property (.only Test)]]]]
+ [\\library
+ ["[0]" /]])
+
+(with_expansions [ (with_template []
+ []
+
+ [/.button]
+ [/.check_box]
+ [/.color]
+ [/.date]
+ [/.local_date_time]
+ [/.email]
+ [/.file]
+ [/.hidden]
+ [/.image]
+ [/.month]
+ [/.number]
+ [/.password]
+ [/.radio]
+ [/.range]
+ [/.reset]
+ [/.search]
+ [/.submit]
+ [/.telephone]
+ [/.text]
+ [/.time]
+ [/.url]
+ [/.week]
+ )]
+ (the .public test
+ Test
+ (<| (_.covering /._)
+ (do [! random.monad]
+ [])
+ (_.for [/.Type])
+ (all _.and
+ (_.coverage []
+ (let [all (is (List /.Type)
+ (list ))
+ uniques (set.of_list text.hash all)]
+ (n.= (list.size all)
+ (set.size uniques))))
+ ))))