reworked styling further, more usable, fun font

Orual 29e57a4e d3731e20

+359 -77
+10
Cargo.lock
··· 1815 ] 1816 1817 [[package]] 1818 name = "dioxus-fullstack" 1819 version = "0.7.1" 1820 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 8623 "diesel", 8624 "diesel_migrations", 8625 "dioxus", 8626 "dioxus-primitives", 8627 "jacquard", 8628 "jacquard-axum",
··· 1815 ] 1816 1817 [[package]] 1818 + name = "dioxus-free-icons" 1819 + version = "0.10.0" 1820 + source = "registry+https://github.com/rust-lang/crates.io-index" 1821 + checksum = "28d356e0f9edad0930bc1cc76744360c0ecca020cb943acaadf42cb774f28284" 1822 + dependencies = [ 1823 + "dioxus", 1824 + ] 1825 + 1826 + [[package]] 1827 name = "dioxus-fullstack" 1828 version = "0.7.1" 1829 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 8632 "diesel", 8633 "diesel_migrations", 8634 "dioxus", 8635 + "dioxus-free-icons", 8636 "dioxus-primitives", 8637 "jacquard", 8638 "jacquard-axum",
+9
crates/weaver-api/lexicons/sh_weaver_notebook_theme.json
··· 57 "description": "Reference to a dark colour scheme", 58 "ref": "com.atproto.repo.strongRef" 59 }, 60 "fonts": { 61 "type": "object", 62 "required": [
··· 57 "description": "Reference to a dark colour scheme", 58 "ref": "com.atproto.repo.strongRef" 59 }, 60 + "defaultTheme": { 61 + "type": "string", 62 + "default": "auto", 63 + "enum": [ 64 + "light", 65 + "dark", 66 + "auto" 67 + ] 68 + }, 69 "fonts": { 70 "type": "object", 71 "required": [
+55 -13
crates/weaver-api/src/sh_weaver/notebook/theme.rs
··· 338 }), 339 ); 340 map.insert( 341 ::jacquard_common::smol_str::SmolStr::new_static("fonts"), 342 ::jacquard_lexicon::lexicon::LexObjectProperty::Object(::jacquard_lexicon::lexicon::LexObject { 343 description: None, ··· 546 /// Reference to a dark colour scheme 547 #[serde(borrow)] 548 pub dark_scheme: crate::com_atproto::repo::strong_ref::StrongRef<'a>, 549 #[serde(borrow)] 550 pub fonts: ThemeFonts<'a>, 551 /// Syntax highlighting theme for light mode ··· 676 __unsafe_private_named: ( 677 ::core::option::Option<ThemeDarkCodeTheme<'a>>, 678 ::core::option::Option<crate::com_atproto::repo::strong_ref::StrongRef<'a>>, 679 ::core::option::Option<ThemeFonts<'a>>, 680 ::core::option::Option<ThemeLightCodeTheme<'a>>, 681 ::core::option::Option<crate::com_atproto::repo::strong_ref::StrongRef<'a>>, ··· 696 pub fn new() -> Self { 697 ThemeBuilder { 698 _phantom_state: ::core::marker::PhantomData, 699 - __unsafe_private_named: (None, None, None, None, None, None), 700 _phantom: ::core::marker::PhantomData, 701 } 702 } ··· 740 } 741 } 742 743 impl<'a, S> ThemeBuilder<'a, S> 744 where 745 S: theme_state::State, ··· 750 mut self, 751 value: impl Into<ThemeFonts<'a>>, 752 ) -> ThemeBuilder<'a, theme_state::SetFonts<S>> { 753 - self.__unsafe_private_named.2 = ::core::option::Option::Some(value.into()); 754 ThemeBuilder { 755 _phantom_state: ::core::marker::PhantomData, 756 __unsafe_private_named: self.__unsafe_private_named, ··· 769 mut self, 770 value: impl Into<ThemeLightCodeTheme<'a>>, 771 ) -> ThemeBuilder<'a, theme_state::SetLightCodeTheme<S>> { 772 - self.__unsafe_private_named.3 = ::core::option::Option::Some(value.into()); 773 ThemeBuilder { 774 _phantom_state: ::core::marker::PhantomData, 775 __unsafe_private_named: self.__unsafe_private_named, ··· 788 mut self, 789 value: impl Into<crate::com_atproto::repo::strong_ref::StrongRef<'a>>, 790 ) -> ThemeBuilder<'a, theme_state::SetLightScheme<S>> { 791 - self.__unsafe_private_named.4 = ::core::option::Option::Some(value.into()); 792 ThemeBuilder { 793 _phantom_state: ::core::marker::PhantomData, 794 __unsafe_private_named: self.__unsafe_private_named, ··· 807 mut self, 808 value: impl Into<ThemeSpacing<'a>>, 809 ) -> ThemeBuilder<'a, theme_state::SetSpacing<S>> { 810 - self.__unsafe_private_named.5 = ::core::option::Option::Some(value.into()); 811 ThemeBuilder { 812 _phantom_state: ::core::marker::PhantomData, 813 __unsafe_private_named: self.__unsafe_private_named, ··· 831 Theme { 832 dark_code_theme: self.__unsafe_private_named.0.unwrap(), 833 dark_scheme: self.__unsafe_private_named.1.unwrap(), 834 - fonts: self.__unsafe_private_named.2.unwrap(), 835 - light_code_theme: self.__unsafe_private_named.3.unwrap(), 836 - light_scheme: self.__unsafe_private_named.4.unwrap(), 837 - spacing: self.__unsafe_private_named.5.unwrap(), 838 extra_data: Default::default(), 839 } 840 } ··· 849 Theme { 850 dark_code_theme: self.__unsafe_private_named.0.unwrap(), 851 dark_scheme: self.__unsafe_private_named.1.unwrap(), 852 - fonts: self.__unsafe_private_named.2.unwrap(), 853 - light_code_theme: self.__unsafe_private_named.3.unwrap(), 854 - light_scheme: self.__unsafe_private_named.4.unwrap(), 855 - spacing: self.__unsafe_private_named.5.unwrap(), 856 extra_data: Some(extra_data), 857 } 858 }
··· 338 }), 339 ); 340 map.insert( 341 + ::jacquard_common::smol_str::SmolStr::new_static( 342 + "defaultTheme", 343 + ), 344 + ::jacquard_lexicon::lexicon::LexObjectProperty::String(::jacquard_lexicon::lexicon::LexString { 345 + description: None, 346 + format: None, 347 + default: None, 348 + min_length: None, 349 + max_length: None, 350 + min_graphemes: None, 351 + max_graphemes: None, 352 + r#enum: None, 353 + r#const: None, 354 + known_values: None, 355 + }), 356 + ); 357 + map.insert( 358 ::jacquard_common::smol_str::SmolStr::new_static("fonts"), 359 ::jacquard_lexicon::lexicon::LexObjectProperty::Object(::jacquard_lexicon::lexicon::LexObject { 360 description: None, ··· 563 /// Reference to a dark colour scheme 564 #[serde(borrow)] 565 pub dark_scheme: crate::com_atproto::repo::strong_ref::StrongRef<'a>, 566 + #[serde(skip_serializing_if = "std::option::Option::is_none")] 567 + #[serde(borrow)] 568 + pub default_theme: Option<jacquard_common::CowStr<'a>>, 569 #[serde(borrow)] 570 pub fonts: ThemeFonts<'a>, 571 /// Syntax highlighting theme for light mode ··· 696 __unsafe_private_named: ( 697 ::core::option::Option<ThemeDarkCodeTheme<'a>>, 698 ::core::option::Option<crate::com_atproto::repo::strong_ref::StrongRef<'a>>, 699 + ::core::option::Option<jacquard_common::CowStr<'a>>, 700 ::core::option::Option<ThemeFonts<'a>>, 701 ::core::option::Option<ThemeLightCodeTheme<'a>>, 702 ::core::option::Option<crate::com_atproto::repo::strong_ref::StrongRef<'a>>, ··· 717 pub fn new() -> Self { 718 ThemeBuilder { 719 _phantom_state: ::core::marker::PhantomData, 720 + __unsafe_private_named: (None, None, None, None, None, None, None), 721 _phantom: ::core::marker::PhantomData, 722 } 723 } ··· 761 } 762 } 763 764 + impl<'a, S: theme_state::State> ThemeBuilder<'a, S> { 765 + /// Set the `defaultTheme` field (optional) 766 + pub fn default_theme( 767 + mut self, 768 + value: impl Into<Option<jacquard_common::CowStr<'a>>>, 769 + ) -> Self { 770 + self.__unsafe_private_named.2 = value.into(); 771 + self 772 + } 773 + /// Set the `defaultTheme` field to an Option value (optional) 774 + pub fn maybe_default_theme( 775 + mut self, 776 + value: Option<jacquard_common::CowStr<'a>>, 777 + ) -> Self { 778 + self.__unsafe_private_named.2 = value; 779 + self 780 + } 781 + } 782 + 783 impl<'a, S> ThemeBuilder<'a, S> 784 where 785 S: theme_state::State, ··· 790 mut self, 791 value: impl Into<ThemeFonts<'a>>, 792 ) -> ThemeBuilder<'a, theme_state::SetFonts<S>> { 793 + self.__unsafe_private_named.3 = ::core::option::Option::Some(value.into()); 794 ThemeBuilder { 795 _phantom_state: ::core::marker::PhantomData, 796 __unsafe_private_named: self.__unsafe_private_named, ··· 809 mut self, 810 value: impl Into<ThemeLightCodeTheme<'a>>, 811 ) -> ThemeBuilder<'a, theme_state::SetLightCodeTheme<S>> { 812 + self.__unsafe_private_named.4 = ::core::option::Option::Some(value.into()); 813 ThemeBuilder { 814 _phantom_state: ::core::marker::PhantomData, 815 __unsafe_private_named: self.__unsafe_private_named, ··· 828 mut self, 829 value: impl Into<crate::com_atproto::repo::strong_ref::StrongRef<'a>>, 830 ) -> ThemeBuilder<'a, theme_state::SetLightScheme<S>> { 831 + self.__unsafe_private_named.5 = ::core::option::Option::Some(value.into()); 832 ThemeBuilder { 833 _phantom_state: ::core::marker::PhantomData, 834 __unsafe_private_named: self.__unsafe_private_named, ··· 847 mut self, 848 value: impl Into<ThemeSpacing<'a>>, 849 ) -> ThemeBuilder<'a, theme_state::SetSpacing<S>> { 850 + self.__unsafe_private_named.6 = ::core::option::Option::Some(value.into()); 851 ThemeBuilder { 852 _phantom_state: ::core::marker::PhantomData, 853 __unsafe_private_named: self.__unsafe_private_named, ··· 871 Theme { 872 dark_code_theme: self.__unsafe_private_named.0.unwrap(), 873 dark_scheme: self.__unsafe_private_named.1.unwrap(), 874 + default_theme: self.__unsafe_private_named.2, 875 + fonts: self.__unsafe_private_named.3.unwrap(), 876 + light_code_theme: self.__unsafe_private_named.4.unwrap(), 877 + light_scheme: self.__unsafe_private_named.5.unwrap(), 878 + spacing: self.__unsafe_private_named.6.unwrap(), 879 extra_data: Default::default(), 880 } 881 } ··· 890 Theme { 891 dark_code_theme: self.__unsafe_private_named.0.unwrap(), 892 dark_scheme: self.__unsafe_private_named.1.unwrap(), 893 + default_theme: self.__unsafe_private_named.2, 894 + fonts: self.__unsafe_private_named.3.unwrap(), 895 + light_code_theme: self.__unsafe_private_named.4.unwrap(), 896 + light_scheme: self.__unsafe_private_named.5.unwrap(), 897 + spacing: self.__unsafe_private_named.6.unwrap(), 898 extra_data: Some(extra_data), 899 } 900 }
+1 -1
crates/weaver-app/Cargo.toml
··· 38 serde = { version = "1.0", features = ["derive"] } 39 serde_json = "1.0" 40 reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } 41 - 42 diesel = { version = "2.3", features = ["sqlite", "returning_clauses_for_sqlite_3_35", "chrono", "serde_json"] } 43 diesel_migrations = { version = "2.3", features = ["sqlite"] } 44
··· 38 serde = { version = "1.0", features = ["derive"] } 39 serde_json = "1.0" 40 reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] } 41 + dioxus-free-icons = { version = "0.10.0" } 42 diesel = { version = "2.3", features = ["sqlite", "returning_clauses_for_sqlite_3_35", "chrono", "serde_json"] } 43 diesel_migrations = { version = "2.3", features = ["sqlite"] } 44
crates/weaver-app/assets/fonts/ioskeley-mono/IoskeleyMono-Bold.woff2

This is a binary file and will not be displayed.

crates/weaver-app/assets/fonts/ioskeley-mono/IoskeleyMono-BoldItalic.woff2

This is a binary file and will not be displayed.

crates/weaver-app/assets/fonts/ioskeley-mono/IoskeleyMono-Italic.woff2

This is a binary file and will not be displayed.

crates/weaver-app/assets/fonts/ioskeley-mono/IoskeleyMono-Light.woff2

This is a binary file and will not be displayed.

crates/weaver-app/assets/fonts/ioskeley-mono/IoskeleyMono-LightItalic.woff2

This is a binary file and will not be displayed.

crates/weaver-app/assets/fonts/ioskeley-mono/IoskeleyMono-Regular.woff2

This is a binary file and will not be displayed.

+5 -4
crates/weaver-app/assets/styling/entry-card.css
··· 27 /* Mobile layout - sidebar becomes header */ 28 @media (max-width: 1400px) { 29 .notebook-layout { 30 - grid-template-columns: 1fr !important; 31 gap: 0 !important; 32 max-width: 100vw !important; 33 box-sizing: border-box !important; 34 } 35 36 .notebook-sidebar { 37 - grid-column: 1; 38 position: static; 39 max-height: none; 40 min-width: 0; 41 } 42 43 .notebook-main { 44 - grid-column: 1; 45 - padding: 1.25rem; 46 min-width: 0; 47 } 48 }
··· 27 /* Mobile layout - sidebar becomes header */ 28 @media (max-width: 1400px) { 29 .notebook-layout { 30 + grid-template-columns: minmax(1rem, 1fr) minmax(0, 90ch) minmax(1rem, 1fr) !important; 31 gap: 0 !important; 32 max-width: 100vw !important; 33 box-sizing: border-box !important; 34 } 35 36 .notebook-sidebar { 37 + grid-column: 2; 38 position: static; 39 max-height: none; 40 min-width: 0; 41 + margin-bottom: 2rem; 42 } 43 44 .notebook-main { 45 + grid-column: 2; 46 + padding: 0; 47 min-width: 0; 48 } 49 }
+3 -3
crates/weaver-app/assets/styling/notebook-card.css
··· 27 /* Mobile layout - sidebar becomes header */ 28 @media (max-width: 1400px) { 29 .repository-layout { 30 - grid-template-columns: 1fr !important; 31 gap: 0 !important; 32 max-width: 100vw !important; 33 box-sizing: border-box !important; 34 } 35 36 .repository-sidebar { 37 - grid-column: 1; 38 position: static; 39 max-height: none; 40 min-width: 0; ··· 42 } 43 44 .repository-main { 45 - grid-column: 1; 46 padding: 0; 47 min-width: 0; 48 }
··· 27 /* Mobile layout - sidebar becomes header */ 28 @media (max-width: 1400px) { 29 .repository-layout { 30 + grid-template-columns: minmax(1rem, 1fr) minmax(0, 90ch) minmax(1rem, 1fr) !important; 31 gap: 0 !important; 32 max-width: 100vw !important; 33 box-sizing: border-box !important; 34 } 35 36 .repository-sidebar { 37 + grid-column: 2; 38 position: static; 39 max-height: none; 40 min-width: 0; ··· 42 } 43 44 .repository-main { 45 + grid-column: 2; 46 padding: 0; 47 min-width: 0; 48 }
+53 -18
crates/weaver-app/assets/styling/profile.css
··· 6 /* No background - same plane as page */ 7 } 8 9 - /* Desktop: sidebar gets top and right borders */ 10 - @media (min-width: 1400px) { 11 - .profile-display { 12 - border-top: 1.5px dashed var(--color-border); 13 - border-right: 1.5px dashed var(--color-border); 14 - } 15 - } 16 - 17 - /* Mobile: header gets top and bottom borders */ 18 - @media (max-width: 1400px) { 19 - .profile-display { 20 - border-top: 1.5px dashed var(--color-border); 21 - border-bottom: 1.5px solid var(--color-border); 22 - } 23 - } 24 - 25 .profile-banner { 26 max-width: 100%; 27 - height: 120px; 28 overflow: hidden; 29 } 30 ··· 45 .profile-identity .avatar { 46 width: 120px; 47 height: 120px; 48 margin-bottom: 1rem; 49 } 50 ··· 69 .profile-handle { 70 font-size: 0.95rem; 71 color: var(--color-subtle); 72 - margin-bottom: 0.5rem; 73 } 74 75 .profile-location { ··· 130 } 131 132 .profile-link-platform { 133 font-weight: 500; 134 } 135 ··· 151 } 152 } 153 154 @media (prefers-color-scheme: dark) { 155 .profile-display { 156 background-color: var(--color-surface); 157 border: 1px dashed var(--color-border); 158 } 159 }
··· 6 /* No background - same plane as page */ 7 } 8 9 .profile-banner { 10 max-width: 100%; 11 + height: 200px; 12 overflow: hidden; 13 } 14 ··· 29 .profile-identity .avatar { 30 width: 120px; 31 height: 120px; 32 + margin-top: -5rem; 33 margin-bottom: 1rem; 34 } 35 ··· 54 .profile-handle { 55 font-size: 0.95rem; 56 color: var(--color-subtle); 57 + margin-bottom: 0rem; 58 } 59 60 .profile-location { ··· 115 } 116 117 .profile-link-platform { 118 + display: inline; 119 font-weight: 500; 120 } 121 ··· 137 } 138 } 139 140 + /* Mobile: header gets top and bottom borders */ 141 + @media (max-width: 1400px) { 142 + .profile-display { 143 + border-top: 1.5px dashed var(--color-border); 144 + border-bottom: 1.5px solid var(--color-border); 145 + } 146 + 147 + .profile-content { 148 + display: flex; 149 + flex-direction: row; 150 + justify-content: space-between; 151 + } 152 + 153 + .profile-extras { 154 + padding-left: 1rem; 155 + border-left: 1.5px dashed var(--color-border); 156 + } 157 + 158 + .profile-block { 159 + display: flex; 160 + flex-direction: row; 161 + } 162 + 163 + .profile-stats { 164 + border-top: none; 165 + } 166 + 167 + .profile-identity .avatar { 168 + margin-bottom: 0rem; 169 + } 170 + 171 + .profile-description { 172 + margin-top: 0rem; 173 + } 174 + 175 + .profile-name-section { 176 + margin-left: 1rem; 177 + margin-top: -0.5rem; 178 + } 179 + } 180 + 181 @media (prefers-color-scheme: dark) { 182 .profile-display { 183 background-color: var(--color-surface); 184 border: 1px dashed var(--color-border); 185 } 186 } 187 + 188 + /* Desktop: sidebar gets top and right borders */ 189 + @media (min-width: 1400px) { 190 + .profile-display { 191 + border-top: 1.5px dashed var(--color-border); 192 + border-right: 1.5px dashed var(--color-border); 193 + } 194 + }
+40 -4
crates/weaver-app/assets/styling/theme-defaults.css
··· 1 /* Default theme variables for non-notebook pages */ 2 /* These match the Rose Pine light/dark defaults */ 3 4 /* CSS Variables - Light Mode (default) */ 5 :root { 6 --color-base: #faf4ed; ··· 20 --color-link: #d7827e; 21 --color-highlight: #cecacd; 22 23 - --font-body: IBM Plex, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; 24 - --font-heading: IBM Plex Sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; 25 - --font-mono: "IBM Plex Mono", "Berkeley Mono", "Cascadia Code", "Roboto Mono", Consolas, monospace; 26 27 --spacing-base: 16px; 28 --spacing-line-height: 1.6; ··· 49 --color-link: #ebbcba; 50 --color-highlight: #524f67; 51 } 52 - 53 }
··· 1 /* Default theme variables for non-notebook pages */ 2 /* These match the Rose Pine light/dark defaults */ 3 4 + @font-face { 5 + font-family: "Ioskeley Mono"; 6 + font-style: normal; 7 + font-weight: normal; 8 + src: url("/assets/IoskeleyMono-Regular.woff2") format("woff2"); 9 + } 10 + @font-face { 11 + font-family: "Ioskeley Mono"; 12 + font-style: normal; 13 + font-weight: lighter; 14 + src: url("/assets/IoskeleyMono-Light.woff2") format("woff2"); 15 + } 16 + @font-face { 17 + font-family: "Ioskeley Mono"; 18 + font-style: italic; 19 + font-weight: lighter; 20 + src: url("/assets/IoskeleyMono-LightItalic.woff2") format("woff2"); 21 + } 22 + @font-face { 23 + font-family: "Ioskeley Mono"; 24 + font-style: normal; 25 + font-weight: bold; 26 + src: url("/assets/IoskeleyMono-Bold.woff2") format("woff2"); 27 + } 28 + @font-face { 29 + font-family: "Ioskeley Mono"; 30 + font-style: italic; 31 + font-weight: normal; 32 + src: url("/assets/IoskeleyMono-Italic.woff2") format("woff2"); 33 + } 34 + @font-face { 35 + font-family: "Ioskeley Mono"; 36 + font-style: italic; 37 + font-weight: bold; 38 + src: url("/assets/IoskeleyMono-BoldItalic.woff2") format("woff2"); 39 + } 40 + 41 /* CSS Variables - Light Mode (default) */ 42 :root { 43 --color-base: #faf4ed; ··· 57 --color-link: #d7827e; 58 --color-highlight: #cecacd; 59 60 + --font-body: "IBM Plex", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; 61 + --font-heading: "IBM Plex Sans", system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; 62 + --font-mono: "Ioskeley Mono", "IBM Plex Mono", "Berkeley Mono", "Cascadia Code", "Roboto Mono", Consolas, monospace; 63 64 --spacing-base: 16px; 65 --spacing-line-height: 1.6; ··· 86 --color-link: #ebbcba; 87 --color-highlight: #524f67; 88 } 89 }
+100
crates/weaver-app/src/components/mod.rs
··· 17 18 pub mod notebook_cover; 19 pub use notebook_cover::NotebookCover;
··· 17 18 pub mod notebook_cover; 19 pub use notebook_cover::NotebookCover; 20 + 21 + use dioxus::prelude::*; 22 + 23 + #[derive(PartialEq, Props, Clone)] 24 + pub struct IconProps { 25 + #[props(default = Some(20))] 26 + pub height: Option<u32>, 27 + /// The width of the `<svg>` element. Defaults to 20. Pass None to omit. 28 + #[props(default = Some(20))] 29 + pub width: Option<u32>, 30 + /// The color to use for filling the icon. Defaults to "currentColor". 31 + #[props(default = "currentColor".to_string())] 32 + pub fill: String, 33 + /// An class for the `<svg>` element. 34 + #[props(default = "".to_string())] 35 + pub class: String, 36 + /// The style of the `<svg>` element. 37 + pub style: Option<String>, 38 + } 39 + 40 + #[component] 41 + pub fn BskyIcon(props: IconProps) -> Element { 42 + rsx! { 43 + svg { 44 + class: "{props.class}", 45 + style: props.style, 46 + height: props.height.map(|height| height.to_string()), 47 + width: props.width.map(|width| width.to_string()), 48 + view_box: "0 0 600 530", 49 + path { 50 + d: "m135.72 44.03c66.496 49.921 138.02 151.14 164.28 205.46 26.262-54.316 97.782-155.54 164.28-205.46 47.98-36.021 125.72-63.892 125.72 24.795 0 17.712-10.155 148.79-16.111 170.07-20.703 73.984-96.144 92.854-163.25 81.433 117.3 19.964 147.14 86.092 82.697 152.22-122.39 125.59-175.91-31.511-189.63-71.766-2.514-7.3797-3.6904-10.832-3.7077-7.8964-0.0174-2.9357-1.1937 0.51669-3.7077 7.8964-13.714 40.255-67.233 197.36-189.63 71.766-64.444-66.128-34.605-132.26 82.697-152.22-67.108 11.421-142.55-7.4491-163.25-81.433-5.9562-21.282-16.111-152.36-16.111-170.07 0-88.687 77.742-60.816 125.72-24.795z", 51 + fill: props.fill 52 + } 53 + } 54 + } 55 + } 56 + 57 + #[component] 58 + pub fn TangledIcon(props: IconProps) -> Element { 59 + rsx! { 60 + svg { 61 + class: "{props.class}", 62 + style: props.style, 63 + height: props.height.map(|height| height.to_string()), 64 + width: props.width.map(|width| width.to_string()), 65 + view_box: "0 0 24.122343 23.274094", 66 + path { 67 + d: "m 16.348974,24.09935 -0.06485,-0.03766 -0.202005,-0.0106 -0.202008,-0.01048 -0.275736,-0.02601 -0.275734,-0.02602 v -0.02649 -0.02648 l -0.204577,-0.04019 -0.204578,-0.04019 -0.167616,-0.08035 -0.167617,-0.08035 -0.0014,-0.04137 -0.0014,-0.04137 -0.266473,-0.143735 -0.266475,-0.143735 -0.276098,-0.20335 -0.2761,-0.203347 -0.262064,-0.251949 -0.262064,-0.25195 -0.22095,-0.284628 -0.220948,-0.284629 -0.170253,-0.284631 -0.170252,-0.284628 -0.01341,-0.0144 -0.0134,-0.0144 -0.141982,0.161297 -0.14198,0.1613 -0.22313,0.21426 -0.223132,0.214264 -0.186025,0.146053 -0.186023,0.14605 -0.252501,0.163342 -0.252502,0.163342 -0.249014,0.115348 -0.249013,0.115336 0.0053,0.03241 0.0053,0.03241 -0.1716725,0.04599 -0.171669,0.046 -0.3379966,0.101058 -0.3379972,0.101058 -0.1778925,0.04506 -0.1778935,0.04508 -0.3913655,0.02601 -0.3913643,0.02603 -0.3557868,-0.03514 -0.3557863,-0.03514 -0.037426,-0.03029 -0.037427,-0.03029 -0.076924,0.02011 -0.076924,0.02011 -0.050508,-0.05051 -0.050405,-0.05056 L 6.6604532,23.110188 6.451745,23.063961 6.1546135,22.960559 5.8574835,22.857156 5.5319879,22.694039 5.2064938,22.530922 4.8793922,22.302961 4.5522905,22.075005 4.247598,21.786585 3.9429055,21.49817 3.7185335,21.208777 3.4941628,20.919385 3.3669822,20.705914 3.239803,20.492443 3.1335213,20.278969 3.0272397,20.065499 2.9015252,19.7275 2.7758105,19.389504 2.6925225,18.998139 2.6092345,18.606774 2.6096814,17.91299 2.6101284,17.219208 2.6744634,16.90029 2.7387984,16.581374 2.8474286,16.242088 2.9560588,15.9028 3.1137374,15.583492 3.2714148,15.264182 3.3415068,15.150766 3.4115988,15.03735 3.3127798,14.96945 3.2139618,14.90157 3.0360685,14.800239 2.8581753,14.698908 2.5913347,14.503228 2.3244955,14.307547 2.0621238,14.055599 1.7997507,13.803651 1.6111953,13.56878 1.4226411,13.333906 1.2632237,13.087474 1.1038089,12.841042 0.97442,12.575195 0.8450307,12.30935 0.724603,11.971351 0.6041766,11.633356 0.52150365,11.241991 0.4388285,10.850626 0.44091592,10.156842 0.44300333,9.4630594 0.54235911,9.0369608 0.6417149,8.6108622 0.7741173,8.2694368 0.9065196,7.9280115 1.0736303,7.6214262 1.2407515,7.3148397 1.45931,7.0191718 1.6778685,6.7235039 1.9300326,6.4611321 2.1821966,6.1987592 2.4134579,6.0137228 2.6447193,5.8286865 2.8759792,5.6776409 3.1072406,5.526594 3.4282004,5.3713977 3.7491603,5.2162016 3.9263009,5.1508695 4.1034416,5.0855373 4.2813348,4.7481598 4.4592292,4.4107823 4.6718,4.108422 4.8843733,3.8060618 5.198353,3.4805372 5.5123313,3.155014 5.7685095,2.9596425 6.0246877,2.7642722 6.329187,2.5851365 6.6336863,2.406002 6.9497657,2.2751596 7.2658453,2.1443184 7.4756394,2.0772947 7.6854348,2.01027 8.0825241,1.931086 8.4796139,1.851902 l 0.5870477,0.00291 0.5870469,0.00291 0.4447315,0.092455 0.444734,0.092455 0.302419,0.1105495 0.302417,0.1105495 0.329929,0.1646046 0.32993,0.1646033 0.239329,-0.2316919 0.239329,-0.2316919 0.160103,-0.1256767 0.160105,-0.1256767 0.160102,-0.1021909 0.160105,-0.1021899 0.142315,-0.082328 0.142314,-0.082328 0.231262,-0.1090091 0.231259,-0.1090091 0.26684,-0.098743 0.266839,-0.098743 0.320208,-0.073514 0.320209,-0.073527 0.355787,-0.041833 0.355785,-0.041834 0.426942,0.023827 0.426945,0.023828 0.355785,0.071179 0.355788,0.0711791 0.284627,0.09267 0.284629,0.09267 0.28514,0.1310267 0.28514,0.1310255 0.238179,0.1446969 0.238174,0.1446979 0.259413,0.1955332 0.259413,0.1955319 0.290757,0.296774 0.290758,0.2967753 0.151736,0.1941581 0.151734,0.1941594 0.135326,0.2149951 0.135327,0.2149952 0.154755,0.3202073 0.154758,0.3202085 0.09409,0.2677358 0.09409,0.267737 0.06948,0.3319087 0.06948,0.3319099 0.01111,0.00808 0.01111,0.00808 0.444734,0.2173653 0.444734,0.2173665 0.309499,0.2161102 0.309497,0.2161101 0.309694,0.2930023 0.309694,0.2930037 0.18752,0.2348726 0.187524,0.2348727 0.166516,0.2574092 0.166519,0.2574108 0.15273,0.3260252 0.152734,0.3260262 0.08972,0.2668403 0.08971,0.2668391 0.08295,0.3913655 0.08295,0.3913652 -6.21e-4,0.6582049 -6.21e-4,0.658204 -0.06362,0.315725 -0.06362,0.315725 -0.09046,0.289112 -0.09046,0.289112 -0.122759,0.281358 -0.12276,0.281356 -0.146626,0.252323 -0.146629,0.252322 -0.190443,0.258668 -0.190448,0.258671 -0.254911,0.268356 -0.254911,0.268355 -0.286872,0.223127 -0.286874,0.223127 -0.320203,0.187693 -0.320209,0.187693 -0.04347,0.03519 -0.04347,0.03521 0.0564,0.12989 0.0564,0.129892 0.08728,0.213472 0.08728,0.213471 0.189755,0.729363 0.189753,0.729362 0.0652,0.302417 0.0652,0.302419 -0.0018,0.675994 -0.0018,0.675995 -0.0801,0.373573 -0.08009,0.373577 -0.09,0.266839 -0.09,0.26684 -0.190389,0.391364 -0.19039,0.391366 -0.223169,0.320207 -0.223167,0.320209 -0.303585,0.315294 -0.303584,0.315291 -0.284631,0.220665 -0.284629,0.220663 -0.220128,0.132359 -0.220127,0.132358 -0.242395,0.106698 -0.242394,0.106699 -0.08895,0.04734 -0.08895,0.04733 -0.249052,0.07247 -0.24905,0.07247 -0.322042,0.0574 -0.322044,0.0574 -0.282794,-0.003 -0.282795,-0.003 -0.07115,-0.0031 -0.07115,-0.0031 -0.177894,-0.0033 -0.177893,-0.0033 -0.124528,0.02555 -0.124528,0.02555 z m -4.470079,-5.349839 0.214838,-0.01739 0.206601,-0.06782 0.206602,-0.06782 0.244389,-0.117874 0.244393,-0.11786 0.274473,-0.206822 0.27447,-0.20682 0.229308,-0.257201 0.229306,-0.2572 0.219161,-0.28463 0.219159,-0.284629 0.188541,-0.284628 0.188543,-0.28463 0.214594,-0.373574 0.214593,-0.373577 0.133861,-0.312006 0.133865,-0.312007 0.02861,-0.01769 0.02861,-0.01769 0.197275,0.26212 0.197278,0.262119 0.163613,0.150814 0.163614,0.150814 0.201914,0.09276 0.201914,0.09276 0.302417,0.01421 0.302418,0.01421 0.213472,-0.08025 0.213471,-0.08025 0.200606,-0.204641 0.200606,-0.204642 0.09242,-0.278887 0.09241,-0.278888 0.05765,-0.302418 0.05764,-0.302416 L 18.41327,13.768114 18.39502,13.34117 18.31849,12.915185 18.24196,12.4892 18.15595,12.168033 18.06994,11.846867 17.928869,11.444534 17.787801,11.042201 17.621278,10.73296 17.454757,10.423723 17.337388,10.263619 17.220021,10.103516 17.095645,9.9837986 16.971268,9.8640816 16.990048,9.6813736 17.008828,9.4986654 16.947568,9.249616 16.886308,9.0005655 16.752419,8.7159355 16.618521,8.4313217 16.435707,8.2294676 16.252892,8.0276114 16.079629,7.9004245 15.906366,7.773238 l -0.20429,0.1230127 -0.204289,0.1230121 -0.26702,0.059413 -0.267022,0.059413 -0.205761,-0.021508 -0.205766,-0.021508 -0.23495,-0.08844 -0.234953,-0.08844 -0.118429,-0.090334 -0.118428,-0.090333 h -0.03944 -0.03944 L 13.711268,7.8540732 13.655958,7.9706205 13.497227,8.1520709 13.338499,8.3335203 13.168394,8.4419112 12.998289,8.550301 12.777045,8.624223 12.5558,8.698155 H 12.275611 11.995429 L 11.799973,8.6309015 11.604513,8.5636472 11.491311,8.5051061 11.37811,8.446565 11.138172,8.2254579 10.898231,8.0043497 l -0.09565,-0.084618 -0.09565,-0.084613 -0.218822,0.198024 -0.218822,0.1980231 -0.165392,0.078387 -0.1653925,0.078387 -0.177894,0.047948 -0.177892,0.047948 L 9.3635263,8.4842631 9.144328,8.4846889 8.9195029,8.4147138 8.6946778,8.3447386 8.5931214,8.4414036 8.491565,8.5380686 8.3707618,8.7019598 8.2499597,8.8658478 8.0802403,8.9290726 7.9105231,8.9922974 7.7952769,9.0780061 7.6800299,9.1637148 7.5706169,9.2778257 7.4612038,9.3919481 7.1059768,9.9205267 6.7507497,10.449105 l -0.2159851,0.449834 -0.2159839,0.449834 -0.2216572,0.462522 -0.2216559,0.462523 -0.1459343,0.337996 -0.1459342,0.337998 -0.055483,0.220042 -0.055483,0.220041 -0.015885,0.206903 -0.015872,0.206901 0.034307,0.242939 0.034307,0.24294 0.096281,0.196632 0.096281,0.196634 0.143607,0.125222 0.1436071,0.125222 0.1873143,0.08737 0.1873141,0.08737 0.2752084,0.002 0.2752084,0.002 0.2312297,-0.09773 0.231231,-0.09772 0.1067615,-0.07603 0.1067614,-0.07603 0.3679062,-0.29377 0.3679065,-0.293771 0.026804,0.01656 0.026804,0.01656 0.023626,0.466819 0.023626,0.466815 0.088326,0.513195 0.088326,0.513193 0.08897,0.364413 0.08897,0.364411 0.1315362,0.302418 0.1315352,0.302418 0.1051964,0.160105 0.1051954,0.160103 0.1104741,0.11877 0.1104731,0.118769 0.2846284,0.205644 0.2846305,0.205642 0.144448,0.07312 0.144448,0.07312 0.214787,0.05566 0.214787,0.05566 0.245601,0.03075 0.245602,0.03075 0.204577,-0.0125 0.204578,-0.0125 z m 0.686342,-3.497495 -0.11281,-0.06077 -0.106155,-0.134033 -0.106155,-0.134031 -0.04406,-0.18371 -0.04406,-0.183707 0.02417,-0.553937 0.02417,-0.553936 0.03513,-0.426945 0.03513,-0.426942 0.07225,-0.373576 0.07225,-0.373575 0.05417,-0.211338 0.05417,-0.211339 0.0674,-0.132112 0.0674,-0.132112 0.132437,-0.10916 0.132437,-0.109161 0.187436,-0.04195 0.187438,-0.04195 0.170366,0.06469 0.170364,0.06469 0.114312,0.124073 0.114313,0.124086 0.04139,0.18495 0.04139,0.184951 -0.111218,0.459845 -0.111219,0.459844 -0.03383,0.26584 -0.03382,0.265841 -0.03986,0.818307 -0.03986,0.818309 -0.0378,0.15162 -0.03779,0.151621 -0.11089,0.110562 -0.110891,0.110561 -0.114489,0.04913 -0.114489,0.04913 -0.187932,-0.0016 -0.187929,-0.0016 z m -2.8087655,-0.358124 -0.146445,-0.06848 -0.088025,-0.119502 -0.088024,-0.119502 -0.038581,-0.106736 -0.038581,-0.106736 -0.02237,-0.134956 -0.02239,-0.134957 -0.031955,-0.46988 -0.031955,-0.469881 0.036203,-0.444733 0.036203,-0.444731 0.048862,-0.215257 0.048862,-0.215255 0.076082,-0.203349 0.076081,-0.203348 0.0936,-0.111244 0.0936,-0.111245 0.143787,-0.06531 0.1437865,-0.06532 h 0.142315 0.142314 l 0.142314,0.06588 0.142316,0.06588 0.093,0.102325 0.093,0.102325 0.04042,0.120942 0.04042,0.120942 v 0.152479 0.152477 l -0.03347,0.08804 -0.03347,0.08805 -0.05693,0.275653 -0.05693,0.275651 2.11e-4,0.430246 2.12e-4,0.430243 0.04294,0.392646 0.04295,0.392647 -0.09189,0.200702 -0.09189,0.200702 -0.148688,0.0984 -0.148687,0.0984 -0.20136,0.01212 -0.2013595,0.01212 z", 68 + fill: props.fill 69 + } 70 + } 71 + 72 + } 73 + } 74 + 75 + #[used] 76 + static _IOSK_BOLD: Asset = asset!( 77 + "/assets/fonts/ioskeley-mono/IoskeleyMono-Bold.woff2", 78 + AssetOptions::builder() 79 + .with_hash_suffix(false) 80 + .into_asset_options() 81 + ); 82 + 83 + #[used] 84 + static _IOSK_REG: Asset = asset!( 85 + "/assets/fonts/ioskeley-mono/IoskeleyMono-Regular.woff2", 86 + AssetOptions::builder() 87 + .with_hash_suffix(false) 88 + .into_asset_options() 89 + ); 90 + 91 + #[used] 92 + static _IOSK_ITAL: Asset = asset!( 93 + "/assets/fonts/ioskeley-mono/IoskeleyMono-Italic.woff2", 94 + AssetOptions::builder() 95 + .with_hash_suffix(false) 96 + .into_asset_options() 97 + ); 98 + 99 + #[used] 100 + static _IOSK_LIGHT: Asset = asset!( 101 + "/assets/fonts/ioskeley-mono/IoskeleyMono-Light.woff2", 102 + AssetOptions::builder() 103 + .with_hash_suffix(false) 104 + .into_asset_options() 105 + ); 106 + #[used] 107 + static _IOSK_LIGHT_ITAL: Asset = asset!( 108 + "/assets/fonts/ioskeley-mono/IoskeleyMono-LightItalic.woff2", 109 + AssetOptions::builder() 110 + .with_hash_suffix(false) 111 + .into_asset_options() 112 + ); 113 + #[used] 114 + static _IOSK_ITAL_BOLD: Asset = asset!( 115 + "/assets/fonts/ioskeley-mono/IoskeleyMono-BoldItalic.woff2", 116 + AssetOptions::builder() 117 + .with_hash_suffix(false) 118 + .into_asset_options() 119 + );
+57 -30
crates/weaver-app/src/components/profile.rs
··· 1 #![allow(non_snake_case)] 2 3 use crate::{ 4 - components::avatar::{Avatar, AvatarImage}, 5 data::use_handle, 6 Route, 7 }; ··· 51 div { class: "profile-content", 52 // Avatar and identity 53 ProfileIdentity { profile_view: profile_view.clone(), ident: ident.clone() } 54 55 - // Stats 56 - ProfileStats { ident: ident.clone() } 57 58 - // Links 59 - ProfileLinks { profile_view: profile_view.clone(), ident: ident.clone() } 60 } 61 } 62 }, ··· 100 101 rsx! { 102 div { class: "profile-identity", 103 - if let Some(ref avatar) = profile.avatar { 104 - Avatar { 105 - AvatarImage { src: avatar.as_ref() } 106 } 107 - } 108 109 - div { class: "profile-name-section", 110 - h1 { class: "profile-display-name", 111 - "{display_name}" 112 - if let Some(ref pronouns) = pronouns_text { 113 - span { class: "profile-pronouns", " ({pronouns})" } 114 } 115 - } 116 - div { class: "profile-handle", "@{use_handle(ident.clone())?}" } 117 118 - if let Some(ref location) = profile.location { 119 - div { class: "profile-location", "{location}" } 120 } 121 } 122 123 if let Some(ref description) = profile.description { 124 div { class: "profile-description", "{description}" } ··· 135 136 rsx! { 137 div { class: "profile-identity", 138 - if let Some(ref avatar) = profile.avatar { 139 - Avatar { 140 - AvatarImage { src: avatar.as_ref() } 141 } 142 - } 143 144 - div { class: "profile-name-section", 145 - h1 { class: "profile-display-name", "{display_name}" } 146 - div { class: "profile-handle", "@{use_handle(ident.clone())?}" } 147 } 148 149 if let Some(ref description) = profile.description { ··· 224 target: "_blank", 225 rel: "noopener noreferrer", 226 class: "profile-link profile-link-platform", 227 - "View on Bluesky" 228 } 229 } 230 231 if profile.tangled.unwrap_or(false) { 232 a { 233 - href: "https://tangled.dev/{ident}", 234 target: "_blank", 235 rel: "noopener noreferrer", 236 class: "profile-link profile-link-platform", 237 - "View on Tangled" 238 } 239 } 240 ··· 259 target: "_blank", 260 rel: "noopener noreferrer", 261 class: "profile-link profile-link-platform", 262 - "View on Bluesky" 263 } 264 } 265 } 266 } ··· 278 } 279 } 280 } 281 282 if profile.bluesky { 283 a { ··· 285 target: "_blank", 286 rel: "noopener noreferrer", 287 class: "profile-link profile-link-platform", 288 - "View on Bluesky" 289 } 290 } 291 }
··· 1 #![allow(non_snake_case)] 2 3 use crate::{ 4 + components::{ 5 + avatar::{Avatar, AvatarImage}, 6 + BskyIcon, TangledIcon, 7 + }, 8 data::use_handle, 9 Route, 10 }; ··· 54 div { class: "profile-content", 55 // Avatar and identity 56 ProfileIdentity { profile_view: profile_view.clone(), ident: ident.clone() } 57 + div { 58 + class: "profile-extras", 59 + // Stats 60 + ProfileStats { ident: ident.clone() } 61 62 + // Links 63 + ProfileLinks { profile_view: profile_view.clone(), ident: ident.clone() } 64 + } 65 66 + 67 } 68 } 69 }, ··· 107 108 rsx! { 109 div { class: "profile-identity", 110 + div { 111 + class: "profile-block", 112 + if let Some(ref avatar) = profile.avatar { 113 + Avatar { 114 + AvatarImage { src: avatar.as_ref() } 115 + } 116 } 117 118 + div { class: "profile-name-section", 119 + h1 { class: "profile-display-name", 120 + "{display_name}" 121 + if let Some(ref pronouns) = pronouns_text { 122 + span { class: "profile-pronouns", " ({pronouns})" } 123 + } 124 } 125 + div { class: "profile-handle", "@{use_handle(ident.clone())?}" } 126 127 + if let Some(ref location) = profile.location { 128 + div { class: "profile-location", "{location}" } 129 + } 130 } 131 } 132 + 133 134 if let Some(ref description) = profile.description { 135 div { class: "profile-description", "{description}" } ··· 146 147 rsx! { 148 div { class: "profile-identity", 149 + div { 150 + class: "profile-block", 151 + if let Some(ref avatar) = profile.avatar { 152 + Avatar { 153 + AvatarImage { src: avatar.as_ref() } 154 + } 155 } 156 157 + div { class: "profile-name-section", 158 + h1 { class: "profile-display-name", "{display_name}" } 159 + div { class: "profile-handle", "@{use_handle(ident.clone())?}" } 160 + } 161 } 162 163 if let Some(ref description) = profile.description { ··· 238 target: "_blank", 239 rel: "noopener noreferrer", 240 class: "profile-link profile-link-platform", 241 + BskyIcon { width: 20, height: 20, style: "vertical-align: text-bottom" } 242 + " Bluesky" 243 } 244 } 245 246 if profile.tangled.unwrap_or(false) { 247 a { 248 + href: "https://tangled.org/@{ident}", 249 target: "_blank", 250 rel: "noopener noreferrer", 251 class: "profile-link profile-link-platform", 252 + TangledIcon { width: 20, height: 20, style: "vertical-align: text-bottom" } 253 + " Tangled" 254 } 255 } 256 ··· 275 target: "_blank", 276 rel: "noopener noreferrer", 277 class: "profile-link profile-link-platform", 278 + BskyIcon { width: 20, height: 20, style: "vertical-align: text-bottom" } 279 + " Bluesky" 280 } 281 + 282 } 283 } 284 } ··· 296 } 297 } 298 } 299 + a { 300 + href: "https://tangled.org/@{ident}", 301 + target: "_blank", 302 + rel: "noopener noreferrer", 303 + class: "profile-link profile-link-platform", 304 + TangledIcon { width: 20, height: 20, style: "vertical-align: text-bottom" } 305 + " Tangled" 306 + } 307 308 if profile.bluesky { 309 a { ··· 311 target: "_blank", 312 rel: "noopener noreferrer", 313 class: "profile-link profile-link-platform", 314 + BskyIcon { width: 20, height: 20, style: "vertical-align: text-bottom" } 315 + " Bluesky" 316 } 317 } 318 }
+2 -2
crates/weaver-renderer/src/code_pretty.rs
··· 27 .find_syntax_by_first_line(code.as_ref()) 28 .unwrap_or_else(|| syn_set.find_syntax_plain_text()) 29 }; 30 - writer.write_str("<pre><code class=\"wvrcode-code language-")?; 31 writer.write_str(&lang_syn.name)?; 32 writer.write_str("\">")?; 33 ··· 46 Ok(()) 47 } 48 49 - pub const CSS_PREFIX: &str = "wvrcode-";
··· 27 .find_syntax_by_first_line(code.as_ref()) 28 .unwrap_or_else(|| syn_set.find_syntax_plain_text()) 29 }; 30 + writer.write_str("<pre><code class=\"wvc-code language-")?; 31 writer.write_str(&lang_syn.name)?; 32 writer.write_str("\">")?; 33 ··· 46 Ok(()) 47 } 48 49 + pub const CSS_PREFIX: &str = "wvc-";
+1 -1
crates/weaver-renderer/src/css.rs
··· 131 text-decoration: none; 132 }} 133 134 - a:hover {{ 135 color: var(--color-emphasis); 136 text-decoration: underline; 137 }}
··· 131 text-decoration: none; 132 }} 133 134 + .notebook-content a:hover {{ 135 color: var(--color-emphasis); 136 text-decoration: underline; 137 }}
+18 -1
crates/weaver-renderer/src/theme.rs
··· 9 use weaver_common::jacquard::cowstr::ToCowStr; 10 use weaver_common::jacquard::prelude::*; 11 12 /// A theme with resolved colour schemes (no strongRefs, actual data) 13 #[derive(Clone, Debug)] 14 pub struct ResolvedTheme<'a> { 15 pub dark_scheme: ColourSchemeColours<'a>, 16 pub light_scheme: ColourSchemeColours<'a>, 17 pub fonts: ThemeFonts<'a>, ··· 51 "'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif", 52 ), 53 monospace: CowStr::new_static( 54 - "'IBM Plex Mono', 'Berkeley Mono', 'Cascadia Code', 'Roboto Mono', Consolas, monospace", 55 ), 56 ..Default::default() 57 } ··· 90 91 pub fn default_resolved_theme() -> ResolvedTheme<'static> { 92 ResolvedTheme { 93 dark_scheme: default_colour_scheme_dark(), 94 light_scheme: default_colour_scheme_light(), 95 fonts: default_fonts(), ··· 123 .into_diagnostic()?; 124 125 let light_scheme: ColourScheme = light_response.into_output().into_diagnostic()?.into(); 126 127 Ok(ResolvedTheme { 128 dark_scheme: dark_scheme.colours.into_static(), 129 light_scheme: light_scheme.colours.into_static(), 130 fonts: theme.fonts.clone().into_static(),
··· 9 use weaver_common::jacquard::cowstr::ToCowStr; 10 use weaver_common::jacquard::prelude::*; 11 12 + #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] 13 + pub enum ThemeDefault { 14 + #[default] 15 + Auto, 16 + Light, 17 + Dark, 18 + } 19 + 20 /// A theme with resolved colour schemes (no strongRefs, actual data) 21 #[derive(Clone, Debug)] 22 pub struct ResolvedTheme<'a> { 23 + pub default: ThemeDefault, 24 pub dark_scheme: ColourSchemeColours<'a>, 25 pub light_scheme: ColourSchemeColours<'a>, 26 pub fonts: ThemeFonts<'a>, ··· 60 "'IBM Plex Sans', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif", 61 ), 62 monospace: CowStr::new_static( 63 + "'Ioskeley Mono', 'IBM Plex Mono', 'Berkeley Mono', 'Cascadia Code', 'Roboto Mono', Consolas, monospace", 64 ), 65 ..Default::default() 66 } ··· 99 100 pub fn default_resolved_theme() -> ResolvedTheme<'static> { 101 ResolvedTheme { 102 + default: ThemeDefault::Auto, 103 dark_scheme: default_colour_scheme_dark(), 104 light_scheme: default_colour_scheme_light(), 105 fonts: default_fonts(), ··· 133 .into_diagnostic()?; 134 135 let light_scheme: ColourScheme = light_response.into_output().into_diagnostic()?.into(); 136 + let default = match theme.default_theme.as_ref().map(|t| t.as_str()) { 137 + Some("auto") => ThemeDefault::Auto, 138 + Some("dark") => ThemeDefault::Dark, 139 + Some("light") => ThemeDefault::Light, 140 + _ => ThemeDefault::Auto, 141 + }; 142 143 Ok(ResolvedTheme { 144 + default, 145 dark_scheme: dark_scheme.colours.into_static(), 146 light_scheme: light_scheme.colours.into_static(), 147 fonts: theme.fonts.clone().into_static(),
+5
lexicons/notebook/theme.json
··· 10 "type": "object", 11 "required": ["darkScheme", "lightScheme", "fonts", "spacing", "darkCodeTheme", "lightCodeTheme"], 12 "properties": { 13 "darkScheme": { 14 "type": "ref", 15 "ref": "com.atproto.repo.strongRef",
··· 10 "type": "object", 11 "required": ["darkScheme", "lightScheme", "fonts", "spacing", "darkCodeTheme", "lightCodeTheme"], 12 "properties": { 13 + "defaultTheme": { 14 + "type": "string", 15 + "enum": ["light", "dark", "auto"], 16 + "default": "auto" 17 + }, 18 "darkScheme": { 19 "type": "ref", 20 "ref": "com.atproto.repo.strongRef",