There are a lot of things to consider about your code, and I will address all of them.
- You are importing all of tkinterwithout any alias
- Calling your root"doc1" implies that you think you will be making a "doc2", "doc3", etc.. out of that class, and that is not going to work. You can't have manyrootinstances. At best, that should beToplevel, but only if you intend to open a new window for every new document.
- You shouldn't be calling mainloopinside the class, at all. You should be using module conventions. This way, you can import elements of this script into another script without worrying about this script running things automatically. At the very least, creating a wrapper formainloopis silly. You can already callmainloop, what is the purpose of sticking it inside another method? (doc1.root.mainloop())
- Creating a method to do very specific grid placement isn't reusable. I would argue that a mixinthat makes certain features more usable, but keeps them dynamic would be a better approach. It isn't necessary to create a custom wrapper for widgets, but if you are going to put agriddingmethod on everything then why not make a bettergriddingmethod and have it automatically "mixed in" to everything that applies? And as long as you go that far you might as well include some other conveniences, as well.
- Something like Document(ie, something where you may need many or may change often) likely shouldn't be theroot. It should be IN theroot. It certainly shouldn't have therootburied in it as a property.
Below gives numerous examples of the things I stated above. Those examples can and should be embellished. For instance, BaseWidget could include properties for x, rootx, y, rooty etc... The way ParentWidget is designed, you can use a range as the first argument of rowcfg and colcfg to do "mass configuring" in one call. They both return self so, they can be used inline.
import tkinter as tk
from typing import Iterable
class BaseWidget:
    @property
    def width(self) -> int:
        self.update_idletasks()
        return self.winfo_width()
        
    @property
    def height(self) -> int:
        self.update_idletasks()
        return self.winfo_height()
    
    def grid_(self, r=None, c=None, rs=1, cs=1, s='nswe', **kwargs):
        #this allows keyword shorthand, as well as original keywords
        #while also allowing you to rearrange the above arguments 
        #so you know the exact order they appear and don't have to use the keyword, at all
        self.grid(**{'row':r, 'column':c, 'rowspan':rs, 'columnspan':cs, 'sticky':s, **kwargs})
        #return self so this can be used inline
        return self
        
        
class ParentWidget:
    @property
    def descendants(self):
        return self.winfo_children()
    
    #inline and ranged grid_rowconfigure
    def rowcfg(self, index, **options):
        index = index if isinstance(index, Iterable) else [index]
        for i in index:
            self.grid_rowconfigure(i, **options)
        #so this can be used inline
        return self
        
    #inline and ranged grid_columnconfigure
    def colcfg(self, index, **options):
        index = index if isinstance(index, Iterable) else [index]
        for i in index:
            self.grid_columnconfigure(i, **options)
        #so this can be used inline
        return self
class Custom_Label(tk.Label, BaseWidget):
    @property
    def text(self) -> str:
        return self['text']
        
    @text.setter
    def text(self, value:str):
        self['text'] = value
    
    def __init__(self, master, **kwargs):
        tk.Label.__init__(self, master, **kwargs)
        
class Document(tk.Frame, ParentWidget, BaseWidget):
    def __init__(self, master, **kwargs):
        tk.Frame.__init__(self, master, **kwargs)
        
        #the rest of this class is an example based on what little code you posted
        #the results are not meant to be ideal. It's a demo of usage ... a gist
        self.file_name = Custom_Label(self, text='File Name').grid_(1,2)
        self.doc_title = Custom_Label(self, text='Document Title').grid_(2,2)
        
        #possible
        #r = range(len(self.descendants))
        #self.colcfg(r, weight=1).rowcfg(r, weight=1)
        self.colcfg(2, weight=1).rowcfg([1,2], weight=1)
        
class Root(tk.Tk, ParentWidget):
   def __init__(self, title, width, height, x, y, **kwargs):
       tk.Tk.__init__(self)
       self.configure(**kwargs)
       self.title(title)
       self.geometry(f'{width}x{height}+{x}+{y}')
       
       self.rowcfg(0, weight=1).colcfg(0, weight=1)
       
       doc1 = Document(self).grid_()
if __name__ == '__main__':
    Root('MyApplication', 800, 600, 200, 200, bg='#000000').mainloop()