ratatui/widgets/
logo.rs

1use indoc::indoc;
2
3use crate::{buffer::Buffer, layout::Rect, text::Text, widgets::Widget};
4
5/// A widget that renders the Ratatui logo
6///
7/// The Ratatui logo takes up two lines of text and comes in two sizes: `Tiny` and `Small`. This may
8/// be used in an application's help or about screen to show that it is powered by Ratatui.
9///
10/// # Examples
11///
12/// The [Ratatui-logo] example demonstrates how to use the `RatatuiLogo` widget. This can be run by
13/// cloning the Ratatui repository and then running the following command with an optional size
14/// argument:
15///
16/// ```shell
17/// cargo run --example ratatui-logo [size]
18/// ```
19///
20/// [Ratatui-logo]: https://github.com/ratatui/ratatui/blob/main/examples/ratatui-logo.rs
21///
22/// ## Tiny (default, 2x15 characters)
23///
24/// ```
25/// use ratatui::widgets::RatatuiLogo;
26///
27/// # fn draw(frame: &mut ratatui::Frame) {
28/// frame.render_widget(RatatuiLogo::tiny(), frame.area());
29/// # }
30/// ```
31///
32/// Renders:
33///
34/// ```text
35/// ▛▚▗▀▖▜▘▞▚▝▛▐ ▌▌
36/// ▛▚▐▀▌▐ ▛▜ ▌▝▄▘▌
37/// ```
38///
39/// ## Small (2x27 characters)
40///
41/// ```
42/// use ratatui::widgets::RatatuiLogo;
43///
44/// # fn draw(frame: &mut ratatui::Frame) {
45/// frame.render_widget(RatatuiLogo::small(), frame.area());
46/// # }
47/// ```
48///
49/// Renders:
50///
51/// ```text
52/// █▀▀▄ ▄▀▀▄▝▜▛▘▄▀▀▄▝▜▛▘█  █ █
53/// █▀▀▄ █▀▀█ ▐▌ █▀▀█ ▐▌ ▀▄▄▀ █
54/// ```
55#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
56pub struct RatatuiLogo {
57    size: Size,
58}
59
60/// The size of the logo
61#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
62#[non_exhaustive]
63pub enum Size {
64    /// A tiny logo
65    ///
66    /// The default size of the logo (2x15 characters)
67    ///
68    /// ```text
69    /// ▛▚▗▀▖▜▘▞▚▝▛▐ ▌▌
70    /// ▛▚▐▀▌▐ ▛▜ ▌▝▄▘▌
71    /// ```
72    #[default]
73    Tiny,
74    /// A small logo
75    ///
76    /// A slightly larger version of the logo (2x27 characters)
77    ///
78    /// ```text
79    /// █▀▀▄ ▄▀▀▄▝▜▛▘▄▀▀▄▝▜▛▘█  █ █
80    /// █▀▀▄ █▀▀█ ▐▌ █▀▀█ ▐▌ ▀▄▄▀ █
81    /// ```
82    Small,
83}
84
85impl RatatuiLogo {
86    /// Create a new Ratatui logo widget
87    ///
88    /// # Examples
89    ///
90    /// ```
91    /// use ratatui::widgets::{RatatuiLogo, RatatuiLogoSize};
92    ///
93    /// let logo = RatatuiLogo::new(RatatuiLogoSize::Tiny);
94    /// ```
95    pub const fn new(size: Size) -> Self {
96        Self { size }
97    }
98
99    /// Set the size of the logo
100    ///
101    /// # Examples
102    ///
103    /// ```
104    /// use ratatui::widgets::{RatatuiLogo, RatatuiLogoSize};
105    ///
106    /// let logo = RatatuiLogo::default().size(RatatuiLogoSize::Small);
107    /// ```
108    #[must_use]
109    pub const fn size(self, size: Size) -> Self {
110        let _ = self;
111        Self { size }
112    }
113
114    /// Create a new Ratatui logo widget with a tiny size
115    ///
116    /// # Examples
117    ///
118    /// ```
119    /// use ratatui::widgets::RatatuiLogo;
120    ///
121    /// let logo = RatatuiLogo::tiny();
122    /// ```
123    pub const fn tiny() -> Self {
124        Self::new(Size::Tiny)
125    }
126
127    /// Create a new Ratatui logo widget with a small size
128    ///
129    /// # Examples
130    ///
131    /// ```
132    /// use ratatui::widgets::RatatuiLogo;
133    ///
134    /// let logo = RatatuiLogo::small();
135    /// ```
136    pub const fn small() -> Self {
137        Self::new(Size::Small)
138    }
139}
140
141impl Widget for RatatuiLogo {
142    fn render(self, area: Rect, buf: &mut Buffer) {
143        let logo = self.size.as_str();
144        Text::raw(logo).render(area, buf);
145    }
146}
147
148impl Size {
149    const fn as_str(self) -> &'static str {
150        match self {
151            Self::Tiny => Self::tiny(),
152            Self::Small => Self::small(),
153        }
154    }
155
156    const fn tiny() -> &'static str {
157        indoc! {"
158            ▛▚▗▀▖▜▘▞▚▝▛▐ ▌▌
159            ▛▚▐▀▌▐ ▛▜ ▌▝▄▘▌
160        "}
161    }
162
163    const fn small() -> &'static str {
164        indoc! {"
165            █▀▀▄ ▄▀▀▄▝▜▛▘▄▀▀▄▝▜▛▘█  █ █
166            █▀▀▄ █▀▀█ ▐▌ █▀▀█ ▐▌ ▀▄▄▀ █
167        "}
168    }
169}
170
171#[cfg(test)]
172mod tests {
173    use rstest::rstest;
174
175    use super::*;
176
177    #[rstest]
178    #[case::tiny(Size::Tiny)]
179    #[case::small(Size::Small)]
180    fn new_size(#[case] size: Size) {
181        let logo = RatatuiLogo::new(size);
182        assert_eq!(logo.size, size);
183    }
184
185    #[test]
186    fn default_logo_is_tiny() {
187        let logo = RatatuiLogo::default();
188        assert_eq!(logo.size, Size::Tiny);
189    }
190
191    #[test]
192    fn set_logo_size_to_small() {
193        let logo = RatatuiLogo::default().size(Size::Small);
194        assert_eq!(logo.size, Size::Small);
195    }
196
197    #[test]
198    fn tiny_logo_constant() {
199        let logo = RatatuiLogo::tiny();
200        assert_eq!(logo.size, Size::Tiny);
201    }
202
203    #[test]
204    fn small_logo_constant() {
205        let logo = RatatuiLogo::small();
206        assert_eq!(logo.size, Size::Small);
207    }
208
209    #[test]
210    #[rustfmt::skip]
211    fn render_tiny() {
212        let mut buf = Buffer::empty(Rect::new(0, 0, 15, 2));
213        RatatuiLogo::tiny().render(buf.area, &mut buf);
214        assert_eq!(
215            buf,
216            Buffer::with_lines([
217                "▛▚▗▀▖▜▘▞▚▝▛▐ ▌▌",
218                "▛▚▐▀▌▐ ▛▜ ▌▝▄▘▌",
219            ])
220        );
221    }
222
223    #[test]
224    #[rustfmt::skip]
225    fn render_small() {
226        let mut buf = Buffer::empty(Rect::new(0, 0, 27, 2));
227        RatatuiLogo::small().render(buf.area, &mut buf);
228        assert_eq!(
229            buf,
230            Buffer::with_lines([
231                "█▀▀▄ ▄▀▀▄▝▜▛▘▄▀▀▄▝▜▛▘█  █ █",
232                "█▀▀▄ █▀▀█ ▐▌ █▀▀█ ▐▌ ▀▄▄▀ █",
233            ])
234        );
235    }
236}