mirror of
https://github.com/ratatui/ratatui.git
synced 2025-09-26 20:40:44 +00:00
docs: update heading image for Ratatui 0.30.0 release 🎉 (#2000)
Co-authored-by: Orhun Parmaksız <orhun@archlinux.org> Co-authored-by: Josh McKinney <joshka@users.noreply.github.com>
This commit is contained in:
parent
c01b7d43ea
commit
cba5cca2bd
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -2692,6 +2692,14 @@ version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
|
||||
|
||||
[[package]]
|
||||
name = "release-header"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"color-eyre",
|
||||
"ratatui",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ring"
|
||||
version = "0.17.14"
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
</details>
|
||||
|
||||

|
||||

|
||||
|
||||
<div align="center">
|
||||
|
||||
|
13
examples/apps/release-header/Cargo.toml
Normal file
13
examples/apps/release-header/Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
||||
[package]
|
||||
name = "release-header"
|
||||
publish = false
|
||||
license.workspace = true
|
||||
edition.workspace = true
|
||||
rust-version.workspace = true
|
||||
|
||||
[dependencies]
|
||||
color-eyre.workspace = true
|
||||
ratatui.workspace = true
|
||||
|
||||
[lints]
|
||||
workspace = true
|
13
examples/apps/release-header/README.md
Normal file
13
examples/apps/release-header/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Release Header
|
||||
|
||||
Generates a banner for Ratatui releases featuring a Ratatui logo, version info, and a list of crates.
|
||||
|
||||
Used for README.md, documentation, and release materials. Updated for every release starting with v0.30.0 "Bryndza".
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
cargo run --p release-header
|
||||
```
|
||||
|
||||
Press any key to exit. Creates a fixed 68x16 terminal viewport.
|
171
examples/apps/release-header/src/main.rs
Normal file
171
examples/apps/release-header/src/main.rs
Normal file
@ -0,0 +1,171 @@
|
||||
//! Generates a terminal banner for Ratatui releases featuring a Ratatui logo, version info, and
|
||||
//! a list of crates.
|
||||
//!
|
||||
//! Used for README.md, documentation, and release materials. Updated for every release starting
|
||||
//! with v0.30.0 "Bryndza".
|
||||
//!
|
||||
//! This example runs with the Ratatui library code in the branch that you are currently
|
||||
//! reading. See the [`latest`] branch for the code which works with the most recent Ratatui
|
||||
//! release.
|
||||
//!
|
||||
//! [`latest`]: https://github.com/ratatui/ratatui/tree/latest
|
||||
|
||||
use std::io::stdout;
|
||||
use std::iter::zip;
|
||||
|
||||
use ratatui::crossterm::terminal::{EnterAlternateScreen, LeaveAlternateScreen};
|
||||
use ratatui::crossterm::{event, execute};
|
||||
use ratatui::layout::{Constraint, Flex, Layout, Margin, Rect, Spacing};
|
||||
use ratatui::style::{Color, Stylize};
|
||||
use ratatui::symbols::merge::MergeStrategy;
|
||||
use ratatui::text::Line;
|
||||
use ratatui::widgets::{Block, BorderType, Padding, Paragraph, RatatuiLogo};
|
||||
use ratatui::{DefaultTerminal, Frame, TerminalOptions, Viewport};
|
||||
|
||||
const SEMVER: &str = "0.30.0";
|
||||
const RELEASE_NAME: &str = "Bryndza";
|
||||
|
||||
const MAIN_DISHES: [&str; 4] = [
|
||||
"> ratatui",
|
||||
"> ratatui-core",
|
||||
"> ratatui-widgets",
|
||||
"> ratatui-macros",
|
||||
];
|
||||
const BACKENDS: [&str; 3] = [
|
||||
"> ratatui-crossterm",
|
||||
"> ratatui-termion",
|
||||
"> ratatui-termwiz",
|
||||
];
|
||||
|
||||
const FG_COLOR: Color = Color::Rgb(246, 214, 187); // #F6D6BB
|
||||
const BG_COLOR: Color = Color::Rgb(20, 20, 50); // #141432
|
||||
const MENU_BORDER_COLOR: Color = Color::Rgb(255, 255, 160); // #FFFFA0
|
||||
|
||||
enum Rainbow {
|
||||
Red,
|
||||
Orange,
|
||||
Yellow,
|
||||
Green,
|
||||
Blue,
|
||||
Indigo,
|
||||
Violet,
|
||||
}
|
||||
|
||||
fn main() -> color_eyre::Result<()> {
|
||||
color_eyre::install()?;
|
||||
let viewport = Viewport::Fixed(Rect::new(0, 0, 68, 16));
|
||||
let terminal = ratatui::init_with_options(TerminalOptions { viewport });
|
||||
execute!(stdout(), EnterAlternateScreen).expect("failed to enter alternate screen");
|
||||
let result = run(terminal);
|
||||
execute!(stdout(), LeaveAlternateScreen).expect("failed to leave alternate screen");
|
||||
ratatui::restore();
|
||||
result
|
||||
}
|
||||
|
||||
fn run(mut terminal: DefaultTerminal) -> color_eyre::Result<()> {
|
||||
loop {
|
||||
terminal.draw(render)?;
|
||||
if event::read()?.is_key_press() {
|
||||
break Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn render(frame: &mut Frame) {
|
||||
let area = frame.area();
|
||||
frame.buffer_mut().set_style(area, (FG_COLOR, BG_COLOR));
|
||||
|
||||
let logo_width = 29;
|
||||
let menu_width = 23;
|
||||
let padding = 2; // Padding between logo and menu
|
||||
let menu_borders = 3;
|
||||
let height = MAIN_DISHES.len() as u16 + BACKENDS.len() as u16 + menu_borders;
|
||||
let width = logo_width + menu_width + padding;
|
||||
let center_area = area.centered(Constraint::Length(width), Constraint::Length(height));
|
||||
let layout = Layout::horizontal(Constraint::from_lengths([logo_width, padding, menu_width]));
|
||||
let [logo_area, _, menu_area] = center_area.layout(&layout);
|
||||
|
||||
render_logo(frame, logo_area);
|
||||
render_menu(frame, menu_area);
|
||||
}
|
||||
|
||||
fn render_logo(frame: &mut Frame, area: Rect) {
|
||||
let area = area.inner(Margin::new(1, 0));
|
||||
let layout = Layout::vertical(Constraint::from_lengths([6, 2, 1])).flex(Flex::End);
|
||||
let [shadow_area, logo_area, version_area] = area.layout(&layout);
|
||||
|
||||
// Divide the logo into letter sections for individual coloring, then render a block for each
|
||||
// letter with a color based on the row index.
|
||||
let letter_layout = Layout::horizontal(Constraint::from_lengths([5, 4, 4, 4, 4, 5, 1]));
|
||||
for (row_index, row) in shadow_area.rows().enumerate() {
|
||||
for (rainbow, letter_area) in zip(Rainbow::ROYGBIV, row.layout_vec(&letter_layout)) {
|
||||
let color = rainbow.gradient_color(row_index);
|
||||
frame.render_widget(Block::new().style(color), letter_area);
|
||||
}
|
||||
// Render the Ratatui logo truncated.
|
||||
frame.render_widget(RatatuiLogo::small(), row);
|
||||
}
|
||||
|
||||
frame.render_widget(Block::new().style(FG_COLOR), logo_area);
|
||||
frame.render_widget(RatatuiLogo::small(), logo_area);
|
||||
frame.render_widget(format!("v{SEMVER} \"{RELEASE_NAME}\"").dim(), version_area);
|
||||
}
|
||||
|
||||
impl Rainbow {
|
||||
const RED_GRADIENT: [u8; 6] = [41, 43, 50, 68, 104, 156];
|
||||
const GREEN_GRADIENT: [u8; 6] = [24, 30, 41, 65, 105, 168];
|
||||
const BLUE_GRADIENT: [u8; 6] = [55, 57, 62, 78, 113, 166];
|
||||
const AMBIENT_GRADIENT: [u8; 6] = [17, 18, 20, 25, 40, 60];
|
||||
|
||||
const ROYGBIV: [Self; 7] = [
|
||||
Self::Red,
|
||||
Self::Orange,
|
||||
Self::Yellow,
|
||||
Self::Green,
|
||||
Self::Blue,
|
||||
Self::Indigo,
|
||||
Self::Violet,
|
||||
];
|
||||
|
||||
fn gradient_color(&self, row: usize) -> Color {
|
||||
let ambient = Self::AMBIENT_GRADIENT[row];
|
||||
let red = Self::RED_GRADIENT[row];
|
||||
let green = Self::GREEN_GRADIENT[row];
|
||||
let blue = Self::BLUE_GRADIENT[row];
|
||||
let blue_sat = Self::AMBIENT_GRADIENT[row].saturating_mul(6 - row as u8);
|
||||
let (r, g, b) = match self {
|
||||
Self::Red => (red, ambient, blue_sat),
|
||||
Self::Orange => (red, green / 2, blue_sat),
|
||||
Self::Yellow => (red, green, blue_sat),
|
||||
Self::Green => (ambient, green, blue_sat),
|
||||
Self::Blue => (ambient, ambient, blue.max(blue_sat)),
|
||||
Self::Indigo => (blue, ambient, blue.max(blue_sat)),
|
||||
Self::Violet => (red, ambient, blue.max(blue_sat)),
|
||||
};
|
||||
Color::Rgb(r, g, b)
|
||||
}
|
||||
}
|
||||
|
||||
fn render_menu(frame: &mut Frame, area: Rect) {
|
||||
let layout = Layout::vertical(Constraint::from_lengths([
|
||||
MAIN_DISHES.len() as u16 + 2,
|
||||
BACKENDS.len() as u16 + 2,
|
||||
]))
|
||||
.spacing(Spacing::Overlap(1)); // Overlap to merge borders
|
||||
let [main_dishes_area, backends_area] = area.layout(&layout);
|
||||
|
||||
render_menu_block(frame, main_dishes_area, "Main Courses", &MAIN_DISHES);
|
||||
render_menu_block(frame, backends_area, "Pairings", &BACKENDS);
|
||||
}
|
||||
|
||||
fn render_menu_block(frame: &mut Frame, area: Rect, title: &str, menu_items: &[&str]) {
|
||||
let menu_block = Block::bordered()
|
||||
.border_type(BorderType::Rounded)
|
||||
.border_style(MENU_BORDER_COLOR)
|
||||
.padding(Padding::horizontal(1))
|
||||
.merge_borders(MergeStrategy::Fuzzy)
|
||||
.title(title);
|
||||
|
||||
let menu_lines: Vec<Line> = menu_items.iter().map(|&item| Line::from(item)).collect();
|
||||
frame.render_widget(Paragraph::new(menu_lines).block(menu_block), area);
|
||||
}
|
19
examples/vhs/release-header.tape
Normal file
19
examples/vhs/release-header.tape
Normal file
@ -0,0 +1,19 @@
|
||||
# This is a vhs script. See https://github.com/charmbracelet/vhs for more info.
|
||||
# To run this script, install vhs and run `vhs ./examples/vhs/release-header.tape`
|
||||
# NOTE: Requires VHS 0.6.1 or later for Screenshot support
|
||||
# The reason for this strange size is that the social preview image for this
|
||||
# demo is 1280x64 with 80 pixels of padding on each side. We want a version
|
||||
# without the padding for README.md, etc.
|
||||
Set Theme {"background": "#141432"}
|
||||
Set FontSize 25
|
||||
Set Width 1120
|
||||
Set Height 480
|
||||
Set Padding 0
|
||||
Hide
|
||||
Type "cargo run -p release-header"
|
||||
Enter
|
||||
Sleep 1s
|
||||
Show
|
||||
Sleep 1s
|
||||
Screenshot assets/release-header.png
|
||||
Sleep 1s
|
@ -7,7 +7,7 @@
|
||||
html_favicon_url = "https://raw.githubusercontent.com/ratatui/ratatui/main/assets/favicon.ico"
|
||||
)]
|
||||
#![warn(missing_docs)]
|
||||
//! 
|
||||
//! 
|
||||
//!
|
||||
//! <div align="center">
|
||||
//!
|
||||
|
Loading…
x
Reference in New Issue
Block a user