{"id":29124251,"url":"https://github.com/zaydek/stylex-dev","last_synced_at":"2025-06-29T20:06:30.336Z","repository":{"id":293647220,"uuid":"984699162","full_name":"zaydek/stylex-dev","owner":"zaydek","description":null,"archived":false,"fork":false,"pushed_at":"2025-05-16T11:27:30.000Z","size":9,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-16T12:28:20.160Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zaydek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-16T11:07:40.000Z","updated_at":"2025-05-16T11:27:33.000Z","dependencies_parsed_at":"2025-05-16T12:38:47.288Z","dependency_job_id":null,"html_url":"https://github.com/zaydek/stylex-dev","commit_stats":null,"previous_names":["zaydek/stylex-dev"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/zaydek/stylex-dev","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaydek%2Fstylex-dev","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaydek%2Fstylex-dev/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaydek%2Fstylex-dev/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaydek%2Fstylex-dev/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zaydek","download_url":"https://codeload.github.com/zaydek/stylex-dev/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zaydek%2Fstylex-dev/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262659986,"owners_count":23344439,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-06-29T20:06:28.300Z","updated_at":"2025-06-29T20:06:30.299Z","avatar_url":"https://github.com/zaydek.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# stylex-dev\n\nA lightweight UMD shim for prototyping [StyleX](https://github.com/facebook/stylex) in the browser, attempting to replace the deprecated [`@stylexjs/dev-runtime`](https://www.npmjs.com/package/@stylexjs/dev-runtime). It supports the 90% use case and simplifies prototyping with AI tools like [Grok](https://grok.com/) and [ChatGPT](https://chatgpt.com/) by enabling StyleX-style code without constraining the browser environment to [StackBlitz](https://stackblitz.com/edit/vitejs-vite-3vkyxg) or relying on local code editors just to get started.\n\nTo be clear: This is a poor man's solution to quickly validate ideas and minimize code editor handoff friction. It is not intended for production use, nor optimized for performance or 100% compatibility (a long-term goal may be to improve this).\n\n## Features\n\n- Supports [`stylex.create`](https://stylexjs.com/docs/api/javascript/create/) for defining styles.\n- Handles [`stylex.props`](https://stylexjs.com/docs/api/javascript/props/) for applying styles, including pseudo-classes (e.g., `:hover`, `:focus`).\n- Implements [`stylex.keyframes`](https://stylexjs.com/docs/api/javascript/keyframes/) for CSS animations.\n\n## Basic Example\n\n\u003csmall\u003eThis is also provided as source code [here](/examples/basic.html).\u003c/small\u003e\u003cbr\u003e\n\u003csmall\u003eThis is also provided as a hosted web demo [here](https://68271e09ee75fc38a25addb6--stylex-dev.netlify.app/basic.html).\u003c/small\u003e\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003ctitle\u003eStyleX React Prototype\u003c/title\u003e\n  \u003c!-- Include React/React DOM --\u003e\n  \u003cscript src=\"https://unpkg.com/react@18/umd/react.development.js\"\u003e\u003c/script\u003e\n  \u003cscript src=\"https://unpkg.com/react-dom@18/umd/react-dom.development.js\"\u003e\u003c/script\u003e\n  \u003c!-- Include Babel (necessary for JSX transpilation) --\u003e\n  \u003cscript src=\"https://unpkg.com/@babel/standalone@7/babel.min.js\"\u003e\u003c/script\u003e\n  \u003c!-- Include the shim --\u003e\n  \u003cscript src=\"https://unpkg.com/stylex-dev@0.0.4/stylex-dev.umd.js\"\u003e\u003c/script\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cdiv id=\"root\"\u003e\u003c/div\u003e\n  \u003cscript type=\"text/babel\"\u003e\n    // Make StyleX a global reference, similar to import * as stylex from \"@stylexjs/stylex\";\n    const stylex = window.stylex;\n\n    // Define a keyframe animation using stylex.keyframes\n    const fadeIn = stylex.keyframes({\n      '0%': { opacity: 0 },\n      '100%': { opacity: 1 },\n    });\n\n    // Define styles using stylex.create\n    const styles = stylex.create({\n      container: {\n        padding: 20,\n        backgroundColor: '#f0f0f0',\n        animationName: fadeIn,\n        animationDuration: '1s',\n      },\n      button: {\n        padding: 10,\n        backgroundColor: '#007bff',\n        color: 'white',\n        ':hover': {\n          default: null,\n          backgroundColor: '#0056b3',\n        },\n      },\n    });\n\n    // Create a simple React component\n    const App = () =\u003e (\n      \u003cdiv {...stylex.props(styles.container)}\u003e\n        \u003cbutton {...stylex.props(styles.button)}\u003eClick Me\u003c/button\u003e\n      \u003c/div\u003e\n    );\n\n    // Render the React component\n    const root = ReactDOM.createRoot(document.getElementById('root'));\n    root.render(\u003cApp /\u003e);\n  \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003e [!TIP]\n\u003e Add something like the above to your favorite AI chat app's system prompt so you can quickly prototype and validate ideas in the browser! This should work in most AI apps that support artifacts like [Claude](https://www.anthropic.com/claude), [ChatGPT](https://chatgpt.com/), and [Grok](https://www.x.ai/grok).\n\u003e\n\u003e Here is an [example prompt](https://gist.github.com/zaydek/af6c69491f3cd6f1f1b835fc3941e799) to get you started. YMMV.\n\n## Comprehensive Example\n\n\u003csmall\u003eThis is also provided as source code [here](/examples/comprehensive.html).\u003c/small\u003e\u003cbr\u003e\n\u003csmall\u003eThis is also provided as a hosted web demo [here](https://68271e09ee75fc38a25addb6--stylex-dev.netlify.app/comprehensive.html).\u003c/small\u003e\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml\u003e\n\u003chead\u003e\n  \u003ctitle\u003eTodo App with React + StyleX\u003c/title\u003e\n  \u003cscript src=\"https://unpkg.com/react@18/umd/react.development.js\"\u003e\u003c/script\u003e\n  \u003cscript src=\"https://unpkg.com/react-dom@18/umd/react-dom.development.js\"\u003e\u003c/script\u003e\n  \u003cscript src=\"https://unpkg.com/@babel/standalone@7/babel.min.js\"\u003e\u003c/script\u003e\n  \u003cscript src=\"https://unpkg.com/stylex-dev@0.0.4/stylex-dev.umd.js\"\u003e\u003c/script\u003e\n  \u003clink rel=\"preconnect\" href=\"https://fonts.googleapis.com\"\u003e\n  \u003clink rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin\u003e\n  \u003clink href=\"https://fonts.googleapis.com/css2?family=Karla:ital,wght@0,200..800;1,200..800\u0026display=swap\" rel=\"stylesheet\"\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n  \u003cdiv id=\"root\"\u003e\u003c/div\u003e\n  \u003cscript type=\"text/babel\"\u003e\n    const stylex = window.stylex;\n\n    const slideIn = stylex.keyframes({\n      '0%': { transform: 'translateY(-20px)', opacity: 0 },\n      '100%': { transform: 'translateY(0)', opacity: 1 },\n    });\n\n    const shimmer = stylex.keyframes({\n      '0%': { backgroundPosition: '-200px 0' },\n      '100%': { backgroundPosition: '200px 0' },\n    });\n\n    const containerStyles = stylex.create({\n      main: {\n        maxInlineSize: '600px',\n        margin: '20px auto',\n        padding: 20,\n        backgroundColor: '#f5f5f5',\n        borderRadius: 8,\n        boxShadow: '0 2px 4px rgba(0,0,0,0.1)',\n        fontFamily: '\"Karla\", sans-serif',\n      },\n      title: {\n        color: '#333',\n        fontSize: 20,\n        marginBlockEnd: 20,\n        textAlign: 'center',\n        fontFamily: '\"Karla\", sans-serif',\n      },\n    });\n\n    const inputStyles = stylex.create({\n      wrapper: {\n        display: 'flex',\n        gap: 10,\n        marginBlockEnd: 20,\n      },\n      input: {\n        flex: 1,\n        padding: 10,\n        fontSize: 16,\n        border: '1px solid #ddd',\n        borderRadius: 4,\n        fontFamily: '\"Karla\", sans-serif',\n        ':focus': {\n          default: null,\n          outline: '2px solid #007bff',\n          borderColor: 'transparent',\n        },\n      },\n      button: {\n        padding: '10px 20px',\n        backgroundColor: '#007bff',\n        color: 'white',\n        border: 'none',\n        borderRadius: 4,\n        cursor: 'pointer',\n        fontFamily: '\"Karla\", sans-serif',\n        fontSize: 14,\n        ':hover': {\n          default: null,\n          backgroundColor: '#0056b3',\n        },\n      },\n    });\n\n    const taskStyles = stylex.create({\n      list: {\n        listStyle: 'none',\n        padding: 0,\n      },\n      item: {\n        display: 'flex',\n        alignItems: 'center',\n        padding: 10,\n        backgroundColor: 'white',\n        borderRadius: 4,\n        marginBlockEnd: 10,\n        animationDuration: '0.3s',\n        animationName: slideIn,\n        boxShadow: '0 1px 3px rgba(0,0,0,0.1)',\n        fontFamily: '\"Karla\", sans-serif',\n      },\n      text: {\n        flex: 1,\n        fontSize: 14,\n        color: '#333',\n        textDecoration: {\n          default: 'none',\n          completed: 'line-through',\n        },\n        fontFamily: '\"Karla\", sans-serif',\n      },\n      checkbox: {\n        marginInlineEnd: 10,\n        inlineSize: 20,\n        blockSize: 20,\n        cursor: 'pointer',\n      },\n      delete: {\n        padding: '5px 10px',\n        backgroundColor: '#ff4d4f',\n        color: 'white',\n        border: 'none',\n        borderRadius: 4,\n        cursor: 'pointer',\n        fontFamily: '\"Karla\", sans-serif',\n        fontSize: 14,\n        ':hover': {\n          default: null,\n          backgroundColor: '#cc0000',\n        },\n      },\n    });\n\n    const skeletonStyles = stylex.create({\n      main: {\n        maxInlineSize: '600px',\n        margin: '20px auto',\n        padding: 20,\n        backgroundColor: '#f5f5f5',\n        borderRadius: 8,\n        boxShadow: '0 2px 4px rgba(0,0,0,0.1)',\n      },\n      title: {\n        inlineSize: 200,\n        blockSize: 24,\n        background: 'linear-gradient(90deg, #e0e0e0 25%, #f0f0f0 50%, #e0e0e0 75%)',\n        backgroundSize: '200px 100%',\n        animationName: shimmer,\n        animationDuration: '1.5s',\n        animationIterationCount: 'infinite',\n        borderRadius: 4,\n        margin: '0 auto 20px',\n      },\n      wrapper: {\n        display: 'flex',\n        gap: 10,\n        marginBlockEnd: 20,\n      },\n      input: {\n        flex: 1,\n        blockSize: 40,\n        background: 'linear-gradient(90deg, #e0e0e0 25%, #f0f0f0 50%, #e0e0e0 75%)',\n        backgroundSize: '200px 100%',\n        animationName: shimmer,\n        animationDuration: '1.5s',\n        animationIterationCount: 'infinite',\n        borderRadius: 4,\n      },\n      button: {\n        inlineSize: 80,\n        blockSize: 40,\n        background: 'linear-gradient(90deg, #e0e0e0 25%, #f0f0f0 50%, #e0e0e0 75%)',\n        backgroundSize: '200px 100%',\n        animationName: shimmer,\n        animationDuration: '1.5s',\n        animationIterationCount: 'infinite',\n        borderRadius: 4,\n      },\n      task: {\n        blockSize: 40,\n        background: 'linear-gradient(90deg, #e0e0e0 25%, #f0f0f0 50%, #e0e0e0 75%)',\n        backgroundSize: '200px 100%',\n        animationName: shimmer,\n        animationDuration: '1.5s',\n        animationIterationCount: 'infinite',\n        borderRadius: 4,\n        marginBlockEnd: 10,\n      },\n    });\n\n    const SkeletonLoader = () =\u003e {\n      return (\n        \u003cdiv {...stylex.props(skeletonStyles.main)}\u003e\n          \u003cdiv {...stylex.props(skeletonStyles.title)}\u003e\u003c/div\u003e\n          \u003cdiv {...stylex.props(skeletonStyles.wrapper)}\u003e\n            \u003cdiv {...stylex.props(skeletonStyles.input)}\u003e\u003c/div\u003e\n            \u003cdiv {...stylex.props(skeletonStyles.button)}\u003e\u003c/div\u003e\n          \u003c/div\u003e\n          \u003cdiv {...stylex.props(skeletonStyles.task)}\u003e\u003c/div\u003e\n          \u003cdiv {...stylex.props(skeletonStyles.task)}\u003e\u003c/div\u003e\n        \u003c/div\u003e\n      );\n    };\n\n    const TodoApp = () =\u003e {\n      const [tasks, setTasks] = React.useState([]);\n      const [newTask, setNewTask] = React.useState('');\n      const [isLoading, setIsLoading] = React.useState(true);\n\n      // Load tasks from local storage on mount\n      React.useEffect(() =\u003e {\n        const savedTasks = localStorage.getItem('tasks');\n        if (savedTasks) {\n          setTasks(JSON.parse(savedTasks));\n        }\n        const timer = setTimeout(() =\u003e {\n          setIsLoading(false);\n        }, 2000);\n        return () =\u003e clearTimeout(timer);\n      }, []);\n\n      // Save tasks to local storage whenever tasks change\n      React.useEffect(() =\u003e {\n        if (!isLoading) {\n          localStorage.setItem('tasks', JSON.stringify(tasks));\n        }\n      }, [tasks, isLoading]);\n\n      const addTask = () =\u003e {\n        if (newTask.trim() === '') return;\n        setTasks([...tasks, { id: Date.now(), text: newTask, completed: false }]);\n        setNewTask('');\n      };\n\n      const toggleTask = (id) =\u003e {\n        setTasks(tasks.map(task =\u003e\n          task.id === id ? { ...task, completed: !task.completed } : task\n        ));\n      };\n\n      const deleteTask = (id) =\u003e {\n        setTasks(tasks.filter(task =\u003e task.id !== id));\n      };\n\n      const handleKeyPress = (e) =\u003e {\n        if (e.key === 'Enter') addTask();\n      };\n\n      if (isLoading) {\n        return \u003cSkeletonLoader /\u003e;\n      }\n\n      return (\n        \u003cdiv {...stylex.props(containerStyles.main)}\u003e\n          \u003ch1 {...stylex.props(containerStyles.title)}\u003eTodo App\u003c/h1\u003e\n          \u003cdiv {...stylex.props(inputStyles.wrapper)}\u003e\n            \u003cinput\n              {...stylex.props(inputStyles.input)}\n              type=\"text\"\n              value={newTask}\n              onChange={(e) =\u003e setNewTask(e.target.value)}\n              onKeyPress={handleKeyPress}\n              placeholder=\"Add a new task...\"\n            /\u003e\n            \u003cbutton\n              {...stylex.props(inputStyles.button)}\n              onClick={addTask}\n            \u003e\n              Add\n            \u003c/button\u003e\n          \u003c/div\u003e\n          \u003cul {...stylex.props(taskStyles.list)}\u003e\n            {tasks.map(task =\u003e (\n              \u003cli\n                {...stylex.props(taskStyles.item)}\n                key={task.id}\n              \u003e\n                \u003cinput\n                  {...stylex.props(taskStyles.checkbox)}\n                  type=\"checkbox\"\n                  checked={task.completed}\n                  onChange={() =\u003e toggleTask(task.id)}\n                /\u003e\n                \u003cspan {...stylex.props(taskStyles.text, task.completed \u0026\u0026 taskStyles.text.completed)}\u003e\n                  {task.text}\n                \u003c/span\u003e\n                \u003cbutton\n                  {...stylex.props(taskStyles.delete)}\n                  onClick={() =\u003e deleteTask(task.id)}\n                \u003e\n                  Delete\n                \u003c/button\u003e\n              \u003c/li\u003e\n            ))}\n          \u003c/ul\u003e\n        \u003c/div\u003e\n      );\n    };\n\n    const root = ReactDOM.createRoot(document.getElementById('root'));\n    root.render(\u003cTodoApp /\u003e);\n  \u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003e [!TIP]\n\u003e Add something like the above to your favorite AI chat app's system prompt so you can quickly prototype and validate ideas in the browser! This should work in most AI apps that support artifacts like [Claude](https://www.anthropic.com/claude), [ChatGPT](https://chatgpt.com/), and [Grok](https://www.x.ai/grok).\n\u003e\n\u003e Here is an [example prompt](https://gist.github.com/zaydek/af6c69491f3cd6f1f1b835fc3941e799) to get you started. YMMV.\n\n## Limitations\n\n- Covers only the 90% use case: `stylex.keyframes`, `stylex.create`, and `stylex.props`.\n- Support is limited to React, though it may technically work with other libraries (untested).\n- Limited support for pseudo-classes (e.g., `:hover`, `:focus`), though others may work (untested).\n- ‼️ DEOPTIMIZED ‼️ This is not intended for production!\n\n## Future\n\nIf useful, I may add support for APIs like [`stylex.defineVars`](https://stylexjs.com/docs/api/javascript/defineVars/) and [`stylex.createTheme`](https://stylexjs.com/docs/api/javascript/createTheme/), etc. to better close the gap.\n\n## License\n\n[MIT](https://github.com/zaydek/stylex-dev/README.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzaydek%2Fstylex-dev","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzaydek%2Fstylex-dev","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzaydek%2Fstylex-dev/lists"}