{"id":31629674,"url":"https://github.com/gregros/react-tk","last_synced_at":"2026-05-15T13:06:54.235Z","repository":{"id":317090896,"uuid":"977765169","full_name":"GregRos/react-tk","owner":"GregRos","description":"React, except it's for desktop UI in Python","archived":false,"fork":false,"pushed_at":"2025-10-16T18:16:42.000Z","size":429,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-17T18:55:11.370Z","etag":null,"topics":["aspect-oriented-programming","desktop-ui","framework","functional-programming","package","python","react","tkinter"],"latest_commit_sha":null,"homepage":"","language":"Python","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/GregRos.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-04T23:02:23.000Z","updated_at":"2025-10-16T18:16:46.000Z","dependencies_parsed_at":"2025-09-28T20:47:48.968Z","dependency_job_id":null,"html_url":"https://github.com/GregRos/react-tk","commit_stats":null,"previous_names":["gregros/reactk","gregros/react-tk"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/GregRos/react-tk","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GregRos%2Freact-tk","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GregRos%2Freact-tk/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GregRos%2Freact-tk/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GregRos%2Freact-tk/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/GregRos","download_url":"https://codeload.github.com/GregRos/react-tk/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/GregRos%2Freact-tk/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33067512,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-15T11:35:32.926Z","status":"ssl_error","status_checked_at":"2026-05-15T11:35:31.362Z","response_time":103,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["aspect-oriented-programming","desktop-ui","framework","functional-programming","package","python","react","tkinter"],"created_at":"2025-10-06T21:32:48.442Z","updated_at":"2026-05-15T13:06:54.223Z","avatar_url":"https://github.com/GregRos.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-tk\r\n\r\nReact-tk is an experimental framework building Tkinter UIs using React principles. It uses a shadow UI reconciliation system, tracking changes in props and context to determine what needs to be updated in the actual Tkinter widgets.\r\n\r\nFeatures and limitations:\r\n\r\n- Full type hints for everything, like props\r\n- Runtime validation for a lot of things, like props\r\n- Narrow interface, you only need a few key imports.\r\n- Most similar to older-style React with class components.\r\n- ShadowNodes use an extensible property schema system using TypedDicts.\r\n\r\n- Two building blocks: ShadowNode and Component. These are \"renderables\"\r\n- ShadowNode are provided by the library and represent Tk UI elements.\r\n- ShadowNodes are equivalent to React-provided HTML components.\r\n- ShadowNode is subclassed by different UI nodes.\r\n- Components are user-defined abstractions that produce other renderables, one or more.\r\n- Components are not used internally by the framework.\r\n- Components act via their `render()` method.\r\n\r\n- There is no JSX equivalent. UI elements are described by Python objects.\r\n- These objects have props passed via their constructors.\r\n- User-defined Components are expected to be dataclasses with `kw_only=True`\r\n- The children of a component or a ShadowNode are specified with square brackets `[...]`\r\n- You can access the children of a component using `self.KIDS`.\r\n\r\n- Components don't support state, only props and context.\r\n- Since there is no state, all the `render()` methods are called with every change.\r\n\r\n- ShadowNodes sometimes accept several kinds of props.\r\n- For example, Widgets accept base props and layout manager props.\r\n- This works using a separate method you need to call. See below.\r\n\r\n## Install\r\n\r\n```bash\r\npoetry add react-tk\r\n```\r\n\r\n## Tk Nodes / Widgets / Resources\r\n\r\nCurrently only a handful of UI elements are supported:\r\n\r\n- Label\r\n- Window\r\n- Frame\r\n\r\n## Step by step\r\n\r\nLet's take a look at building a very simple UI step by step.\r\n\r\n### Importing\r\n\r\nFirst, let's import the stuff we'll need:\r\n\r\n```python\r\nfrom react_tk import Window, WindowRoot, Widget, Label, Component\r\n```\r\n\r\n1. The `WindowRoot` which is used to mount components into Tk.\r\n2. The `Window` node that represents a window.\r\n3. The `Label` node that represents a Label.\r\n4. The `Component` base class.\r\n5. The `Widget` node we use to express Widget components.\r\n\r\n### Define a custom widget component\r\n\r\nWe typically define Components as dataclasses with `kw_only=True`. This Component should have a `render` method that returns other components or ShadowNode objects, such as those representing various Tk elements.\r\n\r\nIn this case, our component returns a single `Label`.\r\n\r\nThe Label's props are divided into the base props and the layout manager props. To set to layout manager props, you need to call the appropriate method on the Widget ShadowNode.\r\n\r\nRight now only `Pack` is supported.\r\n\r\n```python\r\nLabel().Pack(\r\n    ipadx=20,\r\n    fill=\"both\"\r\n)\r\n```\r\n\r\nReturn this from your component:\r\n\r\n```python\r\n@dataclass(kw_only=True)\r\nclass TextComponent(Component[Widget]):\r\n    text: str\r\n\r\n    def render(self):\r\n        return Label(\r\n            text=self.text,\r\n            background=\"#000001\",\r\n            foreground=\"#ffffff\",\r\n            font=Font(family=\"Arial\", size=20, style=\"bold\"),\r\n        ).Pack(ipadx=20, ipady=15, fill=\"both\")\r\n```\r\n\r\nNote that you can just subclass `Component` and not `Component[X]`. It just adds a bit of type checking. There is no difference between `Component[Widget]` and `Component[Window]` during runtime.\r\n\r\n### Define a Window component\r\n\r\nWidgets are must be contained in Windows. Windows aren't contained in anything, as we'll see. We need to create a component that returns Window nodes.\r\n\r\nTo have our previous component be contained in a Window node, we create the Window node and then use `[...]` square brackets to specify children.\r\n\r\n```py\r\nWindow()[\r\n    TextComponent(text=\"abc\")\r\n]\r\n```\r\n\r\nNow we create the Window component. We'll use context, which works kind of like in React. It's passed down all the components. You can access it from a component using `self.ctx`.\r\n\r\n```py\r\n@dataclass(kw_only=True)\r\nclass WindowComponent(Component[Window]):\r\n    def render(self):\r\n        return Window(topmost=True, background=\"black\", alpha=85).Geometry(\r\n            width=500, height=500, x=500, y=500, anchor_point=\"lt\"\r\n        )[TextComponent(text=self.ctx.text)]\r\n```\r\n\r\n1. Inherent Window props are set via the constructor.\r\n2. Window Geometry is kind of like a layout manager and is set separately.\r\n\r\n#### Using a single component\r\n\r\nYou can also just use a single Window component. you don't have to use a widget component at all. However, doing so is less readable.\r\n\r\n```py\r\n@dataclass(kw_only=True)\r\nclass WindowComponent(Component[Window]):\r\n    def render(self):\r\n        displayed_text = self.ctx.text\r\n        lbl = Label(\r\n            text=displayed_text,\r\n            background=\"#000001\",\r\n            foreground=\"#ffffff\",\r\n            font=Font(family=\"Arial\", size=20, style=\"bold\"),\r\n        ).Pack(ipadx=20, ipady=15, fill=\"both\")\r\n        return Window(topmost=True, background=\"black\", alpha=85).Geometry(\r\n            width=500, height=500, x=500, y=500, anchor_point=\"lt\"\r\n        )[lbl]\r\n```\r\n\r\n### Create a WindowRoot\r\n\r\nWindows aren't contained in anything. Instead they're \"mounted\" on the WindowRoot. To do that, we create a `WindowRoot` around a specific component instance. We can pass it kwargs to initialize its context.\r\n\r\nOnce the WindowRoot is constructed, the UI will immediately mount. However, the context starts out as an empty object.\r\n\r\nTo add attributes to it, we can pass them as kwargs to the `WindowRoot` constructor. This part is untyped.\r\n\r\n```py\r\nui_root = WindowRoot(WindowComponent(), text=\"Hello World!\")\r\n```\r\n\r\nAfter this, we can modify the context any time by \"calling\" the `WindowRoot` with kwargs, like this:\r\n\r\n```py\r\nui_root(text=\"Hello again!\")\r\n```\r\n\r\nThis will regenerate the component tree and reconcile any changes with the mounted UI.\r\n\r\n## Technical stuff\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgregros%2Freact-tk","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgregros%2Freact-tk","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgregros%2Freact-tk/lists"}