You wrote:
"That makes sense on the hardware side, but in the Nios IDE I don't see how it would work. When I call the IOWR macro for example, doesn't the input data need to match up to the bit width of the component data bus? How would I use the IOWR/IORD functions to use only the lowest byte of the 4 byte value? "
It is not a matter of figuring out how to restrict IOWR/IORD to manage the lowest byte of the 4 byte value. It always passes and receives 32 bits. It is your custom logic that manages using only the lowest byte of the 4 byte values by utilizing only writedata[7:0], and setting readdata[7:0] bits only. If you desire, you can explicitly set readdata[31:8] to zeros in your module, but it probably is not necessary.
Perhaps you don't like the inconsistency of passing a char/byte variable to the IOWR macro, which in turn writes to a 32-bit port. If that is the case, cast your variable to an unsigned int which will be 32 bits wide with the low order 8 bits equal to your variable. I haven't looked at it, but the macro may already do this. The alternative is to assign a temp 32-bit unsigned int variable equal to your char/byte variable, and passing the temp variable to IOWR and using IORD with your temp variable and assign your 8-bit variable to (temp_var && 0xFF), or something like eight_bit_var = (unsigned char) (IORD(base,offset) & 0xff);
I suggest looking at the macro, or the dissassembly of the code while debugging to see what is going on to satisfy your concerns.