Back when I was on product teams I could do this. The trick is knowing the codebase and problem space well enough that you're doing all the planning upfront in your head*, so the estimate given is basically just implementation of an already-existing plan, with few unknowns - just some padding for testing and bugfixing near the end.
Nowadays I'm on a maintenance team with products I'm not very familiar with, so when something needs fixing I have to spend time investigating it before being able to come up with that plan. I can usually still give vague estimates based on guesses of where the problem is, but nothing like I used to be able to.
* Okay maybe not all all, but enough that you have an outline of the entire solution where you can fill in the details as you go. Some details will increase the overall estimate as you get to them, others will be simpler than you thought and reduce the overall estimate - for me it tended to balance out.