Skip to content

natxocc/sigpro-css

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

6 Commits
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

SigPro CSS

A modern, classless CSS framework that pairs perfectly with SigPro reactive components. Write clean semantic HTML with zero classes and get beautiful, responsive styling with dark mode support.

Features

  • Classless β€” works with semantic HTML and SigPro components, no extra classes needed
  • Dark mode β€” automatic system preference detection + manual data-theme override
  • Modern form controls β€” animated checkboxes, radios, toggle switches, and range sliders
  • Smooth animations β€” accordions, dialogs, drawers, sheets, and sidebars with elegant transitions
  • Fully responsive β€” mobile-first design that works on all devices
  • Accessibility β€” focus states, reduced motion support, and proper contrast ratios
  • SigPro native β€” designed to work seamlessly with SigPro's reactive syntax

Quick Start

Add the CSS file to your HTML:

<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/natxocc/sigpro-css@latest/sigpro.min.css">

Include SigPro runtime (all functions are auto-assigned to window):

<script src="https://unpkg.com/sigpro"></script>

That's it! All SigPro functions ($, $if, $for, $watch, $mount, etc.) and HTML helpers (Div, P, H1, Button, etc.) are available globally.

Basic Example with SigPro

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/natxocc/sigpro-css@latest/sigpro.min.css">
</head>
<body>
  <div id="app"></div>

  <script src="https://unpkg.com/sigpro"></script>
  <script>
    // All SigPro functions are already available globally
    // No need to import or destructure anything!
    
    const App = () => {
      const name = $("");
      const theme = $("light");
      const notifications = $(false);
      const volume = $(50);
      const items = $(["Item 1", "Item 2", "Item 3"]);
      
      return Div({ class: "container" }, [
        Header([
          H1("SigPro CSS Demo"),
          P("No classes needed β€” just clean reactive components")
        ]),
        
        Form([
          // Reactive input with two-way binding
          Input({
            type: "text",
            placeholder: "Your name",
            value: name,
            oninput: (e) => name(e.target.value)
          }),
          P(() => `Hello, ${name() || "stranger"}!`),
          
          // Theme selector with radio buttons
          Fieldset([
            Legend("Theme"),
            Label([
              Input({ 
                type: "radio", 
                name: "theme", 
                value: "light", 
                checked: () => theme() === "light", 
                onchange: (e) => theme(e.target.value) 
              }),
              " Light"
            ]),
            Label([
              Input({ 
                type: "radio", 
                name: "theme", 
                value: "dark", 
                checked: () => theme() === "dark", 
                onchange: (e) => theme(e.target.value) 
              }),
              " Dark"
            ])
          ]),
          
          // Toggle switch (iOS-style)
          Label([
            Input({ 
              type: "checkbox", 
              class: "toggle", 
              checked: notifications, 
              onchange: (e) => notifications(e.target.checked) 
            }),
            " Enable notifications"
          ]),
          
          // Range slider with live value
          Label([
            "Volume: ",
            Input({ 
              type: "range", 
              min: 0, 
              max: 100, 
              value: volume, 
              oninput: (e) => volume(e.target.valueAsNumber) 
            }),
            () => `${volume()}%`
          ]),
          
          // Modern checkbox
          Label([
            Input({ type: "checkbox", checked: () => false }),
            " Accept terms and conditions"
          ]),
          
          // Modern radio group
          Fieldset([
            Legend("Priority"),
            Label([Input({ type: "radio", name: "priority", value: "low" }), " Low"]),
            Label([Input({ type: "radio", name: "priority", value: "medium" }), " Medium"]),
            Label([Input({ type: "radio", name: "priority", value: "high" }), " High"])
          ]),
          
          // Button group
          Div({ style: "display: flex; gap: 0.5rem" }, [
            Button({ type: "submit" }, "Submit"),
            Button({ type: "button", secondary: true }, "Cancel"),
            Input({ type: "reset", value: "Reset" })
          ]),
          
          // Conditional rendering
          $if(notifications, 
            Div({ class: "alert" }, "βœ… Notifications are enabled"),
            Div({ class: "info" }, "πŸ”• Notifications are disabled")
          ),
          
          // List rendering
          H3("Your items:"),
          Ul(
            $for(items, (item, index) => Li({ key: index }, item))
          ),
          
          // Button to add items
          Button({
            onclick: () => items([...items(), `Item ${items().length + 1}`])
          }, "Add Item"),
          
          // Animated accordion
          Details([
            Summary("Click to expand"),
            P("This content slides open with a smooth animation"),
            P("Works with any HTML inside"),
            Code("$if(condition, trueView, falseView)")
          ]),
          
          // Animated modal dialog
          Button({ 
            onclick: () => document.getElementById("demoModal").showModal() 
          }, "Open Modal"),
          
          Dialog({ id: "demoModal" }, [
            H3("Modal Dialog"),
            P("This modal has smooth scale animation"),
            Button({ onclick: () => document.getElementById("demoModal").close() }, "Close")
          ]),
          
          // Animated drawer (bottom sheet)
          Button({ 
            onclick: () => document.getElementById("demoDrawer").showModal() 
          }, "Open Drawer"),
          
          Dialog({ id: "demoDrawer", drawer: true }, [
            H3("Bottom Drawer"),
            P("Slides up from the bottom with smooth animation"),
            Button({ onclick: () => document.getElementById("demoDrawer").close() }, "Close")
          ])
        ]),
        
        // Watch theme changes and update HTML attribute
        $watch(theme, (val) => {
          document.documentElement.setAttribute("data-theme", val);
        })
      ]);
    };
    
    // Mount the app to the DOM
    $mount(App, "#app");
  </script>
</body>
</html>

Available Global Helpers

Reactive Primitives

  • $(initialValue) β€” create a reactive signal
  • $watch(signal, callback) β€” react to signal changes
  • $if(condition, trueView, falseView) β€” conditional rendering
  • $for(array, renderFn) β€” list rendering

DOM Helpers (auto-generated from HTML tags)

All standard HTML tags are available as functions:

  • Div(), Span(), P(), H1() through H6()
  • Header(), Footer(), Section(), Article(), Aside(), Nav()
  • Form(), Input(), Button(), Select(), Textarea(), Label()
  • Ul(), Ol(), Li(), Table(), Tr(), Td(), Th()
  • Dialog(), Details(), Summary(), Progress()
  • And many more...

Special Helpers

  • $mount(component, selector) β€” mount reactive component to DOM
  • $router(routes) β€” hash-based router with reactive views
  • $html(tag, props, children) β€” low-level element creator

Styled Elements

Modern Checkbox

Input({ type: "checkbox", checked: isChecked, onchange: (e) => isChecked(e.target.checked) })

Modern Radio

Input({ type: "radio", name: "group", value: "option1", checked: () => selected() === "option1" })

Toggle Switch (iOS-style)

Add class: "toggle" to any checkbox:

Input({ type: "checkbox", class: "toggle", checked: enabled, onchange: (e) => enabled(e.target.checked) })

Range Slider

Input({ type: "range", min: 0, max: 100, value: volume, oninput: (e) => volume(e.target.valueAsNumber) })

Animated Accordion

Details([
  Summary("Click to expand"),
  P("Content slides open smoothly")
])

Animated Dialog

// Modal
Dialog({ id: "modal" }, [/* content */])

// Drawer (bottom sheet)
Dialog({ id: "drawer", drawer: true }, [/* content */])

// Sheet from right
Dialog({ id: "sheet", "sheet-right": true }, [/* content */])

Tooltips

Add tooltip attributes to any element:

Button({ "tooltip-top": "Click me!" }, "Hover")

Theme Customization

The CSS automatically follows your system's color scheme. Override with data-theme:

$watch(theme, (val) => {
  document.documentElement.setAttribute("data-theme", val);
});

Available themes: "light", "dark"

CSS Variables

Customize colors by overriding these variables in your own CSS:

:root {
  --radius: 0.5rem;
  --background: oklch(1 0 0);
  --foreground: oklch(0.141 0.005 285.823);
  --primary: oklch(0.21 0.006 285.885);
  --secondary: oklch(0.967 0.001 286.375);
  --destructive: oklch(0.577 0.245 27.325);
  --border-color: oklch(0.92 0.004 286.32);
  --shadow: 0px 10px 15px -3px rgba(0,0,0,0.1);
}

Browser Support

  • Chrome (latest)
  • Firefox (latest)
  • Safari (latest)
  • Edge (latest)

License

MIT License

Credits

SigPro CSS β€” Modern classless styling for SigPro reactive components.

About

Classless CSS for rapid SigPro development

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages