diff --git a/ui/components/src/ui/components/headless/Items.scala b/ui/components/src/ui/components/headless/Items.scala index aea5ec0..b3c7098 100644 --- a/ui/components/src/ui/components/headless/Items.scala +++ b/ui/components/src/ui/components/headless/Items.scala @@ -19,15 +19,3 @@ Items(frame, b => renderItem(f(b))) def map(f: A => HtmlElement => HtmlElement): Items[A] = Items(frame, a => f(a)(renderItem(a))) - -final case class GroupedItems[Key, A]( - frame: Seq[HtmlElement] => HtmlElement, - renderItems: Key => Items[A] -) extends ItemContainer[A]: - def apply(items: Seq[(Key, Seq[A])]): HtmlElement = frame( - items.map(renderItems(_)(_)) - ) - def contramap[B](f: B => A): GroupedItems[Key, B] = - GroupedItems(frame, k => renderItems(k).contramap(f)) - def map(f: A => HtmlElement => HtmlElement): GroupedItems[Key, A] = - GroupedItems(frame, k => renderItems(k).map(f)) diff --git a/ui/components/src/ui/components/headless/Items.scala b/ui/components/src/ui/components/headless/Items.scala index aea5ec0..b3c7098 100644 --- a/ui/components/src/ui/components/headless/Items.scala +++ b/ui/components/src/ui/components/headless/Items.scala @@ -19,15 +19,3 @@ Items(frame, b => renderItem(f(b))) def map(f: A => HtmlElement => HtmlElement): Items[A] = Items(frame, a => f(a)(renderItem(a))) - -final case class GroupedItems[Key, A]( - frame: Seq[HtmlElement] => HtmlElement, - renderItems: Key => Items[A] -) extends ItemContainer[A]: - def apply(items: Seq[(Key, Seq[A])]): HtmlElement = frame( - items.map(renderItems(_)(_)) - ) - def contramap[B](f: B => A): GroupedItems[Key, B] = - GroupedItems(frame, k => renderItems(k).contramap(f)) - def map(f: A => HtmlElement => HtmlElement): GroupedItems[Key, A] = - GroupedItems(frame, k => renderItems(k).map(f)) diff --git a/ui/components/src/ui/components/tailwind/TailwindSupport.scala b/ui/components/src/ui/components/tailwind/TailwindSupport.scala index a0e281e..3bd7aa7 100644 --- a/ui/components/src/ui/components/tailwind/TailwindSupport.scala +++ b/ui/components/src/ui/components/tailwind/TailwindSupport.scala @@ -41,5 +41,22 @@ "bg-green-50", "bg-amber-50", "bg-red-50", - "bg-yellow-50" + "bg-yellow-50", + "bg-red-600", + "bg-orange-600", + "bg-amber-600", + "bg-yellow-600", + "bg-lime-600", + "bg-green-600", + "bg-emerald-600", + "bg-teal-600", + "bg-cyan-600", + "bg-sky-600", + "bg-blue-600", + "bg-indigo-600", + "bg-violet-600", + "bg-purple-600", + "bg-fuchsia-600", + "bg-pink-600", + "bg-rose-600" ) diff --git a/ui/components/src/ui/components/headless/Items.scala b/ui/components/src/ui/components/headless/Items.scala index aea5ec0..b3c7098 100644 --- a/ui/components/src/ui/components/headless/Items.scala +++ b/ui/components/src/ui/components/headless/Items.scala @@ -19,15 +19,3 @@ Items(frame, b => renderItem(f(b))) def map(f: A => HtmlElement => HtmlElement): Items[A] = Items(frame, a => f(a)(renderItem(a))) - -final case class GroupedItems[Key, A]( - frame: Seq[HtmlElement] => HtmlElement, - renderItems: Key => Items[A] -) extends ItemContainer[A]: - def apply(items: Seq[(Key, Seq[A])]): HtmlElement = frame( - items.map(renderItems(_)(_)) - ) - def contramap[B](f: B => A): GroupedItems[Key, B] = - GroupedItems(frame, k => renderItems(k).contramap(f)) - def map(f: A => HtmlElement => HtmlElement): GroupedItems[Key, A] = - GroupedItems(frame, k => renderItems(k).map(f)) diff --git a/ui/components/src/ui/components/tailwind/TailwindSupport.scala b/ui/components/src/ui/components/tailwind/TailwindSupport.scala index a0e281e..3bd7aa7 100644 --- a/ui/components/src/ui/components/tailwind/TailwindSupport.scala +++ b/ui/components/src/ui/components/tailwind/TailwindSupport.scala @@ -41,5 +41,22 @@ "bg-green-50", "bg-amber-50", "bg-red-50", - "bg-yellow-50" + "bg-yellow-50", + "bg-red-600", + "bg-orange-600", + "bg-amber-600", + "bg-yellow-600", + "bg-lime-600", + "bg-green-600", + "bg-emerald-600", + "bg-teal-600", + "bg-cyan-600", + "bg-sky-600", + "bg-blue-600", + "bg-indigo-600", + "bg-violet-600", + "bg-purple-600", + "bg-fuchsia-600", + "bg-pink-600", + "bg-rose-600" ) diff --git a/ui/components/src/ui/components/tailwind/list/StackedList.scala b/ui/components/src/ui/components/tailwind/list/StackedList.scala index dc673a3..e86a2f5 100644 --- a/ui/components/src/ui/components/tailwind/list/StackedList.scala +++ b/ui/components/src/ui/components/tailwind/list/StackedList.scala @@ -5,7 +5,6 @@ import org.scalajs.dom import com.raquo.laminar.nodes.ReactiveHtmlElement import works.iterative.ui.components.headless.Items -import works.iterative.ui.components.headless.GroupedItems import works.iterative.ui.components.headless.Toggle class StackedList[Item: AsListRow]: diff --git a/ui/components/src/ui/components/headless/Items.scala b/ui/components/src/ui/components/headless/Items.scala index aea5ec0..b3c7098 100644 --- a/ui/components/src/ui/components/headless/Items.scala +++ b/ui/components/src/ui/components/headless/Items.scala @@ -19,15 +19,3 @@ Items(frame, b => renderItem(f(b))) def map(f: A => HtmlElement => HtmlElement): Items[A] = Items(frame, a => f(a)(renderItem(a))) - -final case class GroupedItems[Key, A]( - frame: Seq[HtmlElement] => HtmlElement, - renderItems: Key => Items[A] -) extends ItemContainer[A]: - def apply(items: Seq[(Key, Seq[A])]): HtmlElement = frame( - items.map(renderItems(_)(_)) - ) - def contramap[B](f: B => A): GroupedItems[Key, B] = - GroupedItems(frame, k => renderItems(k).contramap(f)) - def map(f: A => HtmlElement => HtmlElement): GroupedItems[Key, A] = - GroupedItems(frame, k => renderItems(k).map(f)) diff --git a/ui/components/src/ui/components/tailwind/TailwindSupport.scala b/ui/components/src/ui/components/tailwind/TailwindSupport.scala index a0e281e..3bd7aa7 100644 --- a/ui/components/src/ui/components/tailwind/TailwindSupport.scala +++ b/ui/components/src/ui/components/tailwind/TailwindSupport.scala @@ -41,5 +41,22 @@ "bg-green-50", "bg-amber-50", "bg-red-50", - "bg-yellow-50" + "bg-yellow-50", + "bg-red-600", + "bg-orange-600", + "bg-amber-600", + "bg-yellow-600", + "bg-lime-600", + "bg-green-600", + "bg-emerald-600", + "bg-teal-600", + "bg-cyan-600", + "bg-sky-600", + "bg-blue-600", + "bg-indigo-600", + "bg-violet-600", + "bg-purple-600", + "bg-fuchsia-600", + "bg-pink-600", + "bg-rose-600" ) diff --git a/ui/components/src/ui/components/tailwind/list/StackedList.scala b/ui/components/src/ui/components/tailwind/list/StackedList.scala index dc673a3..e86a2f5 100644 --- a/ui/components/src/ui/components/tailwind/list/StackedList.scala +++ b/ui/components/src/ui/components/tailwind/list/StackedList.scala @@ -5,7 +5,6 @@ import org.scalajs.dom import com.raquo.laminar.nodes.ReactiveHtmlElement import works.iterative.ui.components.headless.Items -import works.iterative.ui.components.headless.GroupedItems import works.iterative.ui.components.headless.Toggle class StackedList[Item: AsListRow]: diff --git a/ui/components/src/ui/components/tailwind/lists/grid_lists/SimpleCards.scala b/ui/components/src/ui/components/tailwind/lists/grid_lists/SimpleCards.scala index fcec536..c271fa4 100644 --- a/ui/components/src/ui/components/tailwind/lists/grid_lists/SimpleCards.scala +++ b/ui/components/src/ui/components/tailwind/lists/grid_lists/SimpleCards.scala @@ -4,103 +4,105 @@ import com.raquo.laminar.api.L.{*, given} import works.iterative.ui.components.tailwind.Color import works.iterative.ui.components.tailwind.ColorWeight +import works.iterative.ui.components.headless.Items object SimpleCards: - case class Initials( + case class Item( + initials: HtmlElement, + body: HtmlElement + ) + + def initials( text: String, color: Color, weight: ColorWeight = ColorWeight.w600 - ): - def element: HtmlElement = - div( - cls := "flex items-center justify-center w-16 text-white text-sm font-medium rounded-l-md", - cls(color.bg(weight)), - text - ) - - case class IconButton(icon: SvgElement, screenReaderText: String): - def element: HtmlElement = - button( - tpe := "button", - cls := "w-8 h-8 bg-white inline-flex items-center justify-center text-gray-400 rounded-full bg-transparent hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500", - span(cls := "sr-only", screenReaderText), - icon - ) - - case class CardTitleLink(text: String, link: String): - def element( - clicked: Option[Observer[Unit]] = None, - classes: String = "text-gray-900 font-meduim hover:text-gray-600" - ): HtmlElement = - a( - href(link), - clicked.map(onClick.mapTo(()) --> _), - cls(classes), - text - ) - - case class CardTitle(text: String): - def element( - classes: String = "text-gray-900 font-meduim hover:text-gray-600" - ): HtmlElement = - div(cls(classes), text) - - case class CardBody( - title: HtmlElement, - subtitle: String, - button: Option[Button] - ): - def element: HtmlElement = div( - cls := "flex items-center justify-between border-t border-r border-b border-gray-200 bg-white rounded-r-md truncate", - div( - cls := "flex-1 px-4 py-2 text-sm truncate", - title, - p(cls := "text-gray-500", subtitle) - ), - div(cls := "flex-shrink-0 pr-2", button) + ): HtmlElement = + div( + cls := "flex-shrink-0 flex items-center justify-center w-16 text-white text-sm font-medium rounded-l-md", + cls(color.toCSSWithColorWeight("bg", weight)), + text ) - case class Card(initials: Initials, body: CardBody): - def element: HtmlElement = - div( - cls := "col-span-1 flex shadow-sm rounded-md", - initials.element.amend(cls("flex-shrink-0")), - body.element.amend(cls("flex-1")) - ) + def iconButton(icon: SvgElement, screenReaderText: String): Button = + button( + tpe := "button", + cls := "w-8 h-8 bg-white inline-flex items-center justify-center text-gray-400 rounded-full bg-transparent hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500", + span(cls := "sr-only", screenReaderText), + icon + ) - case class LinkCard( - initials: Initials, - body: CardBody, - link: String - ): - def element(clicked: Observer[Unit]): HtmlElement = element(Some(clicked)) - def element(clicked: Option[Observer[Unit]] = None): HtmlElement = - a( - cls("block"), - href(link), - clicked.map(onClick.mapTo(()) --> _), - Card(initials, body).element - ) + def titleLink( + clicked: Option[Observer[Unit]] = None, + classes: String = "text-gray-900 font-meduim hover:text-gray-600 truncate" + )(text: String, link: String): HtmlElement = + a( + href(link), + clicked.map(onClick.mapTo(()) --> _), + cls(classes), + text + ) - case class ListHeader(text: String): - def element( - classes: String = - "text-gray-500 text-xs font-medium uppercase tracking-wide" - ): HtmlElement = h2(cls(classes), text) + def title( + classes: String = "text-gray-900 font-meduim hover:text-gray-600 truncate" + )(text: String): HtmlElement = + div(cls(classes), text) - case class SimpleList(header: Option[HtmlElement], cards: Seq[HtmlElement]): - def element( - gap: String = "gap-5 sm:gap-6", - cols: String = "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4" - ): HtmlElement = - div( - header, - ul( - role := "list", - cls := "mt-3 grid", - cls(gap), - cls(cols), - cards.map(li(_)) + def body( + title: HtmlElement, + subtitle: String, + button: Option[Button] = None + ): HtmlElement = div( + cls := "flex-1 flex items-center justify-between border-t border-r border-b border-gray-200 bg-white rounded-r-md truncate", + div( + cls := "flex-1 px-4 py-2 text-sm truncate", + title, + p(cls := "text-gray-500", subtitle) + ), + div(cls := "flex-shrink-0 pr-2", button) + ) + + private def item(i: Item): HtmlElement = + div( + cls := "col-span-1 flex shadow-sm rounded-md", + i.initials, + i.body + ) + + def header( + text: String, + classes: String = + "text-gray-500 text-xs font-medium uppercase tracking-wide" + )(content: HtmlElement): HtmlElement = div(h2(cls(classes), text), content) + + def frame( + gap: String = "gap-5 sm:gap-6", + cols: String = "grid-cols-1 sm:grid-cols-2 lg:grid-cols-4" + )(items: Seq[HtmlElement]): HtmlElement = + ul( + role := "list", + cls := "mt-3 grid", + cls(gap), + cls(cols), + items + ) + + def apply[A](f: A => Item): Items[A] = + Items(frame(), item).contramap(f) + + case class LinkProps(href: String, events: Option[Observer[Unit]] = None) + + def linked[A](l: A => LinkProps)( + f: A => Item + ): Items[A] = + apply(f).map(i => + card => { + val lp = l(i) + a( + cls("block"), + href(lp.href), + lp.events.map(onClick.preventDefault.mapTo(()) --> _), + card ) - ) + } + )