I don't tailor make each menu in my games anymore, but I do have a rather more involved setup than usual. Basically there's a list of options (as usual), and each option has:
- Coordinates of the rectangle it covers on screen
- IDs of the options to go to when pressing up/down/left/right
- Pointers to functions to actions to be taken when pressing up/down/left/right/accept
- Sound effect played when an action is triggered
- Whatever is needed to display them (e.g. sprite or caption)
Note that the second and third points can have any of the parts undefined (meaning the corresponding keys won't do anything), and the fourth point can also be undefined. When creating a new option, all movement and action is by default set to undefined, and the sound effect is set to the usual beep, and then it's up to the code initializing the menu to fill in the gaps.
But yeah, if you handle all of the above, you'll probably have practically all use cases covered. It's quite complex, but you get the ability to make completely arbitrary menus while sharing the same code.