diff --git a/src/components/sectionTitle/section-title.css b/src/components/sectionTitle/section-title.css
new file mode 100644
index 0000000..dcdda05
--- /dev/null
+++ b/src/components/sectionTitle/section-title.css
@@ -0,0 +1,45 @@
+:host {
+ display: block;
+}
+
+.container {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ gap: 16px;
+}
+
+.main {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+}
+
+.heading {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.text-links {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ gap: 16px;
+}
+
+.buttons {
+ display: flex;
+ flex-shrink: 0;
+ align-items: center;
+ gap: 8px;
+}
+
+h2 {
+ margin-block: 3px;
+ padding-inline-start: 8px;
+ font-size: 14px;
+ font-weight: bold;
+ line-height: 1.6;
+ position: relative;
+}
diff --git a/src/components/sectionTitle/sp-section-title.ts b/src/components/sectionTitle/sp-section-title.ts
new file mode 100644
index 0000000..800b47b
--- /dev/null
+++ b/src/components/sectionTitle/sp-section-title.ts
@@ -0,0 +1,97 @@
+// @ts-ignore
+import resetStyle from "@acab/reset.css?inline" assert { type: "css" };
+// @ts-ignore
+import foundationStyle from "../foundation.css?inline" assert { type: "css" };
+// @ts-ignore
+import sectionTitleStyle from "./section-title.css?inline" assert { type: "css" };
+
+const styles = new CSSStyleSheet();
+styles.replaceSync(`${resetStyle} ${foundationStyle} ${sectionTitleStyle}`);
+
+export class SpSectionTitle extends HTMLElement {
+ #headingElement = document.createElement("h2");
+ #textLinkSlotElement = document.createElement("slot");
+ #buttonSlotElement = document.createElement("slot");
+
+ set text(value: string) {
+ this.#headingElement.textContent = value;
+ }
+
+ static get observedAttributes() {
+ return ["text"];
+ }
+
+ constructor() {
+ super();
+ this.attachShadow({ mode: "open" });
+
+ this.shadowRoot!.adoptedStyleSheets = [styles];
+
+ this.#textLinkSlotElement.name = "text-links";
+ this.#buttonSlotElement.name = "buttons";
+ }
+
+ connectedCallback() {
+ this.shadowRoot!.appendChild(this.#createContainer());
+
+ if (this.#textLinkSlotElement.assignedElements().length === 0) {
+ this.shadowRoot!.querySelector(".text-links")?.remove();
+ }
+
+ if (this.#buttonSlotElement.assignedElements().length === 0) {
+ this.shadowRoot!.querySelector(".buttons")?.remove();
+ }
+ }
+
+ attributeChangedCallback(name: string, oldValue: string, newValue: string) {
+ if (name === "text" && oldValue !== newValue) {
+ this.text = newValue;
+ }
+ }
+
+ #createContainer() {
+ const container = document.createElement("div");
+ container.classList.add("container");
+ container.appendChild(this.#createMain());
+ container.appendChild(this.#createButtons());
+ return container;
+ }
+
+ #createMain() {
+ const main = document.createElement("div");
+ main.classList.add("main");
+ main.appendChild(this.#createHeadingBlock());
+ main.appendChild(this.#createTextLinks());
+ return main;
+ }
+
+ #createHeadingBlock() {
+ const div = document.createElement("div");
+ div.classList.add("heading");
+ div.appendChild(this.#headingElement);
+ return div;
+ }
+
+ #createTextLinks() {
+ const div = document.createElement("div");
+ div.classList.add("text-links");
+ div.appendChild(this.#textLinkSlotElement);
+ return div;
+ }
+
+ #createButtons() {
+ const div = document.createElement("div");
+ div.classList.add("buttons");
+ div.appendChild(this.#buttonSlotElement);
+ return div;
+ }
+}
+
+declare global {
+ interface HTMLElementTagNameMap {
+ "sp-section-title": SpSectionTitle;
+ }
+}
+
+customElements.get("sp-section-title") ||
+ customElements.define("sp-section-title", SpSectionTitle);
diff --git a/stories/sectionTitle/sp-section-title.story.ts b/stories/sectionTitle/sp-section-title.story.ts
new file mode 100644
index 0000000..044dd7b
--- /dev/null
+++ b/stories/sectionTitle/sp-section-title.story.ts
@@ -0,0 +1,69 @@
+import "../../src/components/sectionTitle/sp-section-title";
+import "../../src/components/button/sp-button";
+import "@sp-design/token/lib/speeda-tokens.css";
+import { Meta, StoryObj } from "@storybook/web-components";
+import { html } from "lit";
+
+const meta: Meta = {
+ component: "sp-section-title",
+ argTypes: {
+ text: { type: "string" },
+ },
+ args: {
+ text: "Section Title",
+ },
+};
+export default meta;
+
+type Story = StoryObj;
+
+export const Basic: Story = {};
+
+export const WithTextLinks: Story = {
+ render: (args) => html`
+
+ TextLink1
+ TextLink2
+
+ `,
+};
+
+export const WithButtons: Story = {
+ render: (args) => html`
+
+
+
+
+ `,
+};
+
+export const WithFullContents: Story = {
+ render: (args) => html`
+
+ TextLink1
+ TextLink2
+
+
+
+ `,
+};