Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
63db4fa
added new project
seun-ja Apr 7, 2026
7b60c30
Add new project entry for 'momenta' in projects.json
elcharitas May 3, 2026
f48705d
WIP on More accurate buttons
AkinAguda Jul 14, 2026
9b734fe
V1 of Button animation as designed
AkinAguda Jul 16, 2026
953ed21
Added useful comment to shader
AkinAguda Jul 16, 2026
0507db5
some tweaks
AkinAguda Jul 16, 2026
63ef50b
Fixed Grey button not showing correctly
AkinAguda Jul 16, 2026
23a0821
Resolved issues found during build by linter
AkinAguda Jul 16, 2026
97ba3da
Merge pull request #76 from Rust-Nigeria/feat/button-anim-as-designed
AkinAguda Jul 16, 2026
dcaccc6
Merge pull request #75 from elcharitas/patch-1
AkinAguda Jul 16, 2026
e0d773b
Merge branch 'dev' into projects-rpc-agent
AkinAguda Jul 16, 2026
fd2c248
Merge pull request #73 from seun-ja/projects-rpc-agent
AkinAguda Jul 16, 2026
1eb4520
Fixed issues form merged contribs
AkinAguda Jul 17, 2026
e5cc46a
Merge pull request #77 from Rust-Nigeria/chore/bug-fixes
AkinAguda Jul 17, 2026
c0876c2
When button now leaves view, it cancels animation
AkinAguda Jul 17, 2026
b7112d3
removed RAF hack in button to fix incorrect dimesnsions calculations
AkinAguda Jul 17, 2026
7660632
updated leptos version that partially fixes issues with link button v…
AkinAguda Jul 17, 2026
05f9a27
Merge pull request #78 from Rust-Nigeria/feat/button-anim-optimisations
AkinAguda Jul 17, 2026
f63ad67
Fix/Updated rustup version in Dockerfile
AkinAguda Jul 18, 2026
4cc09c8
Fixed the Dockerfile
AkinAguda Jul 18, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
422 changes: 253 additions & 169 deletions Cargo.lock

Large diffs are not rendered by default.

16 changes: 7 additions & 9 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,19 @@ actix-files = { version = "0.6.8", optional = true }
actix-web = { version = "4", optional = true, features = ["macros"] }
console_error_panic_hook = "0.1"
http = { version = "1.3.1", optional = true }
leptos = { version = "0.8.12", features = ["nightly"] }
leptos_meta = { version = "0.8.5" }
leptos_actix = { version = "0.8.6", optional = true }
leptos_router = { version = "0.8.9", features = ["nightly"] }
wasm-bindgen = "=0.2.105"
leptos = { version = "0.8.20", features = ["nightly"] }
leptos_meta = { version = "0.8.6" }
leptos_actix = { version = "0.8.7", optional = true }
leptos_router = { version = "0.8.14", features = ["nightly"] }
wasm-bindgen = "=0.2.126"
tailwind_fuse = { version = "0.3.1", features = ["variant"] }
futures = "0.3.31"
stylance = "0.7.1"
serde = "1.0.228"
serde_json = "1.0"
chrono = {version = "0.4.42", features = ["serde"]}
leptos-use = "0.16.3"
leptos-use = "0.19.0"
simple-bezier-easing = "0.1.1"

[dependencies.web-sys]
version = "0.3.76"
Expand Down Expand Up @@ -135,6 +136,3 @@ scss_prelude = '''
@use "sass:math";
@use "sass:list";
'''



46 changes: 18 additions & 28 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
FROM rust:1.92.0-alpine3.23 AS base
###### Base stage — image toolchain (1.97.1) builds the tools ######
FROM rust:1.97.1-alpine3.23 AS base

RUN apk add --no-cache \
bash \
Expand All @@ -14,74 +15,63 @@ RUN apk add --no-cache \
perl \
python3 \
cmake

COPY rust-toolchain.toml ./
RUN rustup show
# Install all Rust tools once in base
RUN cargo install cargo-binstall
RUN cargo install cargo-chef

# IMPORTANT: install tooling BEFORE rust-toolchain.toml is copied in.
# Otherwise the pinned nightly overrides the image toolchain and tool
# dependencies (kstring, vergen, ...) fail their rustc version checks.
RUN cargo install --locked cargo-binstall
RUN cargo binstall -y --locked cargo-chef stylance-cli cargo-leptos
RUN cargo binstall -y wasm-bindgen-cli --version 0.2.126
RUN npm install -g sass
RUN cargo install stylance-cli
RUN cargo binstall cargo-leptos -y
RUN cargo install -f wasm-bindgen-cli --version 0.2.105
RUN rustup target add wasm32-unknown-unknown

# Now pin the project toolchain and add the wasm target to *it*
COPY rust-toolchain.toml ./
RUN rustup show \
&& rustup target add wasm32-unknown-unknown

WORKDIR /work

###### Planner stage ####
###### Planner stage ######
FROM base AS planner

# Only copy dependency files, NOT source code
COPY . .
RUN cargo chef prepare --recipe-path recipe.json

###### Chef stage - cook dependencies ####
###### Chef stage cook dependencies ######
FROM base AS chef

COPY --from=planner /work/recipe.json recipe.json
RUN cargo chef cook --release --recipe-path recipe.json

###### Builder stage ######
FROM base AS builder

WORKDIR /work

# Copy cooked dependencies
# Reuse cooked dependency artifacts
COPY --from=chef /work/target target
COPY --from=chef /usr/local/cargo /usr/local/cargo

# Now copy source code
COPY . .

# Run stylance and build
RUN stylance .
RUN cargo leptos build --release -vv

##### Production runner #####
###### Production runner ######
FROM debian:bookworm-slim AS runner

WORKDIR /app

# Install runtime dependencies
RUN apt-get update -y \
&& apt-get install -y --no-install-recommends openssl ca-certificates \
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*

# Copy only what's needed for runtime
COPY --from=builder /work/data /app/data
COPY --from=builder /work/target/release/rust-nigeria-website /app/
COPY --from=builder /work/target/site /app/site
COPY --from=builder /work/Cargo.toml /app/




ENV RUST_LOG="debug"
ENV LEPTOS_SITE_ADDR="0.0.0.0:8080"
ENV LEPTOS_SITE_ROOT=./site

EXPOSE 8080

CMD ["/app/rust-nigeria-website"]
10 changes: 10 additions & 0 deletions data/projects.json
Original file line number Diff line number Diff line change
Expand Up @@ -63,5 +63,15 @@
"repo_url": "https://github.com/enigma-137/log-analyzer",
"banner": "https://opengraph.githubassets.com/1/enigma-137/log-analyzer",
"tags": ["cli"]
},
{
"repo_url": "https://github.com/seun-ja/rpc-agent",
"banner": "https://opengraph.githubassets.com/1/seun-ja/rpc-agent",
"tags": ["rpc", "ai", "distributed_system"]
},
{
"repo_url": "https://github.com/elcharitas/momenta",
"banner": "https://opengraph.githubassets.com/1/elcharitas/momenta",
"tags": ["crate", "web"]
}
]
6 changes: 3 additions & 3 deletions src/components/articles_section/articles/article_card.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ pub fn ArticleCard(
#[prop(default = "")] class: &'static str,
#[prop(default = 0)] index: usize,
) -> impl IntoView {
let date = RwSignal::new(None);
let (date, set_date) = signal(None);

Effect::new(move || {
date.set(Some(parse_iso_js(&article.date.to_rfc3339())));
set_date(Some(parse_iso_js(&article.date.to_rfc3339())));
});

view! {
Expand All @@ -45,7 +45,7 @@ pub fn ArticleCard(
</div>

<Button
class="mt-4 w-fit"
class="mt-4"
use_as=ButtonUsecase::Link { href: article.article_link }
color=ButtonColorVariants::Transparent
size=ButtonSizeVariants::Thin
Expand Down
165 changes: 165 additions & 0 deletions src/components/button/button_backdrop.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
use leptos::wasm_bindgen::JsCast;

use web_sys::{
HtmlCanvasElement, WebGlBuffer, WebGlProgram, WebGlRenderingContext as Gl, WebGlUniformLocation,
};

use super::shaders::{FRAGMENT_SHADER, VERTEX_SHADER};
use crate::{
components::button::ButtonColorVariants,
utils::{
resize_canvas_to_display_size::resize_canvas_to_display_size,
webgl::{
create_program, create_shader, get_canvas_to_clipspace_projection_matrix, set_quad,
},
},
};

#[derive(Clone)]
pub struct ButtonBackdropInstance {
gl: Gl,
canvas: HtmlCanvasElement,
program: WebGlProgram,
vertex_position_attribute_loc: i32,
vertex_position_buffer: WebGlBuffer,
canvas_projection_matrix_uniform_loc: WebGlUniformLocation,
canvas_resolution_uniform_location: WebGlUniformLocation,
extension_dimension_uniform_location: WebGlUniformLocation,
progression_uniform_location: WebGlUniformLocation,
}

#[derive(Clone)]
pub struct ButtonBackdropBuilder {}

pub struct ButtonBackdropCfg {
pub color: ButtonColorVariants,
}

impl ButtonBackdropBuilder {
pub async fn load() -> Self {
// We might need this for loading textures etc. I forsee needing this to load the arrow/icon texture maybe
Self {}
}

pub fn create_backdrop(
self,
canvas: HtmlCanvasElement,
cfg: ButtonBackdropCfg,
) -> ButtonBackdropInstance {
ButtonBackdropInstance::new(canvas, cfg)
}
}

impl ButtonBackdropInstance {
pub fn new(canvas: HtmlCanvasElement, cfg: ButtonBackdropCfg) -> Self {
let gl = canvas
.get_context("webgl")
.unwrap()
.unwrap()
.dyn_into::<Gl>()
.unwrap();

let vertex_shader = create_shader(&gl, Gl::VERTEX_SHADER, VERTEX_SHADER).unwrap();
let fragment_shader = create_shader(&gl, Gl::FRAGMENT_SHADER, FRAGMENT_SHADER).unwrap();

let program = create_program(&gl, &vertex_shader, &fragment_shader).unwrap();

gl.pixel_storei(Gl::UNPACK_FLIP_Y_WEBGL, 1);

let canvas_projection_matrix_uniform_loc = gl
.get_uniform_location(&program, "u_canvasProjectionMatrix")
.unwrap();

let vertex_position_attribute_loc = gl.get_attrib_location(&program, "a_position");

let vertex_position_buffer = gl.create_buffer().unwrap();

let canvas_resolution_uniform_location = gl
.get_uniform_location(&program, "u_canvas_resolution")
.unwrap();

let extension_dimension_uniform_location = gl
.get_uniform_location(&program, "u_extension_dimension")
.unwrap();

let progression_uniform_location =
gl.get_uniform_location(&program, "u_progression").unwrap();

let base_color_uniform_location =
gl.get_uniform_location(&program, "u_base_color").unwrap();

let hover_color_uniform_location =
gl.get_uniform_location(&program, "u_hover_color").unwrap();

gl.use_program(Some(&program));

let colors = cfg.color.get_state_rgbs();

gl.uniform4fv_with_f32_array(Some(&base_color_uniform_location), &colors.base);
gl.uniform4fv_with_f32_array(Some(&hover_color_uniform_location), &colors.hover);

ButtonBackdropInstance {
gl,
canvas,
program,
vertex_position_attribute_loc,
vertex_position_buffer,
canvas_projection_matrix_uniform_loc,
canvas_resolution_uniform_location,
extension_dimension_uniform_location,
progression_uniform_location,
}
}

pub fn render(&self, progression: f32) {
let ButtonBackdropInstance {
gl,
canvas,
program,
vertex_position_attribute_loc,
vertex_position_buffer,
canvas_projection_matrix_uniform_loc,
canvas_resolution_uniform_location,
extension_dimension_uniform_location,
progression_uniform_location,
} = self;

gl.use_program(Some(program));

resize_canvas_to_display_size(canvas);

let canvas_width = canvas.width() as f32;
let canvas_height = canvas.height() as f32;

gl.uniform_matrix3fv_with_f32_array(
Some(canvas_projection_matrix_uniform_loc),
false,
&get_canvas_to_clipspace_projection_matrix(canvas_width, canvas_height),
);

gl.uniform2fv_with_f32_array(
Some(canvas_resolution_uniform_location),
&[canvas_width, canvas_height],
);

gl.uniform1f(Some(extension_dimension_uniform_location), canvas_height);

gl.uniform1f(Some(progression_uniform_location), progression);

gl.bind_buffer(Gl::ARRAY_BUFFER, Some(vertex_position_buffer));
set_quad(gl, canvas_width, canvas_height);
gl.enable_vertex_attrib_array(*vertex_position_attribute_loc as u32);
gl.vertex_attrib_pointer_with_i32(
*vertex_position_attribute_loc as u32,
2,
Gl::FLOAT,
false,
0,
0,
);

gl.viewport(0, 0, canvas_width as i32, canvas_height as i32);

gl.draw_arrays(Gl::TRIANGLES, 0, 6);
}
}
Loading
Loading