{"id":19620600,"url":"https://github.com/alphicc/brick","last_synced_at":"2025-04-28T03:32:11.919Z","repository":{"id":41125317,"uuid":"426521641","full_name":"alphicc/Brick","owner":"alphicc","description":"🧱 Brick - Multiplatform navigation library for Compose. ","archived":false,"fork":false,"pushed_at":"2024-10-22T18:58:02.000Z","size":10991,"stargazers_count":54,"open_issues_count":3,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-05T05:51:09.505Z","etag":null,"topics":["android","android-library","compose","compose-multiplatform","desktop","jetpack-compose","kotlin","library","multiplatform","multistack","navigation"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alphicc.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}},"created_at":"2021-11-10T07:16:48.000Z","updated_at":"2025-02-19T05:09:59.000Z","dependencies_parsed_at":"2024-11-11T11:29:46.217Z","dependency_job_id":null,"html_url":"https://github.com/alphicc/Brick","commit_stats":null,"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alphicc%2FBrick","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alphicc%2FBrick/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alphicc%2FBrick/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alphicc%2FBrick/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alphicc","download_url":"https://codeload.github.com/alphicc/Brick/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251246154,"owners_count":21558759,"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":["android","android-library","compose","compose-multiplatform","desktop","jetpack-compose","kotlin","library","multiplatform","multistack","navigation"],"created_at":"2024-11-11T11:19:23.641Z","updated_at":"2025-04-28T03:32:06.910Z","avatar_url":"https://github.com/alphicc.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"![MAVEN](https://img.shields.io/badge/Maven-v2.4.1-blue) ![Platform](https://img.shields.io/badge/platform-android-green?color=lightgray) ![API](https://img.shields.io/badge/API-21-brightgreen?color=brightgreen) ![Platform](https://img.shields.io/badge/platform-desktop-green?color=lightgray)\n\u003ch1 align=\"center\"\u003e\n    \u003cimg height=\"300\" src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/logo.png\"/\u003e\n    \u003cbr\u003e\n\t    Brick\n    \u003c/br\u003e\n    \u003cbr\u003e\n\t\t\u003cem\u003e\n\t\t\tTake control of your apps\n\t\t\u003c/em\u003e\n    \u003c/br\u003e\n\u003c/h1\u003e\n\nBrick is a lightweight library to make navigation.\n\n## Features\n\n+ Framework free (Router can be injected in any layer of project. Navigate from any place you want. Example:\n  UI-navigation or business logic navigation)\n+ Child component navigation (easy BottomSheet navigation, Tab navigation, Dialogs navigation)\n+ Composite navigation (build component from many mini-components.)\n+ Decompose everything (Decompose component by buttons, text fields etc.!)\n+ Nested navigation\n+ Lifecycle\n+ Multi-module navigation (provide router instance from any module to any module or just implement all app navigation\n  inside one module or something else)\n+ Deep-link support\n+ Arguments support\n+ components communication support\n+ Current component check\n+ Transition animations\n+ Overlay navigation\n\n## Samples\n\n\u003ctable align=\"center\"\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003cimg src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/overlay%20sample.gif\" width=\"256\"/\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cimg src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/animations%20sample.gif\" width=\"256\"/\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cimg src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/small%20sample.gif\" width=\"256\"/\u003e\n        \u003c/td\u003e\n        \u003ctd\u003e\n            \u003cimg src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/large%20sample.gif\" width=\"256\"/\u003e\n        \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd align=\"center\"\u003e\n            Overlay sample\n        \u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\n            Transition Animation\n        \u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\n            Small sample\n        \u003c/td\u003e\n        \u003ctd align=\"center\"\u003e\n            Large sample\n        \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003ctable align=\"center\"\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\n            \u003cimg src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/desktop%20sample.gif\"/\u003e\n        \u003c/td\u003e\n    \u003c/tr\u003e\n    \u003ctr\u003e\n        \u003ctd align=\"center\"\u003e\n            Desktop sample\n        \u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\n## Installation\n\nAdd repository in your project\n\n```kotlin\nrepositories {\n    mavenCentral()\n    maven {\n        url \"https://maven.pkg.jetbrains.space/public/p/compose/dev\"\n    }\n}\n```\n\nAdd the dependency in your build.gradle\n\n```kotlin\ndependencies {\n    //Brick\n    implementation 'io.github.alphicc:brick:2.3.0'\n}\n```\n\nAndroid: Set jvmTarget in your build.gradle\n\n```kotlin\nkotlinOptions {\n    jvmTarget = '11'\n}\n```\n\nThats all!\n\n## Usage\n\n1. Create **Router** in **any** place of your project (**Note: router contains all information about component. Router\n   destroyed = all navigation/components data destroyed**).\n\n```kotlin\nval router: TreeRouter = TreeRouter.new()\n```\n\n2. Create **Component**. **Component != UI**. Component has lifecycle, channels to communicate between other components.\n   Component can live without UI. UI - part of Component.\n\n```kotlin\nval component1 = Component\u003cUnit\u003e(\n    key = \"1\",\n    content = { _, _ -\u003e SimpleComponent(1, \"new\") { smallSampleRouter.addComponent(component2) } } // content - ui\n)\n```\n\n3. Provide **ContainerConnector** to **%PLATFORM%AnimatedComponentsContainer** or  **%PLATFORM%ComponentsContainer** .\n   Your Router implements **ContainerConnector**.\n\n```kotlin\nclass SmallSampleActivity : ComponentActivity() {\n\n    val containerConnector: ContainerConnector = ... //inject or provide from application class\n\n    override fun onCreate(savedInstanceState: Bundle?) {\n        super.onCreate(savedInstanceState)\n\n        setContent {\n            AndroidComponentsContainer(containerConnector) {\n                //on router empty callback\n                //called only one router\n                //e.g. : [ParentRouter] (has [ChildRouter1], [ChildRouter2] )\n                //ChildRouter1.cleanRouter -\u003e onRouterEmpty called only inside ChildRouter1\n                //ParentRouter.cleanRouter -\u003e onRouterEmpty called only inside ParentRouter\n                //When you called newRootComponent inside ParentRouter, ChildRouter# onRouterEmpty method didn't called\n            }\n        }\n    }\n}\n```\n\n4. Navigate!\n\n## Work representation\n\n### Integration schema\n\n\u003ch1 align=\"center\"\u003e\n    \u003cimg height=\"500\" src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/integration%20schema.png\"/\u003e\n\u003c/h1\u003e\n\n### Work schema\n\n\u003ch1 align=\"center\"\u003e\n    \u003cimg height=\"500\" src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/work%20schema.png\"/\u003e\n\u003c/h1\u003e\n\n### Lifecycle sample\n\n\u003ch1 align=\"center\"\u003e\n    \u003cimg height=\"600\" src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/lifecycle.png\"/\u003e\n\u003c/h1\u003e\n\n## Multistack navigation\n\n1. Create nested router using **branch** method.\n\n```kotlin\n//Components.bottomMenuComponent.key - component key that contains nested container\nprivate val firstMenuRouter = mainRouter.branch(Components.bottomMenuComponent.key).apply {\n    addComponent(Components.innerNavigationComponent, this)//initial navigation sample\n}\n```\n\n2. Pass created nested router to your nested **%PLATFORM%ComponentsContainer**.\n\n```kotlin\n//inside your composable function\n%PLATFORM % AnimatedComponentsContainer(firstMenuRouter)\n```\n\n3. Use your nested router to make nested navigation!\n\n### Multistack graph sample (simple)\n\n\u003ch1 align=\"center\"\u003e\n    \u003cimg height=\"600\" src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/multistack%20graph%20short.png\"/\u003e\n\u003c/h1\u003e\n\n### Multistack graph sample (extended)\n\n\u003ch1 align=\"center\"\u003e\n    \u003cimg height=\"600\" src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/multistack%20graph%20full.png\"/\u003e\n\u003c/h1\u003e\n\n## Composite navigation\n\nStarting with version 2.* and above, you can extract small UI components to the **Component** and paste this small\ncomponents in any place of other **Component** you want. Thus making them reusable. It also makes it possible to further\ndecompose work when working in the team. Allowing you to work on one small UI component (like button, text field etc.)\nwithout affecting other components.\n\nScreen sample\n\u003ch1 align=\"center\"\u003e\n    \u003cimg height=\"600\" src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/composite%20screen.png\"/\u003e\n\u003c/h1\u003e\n\nDecompose your screen by components\n\n\u003ch1 align=\"center\"\u003e\n    \u003cimg height=\"600\" src=\"https://raw.githubusercontent.com/alphicc/Brick/main/media/screen%20parts.png\"/\u003e\n\u003c/h1\u003e\n\n**Code sample**\n\nMain screen component\n\n```kotlin\nval compositeScreen = Component\u003cUnit\u003e(\n    key = \"CompositeScreen\",\n    content = { _, compositeContainer -\u003e\n        Box(modifier = Modifier.fillMaxSize()) {\n            Box(modifier = Modifier.align(Alignment.TopCenter)) {\n                compositeContainer.place(component1.key)//use place method to define position of your component\n            }\n\n            Box(modifier = Modifier.align(Alignment.Center)) {\n                compositeContainer.place(component3.key)\n            }\n\n            Box(modifier = Modifier.align(Alignment.BottomCenter)) {\n                compositeContainer.place(component2.key)\n            }\n        }\n    }\n)\n```\n\nComponents.\n```kotlin\nval component1 = Component\u003cUnit\u003e(\n    key = \"CompositeScreenInternal 1\",\n    keepAliveCompose = true, //to keep compose ui in the graph (NOTE!!! ANIMATION DIDN'T WORK WITH keepAliveCompose = true. default = false)\n    onCreate = { _, _ -\u003e }, lifecycle of your componentg\n    onDestroy = { _ -\u003e },\n    content = { _, _ -\u003e Text(\"CompositeScreenInternal 1\") }\n)\n\nval component2 = Component\u003cUnit\u003e(\n    key = \"CompositeScreenInternal 2\",\n    content = { _, _ -\u003e Text(\"CompositeScreenInternal 2\") }\n)\n\nval component3 = Component\u003cUnit\u003e(\n    key = \"CompositeScreenInternal 3\",\n    content = { _, _ -\u003e\n        Button({}) {\n            Text(\"CompositeScreenInternal 3\")\n        }\n    }\n)\n```\n\nAttach your components to main component (screen)\n```kotlin\ncompositeSampleRouter.addComponent(compositeScreen) // default navigation method. like addScreen method in 1.*.*\ncompositeSampleRouter.attachCompositeComponent(component1, \"321\") // attach component into compositeScreen\ncompositeSampleRouter.attachCompositeComponent(component2) //composite components will be attached to current main component (screen)\ncompositeSampleRouter.attachCompositeComponent(component3)\ncompositeSampleRouter.detachCompositeComponent(component3) // use to detach composite component from main component\n```\n\n**Note: composite components are shared between the component they are added to and its child components**\n\n## Communicate between components\n\n**Pass data**\n```kotlin\n// router - is your TreeRouter\n// Screens.channelArgumentReceiveComponent.key - key of your destination component\n// counter - argument\nrouter.passArgument(Screens.channelArgumentReceiveComponent.key, counter)\n// Also you can pass broadcast argument to SharedFlow\nval argument: CustomArgumentType = CustomArgumentType()\nrouter.passBroadcastArgument(argument) // Use it to pass argument to SharedFlow\n\nrouter.broadcastFlow // Use it to receive arguments from SharedFlow\n    .filterIsInstance\u003cCustomArgumentType\u003e()\n    .onEach { argument -\u003e\n        \n    }\n    ...\n```\n\n**Receive data**\n```kotlin\n...\nonCreate = { channel, _ -\u003e return@Component ChannelArgumentReceiveViewModel(channel) }, //channel it is a SharedFlow that located in component onCreate lifecycle method\n...\n\n// Use method get\u003cT\u003e to receive your data\nchannel.onEach { _count.value = it.get() }.launchIn(scope)\n```\n\n## Navigation methods list\n\n+ currentComponentKey\n+ backComponent\n+ backToComponent\n+ replaceComponent\n+ addComponent\n+ lastChildKey\n+ backChild\n+ backToChild\n+ replaceChild\n+ addChild\n+ cleanRouter\n+ setOverlay\n+ removeOverlay\n+ newRootComponent\n+ attachCompositeComponent\n+ detachCompositeComponent\n\n## Migrate from 1.* to 2.* version\n+ Rename **AndroidAnimatedScreensContainer** to **AndroidAnimatedComponentsContainer**\n+ Rename **AndroidScreensContainer** to **AndroidComponentsContainer**\n+ Rename **DesktopAnimatedScreensContainer** to **DesktopAnimatedComponentsContainer**\n+ Rename **DesktopScreensContainer** to **DesktopComponentsContainer**\n+ To handle router empty action provide **onRouterEmpty** callback into **%PLATFORM%ComponentsContainer**\n+ Rename **Screen\\\u003cT\u003e** to **Component\\\u003cT\u003e**\n+ Inside **Component\\\u003cT\u003e** change\n```kotlin\n...\ncontent = { dataContainer -\u003e  }\n...\n//to\n...\ncontent = { dataContainer, compositeContainer -\u003e  }\n...\n```\n+ Rename **currentScreenKey** to **currentComponentKey**\n+ Rename **backScreen** to **backComponent**\n+ Rename **backToScreen** to **backToComponent**\n+ Rename **replaceScreen** to **replaceComponent**\n+ Rename **addScreen** to **addComponent**\n+ Rename **newRootScreen** to **newRootComponent**\n+ To fix other package changes just reimport","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falphicc%2Fbrick","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falphicc%2Fbrick","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falphicc%2Fbrick/lists"}