diff --git a/Localization/app.json b/Localization/app.json
index ab5b3f65..8734ea00 100644
--- a/Localization/app.json
+++ b/Localization/app.json
@@ -178,7 +178,9 @@
             "title": {
                 "new_toot": "New Toot",
                 "new_reply": "New Reply"
-            }
+            },
+            "content_input_placeholder": "Type or paste what's on your mind",
+            "compose_action": "Toot"
         }
     }
 }
\ No newline at end of file
diff --git a/Mastodon.xcodeproj/project.pbxproj b/Mastodon.xcodeproj/project.pbxproj
index d999c0e8..532ef6cb 100644
--- a/Mastodon.xcodeproj/project.pbxproj
+++ b/Mastodon.xcodeproj/project.pbxproj
@@ -202,6 +202,7 @@
 		DB9D6C2425E502C60051B173 /* MosaicImageViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9D6C2225E502C60051B173 /* MosaicImageViewModel.swift */; };
 		DB9D6C2E25E504AC0051B173 /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9D6C2D25E504AC0051B173 /* Attachment.swift */; };
 		DB9D6C3825E508BE0051B173 /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9D6C3725E508BE0051B173 /* Attachment.swift */; };
+		DBA0A10925FB3C2B0079C110 /* RoundedEdgesButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA0A10825FB3C2B0079C110 /* RoundedEdgesButton.swift */; };
 		DBBE1B4525F3474B0081417A /* MastodonPickServerAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBBE1B4425F3474B0081417A /* MastodonPickServerAppearance.swift */; };
 		DBD9149025DF6D8D00903DFD /* APIService+Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */; };
 		DBE0821525CD382600FD6BBD /* MastodonRegisterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */; };
@@ -464,6 +465,7 @@
 		DB9D6C2225E502C60051B173 /* MosaicImageViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MosaicImageViewModel.swift; sourceTree = "<group>"; };
 		DB9D6C2D25E504AC0051B173 /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
 		DB9D6C3725E508BE0051B173 /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
+		DBA0A10825FB3C2B0079C110 /* RoundedEdgesButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedEdgesButton.swift; sourceTree = "<group>"; };
 		DBBE1B4425F3474B0081417A /* MastodonPickServerAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonPickServerAppearance.swift; sourceTree = "<group>"; };
 		DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Onboarding.swift"; sourceTree = "<group>"; };
 		DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewController.swift; sourceTree = "<group>"; };
@@ -649,6 +651,7 @@
 				2D42FF8425C8224F004A627A /* HitTestExpandedButton.swift */,
 				DB118A8B25E4BFB500FAB162 /* HighlightDimmableButton.swift */,
 				0FAA101125E105390017CCDE /* PrimaryActionButton.swift */,
+				DBA0A10825FB3C2B0079C110 /* RoundedEdgesButton.swift */,
 			);
 			path = Button;
 			sourceTree = "<group>";
@@ -1633,6 +1636,7 @@
 				2D38F1F125CD477D00561493 /* HomeTimelineViewModel+LoadMiddleState.swift in Sources */,
 				DB68A06325E905E000CFDF14 /* UIApplication.swift in Sources */,
 				DB45FAD725CA6C76005A8AC7 /* UIBarButtonItem.swift in Sources */,
+				DBA0A10925FB3C2B0079C110 /* RoundedEdgesButton.swift in Sources */,
 				2D152A8C25C295CC009AA50C /* StatusView.swift in Sources */,
 				2D42FF8525C8224F004A627A /* HitTestExpandedButton.swift in Sources */,
 				DB72601C25E36A2100235243 /* MastodonServerRulesViewController.swift in Sources */,
diff --git a/Mastodon/Diffiable/Item/ComposeStatusItem.swift b/Mastodon/Diffiable/Item/ComposeStatusItem.swift
index 2e125f63..812a27a6 100644
--- a/Mastodon/Diffiable/Item/ComposeStatusItem.swift
+++ b/Mastodon/Diffiable/Item/ComposeStatusItem.swift
@@ -6,11 +6,34 @@
 //
 
 import Foundation
+import Combine
 import CoreData
 
 enum ComposeStatusItem {
     case replyTo(tootObjectID: NSManagedObjectID)
-    case toot(replyToTootObjectID: NSManagedObjectID?)
+    case toot(replyToTootObjectID: NSManagedObjectID?, attribute: ComposeTootAttribute)
 }
 
 extension ComposeStatusItem: Hashable { }
+
+extension ComposeStatusItem {
+    final class ComposeTootAttribute: Equatable, Hashable {
+        private let id = UUID()
+        
+        let avatarURL = CurrentValueSubject<URL?, Never>(nil)
+        let displayName = CurrentValueSubject<String?, Never>(nil)
+        let username = CurrentValueSubject<String?, Never>(nil)
+        let composeContent = CurrentValueSubject<String?, Never>(nil)
+        
+        static func == (lhs: ComposeTootAttribute, rhs: ComposeTootAttribute) -> Bool {
+            return lhs.avatarURL.value == rhs.avatarURL.value &&
+                lhs.displayName.value == rhs.displayName.value &&
+                lhs.username.value  == rhs.username.value &&
+                lhs.composeContent.value == rhs.composeContent.value
+        }
+        
+        func hash(into hasher: inout Hasher) {
+            hasher.combine(id)
+        }
+    }
+}
diff --git a/Mastodon/Diffiable/Section/ComposeStatusSection.swift b/Mastodon/Diffiable/Section/ComposeStatusSection.swift
index 56b00689..e1405309 100644
--- a/Mastodon/Diffiable/Section/ComposeStatusSection.swift
+++ b/Mastodon/Diffiable/Section/ComposeStatusSection.swift
@@ -5,9 +5,82 @@
 //  Created by MainasuK Cirno on 2021-3-11.
 //
 
-import Foundation
+import UIKit
+import Combine
+import CoreData
+import CoreDataStack
 
 enum ComposeStatusSection: Equatable, Hashable {
     case repliedTo
     case status
 }
+
+extension ComposeStatusSection {
+    enum ComposeKind {
+        case toot
+        case replyToot(tootObjectID: NSManagedObjectID)
+    }
+}
+
+extension ComposeStatusSection {
+    static func tableViewDiffableDataSource(
+        for tableView: UITableView,
+        dependency: NeedsDependency,
+        managedObjectContext: NSManagedObjectContext,
+        composeKind: ComposeKind
+    ) -> UITableViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem> {
+        UITableViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem>(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in
+            switch item {
+            case .replyTo(let tootObjectID):
+                let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ComposeRepliedToTootContentTableViewCell.self), for: indexPath) as! ComposeRepliedToTootContentTableViewCell
+                // TODO:
+                return cell
+            case .toot(let replyToTootObjectID, let attribute):
+                let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ComposeTootContentTableViewCell.self), for: indexPath) as! ComposeTootContentTableViewCell
+                managedObjectContext.perform {
+                    guard let replyToTootObjectID = replyToTootObjectID,
+                          let replyTo = managedObjectContext.object(with: replyToTootObjectID) as? Toot else {
+                        cell.statusView.headerContainerStackView.isHidden = true
+                        return
+                    }
+                    cell.statusView.headerContainerStackView.isHidden = false
+                    cell.statusView.headerInfoLabel.text = "[TODO] \(replyTo.author.displayName)"
+                }
+                ComposeStatusSection.configureComposeTootContent(cell: cell, attribute: attribute)
+                // self size input cell
+                cell.composeContent
+                    .receive(on: DispatchQueue.main)
+                    .sink { text in
+                        tableView.beginUpdates()
+                        tableView.endUpdates()
+                    }
+                    .store(in: &cell.disposeBag)
+                return cell
+            }
+        }
+    }
+}
+
+extension ComposeStatusSection {
+    static func configureComposeTootContent(
+        cell: ComposeTootContentTableViewCell,
+        attribute: ComposeStatusItem.ComposeTootAttribute
+    ) {
+        attribute.avatarURL
+            .receive(on: DispatchQueue.main)
+            .sink { avatarURL in
+                cell.statusView.configure(with: AvatarConfigurableViewConfiguration(avatarImageURL: avatarURL))
+            }
+            .store(in: &cell.disposeBag)
+        Publishers.CombineLatest(
+            attribute.displayName.eraseToAnyPublisher(),
+            attribute.username.eraseToAnyPublisher()
+        )
+        .receive(on: DispatchQueue.main)
+        .sink { displayName, username in
+            cell.statusView.nameLabel.text = displayName
+            cell.statusView.usernameLabel.text = username
+        }
+        .store(in: &cell.disposeBag)
+    }
+}
diff --git a/Mastodon/Generated/Assets.swift b/Mastodon/Generated/Assets.swift
index f6817046..f573d2d1 100644
--- a/Mastodon/Generated/Assets.swift
+++ b/Mastodon/Generated/Assets.swift
@@ -48,6 +48,7 @@ internal enum Asset {
       internal static let actionToolbar = ColorAsset(name: "Colors/Button/action.toolbar")
       internal static let disabled = ColorAsset(name: "Colors/Button/disabled")
       internal static let highlight = ColorAsset(name: "Colors/Button/highlight")
+      internal static let normal = ColorAsset(name: "Colors/Button/normal")
     }
     internal enum Icon {
       internal static let photo = ColorAsset(name: "Colors/Icon/photo")
diff --git a/Mastodon/Generated/Strings.swift b/Mastodon/Generated/Strings.swift
index 6df84fb7..49e4cd7c 100644
--- a/Mastodon/Generated/Strings.swift
+++ b/Mastodon/Generated/Strings.swift
@@ -128,6 +128,10 @@ internal enum L10n {
 
   internal enum Scene {
     internal enum Compose {
+      /// Toot
+      internal static let composeAction = L10n.tr("Localizable", "Scene.Compose.ComposeAction")
+      /// Type or paste what's on your mind
+      internal static let contentInputPlaceholder = L10n.tr("Localizable", "Scene.Compose.ContentInputPlaceholder")
       internal enum Title {
         /// New Reply
         internal static let newReply = L10n.tr("Localizable", "Scene.Compose.Title.NewReply")
diff --git a/Mastodon/Resources/Assets.xcassets/Colors/Button/disabled.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Colors/Button/disabled.colorset/Contents.json
index 78cde95f..bca75461 100644
--- a/Mastodon/Resources/Assets.xcassets/Colors/Button/disabled.colorset/Contents.json
+++ b/Mastodon/Resources/Assets.xcassets/Colors/Button/disabled.colorset/Contents.json
@@ -5,9 +5,9 @@
         "color-space" : "srgb",
         "components" : {
           "alpha" : "1.000",
-          "blue" : "0.784",
-          "green" : "0.682",
-          "red" : "0.608"
+          "blue" : "140",
+          "green" : "130",
+          "red" : "110"
         }
       },
       "idiom" : "universal"
diff --git a/Mastodon/Resources/Assets.xcassets/Colors/Button/normal.colorset/Contents.json b/Mastodon/Resources/Assets.xcassets/Colors/Button/normal.colorset/Contents.json
new file mode 100644
index 00000000..d853a71a
--- /dev/null
+++ b/Mastodon/Resources/Assets.xcassets/Colors/Button/normal.colorset/Contents.json
@@ -0,0 +1,20 @@
+{
+  "colors" : [
+    {
+      "color" : {
+        "color-space" : "srgb",
+        "components" : {
+          "alpha" : "1.000",
+          "blue" : "217",
+          "green" : "144",
+          "red" : "43"
+        }
+      },
+      "idiom" : "universal"
+    }
+  ],
+  "info" : {
+    "author" : "xcode",
+    "version" : 1
+  }
+}
diff --git a/Mastodon/Resources/en.lproj/Localizable.strings b/Mastodon/Resources/en.lproj/Localizable.strings
index a83819dd..f9a1ffe6 100644
--- a/Mastodon/Resources/en.lproj/Localizable.strings
+++ b/Mastodon/Resources/en.lproj/Localizable.strings
@@ -34,6 +34,8 @@
 "Common.Controls.Timeline.LoadMore" = "Load More";
 "Common.Countable.Photo.Multiple" = "photos";
 "Common.Countable.Photo.Single" = "photo";
+"Scene.Compose.ComposeAction" = "Toot";
+"Scene.Compose.ContentInputPlaceholder" = "Type or paste what's on your mind";
 "Scene.Compose.Title.NewReply" = "New Reply";
 "Scene.Compose.Title.NewToot" = "New Toot";
 "Scene.ConfirmEmail.Button.DontReceiveEmail" = "I never got an email";
diff --git a/Mastodon/Scene/Compose/ComposeViewController.swift b/Mastodon/Scene/Compose/ComposeViewController.swift
index adab1dd9..f183bb25 100644
--- a/Mastodon/Scene/Compose/ComposeViewController.swift
+++ b/Mastodon/Scene/Compose/ComposeViewController.swift
@@ -18,6 +18,20 @@ final class ComposeViewController: UIViewController, NeedsDependency {
     var disposeBag = Set<AnyCancellable>()
     var viewModel: ComposeViewModel!
     
+    let composeTootBarButtonItem: UIBarButtonItem = {
+        let button = RoundedEdgesButton(type: .custom)
+        button.setTitle(L10n.Scene.Compose.composeAction, for: .normal)
+        button.titleLabel?.font = .systemFont(ofSize: 14, weight: .bold)
+        button.setBackgroundImage(.placeholder(color: Asset.Colors.Button.normal.color), for: .normal)
+        button.setBackgroundImage(.placeholder(color: Asset.Colors.Button.normal.color.withAlphaComponent(0.5)), for: .highlighted)
+        button.setBackgroundImage(.placeholder(color: Asset.Colors.Button.disabled.color), for: .disabled)
+        button.setTitleColor(.white, for: .normal)
+        button.contentEdgeInsets = UIEdgeInsets(top: 3, left: 16, bottom: 3, right: 16)
+        button.adjustsImageWhenHighlighted = false
+        let barButtonItem = UIBarButtonItem(customView: button)
+        return barButtonItem
+    }()
+    
     let tableView: UITableView = {
         let tableView = ControlContainableTableView()
         tableView.register(ComposeRepliedToTootContentTableViewCell.self, forCellReuseIdentifier: String(describing: ComposeRepliedToTootContentTableViewCell.self))
@@ -34,7 +48,6 @@ extension ComposeViewController {
     override func viewDidLoad() {
         super.viewDidLoad()
         
-        view.backgroundColor = Asset.Colors.Background.systemBackground.color
         viewModel.title
             .receive(on: DispatchQueue.main)
             .sink { [weak self] title in
@@ -42,7 +55,10 @@ extension ComposeViewController {
                 self.title = title
             }
             .store(in: &disposeBag)
+        view.backgroundColor = Asset.Colors.Background.systemBackground.color
         navigationItem.leftBarButtonItem = UIBarButtonItem(title: L10n.Common.Controls.Actions.cancel, style: .plain, target: self, action: #selector(ComposeViewController.cancelBarButtonItemPressed(_:)))
+        navigationItem.rightBarButtonItem = composeTootBarButtonItem
+        
         
         tableView.translatesAutoresizingMaskIntoConstraints = false
         view.addSubview(tableView)
@@ -54,9 +70,7 @@ extension ComposeViewController {
         ])
         
         tableView.delegate = self
-        viewModel.setupDiffableDataSource(for: tableView)
-        
-
+        viewModel.setupDiffableDataSource(for: tableView, dependency: self)
     }
     
     override func viewWillAppear(_ animated: Bool) {
@@ -111,7 +125,9 @@ extension ComposeViewController: TextEditorViewTextAttributesDelegate {
 
 // MARK: - UITableViewDelegate
 extension ComposeViewController: UITableViewDelegate {
-    
+    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+        return UITableView.automaticDimension
+    }
 }
 
 // MARK: - ComposeViewController
diff --git a/Mastodon/Scene/Compose/ComposeViewModel+Diffable.swift b/Mastodon/Scene/Compose/ComposeViewModel+Diffable.swift
index 772bb97b..5c27bf51 100644
--- a/Mastodon/Scene/Compose/ComposeViewModel+Diffable.swift
+++ b/Mastodon/Scene/Compose/ComposeViewModel+Diffable.swift
@@ -9,30 +9,25 @@ import UIKit
 
 extension ComposeViewModel {
     
-    func setupDiffableDataSource(for tableView: UITableView) {
-        diffableDataSource = UITableViewDiffableDataSource(tableView: tableView) { [weak self] tableView, indexPath, item -> UITableViewCell? in
-            guard let self = self else { return nil }
-            
-            switch item {
-            case .replyTo(let tootObjectID):
-                let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ComposeRepliedToTootContentTableViewCell.self), for: indexPath) as! ComposeRepliedToTootContentTableViewCell
-                // TODO:
-                return cell
-            case .toot(let attribute):
-                let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ComposeTootContentTableViewCell.self), for: indexPath) as! ComposeTootContentTableViewCell
-                // TODO:
-                return cell
-            }
-        }
+    func setupDiffableDataSource(
+        for tableView: UITableView,
+        dependency: NeedsDependency
+    ) {
+        diffableDataSource = ComposeStatusSection.tableViewDiffableDataSource(
+            for: tableView,
+            dependency: dependency,
+            managedObjectContext: context.managedObjectContext,
+            composeKind: composeKind
+        )
         
         var snapshot = NSDiffableDataSourceSnapshot<ComposeStatusSection, ComposeStatusItem>()
         snapshot.appendSections([.repliedTo, .status])
         switch composeKind {
         case .replyToot(let tootObjectID):
             snapshot.appendItems([.replyTo(tootObjectID: tootObjectID)], toSection: .repliedTo)
-            snapshot.appendItems([.toot(replyToTootObjectID: tootObjectID)], toSection: .status)
+            snapshot.appendItems([.toot(replyToTootObjectID: tootObjectID, attribute: composeTootAttribute)], toSection: .status)
         case .toot:
-            snapshot.appendItems([.toot(replyToTootObjectID: nil)], toSection: .status)
+            snapshot.appendItems([.toot(replyToTootObjectID: nil, attribute: composeTootAttribute)], toSection: .status)
         }
         diffableDataSource.apply(snapshot, animatingDifferences: false)
     }
diff --git a/Mastodon/Scene/Compose/ComposeViewModel.swift b/Mastodon/Scene/Compose/ComposeViewModel.swift
index bcda6587..7aaadcb7 100644
--- a/Mastodon/Scene/Compose/ComposeViewModel.swift
+++ b/Mastodon/Scene/Compose/ComposeViewModel.swift
@@ -12,18 +12,25 @@ import CoreDataStack
 
 final class ComposeViewModel {
     
+    var disposeBag = Set<AnyCancellable>()
+    
     // input
     let context: AppContext
-    let composeKind: ComposeKind
+    let composeKind: ComposeStatusSection.ComposeKind
+    let composeTootAttribute = ComposeStatusItem.ComposeTootAttribute()
+    let composeContent = CurrentValueSubject<String, Never>("")
+    let activeAuthentication: CurrentValueSubject<MastodonAuthentication?, Never>
     
     // output
     var diffableDataSource: UITableViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem>!
+    
+    // UI & UX
     let title: CurrentValueSubject<String, Never>
     let shouldDismiss = CurrentValueSubject<Bool, Never>(true)
     
     init(
         context: AppContext,
-        composeKind: ComposeKind
+        composeKind: ComposeStatusSection.ComposeKind
     ) {
         self.context = context
         self.composeKind = composeKind
@@ -31,14 +38,30 @@ final class ComposeViewModel {
         case .toot:         self.title = CurrentValueSubject(L10n.Scene.Compose.Title.newToot)
         case .replyToot:    self.title = CurrentValueSubject(L10n.Scene.Compose.Title.newReply)
         }
+        self.activeAuthentication = CurrentValueSubject(context.authenticationService.activeMastodonAuthentication.value)
         // end init
+        
+        // bind active authentication
+        context.authenticationService.activeMastodonAuthentication
+            .assign(to: \.value, on: activeAuthentication)
+            .store(in: &disposeBag)
+        
+        activeAuthentication
+            .sink { [weak self] mastodonAuthentication in
+                guard let self = self else { return }
+                let mastodonUser = mastodonAuthentication?.user
+                let username = mastodonUser?.username ?? " "
+
+                self.composeTootAttribute.avatarURL.value = mastodonUser?.avatarImageURL()
+                self.composeTootAttribute.displayName.value = {
+                    guard let displayName = mastodonUser?.displayName, !displayName.isEmpty else {
+                        return username
+                    }
+                    return displayName
+                }()
+                self.composeTootAttribute.username.value = username
+            }
+            .store(in: &disposeBag)
     }
     
 }
-
-extension ComposeViewModel {
-    enum ComposeKind {
-        case toot
-        case replyToot(tootObjectID: NSManagedObjectID)
-    }
-}
diff --git a/Mastodon/Scene/Compose/TableViewCell/ComposeTootContentTableViewCell.swift b/Mastodon/Scene/Compose/TableViewCell/ComposeTootContentTableViewCell.swift
index 6e7a2058..5a7f311d 100644
--- a/Mastodon/Scene/Compose/TableViewCell/ComposeTootContentTableViewCell.swift
+++ b/Mastodon/Scene/Compose/TableViewCell/ComposeTootContentTableViewCell.swift
@@ -6,19 +6,26 @@
 //
 
 import UIKit
+import Combine
 import TwitterTextEditor
 
 final class ComposeTootContentTableViewCell: UITableViewCell {
     
+    var disposeBag = Set<AnyCancellable>()
+    
     let statusView = StatusView()
+    
     let textEditorView: TextEditorView = {
         let textEditorView = TextEditorView()
         textEditorView.font = .preferredFont(forTextStyle: .body)
-//        textEditorView.scrollView.isScrollEnabled = false
+        textEditorView.scrollView.isScrollEnabled = false
         textEditorView.isScrollEnabled = false
+        textEditorView.placeholderText = L10n.Scene.Compose.contentInputPlaceholder
         return textEditorView
     }()
     
+    let composeContent = PassthroughSubject<String, Never>()
+    
     override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
         super.init(style: style, reuseIdentifier: reuseIdentifier)
         _init()
@@ -56,19 +63,9 @@ extension ComposeTootContentTableViewCell {
             textEditorView.heightAnchor.constraint(greaterThanOrEqualToConstant: 44).priority(.defaultHigh),
         ])
         
-        // let containerStackView = UIStackView()
-        // containerStackView.axis = .vertical
-        // containerStackView.spacing = 8
-        // containerStackView.translatesAutoresizingMaskIntoConstraints = false
-        // contentView.addSubview(containerStackView)
-        // NSLayoutConstraint.activate([
-        //     containerStackView.topAnchor.constraint(equalTo: statusView.bottomAnchor, constant: 10),
-        //     containerStackView.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor),
-        //     containerStackView.trailingAnchor.constraint(equalTo: contentView.readableContentGuide.trailingAnchor),
-        //     contentView.bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor, constant: 20),
-        // ])
-        
         // TODO:
+        
+        textEditorView.changeObserver = self
     }
     
     override func didMoveToWindow() {
@@ -81,3 +78,11 @@ extension ComposeTootContentTableViewCell {
 extension ComposeTootContentTableViewCell {
     
 }
+
+// MARK: - UITextViewDelegate
+extension ComposeTootContentTableViewCell: TextEditorViewChangeObserver {
+    func textEditorView(_ textEditorView: TextEditorView, didChangeWithChangeResult changeResult: TextEditorViewChangeResult) {
+        guard changeResult.isTextChanged else { return }
+        composeContent.send(textEditorView.text)
+    }
+}
diff --git a/Mastodon/Scene/Share/View/Button/RoundedEdgesButton.swift b/Mastodon/Scene/Share/View/Button/RoundedEdgesButton.swift
new file mode 100644
index 00000000..a38b711d
--- /dev/null
+++ b/Mastodon/Scene/Share/View/Button/RoundedEdgesButton.swift
@@ -0,0 +1,19 @@
+//
+//  RoundedEdgesButton.swift
+//  Mastodon
+//
+//  Created by MainasuK Cirno on 2021-3-12.
+//
+
+import UIKit
+
+final class RoundedEdgesButton: UIButton {
+        
+    override func layoutSubviews() {
+        super.layoutSubviews()
+        
+        layer.masksToBounds = true
+        layer.cornerRadius = bounds.height * 0.5
+    }
+    
+}
diff --git a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Statuses.swift b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Statuses.swift
new file mode 100644
index 00000000..f01e6cb4
--- /dev/null
+++ b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API+Statuses.swift
@@ -0,0 +1,8 @@
+//
+//  Mastodon+API+Statuses.swift
+//  
+//
+//  Created by MainasuK Cirno on 2021-3-12.
+//
+
+import Foundation
diff --git a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift
index 073d926e..5443fa22 100644
--- a/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift
+++ b/MastodonSDK/Sources/MastodonSDK/API/Mastodon+API.swift
@@ -96,6 +96,7 @@ extension Mastodon.API {
     public enum Onboarding { }
     public enum Polls { }
     public enum Timeline { }
+    public enum Statuses { }
     public enum Favorites { }
 }