[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-5511":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":16,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":22,"hasPages":22,"topics":23,"createdAt":10,"pushedAt":10,"updatedAt":24,"readmeContent":25,"aiSummary":26,"trendingCount":16,"starSnapshotCount":16,"syncStatus":27,"lastSyncTime":28,"discoverSource":29},5511,"druid","linebender\u002Fdruid","linebender","A data-first Rust-native UI design toolkit. ","https:\u002F\u002Flinebender.org\u002Fdruid\u002F",null,"Rust",9710,564,97,265,0,4,64.66,"Apache License 2.0",false,"master",true,[],"2026-06-12 04:00:25","![druid banner](https:\u002F\u002Fraw.githubusercontent.com\u002Flinebender\u002Fdruid\u002Fscreenshots\u002Fimages\u002Fsmall_banner.png)\n\n## A data-first Rust-native UI toolkit.\n\n[![crates.io](https:\u002F\u002Fimg.shields.io\u002Fcrates\u002Fv\u002Fdruid)](https:\u002F\u002Fcrates.io\u002Fcrates\u002Fdruid)\n[![docs.rs](https:\u002F\u002Fdocs.rs\u002Fdruid\u002Fbadge.svg)](https:\u002F\u002Fdocs.rs\u002Fdruid\u002F)\n[![license](https:\u002F\u002Fimg.shields.io\u002Fcrates\u002Fl\u002Fdruid)](https:\u002F\u002Fgithub.com\u002Flinebender\u002Fdruid\u002Fblob\u002Fmaster\u002FLICENSE)\n[![chat](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002Fzulip-join_chat-brightgreen.svg)](https:\u002F\u002Fxi.zulipchat.com)\n\nDruid was an experimental Rust-native UI toolkit. Its main goal was to offer a\npolished user experience. There were many factors to this goal, including\nperformance, a rich palette of interactions (hence a widget library to support\nthem), and playing well with the native platform.\nSee the [goals section](#Goals) for more details.\n\nWe did periodic releases of Druid on crates.io. All changes were documented\nin [the changelog](https:\u002F\u002Fgithub.com\u002Flinebender\u002Fdruid\u002Fblob\u002Fmaster\u002FCHANGELOG.md).\n\nFor an overview of some key concepts, see the incomplete [Druid book].\n\n## Project status\n\n**UNMAINTAINED**\n\n**The Druid project has been discontinued.**\n\nNew development effort moved on to [Xilem], which has a lot of fundamental changes to allow for\na wider variety of applications with better performance, but it also heavily inherits from Druid.\nWe see [Xilem] as the future of Druid.\n\nDruid is reasonably usable for [some subset of applications](https:\u002F\u002Fgithub.com\u002Flinebender\u002Fdruid\u002Fissues\u002F1360)\nand has a significant testing history, which ensures some stability and correctness.\nHowever, there will not be any new features or bug fixes coming to Druid. As such we don't recommend\nusing Druid for brand new applications. If you insist, then at least make sure your application\ndoesn't require a feature that Druid doesn't have, e.g. accessibility or 3D support.\n\n## Contributions\n\nAs the Druid project has been discontinued, **we will not be accepting any more contributions**.\n\nPlease take a look at some of our other projects instead, especially the Druid successor [Xilem].\n\n## Example\n\nHere's a simple counter example app:\n\n```rust\nuse druid::widget::{Button, Flex, Label};\nuse druid::{AppLauncher, LocalizedString, PlatformError, Widget, WidgetExt, WindowDesc};\n\nfn main() -> Result\u003C(), PlatformError> {\n    let main_window = WindowDesc::new(ui_builder());\n    let data = 0_u32;\n    AppLauncher::with_window(main_window)\n        .log_to_console()\n        .launch(data)\n}\n\nfn ui_builder() -> impl Widget\u003Cu32> {\n    \u002F\u002F The label text will be computed dynamically based on the current locale and count\n    let text =\n        LocalizedString::new(\"hello-counter\").with_arg(\"count\", |data: &u32, _env| (*data).into());\n    let label = Label::new(text).padding(5.0).center();\n    let button = Button::new(\"increment\")\n        .on_click(|_ctx, data, _env| *data += 1)\n        .padding(5.0);\n\n    Flex::column().with_child(label).with_child(button)\n}\n```\n\nCheck out the [the examples folder] for a more comprehensive demonstration of\nDruid's existing functionality and widgets. Check [druid_widget_nursery](https:\u002F\u002Fgithub.com\u002Flinebender\u002Fdruid-widget-nursery) for more widgets.\n\n## Screenshots\n\n[![calc.rs example](https:\u002F\u002Fraw.githubusercontent.com\u002Flinebender\u002Fdruid\u002Fscreenshots\u002Fimages\u002F0.6.0\u002Fcalc.png)](\u002Fdruid\u002Fexamples\u002Fcalc.rs)\n[![flex.rs example](https:\u002F\u002Fraw.githubusercontent.com\u002Flinebender\u002Fdruid\u002Fscreenshots\u002Fimages\u002F0.6.0\u002Fflex.png)](\u002Fdruid\u002Fexamples\u002Fflex.rs)\n[![custom_widget.rs example](https:\u002F\u002Fraw.githubusercontent.com\u002Flinebender\u002Fdruid\u002Fscreenshots\u002Fimages\u002F0.6.0\u002Fcustom_widget.png)](\u002Fdruid\u002Fexamples\u002Fcustom_widget.rs)\n\n## Using Druid\n\nAn explicit goal of Druid was to be easy to build.\nDruid is available on [crates.io] and should work as a lone dependency\n(it re-exports all the parts of `druid-shell`, `piet`, and `kurbo` that you'll need):\n\n```toml\ndruid = \"0.8.3\"\n```\n\n### Platform notes\n\n#### Linux\n\nOn Linux, Druid requires gtk+3; see [GTK installation page].\n(On ubuntu-based distro, running `sudo apt-get install libgtk-3-dev` from the terminal will do the job.)\n\n#### OpenBSD\n\nOn OpenBSD, Druid requires gtk+3;  install from packages:\n```sh\npkg_add gtk+3\n```\n\nAlternatively, there is an X11 backend available, although it is currently\n[missing quite a few features](https:\u002F\u002Fgithub.com\u002Flinebender\u002Fdruid\u002Fissues?q=is%3Aopen+is%3Aissue+label%3Ashell%2Fx11+label%3Amissing).\nYou can try it out with `--features=x11`.\n\n## Goals\n\nDruid's goal was to make it easy to write and deploy high quality desktop\napplications with a smooth and polished user experience on all common\nplatforms. In order to achieve this we strived for a variety of things:\n\n- Make it easy to build and package on all supported platforms.\n- Implement abstractions to avoid platform specific quirks.\n- Respect platform conventions and expectations.\n- Handle display resolution and scaling reliably with little effort.\n- Enable easy, yet powerful internationalization.\n- Offer robust accessibility support.\n- Produce small and fast binaries with low memory usage.\n- Have a small dependency tree, a high quality code base and good organization.\n- Focus on powerful, desktop-grade applications.\n- Provide a flexible set of layouts and common widgets.\n- Ease creation of custom components and application logic as needed.\n\n### Non-Goals\n\nIn order to fulfill those goals, we couldn't support every use case. Luckily\nthe Rust community is working on a variety of different libraries with\ndifferent goals, so here are some of Druid's non-goals and possible\nalternatives that can offer those capabilities:\n\n- Use the platform-native widgets or mimic them. ([Relm], [Slint])\n- Embed easily into custom render pipelines. ([Conrod])\n- Adhere to a specific architectural style such as Elm. ([Iced], [Relm])\n- Support rendering to HTML when targeting the web. ([Iced], [Moxie])\n\nDruid was just one of many ongoing [Rust-native GUI experiments].\n\n## Concepts\n\n### druid-shell\n\nThe Druid toolkit uses `druid-shell` for a platform-abstracting application shell.\n`druid-shell` is responsible for starting a native platform runloop, listening to\nevents, converting them into a platform-agnostic representation, and calling a\nuser-provided handler with them.\n\nWhile `druid-shell` was being developed with the Druid toolkit in mind, it was\nintended to be general enough that it could be reused by other projects\ninterested in experimenting with Rust GUI. The `druid-shell` crate includes a\ncouple of [non-`druid` examples].\n\n### piet\n\nDruid relies on the [Piet library] for drawing and text layout. Piet is a 2D graphics\nabstraction with multiple backends: `piet-direct2d`, `piet-coregraphics`, `piet-cairo`,\n`piet-web`, and `piet-svg` are currently available.\nIn terms of Druid platform support via Piet, macOS uses `piet-coregraphics`,\nLinux\u002FOpenBSD\u002FFreeBSD use `piet-cairo`, Windows uses `piet-direct2d`, and web uses `piet-web`.\n\n```rust\nuse druid::kurbo::{BezPath, Point, Rect};\nuse druid::piet::Color;\n\n\u002F\u002F Create an arbitrary bezier path\n\u002F\u002F (ctx.size() returns the size of the layout rect we're painting in)\nlet mut path = BezPath::new();\npath.move_to(Point::ORIGIN);\npath.quad_to(\n    (80.0, 90.0),\n    (ctx.size().width, ctx.size().height),\n);\n\u002F\u002F Create a color\nlet stroke_color = Color::rgb8(0x00, 0x80, 0x00);\n\u002F\u002F Stroke the path with thickness 1.0\nctx.stroke(path, &stroke_color, 1.0);\n\n\u002F\u002F Rectangles: the path for practical people\nlet rect = Rect::from_origin_size((10., 10.), (100., 100.));\n\u002F\u002F Note the Color:rgba8 which includes an alpha channel (7F in this case)\nlet fill_color = Color::rgba8(0x00, 0x00, 0x00, 0x7F);\nctx.fill(rect, &fill_color);\n```\n\n### widgets\n\nWidgets in Druid (text boxes, buttons, layout components, etc.) are objects\nwhich implement the [Widget trait]. The trait is parametrized by a type (`T`)\nfor associated data. All trait methods (`event`, `lifecycle`, `update`, `paint`,\nand `layout`) are provided with access to this data, and in the case of\n`event` the reference is mutable, so that events can directly update the data.\n\nWhenever the application data changes, the framework traverses the widget\nhierarchy with an `update` method.\n\nAll the widget trait methods are provided with a corresponding context\n([EventCtx], [LifeCycleCtx], [UpdateCtx], [LayoutCtx], [PaintCtx]). The widget can request\nthings and cause actions by calling methods on that context.\n\nIn addition, all trait methods are provided with an environment `Env`, which\nincludes the current theme parameters (colors, dimensions, etc.).\n\n```rust\nimpl\u003CT: Data> Widget\u003CT> for Button\u003CT> {\n    fn event(&mut self, ctx: &mut EventCtx, event: &Event, data: &mut T, env: &Env) {\n      ...\n    }\n\n    fn lifecycle(&mut self, ctx: &mut LifeCycleCtx, event: &LifeCycle, data: &T, env: &Env) {\n      ...\n    }\n\n    fn update(&mut self, ctx: &mut UpdateCtx, old_data: &T, data: &T, env: &Env) {\n      ...\n    }\n\n    fn layout(&mut self, ctx: &mut LayoutCtx, bc: &BoxConstraints, data: &T, env: &Env) -> Size {\n      ...\n    }\n\n    fn paint(&mut self, ctx: &mut PaintCtx, data: &T, env: &Env) {\n      ...\n    }\n}\n```\n\nDruid provides a number of [basic utility and layout widgets] and it's easy to\nimplement your own. You can also compose widgets into new widgets:\n\n```rust\nfn build_widget() -> impl Widget\u003Cu32> {\n    let mut col = Flex::column();\n    for i in 0..30 {\n        let button = Button::new(format!(\"Button {}\", i).padding(5.0);\n        col.add_child(button);\n    }\n    Scroll::new(col)\n}\n```\n\n### layout\n\nDruid's layout protocol was strongly inspired by [Flutter's box layout model].\nIn Druid, widgets are passed a `BoxConstraint` that provides them a minimum and\nmaximum size for layout. Widgets are also responsible for computing appropriate\nconstraints for their children if applicable.\n\n### data\n\nDruid uses a [Data trait] to represent [value types]. These should be cheap to\ncompare and cheap to clone.\n\nIn general, you can use `derive` to generate a `Data` impl for your types.\n\n```rust\n#[derive(Clone, Data)]\nstruct AppState {\n    which: bool,\n    value: f64,\n}\n```\n\n### lens\n\nThe [Lens datatype] gives access to a part of a larger data structure. Like\n`Data`, this can be derived. Derived lenses are accessed as associated constants\nwith the same name as the field.\n\n```rust\n#[derive(Clone, Data, Lens)]\nstruct AppState {\n    which: bool,\n    value: f64,\n}\n```\n\nTo use the lens, wrap your widget with `LensWrap` (note the conversion of\nCamelCase to snake_case):\n\n```rust\nLensWrap::new(WidgetThatExpectsf64::new(), AppState::value);\n```\n\nAlternatively, lenses for structs, tuples, and indexable containers can be\nconstructed on-demand with the `lens` macro:\n\n```rust\nLensWrap::new(WidgetThatExpectsf64::new(), lens!(AppState, value));\n```\n\nThis is particularly useful when working with types defined in another crate.\n\n## Authors\n\nThe main authors are Raph Levien and Colin Rofls, with much support from an\nactive and friendly community. See the AUTHORS file for more.\n\n[Runebender]: https:\u002F\u002Fgithub.com\u002Flinebender\u002Frunebender\n[the examples folder]: \u002Fdruid\u002Fexamples\n[Piet library]: https:\u002F\u002Fgithub.com\u002Flinebender\u002Fpiet\n[custom_widget]: \u002Fdruid\u002Fexamples\u002Fcustom_widget.rs\n[basic utility and layout widgets]: \u002Fdruid\u002Fsrc\u002Fwidget\n[Flutter's box layout model]: https:\u002F\u002Fapi.flutter.dev\u002Fflutter\u002Frendering\u002FBoxConstraints-class.html\n[value types]: https:\u002F\u002Fsinusoid.es\u002Flager\u002Fmodel.html#id2\n[GTK installation page]: https:\u002F\u002Fwww.gtk.org\u002Fdocs\u002Finstallations\u002Flinux\u002F\n[Rust-native GUI experiments]: https:\u002F\u002Fareweguiyet.com\n[CONTRIBUTING.md]: \u002FCONTRIBUTING.md\n[Zulip chat instance]: https:\u002F\u002Fxi.zulipchat.com\n[non-`druid` examples]: \u002Fdruid-shell\u002Fexamples\u002Fshello.rs\n[crates.io]: https:\u002F\u002Fcrates.io\u002Fcrates\u002Fdruid\n[EventCtx]: https:\u002F\u002Fdocs.rs\u002Fdruid\u002F0.8.3\u002Fdruid\u002Fstruct.EventCtx.html\n[LifeCycleCtx]: https:\u002F\u002Fdocs.rs\u002Fdruid\u002F0.8.3\u002Fdruid\u002Fstruct.LifeCycleCtx.html\n[LayoutCtx]: https:\u002F\u002Fdocs.rs\u002Fdruid\u002F0.8.3\u002Fdruid\u002Fstruct.LayoutCtx.html\n[PaintCtx]: https:\u002F\u002Fdocs.rs\u002Fdruid\u002F0.8.3\u002Fdruid\u002Fstruct.PaintCtx.html\n[UpdateCtx]: https:\u002F\u002Fdocs.rs\u002Fdruid\u002F0.8.3\u002Fdruid\u002Fstruct.UpdateCtx.html\n[Widget trait]: https:\u002F\u002Fdocs.rs\u002Fdruid\u002F0.8.3\u002Fdruid\u002Ftrait.Widget.html\n[Data trait]: https:\u002F\u002Fdocs.rs\u002Fdruid\u002F0.8.3\u002Fdruid\u002Ftrait.Data.html\n[Lens datatype]: https:\u002F\u002Fdocs.rs\u002Fdruid\u002F0.8.3\u002Fdruid\u002Ftrait.Lens.html\n[Druid book]: https:\u002F\u002Flinebender.org\u002Fdruid\u002F\n[Iced]: https:\u002F\u002Fgithub.com\u002Fhecrj\u002Ficed\n[Conrod]: https:\u002F\u002Fgithub.com\u002FPistonDevelopers\u002Fconrod\n[Relm]: https:\u002F\u002Fgithub.com\u002Fantoyo\u002Frelm\n[Moxie]: https:\u002F\u002Fgithub.com\u002Fanp\u002Fmoxie\n[Slint]: https:\u002F\u002Fgithub.com\u002Fslint-ui\u002Fslint\n[Xilem]: https:\u002F\u002Fgithub.com\u002Flinebender\u002Fxilem\n","Druid 是一个以数据优先的 Rust 本地 UI 设计工具包。它专注于提供流畅的用户体验，通过高性能、丰富的交互组件库以及良好的平台兼容性来实现这一目标。Druid 支持创建具有复杂用户界面的应用程序，并且在设计上特别注重与 Rust 语言特性的紧密结合。尽管该项目已不再维护，但对于某些特定场景下不需要新功能或高级特性（如无障碍支持或3D渲染）的应用来说，Druid 仍然是一个合理的选择。然而，对于新的开发项目，建议考虑其继任者 Xilem 或其他活跃维护的替代方案。",2,"2026-06-11 03:03:45","top_language"]