Skip to content

About

No description, website, or topics provided.

Resources

Stars

21 stars

Watchers

1 watching

Forks

Latest commit

Β 

History

351 Commits

Folders and files

Repository files navigation

json-to-compose

πŸ€– AI AGENTS: Read AGENTS.md and PROGRESS.md before starting any task. Follow the 5-step process in docs/AI_PLANNING_PROCESS.md.

A library that dynamically converts JSON into Jetpack Compose components.

πŸ“ Description

json-to-compose is an Android library that allows you to convert JSON structures into Jetpack Compose components at runtime. This makes it easy to create dynamic interfaces and update UI based on remote data.

πŸ’‘ Use case

1. Server-Driven UI

This library is perfect for implementing Server-Driven UI patterns, where your backend controls the UI layout and content. Some benefits include:

  • Update your app's UI without deploying new versions
  • A/B testing different layouts and components
  • Dynamic content presentation based on user segments
  • Consistent UI across platforms by sharing the same JSON structure

Example:

@Composable
fun App() {
    var uiDefinition by remember { mutableStateOf(api.fetchUIDefinition()) }

    LaunchedEffect(Unit) {
        uiDefinition = api.fetchUIDefinition()
    }

    uiDefinition.ToCompose()
}

2. Generative UI

Integrate with AI services to create dynamic UIs based on user input or context:

  • AI-powered layout suggestions
  • Dynamic form generation based on user preferences
  • Context-aware UI adaptations
  • Prototype testing with AI-generated interfaces

Example:

@Composable
fun App(userContext: String) {
    val aiGeneratedUI = aiService.generateUIForUser(userContext)
    aiGeneratedUI.ToCompose()
}

⚑️ Installation

Add the following dependency to your build.gradle.kts file:

dependencies {
  implementation("com.jesusdmedinac:json-to-compose:1.1.0")
}

πŸš€ Usage

Basic Usage

@Composable
fun App() {
    MaterialTheme {
        JSON_AS_STRING.ToCompose()
    }
}

val JSON_AS_STRING = """
{
  "type": "Column",
  "properties": {
    "type": "ColumnProps",
    "children": [
      {
        "type": "Text",
        "properties": {
          "type": "TextProps",
          "text": "Hello World"
        }
      }
    ]
  }
}
""".trimIndent()

With Behaviors (Click Events)

@Composable
fun App() {
    val behaviors = mapOf(
        "button_clicked" to object : Behavior {
            override fun onClick() {
                println("Button was clicked!")
            }
        }
    )

    CompositionLocalProvider(LocalBehavior provides behaviors) {
        MaterialTheme {
            JSON_AS_STRING.ToCompose()
        }
    }
}

With State (TextField)

@Composable
fun App() {
    var textValue by remember { mutableStateOf("") }

    val stateHosts = mapOf(
        "my_text_field" to object : StateHost<String> {
            override val state: String get() = textValue
            override fun onStateChange(state: String) {
                textValue = state
            }
        }
    )

    CompositionLocalProvider(LocalStateHost provides stateHosts) {
        JSON_AS_STRING.ToCompose()
    }
}

With Drawable Resources

@Composable
fun App() {
    val drawableResources = mapOf(
        "my_icon" to Res.drawable.my_icon
    )

    CompositionLocalProvider(LocalDrawableResources provides drawableResources) {
        JSON_AS_STRING.ToCompose()
    }
}

With Advanced Actions (Navigation & Platform Abstractions)

json-to-compose supports advanced declarative action chains natively without writing custom behavior lambdas. Provide platform and navigation handlers via LocalNavigationHandler and LocalPlatformHandler CompositionLocals:

@Composable
fun App() {
    val navHandler = remember {
        object : NavigationHandler {
            override fun navigate(route: String, args: Map<String, Any?>) {
                println("Navigate to $route with args: $args")
            }
            override fun navigateBack() {
                println("Navigate Back")
            }
        }
    }

    val platformHandler = remember {
        object : PlatformHandler {
            override fun launchUrl(url: String) {
                // Open external browser URL
            }
            override fun copyToClipboard(text: String) {
                // Copy text to system clipboard
            }
        }
    }

    CompositionLocalProvider(
        LocalNavigationHandler provides navHandler,
        LocalPlatformHandler provides platformHandler
    ) {
        JSON_AS_STRING.ToCompose()
    }
}

Supported Advanced Actions

  • navigate: Navigates to a specific screen route.
  • navigateBack: Pops the current navigation stack.
  • delay: Asynchronously waits for durationMillis before executing the next action in a sequence.
  • conditional: Compares a state value using operator (Equals, NotEquals, GreaterThan, LessThan, Contains) and executes thenAction or optional elseAction.
  • incrementState / decrementState: Safely increments or decrements a numeric state.
  • launchUrl: Opens an external URL.
  • copyToClipboard: Copies text to the device clipboard.
  • updateList: Adds or removes items from a list state.

πŸ”§ Supported Components

Component Description Properties
Text Display text text, fontSize, fontWeight, fontStyle, color, textAlign, maxLines, overflow, letterSpacing, lineHeight, textDecoration, minLines
Button Standard filled button child, enabled, onClickEventName, shape, containerColor, contentColor
ElevatedButton Button with elevation child, enabled, onClickEventName, shape, containerColor, contentColor
FilledTonalButton Button with secondary container color child, enabled, onClickEventName, shape, containerColor, contentColor
OutlinedButton Button with border child, enabled, onClickEventName, shape, containerColor, contentColor
TextButton Button without border or background child, enabled, onClickEventName, shape, containerColor, contentColor
IconButton Button containing an icon child, enabled, onClickEventName, shape, containerColor, contentColor
FloatingActionButton Circular FAB child, containerColor, onClickEventName
ExtendedFAB FAB with icon and text icon, text, containerColor, onClickEventName
Icon Material Design icon iconName, tint
Column Vertical layout container verticalArrangement, horizontalAlignment, children
Row Horizontal layout container horizontalArrangement, verticalAlignment, children
Box Stacking layout container contentAlignment, propagateMinConstraints, children
Spacer Fixed size empty space Used with Width or Height modifiers
HorizontalDivider Material 3 horizontal line thickness, color
VerticalDivider Material 3 vertical line thickness, color
FlowRow Wrapping horizontal layout horizontalArrangement, verticalArrangement, children
FlowColumn Wrapping vertical layout horizontalArrangement, verticalArrangement, children
Surface Material 3 surface container tonalElevation, shadowElevation, color, shape, child
Image Display images url, resourceName, contentDescription, contentScale, alignment, colorFilter
TextField Text input field value, placeholder, label, leadingIcon, trailingIcon, isError, supportingText, singleLine, maxLines, keyboardType, visualTransformation, readOnly, prefix, suffix
OutlinedTextField Outlined text input field value, placeholder, label, leadingIcon, trailingIcon, isError, supportingText, singleLine, maxLines, keyboardType, visualTransformation, readOnly, prefix, suffix
LazyColumn Lazy vertical scrolling list children
LazyRow Lazy horizontal scrolling list children
HorizontalPager Horizontally swipeable pager pages, currentPage, beyondViewportPageCount, userScrollEnabled
VerticalPager Vertically swipeable pager pages, currentPage, beyondViewportPageCount, userScrollEnabled
Scaffold Material Design scaffold topBar, bottomBar, floatingActionButton, floatingActionButtonPosition, containerColor, child
Card Material Design card elevation, cornerRadius, containerColor, borderColor, borderWidth, child
ElevatedCard Card with elevated shadow elevation, cornerRadius, containerColor, borderColor, borderWidth, child
OutlinedCard Card with border outline borderColor, cornerRadius, containerColor, borderWidth, child
AlertDialog Material Design alert dialog title, text, confirmButton, dismissButton, icon, tonalElevation, visibilityState
ModalBottomSheet Bottom sheet modal container child, visible, visibleStateHostName, onDismissRequestEventName, dragHandle, showDragHandle, shape, scrimColor
TopAppBar Material 3 TopAppBar title, navigationIcon, actions, backgroundColor, contentColor
CenterAlignedTopAppBar Material 3 CenterAlignedTopAppBar title, navigationIcon, actions, backgroundColor, contentColor
MediumTopAppBar Material 3 MediumTopAppBar title, navigationIcon, actions, backgroundColor, contentColor
LargeTopAppBar Material 3 LargeTopAppBar title, navigationIcon, actions, backgroundColor, contentColor
NavigationBar Material Design bottom navigation children, containerColor, contentColor
NavigationBarItem Item for NavigationBar selected, label, icon, enabled, alwaysShowLabel, onClickEventName
NavigationRail Material Design side navigation children, header, containerColor, contentColor
NavigationRailItem Item for NavigationRail selected, label, icon, enabled, alwaysShowLabel, onClickEventName
ModalNavigationDrawer Side drawer navigation isOpen, drawerContent, child
NavigationDrawerItem Item for NavigationDrawer selected, label, badge, icon, onClickEventName
TabRow Row of tabs selectedTabIndex, children, containerColor, contentColor
ScrollableTabRow Scrollable row of tabs selectedTabIndex, children, containerColor, contentColor
Tab Item for TabRow selected, text, icon, enabled, onClickEventName
Badge Display notification badge text, textStateHostName, containerColor, contentColor
BadgedBox Layout container for a badge & child badge, child
AssistChip Action chip label, leadingIcon, onClickEventName, enabled, enabledStateHostName
SuggestionChip Suggestion chip label, leadingIcon, onClickEventName, enabled, enabledStateHostName
FilterChip Selection filter chip selected, selectedStateHostName, label, leadingIcon, onClickEventName, enabled, enabledStateHostName
InputChip Entry / tag chip selected, selectedStateHostName, label, leadingIcon, trailingIcon, onClickEventName, enabled, enabledStateHostName
CircularProgressIndicator Circular progress indicator progress, progressStateHostName, color, trackColor
LinearProgressIndicator Linear progress indicator progress, progressStateHostName, color, trackColor
PlainTooltip Plain tooltip text, anchor
RichTooltip Rich tooltip title, text, action, anchor
Custom User-defined components customType, customData
Switch Material toggle switch checked, onCheckedChange, enabled
Checkbox Material checkbox checked, onCheckedChange, enabled
Slider Range selection slider value, valueRange, steps, onValueChange, enabled
RadioButton Single choice button selected, onClick, enabled
SegmentedButtonRow Row of segmented buttons children (supports single and multi-choice)
DatePicker Material 3 date picker selectedDateMillis
TimePicker Material 3 time picker hour, minute, is24Hour
SearchBar Material 3 search bar query, placeholder, leadingIcon, trailingIcon, active, children
ListItem Material 3 list item component headlineContent, supportingContent, overlineContent, leadingContent, trailingContent, onClickEventName

🧩 Custom Components

Extend the library with your own components without forking:

// 1. Define your custom renderer
val customRenderers = mapOf(
    "ProductCard" to { node: ComposeNode ->
        val props = node.properties as? NodeProperties.CustomProps
        val data = props?.customData
        val title = data?.get("title")?.jsonPrimitive?.content ?: ""
        val price = data?.get("price")?.jsonPrimitive?.content ?: ""

        Card {
            Column {
                Text(text = title)
                Text(text = "$$price")
            }
        }
    }
)

// 2. Provide it to the composition
CompositionLocalProvider(LocalCustomRenderers provides customRenderers) {
    JSON_AS_STRING.ToCompose()
}

JSON for custom component:

{
  "type": "Custom",
  "properties": {
    "type": "CustomProps",
    "customType": "ProductCard",
    "customData": {
      "title": "My Product",
      "price": "99.99"
    }
  }
}

🎨 Modifiers

Apply modifiers to any component using composeModifier:

{
  "type": "Box",
  "properties": { "type": "BoxProps" },
  "composeModifier": {
    "operations": [
      { "type": "FillMaxWidth" },
      { "type": "Height", "value": 200 },
      { "type": "Padding", "value": 16 },
      { "type": "BackgroundColor", "color": "#FF5722" }
    ]
  }
}

Available operations:

  • Padding - Add padding (value in dp)
  • FillMaxSize - Fill maximum available size
  • FillMaxWidth - Fill maximum width
  • FillMaxHeight - Fill maximum height
  • Width - Set specific width (value in dp)
  • Height - Set specific height (value in dp)
  • BackgroundColor - Set background color (hex color)
  • Border - Add border (width, color, shape)
  • Shadow - Add shadow (elevation, shape, clip)
  • Clip - Clip to shape
  • Background - Set background (color, shape)
  • Alpha - Set opacity (value)
  • Rotate - Set rotation (degrees)
  • Clickable - Handle click events (onClickEventName)
  • Weight - Assign weight in Row/Column (weight)
  • VerticalScroll - Enable vertical scrolling
  • HorizontalScroll - Enable horizontal scrolling
  • Offset - Offset position (x, y in dp)
  • Size - Set exact size (width, height in dp)
  • WrapContentWidth - Wrap width to content
  • WrapContentHeight - Wrap height to content
  • AspectRatio - Constrain to ratio (ratio)
  • ZIndex - Adjust drawing order (zIndex)
  • MinWidth / MinHeight / MaxWidth / MaxHeight - Set constraints (value in dp)
  • AnimateContentSize - Animate size changes
  • TestTag - Apply tag for UI testing (tag)

πŸ“ Alignment & Arrangement

Box Alignment

{
  "type": "Box",
  "properties": {
    "type": "BoxProps",
    "contentAlignment": "Center"
  }
}

Values: TopStart, TopCenter, TopEnd, CenterStart, Center, CenterEnd, BottomStart, BottomCenter, BottomEnd

Column Arrangement

{
  "type": "Column",
  "properties": {
    "type": "ColumnProps",
    "verticalArrangement": "SpaceBetween",
    "horizontalAlignment": "CenterHorizontally"
  }
}

Vertical Arrangement: Top, Bottom, Center, SpaceEvenly, SpaceBetween, SpaceAround, SpacedBy:X (e.g. SpacedBy:16)

Horizontal Alignment: Start, CenterHorizontally, End

Row Arrangement

{
  "type": "Row",
  "properties": {
    "type": "RowProps",
    "horizontalArrangement": "SpaceEvenly",
    "verticalAlignment": "CenterVertically"
  }
}

Horizontal Arrangement: Start, End, Center, SpaceEvenly, SpaceBetween, SpaceAround

Vertical Alignment: Top, CenterVertically, Bottom

🧩 Composy

Composy is a web and desktop app that facilitates the creation of JSON structures for json-to-compose. It provides a compose-tree editor, real-time preview, and export functionality. Composy is perfect for designing dynamic UIs and generating JSON definitions for your app.

Features

  • Compose-tree editor
  • Real-time preview
  • Export functionality

πŸ§ͺ Testing & Testability

This library prioritizes rigorous UI testing. Beyond basic existence checks, it exposes visual properties (like fontSize, color, padding, and layout arrangements) through Jetpack Compose Semantics.

For detailed guidance, see:

πŸ“š Documentation

WIP

🀝 Contributing

WIP

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ“ž Contact

If you have questions or suggestions, feel free to:

About

No description, website, or topics provided.

Resources

Stars

21 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages