diff --git a/NAMESPACE b/NAMESPACE
index 30d3736e..f65fd458 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -3,6 +3,7 @@
S3method(tinyplot,default)
S3method(tinyplot,density)
S3method(tinyplot,formula)
+S3method(tinyplot,ts)
export(draw_legend)
export(get_saved_par)
export(plt)
@@ -122,6 +123,7 @@ importFrom(stats,quantile)
importFrom(stats,setNames)
importFrom(stats,spline)
importFrom(stats,terms)
+importFrom(stats,time)
importFrom(stats,weighted.mean)
importFrom(tools,file_ext)
importFrom(utils,globalVariables)
diff --git a/NEWS.md b/NEWS.md
index 49a7d229..c173597c 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -6,6 +6,13 @@ where the formatting is also better._
## Development version
+### New features
+
+- New dedicated `tinyplot()` method for `ts` time series. Internally, this sets
+ up a long data frame with columns `Time`, `Value`, and `Series` and then calls
+ the formula method with different possible specifications for the `by` and `facet`
+ variables. (#558 @zeileis)
+
### Aesthetic changes
- The legend plot characters for the `"pointrange"` and `"errorbar"` types now
diff --git a/R/tinyplot.ts.R b/R/tinyplot.ts.R
new file mode 100644
index 00000000..7576049a
--- /dev/null
+++ b/R/tinyplot.ts.R
@@ -0,0 +1,70 @@
+#' tinyplot Method for Plotting ts Objects (Time Series)
+#'
+#' @description Convenience interface for visualizing ts objects
+#' (time sereis with tinyplot.
+#'
+#' @details Internally the time series object is converted to a long
+#' data frame with columns `Time` (time index), `Value` (observations),
+#' and `Series` (factor with column labels). Depending on the settings
+#' of `facet` this data frame is visualized either with the formula
+#' `Value ~ Time` or `Value ~ Time | Series`. See the `facet` argument
+#' description for more details and the examples for some illustrations.
+#'
+#' @param x an object of class `"ts"`.
+#' @param facet specification of `facet` for `tinyplot.formula`. The
+#' default in the `tinyplot` method is to use `facet = NULL` for univariate
+#' series and `facet = ~ Series` (equivalent to `facet = "by"`) for multivariate series.
+#' @param type,facet.args,ylab,... further arguments passed to `tinyplot`.
+#'
+#' @examples
+#' tinytheme("clean2")
+#'
+#' ## univariate series
+#' tinyplot(Nile)
+#'
+#' ## multivariate
+#' tinyplot(EuStockMarkets) ## multiple, same color, free scales
+#' tinyplot(EuStockMarkets, facet.args = NULL) ## multiple, same color, same scale
+#' tinyplot(EuStockMarkets, facet = "by") ## multiple, separate colors, free scales
+#' tinyplot(EuStockMarkets, facet = NULL) ## single, separate colors
+#'
+#' ## further variations
+#' tinyplot(EuStockMarkets, facet = "by", facet.args = NULL)
+#' tinyplot(EuStockMarkets, facet.args = list(free = TRUE, ncol = 1))
+#'
+#' tinytheme() ## reset
+#'
+#' @importFrom stats time
+#' @export
+tinyplot.ts = function(x, facet, type = "l", facet.args = list(free = TRUE), ylab = "", ...) {
+ ## basic object properties
+ n = NROW(x)
+ k = NCOL(x)
+ lab = deparse(substitute(x))
+ if (k > 1L) lab = paste(lab, 1L:k, sep = ".")
+ if (!is.null(colnames(x))) lab = colnames(x)
+
+ ## convert to long data.frame
+ df = data.frame(
+ Time = rep.int(as.numeric(time(x)), k),
+ Value = as.numeric(x),
+ Series = factor(rep(1L:k, each = n), labels = lab)
+ )
+
+ ## default for facet
+ single = k == 1L
+ if(missing(facet)) {
+ auto = TRUE
+ facet = if(single) NULL else ~ Series
+ } else {
+ auto = FALSE
+ }
+ if (is.null(facet)) facet.args = NULL
+
+ ## call tinyplot
+ if(single | (!is.null(facet) & auto)) {
+ tinyplot(Value ~ Time, data = df, facet = facet, facet.args = facet.args, type = type, ylab = ylab, ...)
+ } else {
+ tinyplot(Value ~ Time | Series, data = df, facet = facet, facet.args = facet.args, type = type, ylab = ylab, ...)
+ }
+}
diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-by-free.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-by-free.svg
new file mode 100644
index 00000000..7f761062
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/ts-multivariate-by-free.svg
@@ -0,0 +1,260 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-by-same.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-by-same.svg
new file mode 100644
index 00000000..25240471
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/ts-multivariate-by-same.svg
@@ -0,0 +1,242 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-column.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-column.svg
new file mode 100644
index 00000000..87b988f3
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/ts-multivariate-column.svg
@@ -0,0 +1,228 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-free.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-free.svg
new file mode 100644
index 00000000..88b7b622
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/ts-multivariate-free.svg
@@ -0,0 +1,242 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-same.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-same.svg
new file mode 100644
index 00000000..b70592c3
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/ts-multivariate-same.svg
@@ -0,0 +1,224 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/ts-multivariate-single.svg b/inst/tinytest/_tinysnapshot/ts-multivariate-single.svg
new file mode 100644
index 00000000..6bc4d24c
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/ts-multivariate-single.svg
@@ -0,0 +1,87 @@
+
+
diff --git a/inst/tinytest/_tinysnapshot/ts-univariate.svg b/inst/tinytest/_tinysnapshot/ts-univariate.svg
new file mode 100644
index 00000000..1266463e
--- /dev/null
+++ b/inst/tinytest/_tinysnapshot/ts-univariate.svg
@@ -0,0 +1,65 @@
+
+
diff --git a/inst/tinytest/test-ts.R b/inst/tinytest/test-ts.R
new file mode 100644
index 00000000..39943745
--- /dev/null
+++ b/inst/tinytest/test-ts.R
@@ -0,0 +1,48 @@
+source("helpers.R")
+using("tinysnapshot")
+
+## five random walks
+set.seed(0)
+x = c(0, rnorm(100)) |>
+ cumsum() |>
+ replicate(n = 5) |>
+ ts(start = 0)
+
+## univariate
+
+f = function() {
+ tinyplot(x[, 1])
+}
+expect_snapshot_plot(f, label = "ts-univariate")
+
+## multivariate
+
+f = function() {
+ tinyplot(x)
+}
+expect_snapshot_plot(f, label = "ts-multivariate-free")
+
+f = function() {
+ tinyplot(x, facet.args = NULL)
+}
+expect_snapshot_plot(f, label = "ts-multivariate-same")
+
+f = function() {
+ tinyplot(x, facet = "by")
+}
+expect_snapshot_plot(f, label = "ts-multivariate-by-free")
+
+f = function() {
+ tinyplot(x, facet = "by", facet.args = NULL)
+}
+expect_snapshot_plot(f, label = "ts-multivariate-by-same")
+
+f = function() {
+ tinyplot(x, facet = NULL)
+}
+expect_snapshot_plot(f, label = "ts-multivariate-single")
+
+f = function() {
+ tinyplot(x, facet.args = list(free = TRUE, ncol = 1))
+}
+expect_snapshot_plot(f, label = "ts-multivariate-column")
diff --git a/man/tinyplot.ts.Rd b/man/tinyplot.ts.Rd
new file mode 100644
index 00000000..752897f8
--- /dev/null
+++ b/man/tinyplot.ts.Rd
@@ -0,0 +1,48 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/tinyplot.ts.R
+\name{tinyplot.ts}
+\alias{tinyplot.ts}
+\title{tinyplot Method for Plotting ts Objects (Time Series)}
+\usage{
+\method{tinyplot}{ts}(x, facet, type = "l", facet.args = list(free = TRUE), ylab = "", ...)
+}
+\arguments{
+\item{x}{an object of class \code{"ts"}.}
+
+\item{facet}{specification of \code{facet} for \code{tinyplot.formula}. The
+default in the \code{tinyplot} method is to use \code{facet = NULL} for univariate
+series and \code{facet = ~ Series} (equivalent to \code{facet = "by"}) for multivariate series.}
+
+\item{type, facet.args, ylab, ...}{further arguments passed to \code{tinyplot}.}
+}
+\description{
+Convenience interface for visualizing ts objects
+(time sereis with tinyplot.
+}
+\details{
+Internally the time series object is converted to a long
+data frame with columns \code{Time} (time index), \code{Value} (observations),
+and \code{Series} (factor with column labels). Depending on the settings
+of \code{facet} this data frame is visualized either with the formula
+\code{Value ~ Time} or \code{Value ~ Time | Series}. See the \code{facet} argument
+description for more details and the examples for some illustrations.
+}
+\examples{
+tinytheme("clean2")
+
+## univariate series
+tinyplot(Nile)
+
+## multivariate
+tinyplot(EuStockMarkets) ## multiple, same color, free scales
+tinyplot(EuStockMarkets, facet.args = NULL) ## multiple, same color, same scale
+tinyplot(EuStockMarkets, facet = "by") ## multiple, separate colors, free scales
+tinyplot(EuStockMarkets, facet = NULL) ## single, separate colors
+
+## further variations
+tinyplot(EuStockMarkets, facet = "by", facet.args = NULL)
+tinyplot(EuStockMarkets, facet.args = list(free = TRUE, ncol = 1))
+
+tinytheme() ## reset
+
+}