Closed ddssff closed 1 month ago
What exactly do you mean by type safe class names? What error would you like to rule out? Maybe you have an example?
For example, we have a CssClass
class with a cssClass
method that converts instances to class names. The code for an open/close button looks like this:
data ToggleCss
= ToggleThing
| ToggleButton
deriving (Eq, Ord, Show)
instance CssClass ToggleCss where
cssClass = show
#if SERVER
instance CssStyle ToggleCss () where
cssStyle () = do
star # byClass' ToggleThing ? do
star # byClass' ToggleButton ? do
-- parentUpperRight
color grey
background transparent
#endif
#if CLIENT
toggleButton :: (Renderer' h m, HasCallStack) => Lens' (Sh h) Bool -> m () -> m () -> m ()
toggleButton lns expandedGlyph compressedGlyph = do
expanded <- view lns
buttonA (\_ -> lns %= not >> pure N) (bool compressedGlyph expandedGlyph expanded)
`with` [classes_ [cssClass ToggleButton]]
....
byClass
' is a version of byClass
that takes a CssClass
instead of a string. When we used strings instead of calling cssClass the names in the client code would get out of sync with those in the server code, or disappear altogether when design changes were made in one place or another. I'm also adding a withLocationHash
function to append a uniquifying string to every class name based on the location of the CssClass instance (though the use of the Int
type in the Hashable
class is causing incompatibilities due to the 56 bit ints in ghcjs.)
Oops I commented and closed this thinking it was another issue for another package.
I can't quite follow. What's CssStyle
? What exactly is your proposal here?
I don't have a concrete proposal yet, just a question about how to guarantee that the class names in your HTML match the ones in your CSS. It may be that my web development tools are sufficiently different from those of other people that they don't have this issue.
CssStyle
is just a trick to scan all the instances for to collect and render all the Css values using template haskell.
Update: I'm now using symbol names for css class names, via the template haskell quote mechanism:
import Language.Haskell.TH.Syntax (Name(..), ModName(..), NameFlavour(..), NameSpace(..), OccName(..))
instance CssClass Name where
cssClass (Name (OccName o) (NameG space _ (ModName m))) =
protectCSSIdentifier (pack (m <> "-" <> o <>
case space of
TcClsName -> "_T"
DataName -> "_D"
VarName -> "_V"))
cssClass (Name (OccName o) (NameQ (ModName m))) = protectCSSIdentifier (pack (m <> "-" <> o))
cssClass (Name o f) = error ("cssClass (Name " <> show o <> " " <> show f <> ")")
This way I can immediately identify what module a css class name is coming from.
Update - gave up on class names, using checksums of the generated CSS code now.
Alright :) I guess we can close then? Feel free to reopen if I misunderstood.
One big win from using Haskell to generate CSS is that you can use typed values to ensure that the class names you use in your HTML correspond with the ones you use in your CSS. We have implemented this in a somewhat ad-hoc way, I wonder if there is a case for adding type safe class names (and maybe other things like animation names) to Clay?