Typewriter Text Effect
A common effect in games is to have text progressively appear letter-by-letter as if it were being typed by a human. If all you need is a single line of text, you can achieve this with a simple system that adds letters to a Text entity. However, this naive approach has an issue when the text occupies multiple lines. When the "typewriter" runs out of room on a line of text while typing a word, the layout gets adjusted. This causes the entire word to abruptly move to the next line.
We could get around this by using LineBreak::AnyCharacter, but splitting words over multiple lines makes text awkward to read.
A better approach is to lay out the entire contents of the text immediately, but with Color::NONE. We can then progressively make each character visible.
Bevy 0.15
#[derive(Component)]
struct Typewriter(Timer);
impl Typewriter {
    fn new(delay: f32) -> Self {
        Self(Timer::from_seconds(delay, TimerMode::Repeating))
    }
}
fn update_typewriters(
    time: Res<Time>,
    mut query: Query<(Entity, &mut Typewriter), With<Typewriter>>,
    mut writer: TextUiWriter,
) {
    for (entity, mut typewriter) in query.iter_mut() {
        if !typewriter.0.tick(time.delta()).just_finished() {
            return;
        }
        while !writer.text(entity, 1).is_empty() {
                                    let first_hidden = writer.text(entity, 1).remove(0);
            writer.text(entity, 0).push(first_hidden);
                        if first_hidden != ' ' {
                break;
            }
        }
    }
}
fn setup(mut commands: Commands) {
    let container = commands
        .spawn(Node {
            width: Val::Percent(100.0),
            height: Val::Percent(100.0),
            align_items: AlignItems::Center,
            justify_content: JustifyContent::Center,
            ..default()
        })
        .id();
    let bg = commands
        .spawn((
            Node {
                width: Val::Px(680.0),
                height: Val::Px(300.0),
                padding: UiRect::all(Val::Px(10.)),
                ..default()
            },
            BorderRadius::all(Val::Px(10.)),
            BackgroundColor(Srgba::gray(0.2).into()),
        ))
        .id();
    let typewriter = commands
        .spawn((
            Typewriter::new(0.1),
                        Text::default(),
            Node {
                width: Val::Percent(100.),
                ..default()
            },
        ))
        .with_child((
                                    TextSpan::new(TEXT),
            TextColor(Color::NONE),
        ))
        .id();
    commands.entity(container).add_child(bg);
    commands.entity(bg).add_child(typewriter);
}