Skip to content

atomic-css major refactor! Please Review. Fixes #17 #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

seanhess
Copy link
Owner

@seanhess seanhess commented May 12, 2025

As mentioned in #20 - I have completely rewritten this library. It is now focused exclusively on implementing Atomic CSS. The "View" type with its ViewId reader context will be moved to hyperbole. This library could now be used with Blaze or another html combinator library if desired.

@kfigiela @Skyfold @benjaminweb @benjamin-thomas @tusharad - please review if you can!

New library: atomic-css

This libary will be named "atomic-css" instead of "web-view". The old package will be deprecated. There will be a Web.Hyperbole.View that builds on this libary to add the features it needs.

This will be explicity opt-in for Hyperbole. I changed my mind about ease-of-use. I think it will help to inform users that this functionality comes from this package.

import Web.Hyperbole
import Web.Atomic.CSS

New Interface

Instead of tags requiring a "Mod" argument, we have implemented two operators in the style of Blaze's (!). Attributes are applied with @, and Utility classes are applied with ~.

  el ~ bold . fontSize 32 $ "My page"
  el "no first argument required"
  input @ placeholder "Not Focused" ~ border 1 . pad 10 . bg White

This is what it used to be:

  el (bold . fontSize 32) "My page"
  el id "old version required a first argument or `el_`"
  input (placeholder "Not Focused" . border 1 . pad 10 . bg White)

These are completely separate, so while you can compose attributes with each other, you can't compose an attribute and a utility:

autofocus :: Attributable h => Attributes h -> Attributes h
autofocus = att "autofocus" ""

bold :: Styleable h => CSS h -> CSS h
bold = utility @Text "bold" "font-weight" "bold"

willNotCompile :: Html ()
willNotCompile = do
  tag "div" @ autofocus . bold $ "bad"
  tag "div" ~ autofocus . bold $ "bad"
  tag "div" @ hover autofocus $ "can't hover an attribute"
  
correct :: Html ()
correct = do
  tag "div" @ autofocus ~ bold $ "good"
  tag "div" ~ hover bold $ "good"

Built-in Html Monad

This library includes an Html monad, which makes this a functional rendering library. It does not export any HTML tag functions, leaving this to downstream libraries.

Override Styles, Fixes #17

CSS now automatically overrides any previously applied utilities that affect the same property. If you create a "component" that sets some styles, you can easily override anything without worrying about precedence:

myButton :: Text -> Html ()
myButton lbl = tag "button" ~ border 1 . bold . bg Gray (text lbl)

example :: Html ()
example = do
  myButton "one"
  myButton "thick border" ~ border 10
  myButton "different background" ~ bg Green

Easy Custom CSS

I started down this path after becoming annoyed at the difficulty writing css-only tooltips. These required custom selectors. The previous interface was confusing. Now, you can create custom css rules, and these will not be modified by hover, etc. The example below predicatably adds a "tooltips" class to the the parent, and shows the ".tooltip" child when you hover over anything inside it.

  showTooltips :: Styleable h => CSS h -> CSS h
  showTooltips =
    css
      "tooltips"
      ".tooltips:hover > .tooltip"
      [Declaration "visibility" "visible"]
      
   example :: Html ()
   example = do
      tag "div" ~ showTooltips $ do
        tag "div" ~ hide . cls "tooltip" $ "Show on hover"
        tag "div" "always shown"

It's also much easier to define your own utilities if any are missing or you need something custom:

  borderCollapse :: Styleable h => CSS h -> CSS h
  borderCollapse = utility @Text "brd-cl" "border-collapse" "collapse"
  
  margin :: Styleable h => PxRem -> CSS h -> CSS h
  margin n = utility "brd-cl" "border-collapse" n

  appLogo :: Styleable h => CSS h -> CSS h
  appLogo =
    utility'
      "logo"
      [ Declaration "background" "no-repeat center/90% url(/logo-robot.png)"
      , Declaration "color" "transparent"
      ]

classier, stuck on []

wierd solution with catchall list instance and empty list

ToCSS

major refactor! Class->Rule, Rule+media, new modules

done! big improvement on before

media separate type

removed context

wip

wip refactoring back

simple html definition

merge selector

coming along, stuck with  Html : Html

got Html effect to work with funky nested state stuff

View with Html (). Stuck as attributes require annotations

better factoring of atomic

utility classes with property-based overrides!

hover, bold

external classes

promising direction with 2 different operators

wip

looking good! Just can't do single tags

sexy

stuck on newtypes / stack layer

ModAtts, ModStyles - figured out how to do single tags!

moved things into atomic

cleanup

moving files into place

example of using blaze

making progress!

forced to redefine everything

WIP - wait, how would blaze work

interesting! external type family, Category Attributes and Styles

Working? Moved addAttribute to Attributable

stuck - cant figure out how to resolve text

reverted IsHtml

Working!

Wow! Styles [Rule] etc.

refactored Styleable

refactor Render

fixed blaze example, much simpler!

improved blaze

CSS override rules, tests

render tests, pseudo + media> NEEDS: parent?

RuleSelector = Custom | FromClass

refactoring: Styleable -> CSS, Attributable -> Html, etc

render tests

merge classes with attribute

uniqueRules built in

ancestor!

Ready to publish atomic-css

examples working

switched to colon separator

PxRem, Length, TRBL tests

exports

renamed to atomic-css

renaming

refactor module names

refactor names and modules

attributes

removed web.view

more refactors

added Styleable to CSS

fixed align infinite loop

pseudo refactor

attributable, styleable (a -> b)

exports

fixed blaze example

slow error: speedup with rule map

refactored Html to a list newtype

remove Empty
@tusharad
Copy link

Thanks! I'll take a deeper into it but the new interface operator looks quite intuitive!

@seanhess
Copy link
Owner Author

Any and all comments welcome! I'd especially like to hear how you like the new interface. I'm open to hearing ideas about better operators if you can think of any.

Take a look at example/app/Main.hs to see a bunch of usage

https://github.com/seanhess/atomic-css/blob/atomic-css/example/app/Main.hs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Bug: undefined style precedence when set more than once
2 participants