facebook / facebook/stylex

[docs] Add support for playground persistence

Open
#832 4 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
JavaScript
Stars
10.3k
Forks
481
Avg merge
3d 8h
Merged PRs (30d)
13

Description

### Describe the feature request

Lately, I've been using Claude to prototype a UI, then convert it to StyleX afterward. This works surprisingly well, but I'd love to not rely exclusively on Claude. ChatGPT doesn't support something like artifacts for rendering UI yet.

That said, the new playground opens up the possibility to quickly generate code using any LLM based on the source code provided in the playground and quickly paste the results. This turns out to work!

**What I'm hoping for now is simply the possibility for persistence in the playground tool.**

Some ideas:
- SolidJS's playground used to use a string algorithm (I think it was called Lezer string compression?) to inline the code in the URL (ugly but works and no server required)
- Tailwind Play does the traditional thing which is persist to a server and gives you a simple URL to easily copy, bookmark, etc.

---

This was basically one shot by Claude once it understood it should use StyleX as opposed to Tailwind. I'd really like to be able to persist playgrounds such as this so I can scaffold dozens of ideas and bookmark them or share them for example on social media.

View Code Example

```jsx
import { useState } from 'react';
import * as stylex from '@stylexjs/stylex';

export default function TodoApp() {
const [todos, setTodos] = useState([]);
const [newTodo, setNewTodo] = useState('');

const handleSubmit = (e) => {
e.preventDefault();
if (!newTodo.trim()) return;

setTodos([...todos, {
id: Date.now(),
text: newTodo.trim(),
completed: false
}]);
setNewTodo('');
};

const toggleTodo = (id) => {
setTodos(todos.map(todo =>
todo.id === id ? { ...todo, completed: !todo.completed } : todo
));
};

const deleteTodo = (id) => {
setTodos(todos.filter(todo => todo.id !== id));
};

return (




setNewTodo(e.target.value)}
placeholder="Add a new todo..."
{...stylex.props(form.input)}
/>

Add Todo



{todos.map(todo => (


toggleTodo(todo.id)}
{...stylex.props(todos.checkbox)}
/>

{todo.text}


deleteTodo(todo.id)}
{...stylex.props(button.delete)}
>
Delete


))}

{todos.length === 0 && (


No todos yet. Add some tasks above!


)}


);
}

/* General color scheme */
const LIGHT_MODE = '@media (prefers-color-scheme: light)';

/* Typography Styles */
const text = stylex.create({
title: {
fontSize: '1.8rem',
marginBottom: '0.5em',
textAlign: 'center',
},
description: {
fontSize: '0.9rem',
marginBottom: '1.5em',
color: '#666',
textAlign: 'center',
},
empty: {
textAlign: 'center',
color: '#666',
marginTop: '2em',
fontSize: '0.9rem',
},
});

/* Layout Styles */
const layout = stylex.create({
container: {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: '2em',
minHeight: '100vh',
},
});

/* Card Styles */
const card = stylex.create({
container: {
backgroundColor: {
default: '#1e1e1e',
[LIGHT_MODE]: '#fff',
},
borderRadius: 8,
padding: '2em',
boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
maxWidth: '800px',
width: '100%',
},
});

/* Form Styles */
const form = stylex.create({
container: {
marginBottom: '2em',
},
inputGroup: {
display: 'flex',
gap: '1em',
},
input: {
flex: 1,
padding: '0.5em',
borderRadius: 4,
border: '1px solid #ccc',
fontSize: '1em',
':focus': {
outline: 'none',
borderColor: '#646cff',
},
},
});

/* Button Styles */
const button = stylex.create({
primary: {
padding: '0.6em 1.2em',
fontSize: '1em',
fontWeight: 500,
borderRadius: 4,
border: 'none',
backgroundColor: {
default: '#646cff',
[LIGHT_MODE]: '#747bff',
},
color: '#fff',
cursor: 'pointer',
transition: 'background-color 0.2s',
':hover': {
backgroundColor: '#535bf2',
},
},
delete: {
padding: '0.4em 0.8em',
fontSize: '0.9em',
borderRadius: 4,
border: 'none',
backgroundColor: '#ff4444',
color: '#fff',
cursor: 'pointer',
transition: 'background-color 0.2s',
':hover': {
backgroundColor: '#cc0000',
},
},
});

/* Todos Styles */
const todos = stylex.create({
container: {
display: 'flex',
flexDirection: 'column',
gap: '0.8em',
},
item: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
padding: '0.8em',
backgroundColor: {
default: '#2a2a2a',
[LIGHT_MODE]: '#f5f5f5',
},
borderRadius: 4,
},
label: {
display: 'flex',
alignItems: 'center',
gap: '0.8em',
flex: 1,
},
checkbox: {
width: '1.2em',
height: '1.2em',
cursor: 'pointer',
},
text: {
fontSize: '1em',
color: {
default: '#fff',
[LIGHT_MODE]: '#333',
},
},
completed: {
textDecoration: 'line-through',
color: '#666',
},
});
```

Screenshot 2025-01-03 at 8 42 45 PM

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.