diff --git a/lib/ui/input_widgets_test.go b/lib/ui/input_widgets_test.go
index bc458fbc..6f30a87d 100644
--- a/lib/ui/input_widgets_test.go
+++ b/lib/ui/input_widgets_test.go
@@ -179,6 +179,16 @@ func TestInputFloatWidgets(t *testing.T) {
mustMatch(t, `^$`, got)
}
+// TestRangeRendersExplicitBounds guards the documented workaround for the browser
+// range defaults: min, max and step passed as params render verbatim after the
+// value, letting a caller widen a domain the default 0..100 would otherwise clamp.
+func TestRangeRendersExplicitBounds(t *testing.T) {
+ _, rq := newCoreRequest(t)
+ sf := newTestSetter(150.0)
+ _, got := renderUI(t, rq, NewRange(sf), `min="0"`, `max="200"`, `step="0.5"`)
+ mustMatch(t, `^$`, got)
+}
+
// TestInputFloat_ReconcilesConvertedValues verifies that number and range inputs
// receive the canonical server value when a numeric adapter truncates or rounds
// an input to the value that was already stored.
diff --git a/lib/ui/range.go b/lib/ui/range.go
index ab728014..753163f8 100644
--- a/lib/ui/range.go
+++ b/lib/ui/range.go
@@ -19,6 +19,13 @@ type Range struct{ InputFloat }
// rendering or wire representation, so rendering, updating, or receiving one from
// the browser cancels the [jaws.Request] with a cause wrapping
// [jaws.ErrValueNotFinite].
+//
+// The widget emits no min, max, or step attribute of its own, so the browser
+// applies the HTML range defaults min="0", max="100", step="1". A bound value
+// outside that domain, or off the step grid, is silently clamped and rounded by
+// the browser, and the adjusted value is echoed back through the setter on the
+// next input event. Supply explicit min, max, and step attributes as render
+// params when the defaults do not cover the bound value's domain.
func NewRange(g bind.Setter[float64]) *Range { return &Range{InputFloat{Setter: g}} }
// JawsRender renders ui as an HTML range input.
@@ -28,7 +35,13 @@ func (u *Range) JawsRender(elem *jaws.Element, w io.Writer, params []any) error
// Range renders an HTML range input.
//
-// See [NewRange] for how a non-finite bound value is handled.
+// Supply min, max, and step attributes in params when the browser defaults
+// (min="0", max="100", step="1") do not cover the bound value's domain; a value
+// outside it is silently clamped and rounded by the browser. For example:
+//
+// rw.Range(&v, `min="0"`, `max="200"`, `step="0.5"`)
+//
+// See [NewRange] for details and for how a non-finite bound value is handled.
func (rw RequestWriter) Range(value any, params ...any) error {
return rw.NewUI(NewRange(bind.MakeSetterFloat64(value)), params...)
}