Type-safe CSS styling system with comprehensive support for CSS properties including CSS Grid, Flexbox, animations, and SVG.
type t; /* Style object type */external make: (
/* Layout & Positioning */
~display: string=?,
~position: string=?,
~top: string=?,
~right: string=?,
~bottom: string=?,
~left: string=?,
~width: string=?,
~height: string=?,
~minWidth: string=?,
~minHeight: string=?,
~maxWidth: string=?,
~maxHeight: string=?,
~zIndex: string=?,
~float: string=?,
~clear: string=?,
~overflow: string=?,
~overflowX: string=?,
~overflowY: string=?,
~visibility: string=?,
~opacity: string=?,
/* Box Model */
~margin: string=?,
~marginTop: string=?,
~marginRight: string=?,
~marginBottom: string=?,
~marginLeft: string=?,
~padding: string=?,
~paddingTop: string=?,
~paddingRight: string=?,
~paddingBottom: string=?,
~paddingLeft: string=?,
~border: string=?,
~borderTop: string=?,
~borderRight: string=?,
~borderBottom: string=?,
~borderLeft: string=?,
~borderWidth: string=?,
~borderStyle: string=?,
~borderColor: string=?,
~borderRadius: string=?,
~boxShadow: string=?,
~boxSizing: string=?,
/* Background */
~background: string=?,
~backgroundColor: string=?,
~backgroundImage: string=?,
~backgroundPosition: string=?,
~backgroundSize: string=?,
~backgroundRepeat: string=?,
~backgroundAttachment: string=?,
~backgroundClip: string=?,
/* Typography */
~color: string=?,
~font: string=?,
~fontFamily: string=?,
~fontSize: string=?,
~fontWeight: string=?,
~fontStyle: string=?,
~fontVariant: string=?,
~lineHeight: string=?,
~letterSpacing: string=?,
~wordSpacing: string=?,
~textAlign: string=?,
~textDecoration: string=?,
~textTransform: string=?,
~textIndent: string=?,
~textShadow: string=?,
~whiteSpace: string=?,
~wordWrap: string=?,
~wordBreak: string=?,
/* Flexbox */
~flex: string=?,
~flexDirection: string=?,
~flexWrap: string=?,
~flexFlow: string=?,
~justifyContent: string=?,
~alignItems: string=?,
~alignSelf: string=?,
~alignContent: string=?,
~flexGrow: string=?,
~flexShrink: string=?,
~flexBasis: string=?,
~order: string=?,
/* Grid */
~grid: string=?,
~gridTemplate: string=?,
~gridTemplateRows: string=?,
~gridTemplateColumns: string=?,
~gridTemplateAreas: string=?,
~gridArea: string=?,
~gridRow: string=?,
~gridColumn: string=?,
~gridRowStart: string=?,
~gridRowEnd: string=?,
~gridColumnStart: string=?,
~gridColumnEnd: string=?,
~gridGap: string=?,
~gridRowGap: string=?,
~gridColumnGap: string=?,
~justifyItems: string=?,
~justifySelf: string=?,
/* Transforms & Animation */
~transform: string=?,
~transformOrigin: string=?,
~transformStyle: string=?,
~perspective: string=?,
~perspectiveOrigin: string=?,
~backfaceVisibility: string=?,
~animation: string=?,
~animationName: string=?,
~animationDuration: string=?,
~animationTimingFunction: string=?,
~animationDelay: string=?,
~animationIterationCount: string=?,
~animationDirection: string=?,
~animationFillMode: string=?,
~animationPlayState: string=?,
~transition: string=?,
~transitionProperty: string=?,
~transitionDuration: string=?,
~transitionTimingFunction: string=?,
~transitionDelay: string=?,
/* SVG */
~fill: string=?,
~fillOpacity: string=?,
~fillRule: string=?,
~stroke: string=?,
~strokeWidth: string=?,
~strokeOpacity: string=?,
~strokeDasharray: string=?,
~strokeDashoffset: string=?,
~strokeLinecap: string=?,
~strokeLinejoin: string=?,
~strokeMiterlimit: string=?,
/* Lists */
~listStyle: string=?,
~listStyleType: string=?,
~listStylePosition: string=?,
~listStyleImage: string=?,
/* Tables */
~tableLayout: string=?,
~borderCollapse: string=?,
~borderSpacing: string=?,
~captionSide: string=?,
~emptyCells: string=?,
/* Content */
~content: string=?,
~quotes: string=?,
~counterReset: string=?,
~counterIncrement: string=?,
/* User Interface */
~cursor: string=?,
~outline: string=?,
~outlineColor: string=?,
~outlineStyle: string=?,
~outlineWidth: string=?,
~resize: string=?,
~userSelect: string=?,
~pointerEvents: string=?,
unit
) => t;/* Combine multiple styles */
external combine: (t, t) => t;
/* Unsafe escape hatches */
let unsafeAddProp: (t, string, string) => t;
external unsafeAddStyle: (t, Js.t({..})) => t;let buttonStyle = ReactDOMStyle.make(
~backgroundColor="#007bff",
~color="white",
~border="none",
~borderRadius="4px",
~padding="8px 16px",
~fontSize="14px",
~cursor="pointer",
~transition="background-color 0.2s",
()
);
let hoverStyle = ReactDOMStyle.make(
~backgroundColor="#0056b3",
()
);
[@react.component]
let make = (~onClick, ~children) => {
let (isHovered, setHovered) = React.useState(() => false);
let finalStyle = isHovered
? ReactDOMStyle.combine(buttonStyle, hoverStyle)
: buttonStyle;
<button
style=finalStyle
onClick
onMouseEnter={_ => setHovered(_ => true)}
onMouseLeave={_ => setHovered(_ => false)}
>
{children}
</button>
}let containerStyle = ReactDOMStyle.make(
~display="flex",
~flexDirection="column",
~alignItems="center",
~justifyContent="space-between",
~minHeight="100vh",
~padding="20px",
()
);
let headerStyle = ReactDOMStyle.make(
~display="flex",
~justifyContent="space-between",
~alignItems="center",
~width="100%",
~marginBottom="20px",
()
);
[@react.component]
let make = () => {
<div style=containerStyle>
<header style=headerStyle>
<h1> {React.string("My App")} </h1>
<nav> {React.string("Navigation")} </nav>
</header>
<main style={ReactDOMStyle.make(~flex="1", ())}>
{React.string("Content")}
</main>
<footer> {React.string("Footer")} </footer>
</div>
}let gridStyle = ReactDOMStyle.make(
~display="grid",
~gridTemplateColumns="repeat(auto-fit, minmax(300px, 1fr))",
~gridGap="20px",
~padding="20px",
()
);
let cardStyle = ReactDOMStyle.make(
~border="1px solid #ddd",
~borderRadius="8px",
~padding="16px",
~backgroundColor="white",
~boxShadow="0 2px 4px rgba(0,0,0,0.1)",
()
);
[@react.component]
let make = (~items) => {
<div style=gridStyle>
{items->Array.map(item =>
<div key=item.id style=cardStyle>
<h3> {React.string(item.title)} </h3>
<p> {React.string(item.description)} </p>
</div>
)->React.array}
</div>
}let spinKeyframes = ReactDOMStyle.make(
~animationName="spin",
~animationDuration="1s",
~animationTimingFunction="linear",
~animationIterationCount="infinite",
()
);
let loadingStyle = ReactDOMStyle.combine(
ReactDOMStyle.make(
~width="40px",
~height="40px",
~border="4px solid #f3f3f3",
~borderTop="4px solid #3498db",
~borderRadius="50%",
()
),
spinKeyframes
);
/* Note: You'll need to define the @keyframes rule in CSS */
let globalCSS = {|
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
|};
[@react.component]
let make = () => {
<div>
<style> {React.string(globalCSS)} </style>
<div style=loadingStyle />
</div>
}let responsiveStyle = ReactDOMStyle.make(
~width="100%",
~maxWidth="1200px",
~margin="0 auto",
~padding="20px",
()
);
/* Add media queries using unsafe escape hatch */
let withMediaQueries = ReactDOMStyle.unsafeAddStyle(
responsiveStyle,
{
"@media (max-width: 768px)": {
"padding": "10px",
"fontSize": "14px"
},
"@media (max-width: 480px)": {
"padding": "5px",
"fontSize": "12px"
}
}
);
[@react.component]
let make = () => {
<div style=withMediaQueries>
{React.string("Responsive content")}
</div>
}let svgStyle = ReactDOMStyle.make(
~width="100px",
~height="100px",
~fill="#3498db",
~stroke="#2980b9",
~strokeWidth="2",
()
);
let pathStyle = ReactDOMStyle.make(
~fill="none",
~stroke="#e74c3c",
~strokeWidth="3",
~strokeLinecap="round",
~strokeLinejoin="round",
()
);
[@react.component]
let make = () => {
<svg style=svgStyle viewBox="0 0 100 100">
<circle cx="50" cy="50" r="40" />
<path
style=pathStyle
d="M30,30 L70,70 M70,30 L30,70"
/>
</svg>
}