Skip to content

Commit 0e1701b

Browse files
authored
Merge pull request #54 from namiba-work/main
Adding the announcements page + updates to text
2 parents b451b13 + 742ece2 commit 0e1701b

File tree

9 files changed

+218
-25
lines changed

9 files changed

+218
-25
lines changed

public/images/flag.svg

Lines changed: 1 addition & 0 deletions
Loading

src/components/announce_banner.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
use leptos::prelude::*;
2+
3+
#[component]
4+
pub fn AnnounceBanner() -> impl IntoView {
5+
view! {
6+
<div class="background_announcement w-full flex items-center gap-3 px-6 py-3">
7+
<img src="/images/flag.svg" alt="Flag Icon" class="w-6 h-6" style="display: inline-block;" />
8+
<span class="p3">
9+
<span class="font-bold">{"UPDATE: "}</span>
10+
<span>{"Open Device Partnership Expands Open-Source Efforts; "}</span>
11+
<a href="/announcements?id=welcome-patina-announcement" class="underline hover:text-blue-600 transition-colors duration-150">
12+
{"Patina Project to Launch at UEFI 2025 Developer Conference & Plugfest - read more!"}
13+
</a>
14+
</span>
15+
</div>
16+
}
17+
}

src/components/header.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1+
use crate::components::announce_banner::AnnounceBanner;
12
use leptos::prelude::RwSignal;
23
use leptos::prelude::*;
34
use leptos_router::components::A;
45

56
#[component]
6-
pub fn Header() -> impl IntoView {
7+
pub fn Header(#[prop(optional, default = "header_background")] background_class: &'static str) -> impl IntoView {
78
let menu_open = RwSignal::new(false);
89
view! {
9-
<header class="w-full h-[80px] md:h-[160px] px-2 md:px-[120px] background_primary flex items-center justify-between z-50 m-0 p-0 relative">
10+
<header class={format!("w-full h-[80px] md:h-[160px] px-2 md:px-[120px] {} flex items-center justify-between z-50 m-0 p-0 relative", background_class)}>
1011
<div class="flex items-center space-x-6">
1112
<picture>
1213
<source srcset="/images/dark/odplogo.svg" media="(prefers-color-scheme: dark)" />
@@ -29,10 +30,8 @@ pub fn Header() -> impl IntoView {
2930
<span class="block w-6 h-0.5 bg-black dark:bg-white"></span>
3031
</button>
3132

32-
{/* Navigation */}
33-
<nav
34-
class="hidden md:flex [column-gap:25px]"
35-
>
33+
{/* Desktop Navigation */}
34+
<nav class="hidden md:flex [column-gap:25px]">
3635
<NavButton href="/getting-started" label="Getting Started"/>
3736
<NavButton href="/projects" label="Projects"/>
3837
<ExternalNavButton href="https://opendevicepartnership.github.io/documentation/" label="Library"/>
@@ -52,6 +51,7 @@ pub fn Header() -> impl IntoView {
5251
<NavButton href="/home" label="Home" mobile=true/>
5352
</nav>
5453
</header>
54+
<AnnounceBanner />
5555
}
5656
}
5757

src/components/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod announce_banner;
12
pub mod community_teams;
23
pub mod documentation_training;
34
pub mod footer;

src/components/projects_component.rs

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -117,24 +117,21 @@ pub fn ProjectsComponent() -> impl IntoView {
117117
</span>
118118
<div class="flex flex-col gap-[8px]">
119119
<a
120-
href=""
120+
href="https://opendevicepartnership.github.io/patina"
121121
class="link"
122122
style="text-decoration: none;"
123-
target="_blank"
124123
>
125124
<span style="text-decoration: none;">{"→ "}</span>
126-
<span style="text-decoration: underline;">{"Docs coming soon"}</span>
125+
<span style="text-decoration: underline;">{"Read the Patina Documentation"}</span>
127126
</a>
128-
<span
129-
class="p2_mobile md:p2"
130-
style="
131-
display: block;
132-
text-align: left;
133-
color: #888;
134-
"
127+
<a
128+
href="https://github.com/opendevicepartnership/patina"
129+
class="link"
130+
style="text-decoration: none;"
135131
>
136-
{"Patina GitHub repo coming soon!"}
137-
</span>
132+
<span style="text-decoration: none;">{"→ "}</span>
133+
<span style="text-decoration: underline;">{"View Patina Source Code on GitHub"}</span>
134+
</a>
138135
</div>
139136
</div>
140137
</div>
@@ -176,18 +173,17 @@ pub fn ProjectsComponent() -> impl IntoView {
176173
href="https://opendevicepartnership.github.io/documentation/tracks/embedded_controller/track_overview.html"
177174
class="link"
178175
style="text-decoration: none;"
179-
target="_blank"
180176
>
181177
<span style="text-decoration: none;">{"→ "}</span>
182-
<span style="text-decoration: underline;">{"Read the Secure EC Guide"}</span>
178+
<span style="text-decoration: underline;">{"Read the Secure EC Documentation"}</span>
183179
</a>
184180
<a
185181
href="https://github.com/OpenDevicePartnership/embedded-services"
186182
class="link"
187183
style="text-decoration: none;"
188184
>
189185
<span style="text-decoration: none;">{"→ "}</span>
190-
<span style="text-decoration: underline;">{"View Secure EC (core) on GitHub"}</span>
186+
<span style="text-decoration: underline;">{"View Secure EC Source Code on GitHub"}</span>
191187
</a>
192188
</div>
193189
</div>
@@ -230,18 +226,17 @@ pub fn ProjectsComponent() -> impl IntoView {
230226
href="https://opendevicepartnership.github.io/documentation/guide/intro/concepts/EC_Services.html"
231227
class="link"
232228
style="text-decoration: none;"
233-
target="_blank"
234229
>
235230
<span style="text-decoration: none;">{"→ "}</span>
236-
<span style="text-decoration: underline;">{"Read the EC Services Guide"}</span>
231+
<span style="text-decoration: underline;">{"Read the EC Services Documentation"}</span>
237232
</a>
238233
<a
239234
href="https://github.com/OpenDevicePartnership/haf-ec-service"
240235
class="link"
241236
style="text-decoration: none;"
242237
>
243238
<span style="text-decoration: none;">{"→ "}</span>
244-
<span style="text-decoration: underline;">{"View EC Services on GitHub"}</span>
239+
<span style="text-decoration: underline;">{"View EC Services Source Code on GitHub"}</span>
245240
</a>
246241
</div>
247242
</div>

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod components;
77
mod pages;
88

99
// Top-Level pages
10+
use crate::pages::announcements::AnnouncementsPage;
1011
use crate::pages::boot_firmware::BootFirmware;
1112
use crate::pages::community::Community;
1213
use crate::pages::embedded_controller::EmbeddedController;
@@ -48,6 +49,7 @@ pub fn App() -> impl IntoView {
4849
<Route path=path!("/projects") view=Projects />
4950
<Route path=path!("/") view=Home />
5051
<Route path=path!("/team-ec-services") view=TeamECServices />
52+
<Route path=path!("/announcements") view=AnnouncementsPage />
5153
</Routes>
5254
</Router>
5355
</div>

src/pages/announcements.rs

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
use crate::components::footer::Footer;
2+
use crate::components::header::Header;
3+
use leptos::prelude::Effect;
4+
use leptos::prelude::*;
5+
use leptos_router::hooks::{use_location, use_navigate};
6+
7+
// Welcome Patina Press Release
8+
fn patina_press_release() -> impl IntoView {
9+
view! {
10+
<div>
11+
<p class="mb-4">
12+
<strong>"October 7, 2025 – Redmond, WA"</strong> " – The " <strong>"Open Device Partnership (ODP)"</strong> " is announcing " <strong>"Patina"</strong>", a new open-source firmware project is public, and details will be shared at the upcoming "
13+
<a href="https://uefi.org/events/uefi-2025-developers-conference-and-plugfest" class="underline hover:text-blue-600 transition-colors duration-150">
14+
"UEFI 2025 Developer Conference & Plugfest"
15+
</a>
16+
", October 7–10 in Sunnyvale, California. Patina is a Rust-based, UEFI-compatible firmware designed for memory safety and to address long standing challenges in the PC firmware ecosystem. It reimagines system firmware development to meet the evolving needs of modern hardware, software development lifecycles, supply chains, and industry collaboration. Patina joins a growing portfolio of ODP projects aimed at building a secure, modern foundation for device enablement. To learn more about Patina, please visit the project page and documentation here: "
17+
<a href="https://opendevicepartnership.github.io/patina" class="underline hover:text-blue-600 transition-colors duration-150">
18+
"Patina Documentation"
19+
</a>
20+
"."
21+
</p>
22+
23+
<p class="mb-4">
24+
"ODP is an industry-wide, open-source initiative focused on advancing " <strong>"security, fundamentals, and standardization"</strong> " in device software. The partnership's work addresses long-standing challenges in firmware and system design by leveraging " <strong>"memory-safe programming languages like Rust"</strong> " and " <strong>"hardware-rooted security features"</strong> " and doing so based on standards that will work across a partner's entire device product line. This approach reduces exposure to common vulnerabilities while providing manufacturers with a sustainable, consistent foundation that lowers engineering costs across product lines."
25+
</p>
26+
27+
<p class="mb-4">
28+
"In addition to Patina, ODP is currently focused on three other major projects:"
29+
</p>
30+
<ul class="list-disc pl-12 mb-4">
31+
<li class="mb-2">
32+
<strong>"Secure EC firmware"</strong>", providing a modern, security-focused embedded controller implementation designed to eliminate classes of bugs prevalent in legacy EC codebases."
33+
</li>
34+
<li class="mb-2">
35+
<strong>"Unified OS-EC service interface"</strong>", ensuring that operating systems can interact with embedded controllers in a consistent, well-defined way across devices."
36+
</li>
37+
<li class="mb-2">
38+
<strong>"MPTF"</strong>", extending recent advancements in the Windows power-thermal framework to meet partner needs."
39+
</li>
40+
</ul>
41+
<p class="mb-4">
42+
"Together, these efforts give hardware makers the ability to standardize firmware and device software across their entire portfolios—improving reliability, accelerating time-to-market, and reducing redundant engineering work."
43+
</p>
44+
45+
<p class="mb-4">
46+
"The Open Device Partnership is about building trust at the foundation. By focusing on memory safety, hardware-rooted security, and clear standards, we're making it easier for partners to deliver secure, consistent solutions while also reducing long-term development costs."
47+
</p>
48+
49+
<p class="mb-4">
50+
"With Patina's public launch and the ongoing progress of ODP's other projects, the initiative is now seeking broader industry participation. ODP invites partners, contributors, and stakeholders to join in shaping the future of secure, open device enablement."
51+
</p>
52+
53+
<p class="mb-4">
54+
"👉 Learn more and get involved at "
55+
<a href="https://opendevicepartnership.org/" class="underline hover:text-blue-600 transition-colors duration-150">
56+
"opendevicepartnership.org"
57+
</a>"."
58+
</p>
59+
</div>
60+
}
61+
}
62+
63+
#[component]
64+
pub fn AnnouncementsPage() -> impl IntoView {
65+
let location = use_location();
66+
let navigate = use_navigate();
67+
68+
// List of announcement links and their content (display_text, title, slug)
69+
let announcements = vec![(
70+
"Oct-7-2025 Welcome Patina!",
71+
"Patina Project to Launch at UEFI 2025 Developer Conference & Plugfest",
72+
"welcome-patina-announcement",
73+
)];
74+
75+
let (selected, set_selected) = signal(0);
76+
77+
// Set selected from query param if present
78+
{
79+
let location = location.clone();
80+
let set_selected = set_selected.clone();
81+
let announcements_clone = announcements.clone();
82+
Effect::new(move |_| {
83+
let search = location.search.get();
84+
85+
// Check for new slug-based format: ?id=slug
86+
if search.contains("id=") {
87+
// Try to extract the id value more flexibly
88+
if let Some(id_start) = search.find("id=") {
89+
let slug = &search[id_start + 3..];
90+
// Remove any trailing parameters
91+
let slug = if let Some(amp_pos) = slug.find('&') {
92+
&slug[..amp_pos]
93+
} else {
94+
slug
95+
};
96+
if let Some(idx) = announcements_clone.iter().position(|(_, _, s)| *s == slug) {
97+
set_selected.set(idx);
98+
}
99+
}
100+
}
101+
});
102+
}
103+
104+
view! {
105+
<div class="flex flex-col w-full min-h-screen background_quaternary">
106+
<Header background_class="background_quaternary" />
107+
<div class="h2_mobile md:h1 px-4 md:px-10 pt-4 md:pt-20 pb-4 md:pb-20">Announcements</div>
108+
<div class="flex flex-col md:flex-row w-full flex-1 relative">
109+
<div class="w-full md:w-[450px] h-[300px] md:h-[700px] overflow-y-auto background_tertiary z-10 p-2 md:p-6 mb-4 md:mb-0">
110+
<ul class="space-y-2 md:space-y-4">
111+
{announcements.iter().enumerate().map(|(i, (link, _, slug))| {
112+
let navigate = navigate.clone();
113+
let slug = *slug;
114+
view! {
115+
<li>
116+
<button
117+
class="link_mobile md:link w-full text-left p-2 md:p-3"
118+
on:click=move |_| {
119+
set_selected.set(i);
120+
navigate(&format!("/announcements?id={}", slug), Default::default());
121+
}
122+
>
123+
{*link}
124+
</button>
125+
</li>
126+
}
127+
}).collect::<Vec<_>>()}
128+
</ul>
129+
</div>
130+
<div class="flex-1 h-[300px] md:h-[700px] background_primary rounded-tl-[30px] md:rounded-tl-[50px] -ml-0 md:-ml-16 z-20 overflow-y-auto p-4 md:p-10">
131+
{move || {
132+
let (title, content): (String, AnyView) = if let Some((_, title, slug)) = announcements.get(selected.get()) {
133+
let content = match *slug {
134+
"welcome-patina-announcement" => patina_press_release().into_any(),
135+
_ => view! { <p>"Content not found"</p> }.into_any(),
136+
};
137+
(title.to_string(), content)
138+
} else {
139+
("No announcement selected".to_string(), view! { <p>{""}</p> }.into_any())
140+
};
141+
view! {
142+
<div class="p_mobile md:p">
143+
<div class="h2_mobile md:h2 pb-4 md:pb-6">{title}</div>
144+
<div class="p2_mobile md:p2">
145+
{content}
146+
</div>
147+
</div>
148+
}
149+
}}
150+
</div>
151+
</div>
152+
<Footer />
153+
</div>
154+
}
155+
}

src/pages/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub mod announcements;
12
pub mod home;
23
pub mod not_found;
34

style/tailwind.css

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,12 @@
2020
}
2121

2222
@layer utilities {
23+
.header_background {
24+
@apply bg-[#FFFFFF] dark:bg-[#171717];
25+
}
26+
2327
.background_primary {
24-
@apply bg-white dark:bg-black;
28+
@apply bg-[#FFFFFF] dark:bg-[#171717];
2529
}
2630

2731
.background_secondary {
@@ -31,6 +35,14 @@
3135
.background_tertiary {
3236
@apply bg-[#E2E2E2] dark:bg-[#595959];
3337
}
38+
39+
.background_quaternary {
40+
@apply bg-[#CACACA] dark:bg-[#797979];
41+
}
42+
43+
.background_announcement {
44+
@apply bg-[#FEEED6] dark:bg-[#FEEED6];
45+
}
3446

3547
.h1 {
3648
@apply text-black dark:text-white;
@@ -292,6 +304,15 @@
292304
@apply bg-black dark:bg-white border-white dark:border-black;
293305
}
294306

307+
/* Header buttons on quaternary background (announcements page) */
308+
.background_quaternary .odp-header-btn {
309+
@apply bg-[#CACACA] dark:bg-[#797979] border-black dark:border-white;
310+
}
311+
312+
.background_quaternary .odp-header-btn-active {
313+
@apply bg-black dark:bg-white border-white dark:border-black;
314+
}
315+
295316
.grid-container {
296317
display: grid;
297318
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));

0 commit comments

Comments
 (0)