Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/web/core/components/pages/version/editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { useParams } from "next/navigation";
// plane imports
import type { TDisplayConfig } from "@plane/editor";
import type { JSONContent, TPageVersion } from "@plane/types";
import { isJSONContentEmpty } from "@plane/utils";
import { Loader } from "@plane/ui";
import { isJSONContentEmpty } from "@plane/utils";
// components
import { DocumentEditor } from "@/components/editor/document/editor";
// hooks
Expand Down
1 change: 1 addition & 0 deletions packages/propel/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
"./emoji-reaction": "./dist/emoji-reaction/index.js",
"./emoji-reaction-picker": "./dist/emoji-reaction-picker/index.js",
"./icons": "./dist/icons/index.js",
"./input": "./dist/input/index.js",
"./menu": "./dist/menu/index.js",
"./pill": "./dist/pill/index.js",
"./popover": "./dist/popover/index.js",
Expand Down
1 change: 1 addition & 0 deletions packages/propel/src/input/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./input";
153 changes: 153 additions & 0 deletions packages/propel/src/input/input.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import type { Meta, StoryObj } from "@storybook/react-vite";
import { Input } from "./index";

const meta: Meta<typeof Input> = {
title: "Components/Input",
component: Input,
parameters: {
layout: "centered",
},
tags: ["autodocs"],
argTypes: {
mode: {
control: "select",
options: ["primary", "transparent", "true-transparent"],
},
inputSize: {
control: "select",
options: ["xs", "sm", "md"],
},
hasError: {
control: "boolean",
},
type: {
control: "select",
options: ["text", "email", "password", "number", "tel", "url", "search"],
},
autoComplete: {
control: "select",
options: ["on", "off"],
},
disabled: {
control: "boolean",
},
},
};

export default meta;
type Story = StoryObj<typeof Input>;

const createStory = (args: Partial<React.ComponentProps<typeof Input>>): Story => ({
args: { placeholder: "Enter text...", className: "w-[400px]", ...args },
});

const createShowcaseStory = (
title: string,
sections: Array<{ label: string; props: Partial<React.ComponentProps<typeof Input>> }>
): Story => ({
render: () => (
<div className="space-y-4 w-[400px]">
<div className="space-y-2">
<h3 className="text-sm font-medium">{title}</h3>
<div className="space-y-2">
{sections.map(({ label, props }, index) => (
<div key={index} className="w-full">
<label className="text-xs text-gray-500">{label}</label>
<Input className="w-full" {...props} />
</div>
))}
</div>
</div>
</div>
),
});

export const Default = createStory({});

export const Primary = createStory({
mode: "primary",
placeholder: "Primary input",
});

export const Transparent = createStory({
mode: "transparent",
placeholder: "Transparent input",
});

export const TrueTransparent = createStory({
mode: "true-transparent",
placeholder: "True transparent input",
});

export const ExtraSmall = createStory({
inputSize: "xs",
placeholder: "Extra small input",
});

export const Small = createStory({
inputSize: "sm",
placeholder: "Small input",
});

export const Medium = createStory({
inputSize: "md",
placeholder: "Medium input",
});

export const WithError = createStory({
hasError: true,
placeholder: "Input with error",
defaultValue: "Invalid input",
});

export const Disabled = createStory({
disabled: true,
placeholder: "Disabled input",
defaultValue: "Cannot edit this",
});

export const WithValue = createStory({
defaultValue: "Pre-filled value",
placeholder: "Input with value",
});

export const Email = createStory({
type: "email",
placeholder: "Enter your email",
autoComplete: "on",
});

export const Password = createStory({
type: "password",
placeholder: "Enter your password",
autoComplete: "off",
});

export const Number = createStory({
type: "number",
placeholder: "Enter a number",
});

export const Search = createStory({
type: "search",
placeholder: "Search...",
});

export const AllModes = createShowcaseStory("Input Modes", [
{ label: "Primary", props: { mode: "primary", placeholder: "Primary input" } },
{ label: "Transparent", props: { mode: "transparent", placeholder: "Transparent input" } },
{ label: "True Transparent", props: { mode: "true-transparent", placeholder: "True transparent input" } },
]);

export const AllSizes = createShowcaseStory("Input Sizes", [
{ label: "Extra Small (xs)", props: { inputSize: "xs", placeholder: "Extra small input" } },
{ label: "Small (sm)", props: { inputSize: "sm", placeholder: "Small input" } },
{ label: "Medium (md)", props: { inputSize: "md", placeholder: "Medium input" } },
]);

export const AllStates = createShowcaseStory("Input States", [
{ label: "Normal", props: { placeholder: "Normal input" } },
{ label: "With Error", props: { hasError: true, placeholder: "Input with error" } },
{ label: "Disabled", props: { disabled: true, placeholder: "Disabled input" } },
{ label: "With Value", props: { defaultValue: "Pre-filled value", placeholder: "Input with value" } },
]);
55 changes: 55 additions & 0 deletions packages/propel/src/input/input.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import * as React from "react";
import { Input as BaseInput } from "@base-ui-components/react/input";
// helpers
import { cn } from "../utils";

export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
mode?: "primary" | "transparent" | "true-transparent";
inputSize?: "xs" | "sm" | "md";
hasError?: boolean;
className?: string;
autoComplete?: "on" | "off";
}

const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => {
const {
id,
type,
name,
mode = "primary",
inputSize = "sm",
hasError = false,
className = "",
autoComplete = "off",
...rest
} = props;

return (
<BaseInput
id={id}
ref={ref}
type={type}
name={name}
className={cn(
"block rounded-md bg-transparent text-sm placeholder-custom-text-400 focus:outline-none",
{
"rounded-md border-[0.5px] border-custom-border-200": mode === "primary",
"rounded border-none bg-transparent ring-0 transition-all focus:ring-1 focus:ring-custom-primary":
mode === "transparent",
"rounded border-none bg-transparent ring-0": mode === "true-transparent",
"border-red-500": hasError,
"px-1.5 py-1": inputSize === "xs",
"px-3 py-2": inputSize === "sm",
"p-3": inputSize === "md",
},
className
)}
autoComplete={autoComplete}
{...rest}
/>
);
});

Input.displayName = "form-input-field";

export { Input };
1 change: 1 addition & 0 deletions packages/propel/tsdown.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export default defineConfig({
"src/emoji-reaction/index.ts",
"src/emoji-reaction-picker/index.ts",
"src/icons/index.ts",
"src/input/index.ts",
"src/menu/index.ts",
"src/pill/index.ts",
"src/popover/index.ts",
Expand Down
Loading