packages feed

atomic-css-0.1.0: src/Web/Atomic/CSS/Box.hs

module Web.Atomic.CSS.Box where

import Web.Atomic.Types


{- | Space surrounding the children of the element

To create even spacing around and between all elements combine with 'gap'

> el ~ flexCol . pad 10 . gap 10 $ do
>   el "one"
>   el "two"
>   el "three"
-}
pad :: (Styleable h) => Sides Length -> CSS h -> CSS h
pad =
  sides "p" ("padding" <>)


-- | The space between child elements. See 'pad'
gap :: (Styleable h) => Length -> CSS h -> CSS h
gap n = utility ("gap" -. n) ["gap" :. style n]


-- | Element margin. Using 'gap' and 'pad' on parents is more intuitive and usually makes margin redundant
margin :: (Styleable h) => Sides Length -> CSS h -> CSS h
margin =
  sides "m" ("margin" <>)


{- | Add a drop shadow to an element

> input ~ shadow Inner $ "Inset Shadow"
> button ~ shadow () $ "Click Me"
-}
shadow :: (Styleable h, PropertyStyle Shadow a, ToClassName a) => a -> CSS h -> CSS h
shadow a =
  utility ("shadow" -. a) ["box-shadow" :. propertyStyle @Shadow a]


data Shadow
data Inner = Inner
  deriving (Show, ToClassName)


instance PropertyStyle Shadow () where
  propertyStyle _ = "0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);"
instance PropertyStyle Shadow None where
  propertyStyle _ = "0 0 #0000;"
instance PropertyStyle Shadow Inner where
  propertyStyle _ = "inset 0 2px 4px 0 rgb(0 0 0 / 0.05);"


-- | Set the background color. See 'ToColor'
bg :: (ToColor clr, Styleable h) => clr -> CSS h -> CSS h
bg c = utility ("bg" -. colorName c) ["background-color" :. style (colorValue c)]


-- | Round the corners of the element
rounded :: (Styleable h) => Length -> CSS h -> CSS h
rounded n = utility ("rnd" -. n) ["border-radius" :. style n]


{- | Set a border around the element

> el ~ border 1 $ "all sides"
> el ~ border (X 1) $ "only left and right"
-}
border :: (Styleable h) => Sides PxRem -> CSS h -> CSS h
border s = borderWidth s . borderStyle Solid


borderStyle :: (Styleable h) => BorderStyle -> CSS h -> CSS h
borderStyle s = utility ("brds" -. s) ["border-style" :. style s]


data BorderStyle
  = Solid
  | Dashed
  deriving (Show, ToStyle, ToClassName)


borderWidth :: (Styleable h) => Sides PxRem -> CSS h -> CSS h
borderWidth =
  sides "brd" prop
 where
  prop "" = "border-width"
  prop p = "border" <> p <> "-width"


-- | Set a border color. See 'ToColor'
borderColor :: (ToColor clr, Styleable h) => clr -> CSS h -> CSS h
borderColor c =
  utility ("brdc" -. colorName c) ["border-color" :. style (colorValue c)]


opacity :: (Styleable h) => Float -> CSS h -> CSS h
opacity n =
  utility ("opacity" -. n) ["opacity" :. style n]


-- | utilities for every side with (Sides a)
sides :: (Styleable h, ToStyle a, ToClassName a, Num a) => ClassName -> (Property -> Property) -> Sides a -> CSS h -> CSS h
sides c toProp =
  sides'
    (\a -> utility (c -. a) [toProp "" :. style a])
    (\a -> utility (c <> "t" -. a) [toProp "-top" :. style a])
    (\a -> utility (c <> "r" -. a) [toProp "-right" :. style a])
    (\a -> utility (c <> "b" -. a) [toProp "-bottom" :. style a])
    (\a -> utility (c <> "l" -. a) [toProp "-left" :. style a])


-- | case analysis for (Sides a)
sides' :: (Styleable h, ToStyle a, ToClassName a, Num a) => (a -> CSS h -> CSS h) -> (a -> CSS h -> CSS h) -> (a -> CSS h -> CSS h) -> (a -> CSS h -> CSS h) -> (a -> CSS h -> CSS h) -> Sides a -> CSS h -> CSS h
sides' all_ top right bottom left s =
  case s of
    (All n) -> all_ n
    (Y n) -> top n . bottom n
    (X n) -> left n . right n
    (XY x y) -> top y . bottom y . left x . right x
    (TRBL t r b l) ->
      top t . right r . bottom b . left l
    (T x) -> top x
    (R x) -> right x
    (B x) -> bottom x
    (L x) -> left x
    (TR t r) -> top t . right r
    (TL t l) -> top t . left l
    (BR b r) -> bottom b . right r
    (BL b l) -> bottom b . left l