Bash is one of the popular command-line shells, programs whose chief job is to start other programs (in addition to some auxiliary functions).
The command-line part means you control it by typing commands one line at a time.
Properly speaking, a GUI you use to start programs by double-clicking on icons is also a shell, but in practice by "shell" people mostly mean command-line ones.
All modern command-line shells take their input and send their output as abstract streams of characters, and the other ends of those streams can be connected to a keyboard, a printer, a file, another program. The shell mostly doesn't care - it reads the characters, interprets them as commands telling it to run other programs, and writes back characters such as "command not found". When it runs another program, by default it connects the inputs and outputs of that program to the same streams.
Now, Terminal is a program that provides a graphical interface between the shell and the user. It receives from the shell e.g. the characters "command not found" and figures out how to display them to you - with what font, where on the screen, in what colour, whether there should be a scrollbar. When you press some keys, it figures out whether to send them on to the shell as characters (e.g.
ls -l), or to interpret them on its own (e.g. ⌘C).
When you open the Terminal app, it automatically opens a shell to connect you to. In its settings, you could choose a different shell from Bash. If you're feeling cheeky, you could even make it use a program that isn't a shell at all - not too useful, but it demonstrates how Terminal cares only about passing characters in and out, not about what the shell does with them.
What happens when you type
bash into Bash (through Terminal)? It starts the program Bash - that is, another copy of itself inside itself.
ETA: The prompt that Bash gives you before you're typing each command is usefully customizable, and controlled (using a special format) by the variable
PS1. Try typing
echo $PS1 in both the parent and child instance of Bash.
When run from the Terminal app, that variable is set to prompt you with the machine name, directory and user. This is set up for you in
/etc/bashrc, but you can set a new value, ideally in
~/.bash_profile. NB. that's somewhat OSX-specific; on most other systems, you'd prefer
~/.bashrc for that.
When you just run a child instance of Bash,
/etc/bashrc isn't re-executed, so this variable isn't set. It's also not set up to be inherited by child shells (which is totally a thing for environment variables) so Bash reverts to the unhelpful default of just showing you which version of it is running.