diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/target
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..726eb15
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,7 @@
+[package]
+name = "theming"
+version = "0.1.0"
+edition = "2024"
+
+[dependencies]
+makepad-widgets = { path = "../../../../makepad/widgets" }
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..c0cc733
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1,103 @@
+pub use makepad_widgets;
+pub mod streem_theme
+pub mod streem_i18n
+
+use makepad_widgets::*;
+use std::sync::atomic::{AtomicU8, Ordering};
+
+app_main!(App);
+static CURRENT_THEME: AtomicU8 = AtomicU8::new(0); // 0 = light, 1 = dark
+static CURRENT_I18N: AtomicU8 = AtomicU8::new(0); // 0 = light, 1 = dark
+
+
+script_mod! {
+ use mod.prelude.widgets.*
+ use mod.widgets.*
+
+ let app = startup() do #(App::script_component(vm)){
+ ui: Root{ main_window := Window{ window.title: "Runtime theme swap"
+ body +: {
+ width: Fill height: Fill flow: Down padding: 24.0 spacing: 16.0
+ View{ width: Fill height: Fit flow: Right spacing: 16.0 align: Align{y: 0.5}
+ toggle_theme := Button{text: "Toggle theme"}
+ status_label := Label{
+ text: "Current: light | reapply: 0"
+ draw_text.text_style: theme.font_bold{font_size: 12.0}
+ draw_text.color: s_themes.color_primary
+ }
+ }
+ View{ width: Fill height: Fit flow: Right spacing: 24.0
+ View{ width: Fill height: Fit flow: Down spacing: 8.0
+ Label{text: "Markdown" draw_text.text_style: theme.font_bold{font_size: 10.0} draw_text.color: s_themes.color_primary}
+ Markdown{ width: Fill height: Fit
+ body: "# Tasks\n\n| Task | Status | Owner |\n|---|---|---|\n| **API** | *WIP* | Alice |\n| ~~Legacy~~ | *Done* | Bob |\n| UI | **Blocked** | Carol |"
+ }
+ }
+ View{ width: Fill height: Fit flow: Down spacing: 8.0
+ Label{text: "HTML" draw_text.text_style: theme.font_bold{font_size: 10.0} draw_text.color: s_themes.color_primary}
+ Html{ width: Fill height: Fit
+ body: "
Tasks
| Task | Status | Owner |
|---|
| API | WIP | Alice |
Legacy | Done | Bob |
| UI | Blocked | Carol |
"
+ }
+ }
+ }
+ }
+ }}
+ }
+ app
+}
+
+#[derive(Script, ScriptHook)]
+pub struct App {
+ #[live] ui: WidgetRef,
+ #[rust] is_dark: bool,
+ #[rust] n: u32
+}
+
+impl MatchEvent for App {
+ fn handle_actions(&mut self, cx: &mut Cx, actions: &Actions) {
+ if self.ui.button(cx, ids!(toggle_theme)).clicked(actions) {
+ self.is_dark = !self.is_dark;
+ CURRENT_THEME.store(if self.is_dark { 1 } else { 0 }, Ordering::Relaxed);
+ // Re-run script_mod (same pipeline as file-based LiveEdit) so widget
+ // templates rebuild against the new mod.theme, then re-apply the tree.
+ cx.with_vm(|vm| {
+ let value = vm.with_reload(|vm| ::script_mod(vm));
+ ::script_apply(
+ self, vm, &Apply::Reload, &mut Scope::empty(), value,
+ );
+ });
+ self.n += 1;
+ let t = if self.is_dark { "dark" } else { "light" };
+ self.ui.label(cx, ids!(status_label))
+ .set_text(cx, &format!("Current: {} | reapply: {}", t, self.n));
+ self.ui.redraw(cx);
+ }
+ }
+}
+
+impl AppMain for App {
+ fn script_mod(vm: &mut ScriptVm) -> ScriptValue {
+ crate::makepad_widgets::theme_mod(vm);
+ crate::streem_theme::script_mod(vm);
+ crate::streem_i18n::script_mod(vm);
+
+ if CURRENT_I18N.load(Ordering::Relaxed) == 1 {
+ script_eval!(vm, { mod.theme = mod.streem_i18n.en });
+ } else {
+ script_eval!(vm, { mod.theme = mod.streem_i18n.sw });
+ }
+
+ if CURRENT_THEME.load(Ordering::Relaxed) == 1 {
+ script_eval!(vm, { mod.theme = mod.streem_theme.dark });
+ } else {
+ script_eval!(vm, { mod.theme = mod.streem_theme.light });
+ }
+ crate::makepad_widgets::widgets_mod(vm);
+ self::script_mod(vm)
+ }
+
+ fn handle_event(&mut self, cx: &mut Cx, event: &Event) {
+ self.match_event(cx, event);
+ self.ui.handle_event(cx, event, &mut Scope::empty());
+ }
+}
\ No newline at end of file
diff --git a/src/streem_i18n/en.rs b/src/streem_i18n/en.rs
new file mode 100644
index 0000000..a6654f9
--- /dev/null
+++ b/src/streem_i18n/en.rs
@@ -0,0 +1,25 @@
+use makepad_widgets::*;
+
+script_mod! {
+
+ use mod.prelude.widgets.*
+ use mod.widgets.*
+
+ mod.widgets.i18n = {
+ en: {
+ title_streem: "Streem Video Player"
+ tab_vehicles: "My Vehicles"
+ tab_service: "Service"
+ tab_parts: "Parts"
+ tab_recalls: "Recalls"
+ open_workflow: "Open workflow"
+ grant_permission: "Grant Permission"
+ cancel: "Cancel"
+
+ // Video Player Strings
+ player_no_video: "No video selected"
+ player_skip: "Skip to saved position"
+ player_local_file: "Local File"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/streem_i18n/mod.rs b/src/streem_i18n/mod.rs
new file mode 100644
index 0000000..5704c4f
--- /dev/null
+++ b/src/streem_i18n/mod.rs
@@ -0,0 +1,9 @@
+use makepad_widgets::ScriptVm;
+
+pub mod en;
+pub mod sw;
+
+pub fn script_mod(vm: &mut ScriptVm) {
+ en::script_mod(vm);
+ sw::script_mod(vm);
+}
\ No newline at end of file
diff --git a/src/streem_i18n/sw.rs b/src/streem_i18n/sw.rs
new file mode 100644
index 0000000..b50e408
--- /dev/null
+++ b/src/streem_i18n/sw.rs
@@ -0,0 +1,25 @@
+use makepad_widgets::*;
+
+script_mod! {
+
+ use mod.prelude.widgets.*
+ use mod.widgets.*
+
+ mod.widgets.i18n = {
+ sw: {
+ title_streem: "Kicheza Video cha Streem"
+ tab_vehicles: "Magari Yangu"
+ tab_service: "Huduma"
+ tab_parts: "Vipuri"
+ tab_recalls: "Marejesho"
+ open_workflow: "Fungua mchakato"
+ grant_permission: "Toa Ruhusa"
+ cancel: "Ghairi"
+
+ // Video Player Strings
+ player_no_video: "Hakuna video iliyochaguliwa"
+ player_skip: "Nenda kwenye nafasi iliyohifadhiwa"
+ player_local_file: "Faili ya Ndani"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/streem_theme/colors.rs b/src/streem_theme/colors.rs
new file mode 100644
index 0000000..d2fb71c
--- /dev/null
+++ b/src/streem_theme/colors.rs
@@ -0,0 +1,22 @@
+use makepad_widgets::*;
+
+script_mod! {
+
+ use mod.prelude.widgets.*
+ use mod.widgets.*
+
+ mod.widgets.colors = {
+ white: #xFFFFFF
+ white_150: #xFFFFFF26
+ white_850: #xFFFFFFD9
+
+ pink_100: #FFF1F1
+ pink_900: #3F2C2C
+
+ gray: #232323
+
+ green_300: #B8C9B8
+ green_900: #2D3B2D
+ }
+}
+
diff --git a/src/streem_theme/dark.rs b/src/streem_theme/dark.rs
new file mode 100644
index 0000000..e904359
--- /dev/null
+++ b/src/streem_theme/dark.rs
@@ -0,0 +1,16 @@
+// src/dark.rs
+
+use makepad_widgets::*;
+
+script_mod! {
+
+ use mod.prelude.widgets.*
+ use mod.widgets.*
+
+ mod.widgets.streem_themes = {
+ dark: {
+ color_primary: mod.widgets.green_900
+ }
+ }
+ mod.widgets.streem_themes = mod.widgets.streem_themes.dark
+}
diff --git a/src/streem_theme/light.rs b/src/streem_theme/light.rs
new file mode 100644
index 0000000..b7288cf
--- /dev/null
+++ b/src/streem_theme/light.rs
@@ -0,0 +1,15 @@
+// src/light.rs
+use makepad_widgets::*;
+
+script_mod! {
+
+ use mod.prelude.widgets.*
+ use mod.widgets.*
+
+ mod.widgets.streem_themes = {
+ light: {
+ color_primary: mod.widgets.pink_100
+ }
+ }
+ mod.widgets.streem_themes = mod.widgets.streem_themes.light
+}
\ No newline at end of file
diff --git a/src/streem_theme/mod.rs b/src/streem_theme/mod.rs
new file mode 100644
index 0000000..50e2fd3
--- /dev/null
+++ b/src/streem_theme/mod.rs
@@ -0,0 +1,14 @@
+pub mod dark;
+pub mod light;
+pub mod colors;
+pub mod shapes;
+pub mod typography;
+
+
+pub fn script_mod(vm: &mut ScriptVm) {
+ colors::script_mod(vm);
+ shapes::script_mod(vm);
+ typography::script_mod(vm);
+ dark::script_mod(vm);
+ light::script_mod(vm);
+}
\ No newline at end of file
diff --git a/src/streem_theme/shapes.rs b/src/streem_theme/shapes.rs
new file mode 100644
index 0000000..e6b4d57
--- /dev/null
+++ b/src/streem_theme/shapes.rs
@@ -0,0 +1,16 @@
+use makepad_widgets::*;
+
+script_mod! {
+
+ use mod.prelude.widgets.*
+ use mod.widgets.*
+
+ mod.widgets.shapes = {
+ small: 4.0
+ medium: 24.0
+ large: 0.0
+
+ button_height: 48.0
+ input_height: 56.0
+ }
+}
\ No newline at end of file
diff --git a/src/streem_theme/typography.rs b/src/streem_theme/typography.rs
new file mode 100644
index 0000000..d148d1f
--- /dev/null
+++ b/src/streem_theme/typography.rs
@@ -0,0 +1,44 @@
+use makepad_widgets::*;
+
+script_mod! {
+
+ use mod.prelude.widgets.*
+ use mod.widgets.*
+
+ mod.widgets.typography = {
+ h1: theme.font_bold {
+ font_size: 18.0
+ line_spacing: 1.2
+ }
+
+ h2: theme.font_bold {
+ font_size: 14.0
+ line_spacing: 1.2
+ }
+
+ subtitle1: theme.font_regular {
+ font_size: 16.0
+ line_spacing: 1.2
+ }
+
+ body1: theme.font_regular {
+ font_size: 14.0
+ line_spacing: 1.2
+ }
+
+ body2: theme.font_regular {
+ font_size: 12.0
+ line_spacing: 1.2
+ }
+
+ button: theme.font_bold {
+ font_size: 14.0
+ line_spacing: 1.0
+ }
+
+ caption: theme.font_bold {
+ font_size: 12.0
+ line_spacing: 1.2
+ }
+ }
+}
\ No newline at end of file