Extract components into base classes

NB: this almost certainly breaks everything. That will be dealt with via
subsequent patches which will add tests for all the things.