On example is also here


First part:
1. Start new class library for .NET Framework (not core)
2. Name it MyControls.
3. Rename Class1 to MyButton.
4. Reference System.Windows.Forms in my case it was like: C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Windows.Forms.dll
5. MyButton inherit from Button.
6. Add property like:
public string MyProperty { get; set; }
7. Create new App Windows forms for .NET Framework (not core)
8. Add new tab in toolbox
9. Drag and drop MyControls.dll

---

Second part - smart tag:

10. Add attribute [Designer(typeof(MyButtonDesigner))]:

using System.ComponentModel;
using System.Windows.Forms;

namespace MyControls
{
    [Designer(typeof(MyButtonDesigner))]
    public class MyButton: Button
    {
        public string MyProperty { get; set; }
    }
}
11. Add class MyButtonDesigner
12. Add reference to System.Design C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.7.2\System.Design.dll in usings add System.Windows.Forms.
13. Add class MyButtonDesigner and inherit from ControlDesigner:
using System.ComponentModel.Design;
using System.Windows.Forms.Design;

namespace MyControls
{
    public class MyButtonDesigner: ControlDesigner
    {
        private DesignerActionListCollection _myButtonActionLists;

        public override DesignerActionListCollection ActionLists
        {
            get
            {
                if (_myButtonActionLists is null)
                {
                    _myButtonActionLists = new DesignerActionListCollection
                    {
                        new MyButtonActionList(Component)
                    };
                }
                return _myButtonActionLists;
            }
        }
    }
}
14. Add class MyButtonActionList, inherit from DesignerActionList:
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Reflection;

namespace MyControls
{
    public class MyButtonActionList: DesignerActionList
    {
        private readonly MyButton _myButton;
        private readonly DesignerActionUIService _designerActionUiSvc = null;

        public MyButtonActionList(IComponent component) : base(component)
        {
            _myButton = component as MyButton;
            _designerActionUiSvc =
                GetService(typeof(DesignerActionUIService))
                    as DesignerActionUIService;
        }

        public string MyProperty
        {
            get => _myButton.MyProperty;
            set
            {
                GetPropertyByName("MyProperty").SetValue(_myButton, value);

                _designerActionUiSvc.Refresh(Component);
            }
        }

        public override DesignerActionItemCollection GetSortedActionItems()
        {
            DesignerActionItemCollection items = new DesignerActionItemCollection();

            items.Add(new DesignerActionHeaderItem("My Smart tag"));

            items.Add(new DesignerActionPropertyItem("MyProperty", "MyProperty"));

            return items;
        }

        private PropertyDescriptor GetPropertyByName(string propName)
        {
            var prop = TypeDescriptor.GetProperties(_myButton)[propName];
            if (null == prop)
                throw new ArgumentException(
                    "Matching MyProperty property not found!",
                    propName);
            return prop;
        }
    }
}

Example until now download from here.

---

Third part - UIEditor:

15. In MyButton change MyProperty to:

public MyPropertyType MyProperty { get; set; }

16. Add new class MyPropertyType, decorate with Editor and TypeConverter:

using System.ComponentModel;
using System.Drawing.Design;

namespace MyControls
{

    [Editor(typeof(MyButtonEditor), typeof(UITypeEditor))]
    [TypeConverter(typeof(MyPropertyTypeConverter))]
    public class MyPropertyType
    {
        public string AnotherMyProperty { get; set; }

        public MyPropertyType(string test)
        {
            AnotherMyProperty = test;
        }
    }
}
17. Add one more class MyPropertyTypeConverter:
using System;
using System.ComponentModel;
using System.Globalization;

namespace MyControls
{
        public class MyPropertyTypeConverter : TypeConverter
    {
        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            return true;
        }

        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            return true;
        }

        public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
        {
            if (value is null)
            {
                return string.Empty;
            }
            return new MyPropertyType(value.ToString());
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
			return ((MyPropertyType)value)?.AnotherMyProperty;
        }
    }
}
18. Again add class MyButtonEditor:
using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Windows.Forms;
using System.Windows.Forms.Design;

namespace MyControls
{
    public class MyButtonEditor: UITypeEditor
    {
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
            => UITypeEditorEditStyle.Modal;

        public override object EditValue(ITypeDescriptorContext context,
            IServiceProvider provider, object value)
        {
            IWindowsFormsEditorService svc = provider.GetService(typeof(IWindowsFormsEditorService)) as IWindowsFormsEditorService;
            Form myForm = new Form();
            svc?.ShowDialog(myForm);

            return new MyPropertyType("test");
        }
    }
}
Example download from here.