pure-extras: example, publish(M2)Local/compileAll. default tip
authorTomas Zeman <tomas@functionals.cz>
Sun, 27 Dec 2020 22:54:33 +0100
changeset 28 fe846f058e41
parent 27 f30a3e465836
pure-extras: example, publish(M2)Local/compileAll.
build.sc
example/src/example/ExampleApp.scala
example/src/extras.scalatex
extras/shared/src/main/scala/purecss/Extras.scala
--- a/build.sc	Sat Dec 26 21:46:29 2020 +0100
+++ b/build.sc	Sun Dec 27 22:54:33 2020 +0100
@@ -8,6 +8,7 @@
  * ./mill mill.scalalib.GenIdea/idea
  *
  */
+import ammonite.ops
 import mill._
 import mill.api.Loose
 import mill.define.{Command, Input, Sources, Target}
@@ -28,8 +29,24 @@
 object D {
   val scalatags211 = ivy"com.lihaoyi::scalatags::0.6.8"
   val scalatags = ivy"com.lihaoyi::scalatags::${V.scalatags}"
+  val scalatex = ivy"org.openmole::scalatex-api:0.4.6"
+  val oslib = ivy"com.lihaoyi::os-lib::0.7.1"
 }
 
+val compilerOptions = Seq(
+    "-deprecation",                      // Emit warning and location for usages of deprecated APIs.
+    "-encoding", "utf-8",                // Specify character encoding used by source files.
+    "-explaintypes",                     // Explain type errors in more detail.
+    "-feature",                          // Emit warning and location for usages of features that should be imported explicitly.
+    "-language:higherKinds",             // Allow higher-kinded types
+    "-language:implicitConversions",     // Allow definition of implicit functions called views
+    "-language:reflectiveCalls",
+    "-language:postfixOps",
+    "-unchecked",                        // Enable additional warnings where generated code depends on assumptions.
+    "-Xcheckinit",                       // Wrap field accessors to throw an exception on uninitialized access.
+    "-target:jvm-1.8"
+  )
+
 trait Common extends CrossSbtModule with PublishModule {
 
   def pomSettings: T[PomSettings] = PomSettings(
@@ -46,19 +63,7 @@
 
   override def artifactName = "purecss" 
 
-  override def scalacOptions = T{Seq(
-    "-deprecation",                      // Emit warning and location for usages of deprecated APIs.
-    "-encoding", "utf-8",                // Specify character encoding used by source files.
-    "-explaintypes",                     // Explain type errors in more detail.
-    "-feature",                          // Emit warning and location for usages of features that should be imported explicitly.
-    "-language:higherKinds",             // Allow higher-kinded types
-    "-language:implicitConversions",     // Allow definition of implicit functions called views
-    "-language:reflectiveCalls",
-    "-language:postfixOps",
-    "-unchecked",                        // Enable additional warnings where generated code depends on assumptions.
-    "-Xcheckinit",                       // Wrap field accessors to throw an exception on uninitialized access.
-    "-target:jvm-1.8"
-  )}
+  override def scalacOptions = T{compilerOptions}
 
   def hgId: Input[String] = T.input {
     os.proc("hg", "id", "-i").call().out.text.trim
@@ -106,6 +111,35 @@
   V.scala213 -> V.scalaJs
 )
 
+object extras extends Module {
+
+  val name = "pure-extras"
+
+  class JvmModule(val crossScalaVersion: String) extends Common {
+    override def artifactName = name
+  }
+
+  class JsModule(val crossScalaVersion: String, crossJSVersion: String)
+    extends ScalaJSModule with Common {
+
+    override def scalaJSVersion: Target[String] = crossJSVersion
+
+    override def millSourcePath = super.millSourcePath / os.up
+
+    override def artifactName = name
+  }
+
+  object jvm extends Cross[JvmModule](V.scala211, V.scala212, V.scala213)
+  object js extends Cross[JsModule](
+    V.scala211 -> V.scalaJs06,
+    V.scala212 -> V.scalaJs06,
+    V.scala212 -> V.scalaJs,
+    V.scala213 -> V.scalaJs06,
+    V.scala213 -> V.scalaJs
+  )
+
+}
+
 def compileAll(): Command[Unit] = T.command{
   jvm(V.scala213).compile()
   js(V.scala213, V.scalaJs).compile()
@@ -115,6 +149,14 @@
   js(V.scala212, V.scalaJs06).compile()
   jvm(V.scala211).compile()
   js(V.scala211, V.scalaJs06).compile()
+  extras.jvm(V.scala213).compile()
+  extras.js(V.scala213, V.scalaJs).compile()
+  extras.js(V.scala213, V.scalaJs06).compile()
+  extras.jvm(V.scala212).compile()
+  extras.js(V.scala212, V.scalaJs).compile()
+  extras.js(V.scala212, V.scalaJs06).compile()
+  extras.jvm(V.scala211).compile()
+  extras.js(V.scala211, V.scalaJs06).compile()
   ()
 }
 
@@ -127,6 +169,14 @@
   js(V.scala212, V.scalaJs06).publishLocal()()
   jvm(V.scala211).publishLocal()()
   js(V.scala211, V.scalaJs06).publishLocal()()
+  extras.jvm(V.scala213).publishLocal()()
+  extras.js(V.scala213, V.scalaJs).publishLocal()()
+  extras.js(V.scala213, V.scalaJs06).publishLocal()()
+  extras.jvm(V.scala212).publishLocal()()
+  extras.js(V.scala212, V.scalaJs).publishLocal()()
+  extras.js(V.scala212, V.scalaJs06).publishLocal()()
+  extras.jvm(V.scala211).publishLocal()()
+  extras.js(V.scala211, V.scalaJs06).publishLocal()()
 }
 
 def publishM2Local(p: os.Path): Command[Unit] = T.command{
@@ -138,28 +188,77 @@
   js(V.scala212, V.scalaJs06).publishM2Local(p.toString)()
   jvm(V.scala211).publishM2Local(p.toString)()
   js(V.scala211, V.scalaJs06).publishM2Local(p.toString)()
+  extras.jvm(V.scala213).publishM2Local(p.toString)()
+  extras.js(V.scala213, V.scalaJs).publishM2Local(p.toString)()
+  extras.js(V.scala213, V.scalaJs06).publishM2Local(p.toString)()
+  extras.jvm(V.scala212).publishM2Local(p.toString)()
+  extras.js(V.scala212, V.scalaJs).publishM2Local(p.toString)()
+  extras.js(V.scala212, V.scalaJs06).publishM2Local(p.toString)()
+  extras.jvm(V.scala211).publishM2Local(p.toString)()
+  extras.js(V.scala211, V.scalaJs06).publishM2Local(p.toString)()
   ()
 }
 
-object extras extends Module {
+object example extends ScalaModule {
+  override def scalaVersion: T[String] = V.scala213
+
+  override def scalacOptions = T{compilerOptions}
+
+  override def moduleDeps = Seq(jvm(V.scala213), extras.jvm(V.scala213))
+
+  override def ivyDeps = Agg(D.scalatex, D.oslib)
 
-  class JvmModule(val crossScalaVersion: String) extends Common
-  class JsModule(val crossScalaVersion: String, crossJSVersion: String)
-    extends ScalaJSModule with Common {
+  override def generatedSources: Target[Seq[PathRef]] = T{
+    val dir = T.ctx().dest
+    val src = sources() map(_.path)
+    val ids = src flatMap(ops.ls! _ filter(_.ext == "scalatex") map { p =>
+      val id = p.last replaceAllLiterally (".scalatex", "")
+      os.write(dir / s"$id.scala",
+        s"""
+           | package example
+           | import scalatags.Text.all._
+           | import scalatex._
+           | import purecss.Extras
+           | import purecss.text.PureCss._
+           | object `$id` {
+           |   val id = "$id"
+           |   val content = twf("${p.toString}")
+           | }
+           |
+           |/*
+           |${os.read(p)}
+           |*/
+        """.stripMargin)
+      id
+    })
 
-    override def scalaJSVersion: Target[String] = crossJSVersion
+    os.write(dir / "initializer.scala",
+      s"""
+         | package example
+         | trait ContentInitializer {
+         |   Seq(${ids mkString("`", "`, `", "`")})
+         | }
+      """.stripMargin)
 
-    override def millSourcePath = super.millSourcePath / os.up
+    os.write(dir / "main.scala",
+      s"""
+         | package example
+         | import os.Path
+         | object A extends ExampleApp with App {
+         |   override def export: Path = Path("${exportDir().path}")
+         | }
+      """.stripMargin)
+
+    Seq(PathRef(dir))
   }
 
-  object jvm extends Cross[JvmModule](V.scala211, V.scala212, V.scala213)
-  object js extends Cross[JsModule](
-    V.scala211 -> V.scalaJs06,
-    V.scala212 -> V.scalaJs06,
-    V.scala212 -> V.scalaJs,
-    V.scala213 -> V.scalaJs06,
-    V.scala213 -> V.scalaJs
-  )
+  override def mainClass: T[Option[String]] = Some("example.A")
+
+  def exportDir = T{
+    val dir = T.ctx().dest
+    PathRef(dir)
+  }
 
 }
+
 // vim: et ts=2 sw=2 syn=scala
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example/src/example/ExampleApp.scala	Sun Dec 27 22:54:33 2020 +0100
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2020 Tomas Zeman <tomas@functionals.cz>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package example
+
+import os.Path
+import purecss.Extras
+import scalatags.Text.all._
+import scalatags.Text.tags2
+
+trait ExampleApp extends ContentInitializer {
+
+  def export: Path
+
+  os.write.over(export / s"${`extras`.id}.html",
+    "<!DOCTYPE html>" + html(head(
+      meta(charset:="utf-8"),
+      meta(name:="viewport", content:="width=device-width, initial-scale=1.0"),
+      tags2.title(s"Example of ${`extras`.id} | PureCSS"),
+      link(href:="https://unpkg.com/purecss@2.0.3/build/pure-min.css",
+        rel:="stylesheet", tpe:="text/css"),
+      tags2.style(Extras.styleSheetText)
+    ), body(
+      `extras`.content
+    ))
+  )
+
+  println(
+    s"""Please open your browser at
+       |file:///$export
+       |""".stripMargin)
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/example/src/extras.scalatex	Sun Dec 27 22:54:33 2020 +0100
@@ -0,0 +1,289 @@
+@val img200 = src:="http://placehold.it/200x200"
+@val img250 = img(src:="http://placehold.it/250x250")
+@val sasquatch = img(src:="http://dribbble.s3.amazonaws.com/users/4467/screenshots/661196/sasquatch-troop-full.jpg")
+
+@div
+  @h1
+    Pure Extras
+  @h2
+    CSS styles for images, thumbnails, badges, contextual menus and alerts.
+    Depends on Pure CSS.
+  @p
+    Pure-Scala 1:1 reimplementation of
+    @a(href:="http://github.com/tilomitra/cssextras", "pure-extras").
+
+  @h2
+    Images
+  @p
+    Styling of three different types are available for images, eliptical,
+    rounded, bordered. To use them, just add one of these classes to the
+    @code(raw("&lt;img&gt;")) tag.
+
+  @div(pure.g)
+    @div(pure.u_1_3)
+      @img(Extras.pure_img_elliptical, width:="200", height:="150",
+        src:="http://dribbble.s3.amazonaws.com/users/9418/screenshots/928345/suhio_shoot.png")
+    @div(pure.u_1_3)
+      @img(Extras.pure_img_rounded, width:="200", height:="150",
+        src:="http://dribbble.s3.amazonaws.com/users/9418/screenshots/928345/suhio_shoot.png")
+    @div(pure.u_1_3)
+      @img(Extras.pure_img_bordered, width:="200", height:="150",
+        src:="http://dribbble.s3.amazonaws.com/users/9418/screenshots/928345/suhio_shoot.png")
+
+  @p
+    When using class @code("Extras.pure_img_elliptical"), if the width and
+    height of the image are equal, it will appear as a circle. Otherwise, it
+    will appear as an ellipse.
+  @img(Extras.pure_img_elliptical, width:="200", height:="200", img200)
+
+  @h2
+    Thumbnails
+  @p
+    Add the class @code("Extras.pure_thumbnails") to the container
+    @code(raw("&lt;ul&gt;")). Then add one of the classes,
+    @code("Extras.pure_thumb_elliptical"), @code("Extras.pure_thumb_rounded"),
+    or @code("Extras.pure_thumb_bordered"), to the @code(raw("&lt;a&gt;")).
+
+  @ul(Extras.pure_thumbnails, pure.g)
+    @li(pure.u_1_4)
+      @a(Extras.pure_thumb, Extras.pure_thumb_elliptical, href:="#")
+        @img250
+    @li(pure.u_1_4)
+      @a(Extras.pure_thumb, Extras.pure_thumb_rounded, href:="#")
+        @img250
+    @li(pure.u_1_4)
+      @a(Extras.pure_thumb, Extras.pure_thumb_bordered, href:="#")
+        @img250
+    @li(pure.u_1_4)
+      @a(Extras.pure_thumb, Extras.pure_thumb_bordered, href:="#")
+        @img250
+        @div(Extras.caption_)
+          @h3(Extras.caption_head)
+            Rocket – game concept
+          @p
+            This is a great shot from Jozef Mak from Dribbble.
+
+  @p
+    Adding a @code("div(Extras.caption_)") allows you to customize the
+    thumbnail with additional content.
+
+  @p
+    If you have YUI grids on the page, add @code("pure_u_*") for multi-column
+    thumbnails that scale to fit the columns.
+
+  @ul(Extras.pure_thumbnails, pure.g)
+    @li(pure.u_1_4)
+      @a(Extras.pure_thumb, Extras.pure_thumb_elliptical, href:="#")
+        @sasquatch
+    @li(pure.u_1_4)
+      @a(Extras.pure_thumb, Extras.pure_thumb_rounded, href:="#")
+        @sasquatch
+    @li(pure.u_1_4)
+      @a(Extras.pure_thumb, href:="#")
+        @sasquatch
+    @li(pure.u_1_4)
+      @a(Extras.pure_thumb, Extras.pure_thumb_bordered, href:="#")
+        @sasquatch
+        @div(Extras.caption_)
+          @h3(Extras.caption_head)
+            Thumbnail label
+          @p
+            Curabitur et sapien ac diam pharetra lacinia quis ac tortor.
+            Suspendisse dictum fermentum dui at mollis. Nunc pulvinar blandit
+            diam in vehicula.
+
+  @h2
+    Badges
+  @p
+    To create a badge, use a @code("span") tag, and add one of the badge
+    classes as shown below.
+
+  @span(Extras.pure_badge)
+    A badge
+  @span(Extras.pure_badge_success)
+    Success badge
+  @span(Extras.pure_badge_warning)
+    Warning badge
+  @span(Extras.pure_badge_error)
+    Badges can have a bunch of content
+  @span(Extras.pure_badge_info)
+    Info badge
+  @span(Extras.pure_badge_inverse)
+    or not much at all.
+
+  @h2
+    Alerts
+  @p
+    Create alerts by adding a class to it's @code("div").
+
+  @h3
+    Default Alert
+  @p
+    The default alert can be set by adding the @code("Extras.pure_alert") class name.
+  @div(Extras.pure_alert)
+    @label
+      Welcome back, Tilo.
+
+  @h3
+    Error Alert
+  @p
+    Alerts in red have the connotation of something going wrong. The error
+    alert can be set by appending the @code("Extras.pure_alert_error") class name
+    in addition to the @code("Extras.pure_alert").
+  @div(Extras.pure_alert, Extras.pure_alert_error)
+    @label(strong("Breaking News"))
+    'Most' of Atlanic City Underwater. Atlantic City Boardwalk Destroyed by Sandy.
+
+  @h3
+    Warning Alert
+  @p
+    If you want to send a warning notification, use the warning alert. It can
+    be set by appending the @code("Extras.pure_alert_warning") class name in
+    addition to the @code("Extras.pure_alert").
+  @div(Extras.pure_alert, Extras.pure_alert_warning)
+    @label(strong("Update"))
+    Looks like you like the Green Bay Packers so we added the team to your Sports App!
+
+  @h3
+    Success Alert
+  @p
+    Mission successful? Use the Success Alert! It can be set by appending the
+    @code("Extras.pure_alert_success") in addition to the
+    @code("Extras.pure_alert").
+  @div(Extras.pure_alert, Extras.pure_alert_success)
+    @label(strong("New Badge Unlocked!"))
+    You unlocked the "Paradise" badge!
+
+  @h2
+    Contextual Modals
+
+  @div(pure.g)
+    @div(pure.u_1_2)
+      @h3
+        Bottom Arrow
+      @div(Extras.pure_popover, Extras.pure_popover_bottom)
+        @div
+          @p
+            You have no new notifications.
+          @p
+            Receive notifications when you comment or discuss content with
+            friends on Yahoo!
+          @p
+            @a(pure.button, Extras.pure_button_block, href:="#")
+              Learn More
+        @div(Extras.pure_arrow_border)
+        @div(Extras.pure_arrow)
+    @div(pure.u_1_2)
+      @h3
+        Left Arrow
+      @div(Extras.pure_popover, Extras.pure_popover_left)
+        @div
+          @p
+            You have no new notifications.
+          @p
+            Receive notifications when you comment or discuss content with
+            friends on Yahoo!
+          @p
+            @a(pure.button, Extras.pure_button_block, href:="#")
+              Learn More
+        @div(Extras.pure_arrow_border)
+        @div(Extras.pure_arrow)
+
+  @div(pure.g)
+    @div(pure.u_1_2)
+      @h3
+        Top Arrow
+      @div(Extras.pure_popover, Extras.pure_popover_top)
+        @div
+          @p
+            You have no new notifications.
+          @p
+            Receive notifications when you comment or discuss content with
+            friends on Yahoo!
+          @p
+            @a(pure.button, Extras.pure_button_block, href:="#")
+              Learn More
+        @div(Extras.pure_arrow_border)
+        @div(Extras.pure_arrow)
+    @div(pure.u_1_2)
+      @h3
+        Right Arrow
+      @div(Extras.pure_popover, Extras.pure_popover_right)
+        @div
+          @p
+            You have no new notifications.
+          @p
+            Receive notifications when you comment or discuss content with
+            friends on Yahoo!
+          @p
+            @a(pure.button, Extras.pure_button_block, href:="#")
+              Learn More
+        @div(Extras.pure_arrow_border)
+        @div(Extras.pure_arrow)
+
+  @h2
+    Contextual Modals with Grids
+  @p
+    You can use grids within these contextual menus for interesting effects.
+  @div(pure.g)
+    @div(pure.u_1)
+      @h4
+        You have mail.
+      @div(Extras.pure_popover, Extras.pure_popover_bottom, width:="70%")
+        @div(pure.g)
+          @div(pure.u_1_5)
+            @strong
+              Yahoo! Mail
+          @div(pure.u_3_5)
+            You have 3 new messages.
+          @div(pure.u_1_5, cls:="text-right")
+            @a(pure.button, Extras.pure_button_small, href:="#")
+              Read
+        @div(Extras.pure_arrow_border)
+        @div(Extras.pure_arrow)
+
+  @h2
+    Buttons
+  @h3
+    Button Types
+  @p
+    @a(pure.button)
+      A regular button
+    @a(pure.button, Extras.pure_button_selected)
+      Selected
+  @p
+    @a(pure.button, Extras.pure_button_secondary)
+      Secondary
+    @a(pure.button, Extras.pure_button_error)
+      Error
+    @a(pure.button, Extras.pure_button_success)
+      Success
+    @a(pure.button, Extras.pure_button_warning)
+      Warning
+  @p
+    @a(pure.button, Extras.pure_button_block)
+      Block
+
+  @h3
+    Button Sizes
+  @p
+    Large buttons have twice the padding of regular buttons. Apply the
+    @code("Extras.pure_button_large").
+  @a(pure.button, Extras.pure_button_large)
+    Big click target
+  @a(pure.button, Extras.pure_button_success, Extras.pure_button_large)
+    Big Success
+
+  @p
+    Small buttons have half the padding of regular buttons. Apply the
+    @code("Extras.pure_button_small").
+  @a(pure.button, Extras.pure_button_small)
+    Smaller target
+  @a(pure.button, Extras.pure_button_secondary, Extras.pure_button_small)
+    Smaller Secondary Button
+  @a(pure.button, Extras.pure_button_warning, Extras.pure_button_small)
+    Smaller Warning Button
+  @a(pure.button, Extras.pure_button_error, Extras.pure_button_small)
+    Smaller Error Button
+
+// vim: et ts=2 sw=2 syn=scala 
--- a/extras/shared/src/main/scala/purecss/Extras.scala	Sat Dec 26 21:46:29 2020 +0100
+++ b/extras/shared/src/main/scala/purecss/Extras.scala	Sun Dec 27 22:54:33 2020 +0100
@@ -23,7 +23,7 @@
 /*
  * https://github.com/tilomitra/cssextras/blob/master/css/pure-extras.css
  */
-object Extras extends CascadingStyleSheet {
+trait Extras extends CascadingStyleSheet {
   initStyleSheet()
 
   /* Images. */
@@ -96,6 +96,10 @@
     border:="1px solid rgba(0, 0, 0, 0.2)"
   )
 
+  val pure_thumb_elliptical: Cls = cls(img(borderRadius:="50%"))
+
+  val pure_thumb_rounded: Cls = cls(img(borderRadius:=3))
+
   /* Badges/Pills */
   private val badge_common = immutable.Seq[StyleSheetFrag](
     padding:="0.35em 0.9em 0.35em",
@@ -151,7 +155,7 @@
   val left_ : Cls = cls()
   private val arrow_common = immutable.Seq[StyleSheetFrag](
     borderStyle:="solid",
-    borderWidth:=10,
+    borderWidth:="10px",
     height:=0,
     width:=0,
     position.absolute
@@ -171,61 +175,61 @@
     // box-padding: border-box;
     // -webkit-background-clip: padding-box;
     // -moz-background-clip: padding;
-    backgroundClip.`padding-box`,
-    bottom_(
-      pure_arrow_border(
-        borderColor:="#bfc0c8 transparent transparent transparent",
-        bottom:="-20px",
-        left:="50%"
-      ),
-      pure_arrow(
-        borderColor:="#f0f1f3 transparent transparent transparent",
-        bottom:="-19px",
-        left:="50%"
-      )
+    backgroundClip.`padding-box`
+  )
+  val pure_popover_bottom: Cls = cls(
+    pure_arrow_border(
+      borderColor:="#bfc0c8 transparent transparent transparent",
+      bottom:="-20px",
+      left:="50%"
+    ),
+    pure_arrow(
+      borderColor:="#f0f1f3 transparent transparent transparent",
+      bottom:="-19px",
+      left:="50%"
+    )
+  )
+  val pure_popover_top: Cls = cls(
+    pure_arrow_border(
+      borderColor:="transparent transparent #bfc0c8 transparent",
+      top:="-21px",
+      left:="50%"
     ),
-    top_(
-      pure_arrow_border(
-        borderColor:="transparent transparent #bfc0c8 transparent",
-        top:="-21px",
-        left:="50%"
-      ),
-      pure_arrow(
-        borderColor:="transparent transparent #f0f1f3 transparent",
-        top:="-20px",
-        left:="50%"
-      )
+    pure_arrow(
+      borderColor:="transparent transparent #f0f1f3 transparent",
+      top:="-20px",
+      left:="50%"
+    )
+  )
+  val pure_popover_right: Cls = cls(
+    pure_arrow_border(
+      borderColor:="transparent transparent transparent #bfc0c8",
+      top:="45%",
+      right:="-21px"
     ),
-    right_(
-      pure_arrow_border(
-        borderColor:="transparent transparent transparent #bfc0c8",
-        top:="45%",
-        right:="-21px"
-      ),
-      pure_arrow(
-        borderColor:="transparent transparent transparent #f0f1f3",
-        top:="45%",
-        right:="-20px"
-      )
+    pure_arrow(
+      borderColor:="transparent transparent transparent #f0f1f3",
+      top:="45%",
+      right:="-20px"
+    )
+  )
+  val pure_popover_left: Cls = cls(
+    pure_arrow_border(
+      borderColor:="transparent #bfc0c8 transparent transparent",
+      top:="45%",
+      left:="-21px"
     ),
-    left_(
-      pure_arrow_border(
-        borderColor:="transparent #bfc0c8 transparent transparent",
-        top:="45%",
-        left:="-21px"
-      ),
-      pure_arrow(
-        borderColor:="transparent #f0f1f3 transparent transparent",
-        top:="45%",
-        left:="-20px"
-      )
+    pure_arrow(
+      borderColor:="transparent #f0f1f3 transparent transparent",
+      top:="45%",
+      left:="-20px"
     )
   )
 
   /* BUTTON IMPROVEMENTS */
   val pure_button_block: Cls = cls(display.block)
   val pure_button_small: Cls = cls(padding:=".6em 2em .65em", fontSize:="70%")
-  val pure_button_large: Cls = cls(padding:=".8em 5em .9em", fontSize:="70%")
+  val pure_button_large: Cls = cls(padding:=".8em 5em .9em", fontSize:="110%")
   val pure_button_selected: Cls = cls(backgroundColor:="#345fcb", color:="#fff")
   val pure_button_secondary: Cls =
     cls(background:="rgb(161, 195, 238)", color:="rgb(26, 88, 122)")
@@ -236,3 +240,5 @@
     cls(background:="rgb(255, 163, 0)", color.white)
 
 }
+
+object Extras extends Extras
\ No newline at end of file