diff --git a/package-lock.json b/package-lock.json
index d9bdf3da59afc1f3de0178bdd0df0a359307b4a7..8f0b98286b83fb19ae4487eb4de8bff2cb6a9ea6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -31106,6 +31106,7 @@
       "version": "1.0.1",
       "license": "UNLICENSED",
       "dependencies": {
+        "@sikt/sds-button": "^2.0.0",
         "@sikt/sds-core": "^1.0.1",
         "@sikt/sds-icons": "^1.0.0"
       },
diff --git a/packages/input/Input.test.tsx b/packages/input/Input.test.tsx
index 14b4b900499509ec8d031913e4e71dd697532f33..2b0713b1f279ea8ec5d776893e6978af48cf5cbd 100644
--- a/packages/input/Input.test.tsx
+++ b/packages/input/Input.test.tsx
@@ -102,15 +102,8 @@ describe("Input", () => {
       expect(errorEl).toHaveClass("sds-input__help-text");
     });
 
-    it("should have left icon element", async () => {
-      render(
-        <TextInput
-          label="Foo"
-          data-testid="test"
-          icon="icon"
-          iconPosition="start"
-        />
-      );
+    it("should have icon element", async () => {
+      render(<TextInput label="Foo" data-testid="test" icon="icon" />);
 
       const container = screen.getByTestId("test");
       const icon = container.getElementsByClassName("sds-input__icon")[0];
@@ -121,23 +114,23 @@ describe("Input", () => {
       expect(screen.getByText("Foo")).toBeInTheDocument();
     });
 
-    it("should have right icon element", async () => {
+    it("should have action element", async () => {
       render(
-        <TextInput
+        <SearchInput
           label="Foo"
           data-testid="test"
-          icon="icon"
-          iconPosition="end"
+          actionProps={{ label: "Test label" }}
         />
       );
 
       const container = screen.getByTestId("test");
-      const icon = container.getElementsByClassName("sds-input__icon")[0];
+      const action = container.getElementsByClassName("sds-input__action")[0];
       const input = container.getElementsByClassName("sds-input__input")[0];
-      expect(icon.compareDocumentPosition(input)).toBe(
+      expect(action.compareDocumentPosition(input)).toBe(
         Node.DOCUMENT_POSITION_PRECEDING
       );
       expect(screen.getByText("Foo")).toBeInTheDocument();
+      expect(action).toHaveAccessibleName("Test label");
     });
   });
 });
diff --git a/packages/input/Input.tsx b/packages/input/Input.tsx
index aebf782415ddafff5ffad13ee07963201f1d5169..40d33aa7b03cff47addcc38832690020359b5fc3 100644
--- a/packages/input/Input.tsx
+++ b/packages/input/Input.tsx
@@ -16,6 +16,7 @@ import {
   PhoneIcon,
   WarningIcon,
 } from "@sikt/sds-icons";
+import { InputActionButton, InputActionButtonProps } from "./InputActionButton";
 import "./input.pcss";
 
 type InputTypes =
@@ -43,7 +44,7 @@ export interface InputProps
   ) => void;
   value?: string;
   icon?: ReactNode;
-  iconPosition?: "start" | "end";
+  actionProps?: Omit<InputActionButtonProps, "icon">;
   errorText?: string;
   helpText?: string;
   inputProps?: InputHTMLAttributes<HTMLInputElement | HTMLTextAreaElement>;
@@ -62,7 +63,7 @@ const Input = forwardRef<
       onChange,
       value,
       icon,
-      iconPosition = "start",
+      actionProps,
       type,
       errorText,
       helpText,
@@ -97,9 +98,7 @@ const Input = forwardRef<
             {label}
           </div>
           <div className="sds-input__wrapper">
-            {iconPosition === "start" && icon && (
-              <div className="sds-input__icon">{icon}</div>
-            )}
+            {icon && <div className="sds-input__icon">{icon}</div>}
             {type === "textarea" ? (
               <textarea
                 ref={ref as ForwardedRef<HTMLTextAreaElement>}
@@ -129,8 +128,14 @@ const Input = forwardRef<
                 {...inputProps}
               />
             )}
-            {iconPosition === "end" && icon && (
-              <div className="sds-input__icon">{icon}</div>
+            {type === "search" && (
+              <InputActionButton
+                type="submit"
+                className="sds-input__action"
+                label="Søk"
+                icon={<MagnifyingGlassIcon />}
+                {...actionProps}
+              />
             )}
           </div>
         </label>
@@ -175,14 +180,6 @@ export const TelInput = forwardRef<HTMLInputElement, InputProps>(
 );
 TelInput.displayName = "TelInput";
 export const SearchInput = forwardRef<HTMLInputElement, InputProps>(
-  (props, ref) => (
-    <Input
-      type="search"
-      icon={<MagnifyingGlassIcon />}
-      iconPosition="end"
-      ref={ref}
-      {...props}
-    />
-  )
+  (props, ref) => <Input type="search" ref={ref} {...props} />
 );
 SearchInput.displayName = "SearchInput";
diff --git a/packages/input/InputActionButton.test.tsx b/packages/input/InputActionButton.test.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..54bd21633ce892b73cb9573149d5b44dc469797f
--- /dev/null
+++ b/packages/input/InputActionButton.test.tsx
@@ -0,0 +1,65 @@
+import React from "react";
+import { render, screen } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { axe } from "jest-axe";
+import { InputActionButton } from "./InputActionButton";
+import { MagnifyingGlassIcon } from "@sikt/sds-icons";
+
+describe("InputActionButton", () => {
+  describe("a11y", () => {
+    it("should be accessible", async () => {
+      const { container } = render(
+        <InputActionButton label="Foo" icon={<MagnifyingGlassIcon />} />
+      );
+
+      expect(await axe(container)).toHaveNoViolations();
+    });
+  });
+
+  describe("api", () => {
+    it("should render", async () => {
+      render(
+        <InputActionButton
+          label="Foo"
+          icon={<MagnifyingGlassIcon />}
+          data-testid="test"
+        />
+      );
+
+      expect(screen.getByTestId("test")).toHaveClass("sds-input-action");
+      expect(screen.getByTestId("test")).toHaveAccessibleName("Foo");
+    });
+
+    it("calls click handler", async () => {
+      const user = userEvent.setup();
+      const clickHandler = jest.fn();
+      render(
+        <InputActionButton
+          label="Foo"
+          icon={<MagnifyingGlassIcon />}
+          data-testid="test"
+          onClick={clickHandler}
+        />
+      );
+
+      await user.click(screen.getByTestId("test"));
+
+      expect(clickHandler).toHaveBeenCalled();
+    });
+
+    it("should have class name", async () => {
+      render(
+        <InputActionButton
+          label="Foo"
+          icon={<MagnifyingGlassIcon />}
+          data-testid="test"
+          className="test-class-name"
+        />
+      );
+
+      expect(screen.getByTestId("test")).toHaveClass(
+        "sds-input-action test-class-name"
+      );
+    });
+  });
+});
diff --git a/packages/input/InputActionButton.tsx b/packages/input/InputActionButton.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..394c2deb101f07200c939c8e3f8a4fe5d4e9802e
--- /dev/null
+++ b/packages/input/InputActionButton.tsx
@@ -0,0 +1,27 @@
+import React, { ButtonHTMLAttributes, ReactNode } from "react";
+import clsx from "clsx";
+import { TertiaryButton } from "@sikt/sds-button";
+import "./input-action-button.pcss";
+
+export interface InputActionButtonProps
+  extends ButtonHTMLAttributes<HTMLButtonElement> {
+  label: string;
+  icon: ReactNode;
+}
+
+export const InputActionButton = ({
+  className,
+  label,
+  icon,
+  ...rest
+}: InputActionButtonProps) => (
+  <TertiaryButton
+    type="button"
+    className={clsx("sds-input-action", className)}
+    aria-label={label}
+    title={label}
+    icon={icon}
+    iconType="only"
+    {...rest}
+  />
+);
diff --git a/packages/input/input-action-button.pcss b/packages/input/input-action-button.pcss
new file mode 100644
index 0000000000000000000000000000000000000000..96d161cb57d3626e70cd76e256843d0f6c3d0a96
--- /dev/null
+++ b/packages/input/input-action-button.pcss
@@ -0,0 +1,3 @@
+.sds-input-action .sds-button__icon {
+  font-size: var(--sds-size-text-m);
+}
diff --git a/packages/input/input.pcss b/packages/input/input.pcss
index 3ed84acfa1c76dc9cb2b20f764b27bf446d9786b..d2a13c8cfeceeefd8dcc01c767761f4530f3914f 100644
--- a/packages/input/input.pcss
+++ b/packages/input/input.pcss
@@ -52,6 +52,11 @@
       &:focus-visible {
         outline: none;
       }
+
+      /* Hide native clear search button in Chrome and Safari */
+      &::-webkit-search-cancel-button {
+        appearance: none;
+      }
     }
 
     &:hover {
@@ -78,15 +83,23 @@
     }
   }
 
-  &__icon {
+  &__icon,
+  &__action {
     align-items: center;
     display: inline-flex;
     font-size: var(--sds-size-text-m);
     justify-content: center;
-    width: var(--sds-size-text-m);
     height: 100%;
   }
 
+  &__icon {
+    width: var(--sds-size-text-m);
+  }
+
+  &__action {
+    margin-right: calc(-1 * var(--sds-size-base-s));
+  }
+
   &--error {
     --sds-input-border-color: var(--sds-color-surface-danger);
     --sds-input-label-color: var(--sds-color-text-danger);
diff --git a/packages/input/package.json b/packages/input/package.json
index 94a914992e2d974dec643487c5da8ee76e5f8f6e..fa5756641abc72905c86abec10c528f0ad06afa6 100644
--- a/packages/input/package.json
+++ b/packages/input/package.json
@@ -13,6 +13,7 @@
     "build": "rollup -c ../../rollup.config.mjs"
   },
   "dependencies": {
+    "@sikt/sds-button": "^2.0.0",
     "@sikt/sds-core": "^1.0.1",
     "@sikt/sds-icons": "^1.0.0"
   },
diff --git a/packages/input/stories/EmailInput.stories.tsx b/packages/input/stories/EmailInput.stories.tsx
index 66bd9704c2dec7cde5c0298af272239fae5d3a77..fa883b84490c0bda6aed0c535209a71771e0640e 100644
--- a/packages/input/stories/EmailInput.stories.tsx
+++ b/packages/input/stories/EmailInput.stories.tsx
@@ -23,7 +23,6 @@ export const WithCustomIcon: Story = {
   args: {
     ...Input.args,
     icon: <GearIcon />,
-    iconPosition: "end",
   },
 };
 
diff --git a/packages/input/stories/PasswordInput.stories.tsx b/packages/input/stories/PasswordInput.stories.tsx
index 5951dd0e051f9abbc3475b9793e3ac66c804a2fe..4d77d95418cf53187d6c93bd7c0fd610747dd113 100644
--- a/packages/input/stories/PasswordInput.stories.tsx
+++ b/packages/input/stories/PasswordInput.stories.tsx
@@ -23,7 +23,6 @@ export const WithCustomIcon: Story = {
   args: {
     ...Default.args,
     icon: <UserCircleIcon />,
-    iconPosition: "end",
   },
 };
 
diff --git a/packages/input/stories/SearchInput.stories.tsx b/packages/input/stories/SearchInput.stories.tsx
index 6b16ad0f52bbb6333dd36c3b0e2ecaf3f06d567e..c474290532c830535e8e9090b2036c09c36da2d1 100644
--- a/packages/input/stories/SearchInput.stories.tsx
+++ b/packages/input/stories/SearchInput.stories.tsx
@@ -23,7 +23,6 @@ export const WithCustomIcon: Story = {
   args: {
     ...Default.args,
     icon: <MapPinIcon />,
-    iconPosition: "start",
   },
 };
 
@@ -34,3 +33,7 @@ export const WithHelpText: Story = {
 export const WithError: Story = {
   args: { ...Default.args, errorText: "Error!" },
 };
+
+export const WithCustomActionLabel: Story = {
+  args: { ...Default.args, actionProps: { label: "Finn resultater" } },
+};
diff --git a/packages/input/stories/TelInput.stories.tsx b/packages/input/stories/TelInput.stories.tsx
index 1a9f31366ff239ae3544cc895b70261b36ac0501..b8cfc392837283c041c8e0bb4bc177573804fb40 100644
--- a/packages/input/stories/TelInput.stories.tsx
+++ b/packages/input/stories/TelInput.stories.tsx
@@ -23,7 +23,6 @@ export const WithCustomIcon: Story = {
   args: {
     ...Default.args,
     icon: <SlidersIcon />,
-    iconPosition: "end",
   },
 };