Update text input component
This commit is contained in:
+152
-595
@@ -1,29 +1,14 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import Tooltip from "../components/Tooltip";
|
import TextInput from "../components/TextInput";
|
||||||
import Alert from "../components/Alert";
|
import SelectInput from "../components/SelectInput";
|
||||||
import Button from "../components/Button";
|
|
||||||
import Stepper from "../components/Stepper";
|
|
||||||
import Progress from "../components/Progress";
|
|
||||||
import Create from "../components/Create";
|
|
||||||
import Input from "../components/Input";
|
|
||||||
import InputWithCounter from "../components/InputWithCounter";
|
|
||||||
import IconCard from "../components/IconCard";
|
|
||||||
import { getAssetPath } from "../../lib/assetUtils";
|
|
||||||
|
|
||||||
export default function ComponentsPreview() {
|
export default function ComponentsPreview() {
|
||||||
const [alertVisible, setAlertVisible] = useState({
|
const [defaultInputValue, setDefaultInputValue] = useState("");
|
||||||
default: true,
|
const [activeInputValue, setActiveInputValue] = useState("");
|
||||||
positive: true,
|
const [errorInputValue, setErrorInputValue] = useState("");
|
||||||
warning: true,
|
const [selectValue, setSelectValue] = useState("");
|
||||||
danger: true,
|
|
||||||
banner: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
const [createOpen, setCreateOpen] = useState(false);
|
|
||||||
const [createStep, setCreateStep] = useState(1);
|
|
||||||
const [policyName, setPolicyName] = useState("");
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-[var(--color-surface-default-primary)] p-[var(--spacing-scale-032)]">
|
<div className="min-h-screen bg-[var(--color-surface-default-primary)] p-[var(--spacing-scale-032)]">
|
||||||
@@ -37,600 +22,172 @@ export default function ComponentsPreview() {
|
|||||||
</p>
|
</p>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
{/* Button Section */}
|
{/* Text Input Section */}
|
||||||
<section className="space-y-[var(--spacing-scale-024)]">
|
<section className="space-y-[var(--spacing-scale-024)]">
|
||||||
<h2 className="font-bricolage-grotesque text-[32px] leading-[40px] font-bold text-[var(--color-content-default-primary)]">
|
<h2 className="font-bricolage-grotesque text-[32px] leading-[40px] font-bold text-[var(--color-content-default-primary)]">
|
||||||
Button Component
|
Text Input Component
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div className="bg-[var(--color-surface-default-secondary)] rounded-[var(--radius-300,12px)] p-[var(--spacing-scale-032)] space-y-[var(--spacing-scale-024)]">
|
<div className="bg-[var(--color-surface-default-secondary)] rounded-[var(--radius-300,12px)] p-[var(--spacing-scale-032)] space-y-[var(--spacing-scale-024)]">
|
||||||
<div className="space-y-[var(--spacing-scale-016)]">
|
<div className="space-y-[var(--spacing-scale-016)]">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
||||||
All Variants
|
States
|
||||||
</h3>
|
</h3>
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-012)]">
|
|
||||||
<Button variant="filled" size="medium">
|
|
||||||
Filled
|
|
||||||
</Button>
|
|
||||||
<Button variant="filled-inverse" size="medium">
|
|
||||||
Filled Inverse
|
|
||||||
</Button>
|
|
||||||
<Button variant="outline" size="medium">
|
|
||||||
Outline
|
|
||||||
</Button>
|
|
||||||
<Button variant="outline-inverse" size="medium">
|
|
||||||
Outline Inverse
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost" size="medium">
|
|
||||||
Ghost
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost-inverse" size="medium">
|
|
||||||
Ghost Inverse
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger" size="medium">
|
|
||||||
Danger
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger-inverse" size="medium">
|
|
||||||
Danger Inverse
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
|
||||||
All Sizes - Danger Variant
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-012)] items-center">
|
|
||||||
<Button variant="danger" size="xsmall">
|
|
||||||
XSmall
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger" size="small">
|
|
||||||
Small
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger" size="medium">
|
|
||||||
Medium
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger" size="large">
|
|
||||||
Large
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger" size="xlarge">
|
|
||||||
XLarge
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
|
||||||
All Sizes - Danger Inverse Variant
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-012)] items-center">
|
|
||||||
<Button variant="danger-inverse" size="xsmall">
|
|
||||||
XSmall
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger-inverse" size="small">
|
|
||||||
Small
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger-inverse" size="medium">
|
|
||||||
Medium
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger-inverse" size="large">
|
|
||||||
Large
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger-inverse" size="xlarge">
|
|
||||||
XLarge
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
|
||||||
All Sizes - Ghost Variant
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-012)] items-center">
|
|
||||||
<Button variant="ghost" size="xsmall">
|
|
||||||
XSmall
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost" size="small">
|
|
||||||
Small
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost" size="medium">
|
|
||||||
Medium
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost" size="large">
|
|
||||||
Large
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost" size="xlarge">
|
|
||||||
XLarge
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
|
||||||
All Sizes - Ghost Inverse Variant
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-012)] items-center">
|
|
||||||
<Button variant="ghost-inverse" size="xsmall">
|
|
||||||
XSmall
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost-inverse" size="small">
|
|
||||||
Small
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost-inverse" size="medium">
|
|
||||||
Medium
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost-inverse" size="large">
|
|
||||||
Large
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost-inverse" size="xlarge">
|
|
||||||
XLarge
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
|
||||||
States - Danger Variant
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-012)]">
|
|
||||||
<Button variant="danger" size="medium">
|
|
||||||
Normal
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger" size="medium" disabled>
|
|
||||||
Disabled
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
|
||||||
States - Danger Inverse Variant
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-012)]">
|
|
||||||
<Button variant="danger-inverse" size="medium">
|
|
||||||
Normal
|
|
||||||
</Button>
|
|
||||||
<Button variant="danger-inverse" size="medium" disabled>
|
|
||||||
Disabled
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
|
||||||
States - Ghost Variant
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-012)]">
|
|
||||||
<Button variant="ghost" size="medium">
|
|
||||||
Normal
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost" size="medium" disabled>
|
|
||||||
Disabled
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
|
||||||
States - Ghost Inverse Variant
|
|
||||||
</h3>
|
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-012)]">
|
|
||||||
<Button variant="ghost-inverse" size="medium">
|
|
||||||
Normal
|
|
||||||
</Button>
|
|
||||||
<Button variant="ghost-inverse" size="medium" disabled>
|
|
||||||
Disabled
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Tooltip Section */}
|
|
||||||
<section className="space-y-[var(--spacing-scale-024)]">
|
|
||||||
<h2 className="font-bricolage-grotesque text-[32px] leading-[40px] font-bold text-[var(--color-content-default-primary)]">
|
|
||||||
Tooltip Component
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="bg-[var(--color-surface-default-secondary)] rounded-[var(--radius-300,12px)] p-[var(--spacing-scale-032)] space-y-[var(--spacing-scale-024)]">
|
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-024)] items-center">
|
|
||||||
<Tooltip text="Tooltip positioned at top" position="top">
|
|
||||||
<Button variant="filled" size="medium">
|
|
||||||
Hover me (Top)
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip text="Tooltip positioned at bottom" position="bottom">
|
|
||||||
<Button variant="filled-inverse" size="medium">
|
|
||||||
Hover me (Bottom)
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip text="Disabled tooltip" disabled>
|
|
||||||
<Button variant="ghost" size="medium">
|
|
||||||
Disabled Tooltip
|
|
||||||
</Button>
|
|
||||||
</Tooltip>
|
|
||||||
|
|
||||||
<Tooltip text="Tooltip with icon button" position="top">
|
|
||||||
<button className="p-[var(--spacing-scale-012)] rounded-full hover:bg-[var(--color-surface-default-tertiary)] transition-colors">
|
|
||||||
<svg
|
|
||||||
width="20"
|
|
||||||
height="20"
|
|
||||||
viewBox="0 0 20 20"
|
|
||||||
fill="none"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
>
|
|
||||||
<path
|
|
||||||
d="M10 9V11M10 15H10.01M19 10C19 14.9706 14.9706 19 10 19C5.02944 19 1 14.9706 1 10C1 5.02944 5.02944 1 10 1C14.9706 1 19 5.02944 19 10Z"
|
|
||||||
stroke="currentColor"
|
|
||||||
strokeWidth="2"
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
</button>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Alert Section */}
|
|
||||||
<section className="space-y-[var(--spacing-scale-024)]">
|
|
||||||
<h2 className="font-bricolage-grotesque text-[32px] leading-[40px] font-bold text-[var(--color-content-default-primary)]">
|
|
||||||
Alert Component
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="space-y-[var(--spacing-scale-024)]">
|
|
||||||
{/* Toast Alerts */}
|
|
||||||
<div className="bg-[var(--color-surface-default-secondary)] rounded-[var(--radius-300,12px)] p-[var(--spacing-scale-032)] space-y-[var(--spacing-scale-016)]">
|
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)]">
|
|
||||||
Toast Alerts
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
{alertVisible.default && (
|
|
||||||
<Alert
|
|
||||||
title="Short alert banner message goes here"
|
|
||||||
description="Nascetur ipsum a nisi tempor cras nam neque volutpat. Aliquam id est faucibus nunc quis. Eleifend suspendisse."
|
|
||||||
status="default"
|
|
||||||
type="toast"
|
|
||||||
onClose={() =>
|
|
||||||
setAlertVisible({ ...alertVisible, default: false })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{alertVisible.positive && (
|
|
||||||
<Alert
|
|
||||||
title="Short alert banner message goes here"
|
|
||||||
description="Nascetur ipsum a nisi tempor cras nam neque volutpat. Aliquam id est faucibus nunc quis. Eleifend suspendisse."
|
|
||||||
status="positive"
|
|
||||||
type="toast"
|
|
||||||
onClose={() =>
|
|
||||||
setAlertVisible({ ...alertVisible, positive: false })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{alertVisible.warning && (
|
|
||||||
<Alert
|
|
||||||
title="Short alert banner message goes here"
|
|
||||||
description="Nascetur ipsum a nisi tempor cras nam neque volutpat. Aliquam id est faucibus nunc quis. Eleifend suspendisse."
|
|
||||||
status="warning"
|
|
||||||
type="toast"
|
|
||||||
onClose={() =>
|
|
||||||
setAlertVisible({ ...alertVisible, warning: false })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{alertVisible.danger && (
|
|
||||||
<Alert
|
|
||||||
title="Short alert banner message goes here"
|
|
||||||
description="Nascetur ipsum a nisi tempor cras nam neque volutpat. Aliquam id est faucibus nunc quis. Eleifend suspendisse."
|
|
||||||
status="danger"
|
|
||||||
type="toast"
|
|
||||||
onClose={() =>
|
|
||||||
setAlertVisible({ ...alertVisible, danger: false })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Banner Alerts */}
|
|
||||||
<div className="bg-[var(--color-surface-default-secondary)] rounded-[var(--radius-300,12px)] p-[var(--spacing-scale-032)] space-y-[var(--spacing-scale-016)]">
|
|
||||||
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)]">
|
|
||||||
Banner Alerts
|
|
||||||
</h3>
|
|
||||||
|
|
||||||
{alertVisible.banner && (
|
|
||||||
<Alert
|
|
||||||
title="Short alert banner message goes here"
|
|
||||||
description="Nascetur ipsum a nisi tempor cras nam neque volutpat. Aliquam id est faucibus nunc quis. Eleifend suspendisse."
|
|
||||||
status="default"
|
|
||||||
type="banner"
|
|
||||||
onClose={() =>
|
|
||||||
setAlertVisible({ ...alertVisible, banner: false })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<Alert
|
|
||||||
title="Positive banner alert"
|
|
||||||
description="This is a positive banner message"
|
|
||||||
status="positive"
|
|
||||||
type="banner"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Alert
|
|
||||||
title="Warning banner alert"
|
|
||||||
description="This is a warning banner message"
|
|
||||||
status="warning"
|
|
||||||
type="banner"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<Alert
|
|
||||||
title="Danger banner alert"
|
|
||||||
description="This is a danger banner message"
|
|
||||||
status="danger"
|
|
||||||
type="banner"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Stepper Section */}
|
|
||||||
<section className="space-y-[var(--spacing-scale-024)]">
|
|
||||||
<h2 className="font-bricolage-grotesque text-[32px] leading-[40px] font-bold text-[var(--color-content-default-primary)]">
|
|
||||||
Stepper Component
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="bg-[var(--color-surface-default-secondary)] rounded-[var(--radius-300,12px)] p-[var(--spacing-scale-032)] space-y-[var(--spacing-scale-024)]">
|
|
||||||
<div className="space-y-[var(--spacing-scale-016)]">
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Step 1 of 5
|
|
||||||
</p>
|
|
||||||
<Stepper active={1} totalSteps={5} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Step 2 of 5
|
|
||||||
</p>
|
|
||||||
<Stepper active={2} totalSteps={5} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Step 3 of 5
|
|
||||||
</p>
|
|
||||||
<Stepper active={3} totalSteps={5} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Step 4 of 5
|
|
||||||
</p>
|
|
||||||
<Stepper active={4} totalSteps={5} />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Step 5 of 5
|
|
||||||
</p>
|
|
||||||
<Stepper active={5} totalSteps={5} />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Progress Section */}
|
|
||||||
<section className="space-y-[var(--spacing-scale-024)]">
|
|
||||||
<h2 className="font-bricolage-grotesque text-[32px] leading-[40px] font-bold text-[var(--color-content-default-primary)]">
|
|
||||||
Progress Component
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="bg-white rounded-[var(--radius-300,12px)] p-[var(--spacing-scale-032)] space-y-[var(--spacing-scale-024)]">
|
|
||||||
<div className="space-y-[var(--spacing-scale-016)]">
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 1-0
|
|
||||||
</p>
|
|
||||||
<Progress progress="1-0" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 1-1
|
|
||||||
</p>
|
|
||||||
<Progress progress="1-1" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 1-2
|
|
||||||
</p>
|
|
||||||
<Progress progress="1-2" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 1-3
|
|
||||||
</p>
|
|
||||||
<Progress progress="1-3" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 1-4
|
|
||||||
</p>
|
|
||||||
<Progress progress="1-4" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 1-5
|
|
||||||
</p>
|
|
||||||
<Progress progress="1-5" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 2-0
|
|
||||||
</p>
|
|
||||||
<Progress progress="2-0" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 2-1
|
|
||||||
</p>
|
|
||||||
<Progress progress="2-1" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 2-2
|
|
||||||
</p>
|
|
||||||
<Progress progress="2-2" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 3-0
|
|
||||||
</p>
|
|
||||||
<Progress progress="3-0" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 3-1
|
|
||||||
</p>
|
|
||||||
<Progress progress="3-1" />
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)] mb-[var(--spacing-scale-008)]">
|
|
||||||
Progress: 3-2
|
|
||||||
</p>
|
|
||||||
<Progress progress="3-2" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Create Component Section */}
|
|
||||||
<section className="space-y-[var(--spacing-scale-024)]">
|
|
||||||
<h2 className="font-bricolage-grotesque text-[32px] leading-[40px] font-bold text-[var(--color-content-default-primary)]">
|
|
||||||
Create Component
|
|
||||||
</h2>
|
|
||||||
|
|
||||||
<div className="bg-[var(--color-surface-default-secondary)] rounded-[var(--radius-300,12px)] p-[var(--spacing-scale-032)] space-y-[var(--spacing-scale-024)]">
|
|
||||||
<div className="space-y-[var(--spacing-scale-016)]">
|
|
||||||
<Button
|
|
||||||
variant="filled-inverse"
|
|
||||||
size="medium"
|
|
||||||
onClick={() => setCreateOpen(true)}
|
|
||||||
>
|
|
||||||
Open Create Dialog
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<div className="space-y-[var(--spacing-scale-008)]">
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)]">
|
|
||||||
Step {createStep} of 3
|
|
||||||
</p>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="small"
|
|
||||||
onClick={() => setCreateStep((prev) => Math.max(1, prev - 1))}
|
|
||||||
disabled={createStep === 1}
|
|
||||||
>
|
|
||||||
Previous Step
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="small"
|
|
||||||
onClick={() => setCreateStep((prev) => Math.min(3, prev + 1))}
|
|
||||||
disabled={createStep === 3}
|
|
||||||
>
|
|
||||||
Next Step
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Create
|
|
||||||
isOpen={createOpen}
|
|
||||||
onClose={() => setCreateOpen(false)}
|
|
||||||
title={
|
|
||||||
createStep === 1
|
|
||||||
? "What do you call your group's new policy?"
|
|
||||||
: createStep === 2
|
|
||||||
? "How should conflicts be resolved?"
|
|
||||||
: "Review your policy"
|
|
||||||
}
|
|
||||||
description="You can also combine or add new approaches to the list"
|
|
||||||
showBackButton={true}
|
|
||||||
showNextButton={true}
|
|
||||||
onBack={() => setCreateStep((prev) => Math.max(1, prev - 1))}
|
|
||||||
onNext={() => setCreateStep((prev) => Math.min(3, prev + 1))}
|
|
||||||
backButtonText="Back"
|
|
||||||
nextButtonText={createStep === 3 ? "Finish" : "Next"}
|
|
||||||
nextButtonDisabled={createStep === 1 && !policyName.trim()}
|
|
||||||
currentStep={createStep}
|
|
||||||
totalSteps={3}
|
|
||||||
>
|
|
||||||
<div className="space-y-[var(--spacing-scale-024)]">
|
|
||||||
{createStep === 1 && (
|
|
||||||
<InputWithCounter
|
|
||||||
label="Label"
|
|
||||||
placeholder="Policy name"
|
|
||||||
value={policyName}
|
|
||||||
onChange={setPolicyName}
|
|
||||||
maxLength={48}
|
|
||||||
showHelpIcon
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{createStep === 2 && (
|
|
||||||
<div className="space-y-[var(--spacing-scale-008)]">
|
|
||||||
<Input
|
|
||||||
label="Conflict Resolution Method"
|
|
||||||
placeholder="Enter method"
|
|
||||||
value=""
|
|
||||||
/>
|
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-primary)]">
|
|
||||||
Select how conflicts should be resolved in your group.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{createStep === 3 && (
|
|
||||||
<div className="space-y-[var(--spacing-scale-016)]">
|
<div className="space-y-[var(--spacing-scale-016)]">
|
||||||
<p className="font-inter text-[16px] leading-[24px] text-[var(--color-content-default-primary)]">
|
<TextInput
|
||||||
Review your policy configuration before finalizing.
|
label="Default Text Input"
|
||||||
</p>
|
placeholder="Enter text"
|
||||||
<div className="bg-[var(--color-surface-default-secondary)] rounded-[var(--radius-200,8px)] p-[var(--spacing-scale-016)]">
|
value={defaultInputValue}
|
||||||
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)]">
|
onChange={(e) => setDefaultInputValue(e.target.value)}
|
||||||
Policy details will appear here
|
/>
|
||||||
</p>
|
<TextInput
|
||||||
</div>
|
label="Interactive Text Input (click = active, tab = focus)"
|
||||||
|
placeholder="Enter text"
|
||||||
|
value={activeInputValue}
|
||||||
|
onChange={(e) => setActiveInputValue(e.target.value)}
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Disabled Text Input"
|
||||||
|
placeholder="Enter text"
|
||||||
|
value=""
|
||||||
|
disabled
|
||||||
|
/>
|
||||||
|
<TextInput
|
||||||
|
label="Error Text Input"
|
||||||
|
placeholder="Enter text"
|
||||||
|
value={errorInputValue}
|
||||||
|
onChange={(e) => setErrorInputValue(e.target.value)}
|
||||||
|
error
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</Create>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* IconCard Component Section */}
|
{/* Select Input Section */}
|
||||||
<section className="space-y-[var(--spacing-scale-024)]">
|
<section className="space-y-[var(--spacing-scale-024)]">
|
||||||
<h2 className="font-bricolage-grotesque text-[32px] leading-[40px] font-bold text-[var(--color-content-default-primary)]">
|
<h2 className="font-bricolage-grotesque text-[32px] leading-[40px] font-bold text-[var(--color-content-default-primary)]">
|
||||||
IconCard Component
|
Select Input Component
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<div className="bg-[var(--color-surface-default-secondary)] rounded-[var(--radius-300,12px)] p-[var(--spacing-scale-032)] space-y-[var(--spacing-scale-024)]">
|
<div className="bg-[var(--color-surface-default-secondary)] rounded-[var(--radius-300,12px)] p-[var(--spacing-scale-032)] space-y-[var(--spacing-scale-024)]">
|
||||||
<div className="flex flex-wrap gap-[var(--spacing-scale-024)]">
|
<div className="space-y-[var(--spacing-scale-016)]">
|
||||||
<IconCard
|
<div>
|
||||||
icon={
|
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
||||||
<img
|
All Sizes
|
||||||
src={getAssetPath("assets/Vector_WorkerCoop.svg")}
|
</h3>
|
||||||
alt=""
|
<div className="space-y-[var(--spacing-scale-016)]">
|
||||||
className="w-[36px] h-[36px]"
|
<SelectInput
|
||||||
width="36"
|
label="Small Select Input"
|
||||||
height="36"
|
placeholder="Choose an option"
|
||||||
|
size="small"
|
||||||
|
value={selectValue}
|
||||||
|
onChange={(data) => setSelectValue(data.target.value)}
|
||||||
|
options={[
|
||||||
|
{ value: "option1", label: "Option 1" },
|
||||||
|
{ value: "option2", label: "Option 2" },
|
||||||
|
{ value: "option3", label: "Option 3" },
|
||||||
|
]}
|
||||||
/>
|
/>
|
||||||
}
|
<SelectInput
|
||||||
title="Worker's cooperatives"
|
label="Medium Select Input"
|
||||||
description="Employee-owned businesses often need to clarify how power is shared, decisions are made, and how processes operate within their organizations."
|
placeholder="Choose an option"
|
||||||
onClick={() => {
|
size="medium"
|
||||||
// IconCard clicked handler
|
value={selectValue}
|
||||||
}}
|
onChange={(data) => setSelectValue(data.target.value)}
|
||||||
/>
|
options={[
|
||||||
|
{ value: "option1", label: "Option 1" },
|
||||||
|
{ value: "option2", label: "Option 2" },
|
||||||
|
{ value: "option3", label: "Option 3" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<SelectInput
|
||||||
|
label="Large Select Input"
|
||||||
|
placeholder="Choose an option"
|
||||||
|
size="large"
|
||||||
|
value={selectValue}
|
||||||
|
onChange={(data) => setSelectValue(data.target.value)}
|
||||||
|
options={[
|
||||||
|
{ value: "option1", label: "Option 1" },
|
||||||
|
{ value: "option2", label: "Option 2" },
|
||||||
|
{ value: "option3", label: "Option 3" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
||||||
|
States
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-[var(--spacing-scale-016)]">
|
||||||
|
<SelectInput
|
||||||
|
label="Default Select Input"
|
||||||
|
placeholder="Choose an option"
|
||||||
|
value=""
|
||||||
|
options={[
|
||||||
|
{ value: "option1", label: "Option 1" },
|
||||||
|
{ value: "option2", label: "Option 2" },
|
||||||
|
{ value: "option3", label: "Option 3" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<SelectInput
|
||||||
|
label="Disabled Select Input"
|
||||||
|
placeholder="Choose an option"
|
||||||
|
value=""
|
||||||
|
disabled
|
||||||
|
options={[
|
||||||
|
{ value: "option1", label: "Option 1" },
|
||||||
|
{ value: "option2", label: "Option 2" },
|
||||||
|
{ value: "option3", label: "Option 3" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<SelectInput
|
||||||
|
label="Error Select Input"
|
||||||
|
placeholder="Choose an option"
|
||||||
|
value=""
|
||||||
|
error
|
||||||
|
options={[
|
||||||
|
{ value: "option1", label: "Option 1" },
|
||||||
|
{ value: "option2", label: "Option 2" },
|
||||||
|
{ value: "option3", label: "Option 3" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h3 className="font-inter text-[20px] leading-[24px] font-semibold text-[var(--color-content-default-primary)] mb-[var(--spacing-scale-012)]">
|
||||||
|
Label Variants
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-[var(--spacing-scale-016)]">
|
||||||
|
<SelectInput
|
||||||
|
label="Default Label"
|
||||||
|
placeholder="Choose an option"
|
||||||
|
value=""
|
||||||
|
labelVariant="default"
|
||||||
|
options={[
|
||||||
|
{ value: "option1", label: "Option 1" },
|
||||||
|
{ value: "option2", label: "Option 2" },
|
||||||
|
{ value: "option3", label: "Option 3" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<SelectInput
|
||||||
|
label="Horizontal Label"
|
||||||
|
placeholder="Choose an option"
|
||||||
|
value=""
|
||||||
|
labelVariant="horizontal"
|
||||||
|
options={[
|
||||||
|
{ value: "option1", label: "Option 1" },
|
||||||
|
{ value: "option2", label: "Option 2" },
|
||||||
|
{ value: "option3", label: "Option 3" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
@@ -1,176 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { memo, forwardRef } from "react";
|
|
||||||
import { useComponentId, useFormField } from "../../hooks";
|
|
||||||
import { InputView } from "./Input.view";
|
|
||||||
import type { InputProps } from "./Input.types";
|
|
||||||
|
|
||||||
const InputContainer = forwardRef<HTMLInputElement, InputProps>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
size = "medium",
|
|
||||||
labelVariant = "default",
|
|
||||||
state = "default",
|
|
||||||
disabled = false,
|
|
||||||
error = false,
|
|
||||||
label,
|
|
||||||
placeholder,
|
|
||||||
value,
|
|
||||||
onChange,
|
|
||||||
onFocus,
|
|
||||||
onBlur,
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
type = "text",
|
|
||||||
className = "",
|
|
||||||
...props
|
|
||||||
},
|
|
||||||
ref,
|
|
||||||
) => {
|
|
||||||
// Generate unique ID for accessibility if not provided
|
|
||||||
const { id: inputId, labelId } = useComponentId("input", id);
|
|
||||||
|
|
||||||
// Size variants
|
|
||||||
const sizeStyles: Record<
|
|
||||||
string,
|
|
||||||
{
|
|
||||||
input: string;
|
|
||||||
label: string;
|
|
||||||
container: string;
|
|
||||||
radius: string;
|
|
||||||
}
|
|
||||||
> = {
|
|
||||||
small: {
|
|
||||||
input:
|
|
||||||
labelVariant === "horizontal"
|
|
||||||
? "h-[30px] px-[12px] py-[8px] text-[10px]"
|
|
||||||
: "h-[32px] px-[12px] py-[8px] text-[10px]",
|
|
||||||
label: "text-[12px] leading-[14px] font-medium",
|
|
||||||
container: "gap-[4px]",
|
|
||||||
radius: "var(--measures-radius-small)",
|
|
||||||
},
|
|
||||||
medium: {
|
|
||||||
input: "h-[36px] px-[12px] py-[8px] text-[14px] leading-[20px]",
|
|
||||||
label: "text-[14px] leading-[16px] font-medium",
|
|
||||||
container: "gap-[8px]",
|
|
||||||
radius: "var(--measures-radius-medium)",
|
|
||||||
},
|
|
||||||
large: {
|
|
||||||
input: "h-[40px] px-[12px] py-[8px] text-[16px] leading-[24px]",
|
|
||||||
label: "text-[16px] leading-[20px] font-medium",
|
|
||||||
container: "gap-[12px]",
|
|
||||||
radius: "var(--measures-radius-large)",
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// State styles
|
|
||||||
const getStateStyles = (): {
|
|
||||||
input: string;
|
|
||||||
label: string;
|
|
||||||
} => {
|
|
||||||
if (disabled) {
|
|
||||||
return {
|
|
||||||
input:
|
|
||||||
"bg-[var(--color-content-default-secondary)] text-[var(--color-content-default-primary)] border border-[var(--color-border-default-tertiary)] cursor-not-allowed",
|
|
||||||
label: "text-[var(--color-content-default-secondary)]",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
return {
|
|
||||||
input:
|
|
||||||
"bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)] border border-[var(--color-border-default-utility-negative)]",
|
|
||||||
label: "text-[var(--color-content-default-secondary)]",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (state) {
|
|
||||||
case "active":
|
|
||||||
return {
|
|
||||||
input:
|
|
||||||
"bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)] border border-[var(--color-border-default-tertiary)]",
|
|
||||||
label: "text-[var(--color-content-default-secondary)]",
|
|
||||||
};
|
|
||||||
case "hover":
|
|
||||||
return {
|
|
||||||
input:
|
|
||||||
"bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)] border border-[var(--color-border-default-tertiary)] shadow-[0_0_0_2px_var(--color-border-default-tertiary)]",
|
|
||||||
label: "text-[var(--color-content-default-secondary)]",
|
|
||||||
};
|
|
||||||
case "focus":
|
|
||||||
return {
|
|
||||||
input:
|
|
||||||
"bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)] border border-[var(--color-border-default-utility-info)] shadow-[0_0_5px_3px_#3281F8]",
|
|
||||||
label: "text-[var(--color-content-default-secondary)]",
|
|
||||||
};
|
|
||||||
default:
|
|
||||||
return {
|
|
||||||
input:
|
|
||||||
"bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)] border border-[var(--color-border-default-tertiary)] hover:shadow-[0_0_0_2px_var(--color-border-default-tertiary)]",
|
|
||||||
label: "text-[var(--color-content-default-secondary)]",
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const stateStyles = getStateStyles();
|
|
||||||
const currentSize = sizeStyles[size];
|
|
||||||
|
|
||||||
// Container classes based on label variant
|
|
||||||
const containerClasses =
|
|
||||||
labelVariant === "horizontal"
|
|
||||||
? `flex items-center gap-[12px]`
|
|
||||||
: `flex flex-col ${currentSize.container}`;
|
|
||||||
|
|
||||||
const labelClasses =
|
|
||||||
labelVariant === "horizontal"
|
|
||||||
? `${currentSize.label} font-inter min-w-fit`
|
|
||||||
: `${currentSize.label} font-inter`;
|
|
||||||
|
|
||||||
const inputClasses = `
|
|
||||||
w-full border transition-all duration-200 ease-in-out
|
|
||||||
focus:outline-none focus:ring-0
|
|
||||||
${currentSize.input}
|
|
||||||
${stateStyles.input}
|
|
||||||
${className}
|
|
||||||
`.trim();
|
|
||||||
|
|
||||||
// Form field handlers with disabled state handling
|
|
||||||
const { handleChange, handleFocus, handleBlur } =
|
|
||||||
useFormField<HTMLInputElement>(disabled, {
|
|
||||||
onChange,
|
|
||||||
onFocus,
|
|
||||||
onBlur,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<InputView
|
|
||||||
ref={ref}
|
|
||||||
inputId={inputId}
|
|
||||||
labelId={labelId}
|
|
||||||
size={size}
|
|
||||||
labelVariant={labelVariant}
|
|
||||||
state={state}
|
|
||||||
disabled={disabled}
|
|
||||||
error={error}
|
|
||||||
label={label}
|
|
||||||
placeholder={placeholder}
|
|
||||||
value={value}
|
|
||||||
name={name}
|
|
||||||
type={type}
|
|
||||||
className={className}
|
|
||||||
containerClasses={containerClasses}
|
|
||||||
labelClasses={labelClasses}
|
|
||||||
inputClasses={inputClasses}
|
|
||||||
borderRadius={currentSize.radius}
|
|
||||||
handleChange={handleChange}
|
|
||||||
handleFocus={handleFocus}
|
|
||||||
handleBlur={handleBlur}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
InputContainer.displayName = "Input";
|
|
||||||
|
|
||||||
export default memo(InputContainer);
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
import { forwardRef } from "react";
|
|
||||||
import type { InputViewProps } from "./Input.types";
|
|
||||||
|
|
||||||
export const InputView = forwardRef<HTMLInputElement, InputViewProps>(
|
|
||||||
(
|
|
||||||
{
|
|
||||||
inputId,
|
|
||||||
labelId,
|
|
||||||
label,
|
|
||||||
placeholder,
|
|
||||||
value,
|
|
||||||
name,
|
|
||||||
type,
|
|
||||||
disabled,
|
|
||||||
size: _size,
|
|
||||||
labelVariant: _labelVariant,
|
|
||||||
state: _state,
|
|
||||||
error: _error,
|
|
||||||
className: _className,
|
|
||||||
containerClasses,
|
|
||||||
labelClasses,
|
|
||||||
inputClasses,
|
|
||||||
borderRadius,
|
|
||||||
handleChange,
|
|
||||||
handleFocus,
|
|
||||||
handleBlur,
|
|
||||||
},
|
|
||||||
ref,
|
|
||||||
) => {
|
|
||||||
return (
|
|
||||||
<div className={containerClasses}>
|
|
||||||
{label && (
|
|
||||||
<label
|
|
||||||
id={labelId}
|
|
||||||
htmlFor={inputId}
|
|
||||||
className={`${labelClasses} font-inter font-medium text-[var(--color-content-default-secondary)]`}
|
|
||||||
>
|
|
||||||
{label}
|
|
||||||
</label>
|
|
||||||
)}
|
|
||||||
<div className={disabled ? "opacity-40" : ""}>
|
|
||||||
<input
|
|
||||||
ref={ref}
|
|
||||||
id={inputId}
|
|
||||||
name={name}
|
|
||||||
type={type}
|
|
||||||
value={value}
|
|
||||||
placeholder={placeholder}
|
|
||||||
onChange={handleChange}
|
|
||||||
onFocus={handleFocus}
|
|
||||||
onBlur={handleBlur}
|
|
||||||
disabled={disabled}
|
|
||||||
className={inputClasses}
|
|
||||||
style={{ borderRadius }}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
InputView.displayName = "InputView";
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export { default } from "./Input.container";
|
|
||||||
export type { InputProps } from "./Input.types";
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
export { default } from "./Select.container";
|
|
||||||
export type { SelectProps, SelectOptionData } from "./Select.types";
|
|
||||||
+7
-7
@@ -14,10 +14,10 @@ import React, {
|
|||||||
useEffect,
|
useEffect,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { useClickOutside } from "../../hooks";
|
import { useClickOutside } from "../../hooks";
|
||||||
import { SelectView } from "./Select.view";
|
import { SelectInputView } from "./SelectInput.view";
|
||||||
import type { SelectProps } from "./Select.types";
|
import type { SelectInputProps } from "./SelectInput.types";
|
||||||
|
|
||||||
const SelectContainer = forwardRef<HTMLButtonElement, SelectProps>(
|
const SelectInputContainer = forwardRef<HTMLButtonElement, SelectInputProps>(
|
||||||
(
|
(
|
||||||
{
|
{
|
||||||
id,
|
id,
|
||||||
@@ -38,7 +38,7 @@ const SelectContainer = forwardRef<HTMLButtonElement, SelectProps>(
|
|||||||
ref,
|
ref,
|
||||||
) => {
|
) => {
|
||||||
const generatedId = useId();
|
const generatedId = useId();
|
||||||
const selectId = id || `select-${generatedId}`;
|
const selectId = id || `select-input-${generatedId}`;
|
||||||
const labelId = `${selectId}-label`;
|
const labelId = `${selectId}-label`;
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
const [selectedValue, setSelectedValue] = useState(value || "");
|
const [selectedValue, setSelectedValue] = useState(value || "");
|
||||||
@@ -267,7 +267,7 @@ const SelectContainer = forwardRef<HTMLButtonElement, SelectProps>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SelectView
|
<SelectInputView
|
||||||
label={label}
|
label={label}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
size={size}
|
size={size}
|
||||||
@@ -299,6 +299,6 @@ const SelectContainer = forwardRef<HTMLButtonElement, SelectProps>(
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
SelectContainer.displayName = "Select";
|
SelectInputContainer.displayName = "SelectInput";
|
||||||
|
|
||||||
export default memo(SelectContainer);
|
export default memo(SelectInputContainer);
|
||||||
+1
-1
@@ -5,7 +5,7 @@ export interface SelectOptionData {
|
|||||||
label: string;
|
label: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SelectProps {
|
export interface SelectInputProps {
|
||||||
id?: string;
|
id?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
labelVariant?: "default" | "horizontal";
|
labelVariant?: "default" | "horizontal";
|
||||||
+4
-4
@@ -1,9 +1,9 @@
|
|||||||
import React, { Children, type ReactNode } from "react";
|
import React, { Children, type ReactNode } from "react";
|
||||||
import SelectDropdown from "../SelectDropdown";
|
import SelectDropdown from "../SelectDropdown";
|
||||||
import SelectOption from "../SelectOption";
|
import SelectOption from "../SelectOption";
|
||||||
import type { SelectOptionData } from "./Select.types";
|
import type { SelectOptionData } from "./SelectInput.types";
|
||||||
|
|
||||||
export interface SelectViewProps {
|
export interface SelectInputViewProps {
|
||||||
label?: string;
|
label?: string;
|
||||||
placeholder: string;
|
placeholder: string;
|
||||||
size: "small" | "medium" | "large";
|
size: "small" | "medium" | "large";
|
||||||
@@ -36,7 +36,7 @@ export interface SelectViewProps {
|
|||||||
ariaInvalid?: boolean;
|
ariaInvalid?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function SelectView({
|
export function SelectInputView({
|
||||||
label,
|
label,
|
||||||
placeholder: _placeholder,
|
placeholder: _placeholder,
|
||||||
size,
|
size,
|
||||||
@@ -62,7 +62,7 @@ export function SelectView({
|
|||||||
ariaLabelledby,
|
ariaLabelledby,
|
||||||
ariaInvalid,
|
ariaInvalid,
|
||||||
...props
|
...props
|
||||||
}: SelectViewProps) {
|
}: SelectInputViewProps) {
|
||||||
return (
|
return (
|
||||||
<div className={containerClasses}>
|
<div className={containerClasses}>
|
||||||
{label && (
|
{label && (
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export { default } from "./SelectInput.container";
|
||||||
|
export type { SelectInputProps, SelectOptionData } from "./SelectInput.types";
|
||||||
@@ -0,0 +1,227 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { memo, forwardRef, useState, useRef } from "react";
|
||||||
|
import { useComponentId, useFormField } from "../../hooks";
|
||||||
|
import { TextInputView } from "./TextInput.view";
|
||||||
|
import type { TextInputProps } from "./TextInput.types";
|
||||||
|
|
||||||
|
const TextInputContainer = forwardRef<HTMLInputElement, TextInputProps>(
|
||||||
|
(
|
||||||
|
{
|
||||||
|
state: externalState = "default",
|
||||||
|
disabled = false,
|
||||||
|
error = false,
|
||||||
|
label,
|
||||||
|
placeholder,
|
||||||
|
value,
|
||||||
|
onChange,
|
||||||
|
onFocus,
|
||||||
|
onBlur,
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
type = "text",
|
||||||
|
className = "",
|
||||||
|
showHelpIcon = true,
|
||||||
|
...props
|
||||||
|
},
|
||||||
|
ref,
|
||||||
|
) => {
|
||||||
|
// Generate unique ID for accessibility if not provided
|
||||||
|
const { id: inputId, labelId } = useComponentId("text-input", id);
|
||||||
|
|
||||||
|
// Internal state management: track if focused and how (mouse vs keyboard)
|
||||||
|
const [isFocused, setIsFocused] = useState(false);
|
||||||
|
const [focusMethod, setFocusMethod] = useState<"mouse" | "keyboard" | null>(null);
|
||||||
|
const wasMouseDownRef = useRef(false);
|
||||||
|
|
||||||
|
// Determine if we should auto-manage focus (only when state is "default" or undefined)
|
||||||
|
// If state is "active", "hover", or "focus", respect it and don't override
|
||||||
|
const shouldAutoManageFocus = externalState === "default" || externalState === undefined;
|
||||||
|
|
||||||
|
// Determine actual state:
|
||||||
|
// - Active: when clicked (mouse focus)
|
||||||
|
// - Focus: when tabbed (keyboard focus)
|
||||||
|
// - Default: when not focused
|
||||||
|
const actualState = shouldAutoManageFocus
|
||||||
|
? isFocused
|
||||||
|
? focusMethod === "mouse"
|
||||||
|
? "active"
|
||||||
|
: "focus"
|
||||||
|
: "default"
|
||||||
|
: externalState;
|
||||||
|
|
||||||
|
// Determine if input is filled (has value)
|
||||||
|
const isFilled = Boolean(value && value.trim().length > 0);
|
||||||
|
|
||||||
|
// Fixed size styles (medium only per Figma designs)
|
||||||
|
const sizeStyles = {
|
||||||
|
input: "h-[40px] px-[12px] py-[8px] text-[16px]",
|
||||||
|
label: "text-[14px] leading-[20px] font-medium",
|
||||||
|
container: "gap-[8px]",
|
||||||
|
radius: "var(--measures-radius-200,8px)",
|
||||||
|
};
|
||||||
|
|
||||||
|
// State styles based on Figma designs
|
||||||
|
const getStateStyles = (): {
|
||||||
|
input: string;
|
||||||
|
label: string;
|
||||||
|
inputWrapper: string;
|
||||||
|
focusRing: string;
|
||||||
|
} => {
|
||||||
|
if (disabled) {
|
||||||
|
return {
|
||||||
|
input:
|
||||||
|
"bg-[var(--color-surface-default-secondary)] text-[var(--color-content-inverse-tertiary,#2d2d2d)] border border-solid border-[var(--color-border-default-primary)] cursor-not-allowed",
|
||||||
|
label: "text-[var(--color-content-default-secondary)]",
|
||||||
|
inputWrapper: "relative",
|
||||||
|
focusRing: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (error) {
|
||||||
|
const filledStyles = isFilled
|
||||||
|
? "font-medium leading-[20px]"
|
||||||
|
: "font-normal leading-[24px]";
|
||||||
|
return {
|
||||||
|
input: `bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)] border-2 border-solid border-[var(--color-border-default-utility-negative)] ${filledStyles}`,
|
||||||
|
label: "text-[var(--color-content-default-secondary)]",
|
||||||
|
inputWrapper: "relative",
|
||||||
|
focusRing: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (actualState) {
|
||||||
|
case "active": {
|
||||||
|
const filledStyles = isFilled
|
||||||
|
? "font-medium leading-[20px]"
|
||||||
|
: "font-normal leading-[24px]";
|
||||||
|
return {
|
||||||
|
input: `bg-[var(--color-surface-default-primary)] text-[var(--color-content-default-primary)] border-2 border-solid border-[var(--color-border-default-tertiary)] ${filledStyles}`,
|
||||||
|
label: "text-[var(--color-content-default-secondary)]",
|
||||||
|
inputWrapper: "relative",
|
||||||
|
focusRing: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
case "focus": {
|
||||||
|
const filledStyles = isFilled
|
||||||
|
? "font-medium leading-[20px]"
|
||||||
|
: "font-normal leading-[24px]";
|
||||||
|
return {
|
||||||
|
input: `bg-[var(--color-surface-default-secondary)] text-[var(--color-content-default-primary)] border border-solid border-[var(--color-border-default-tertiary)] ${filledStyles}`,
|
||||||
|
label: "text-[var(--color-content-default-secondary)]",
|
||||||
|
inputWrapper: "relative",
|
||||||
|
focusRing:
|
||||||
|
"absolute border-2 border-solid border-[var(--color-border-inverse-primary)] inset-0 rounded-[var(--measures-radius-200,8px)] shadow-[0px_0px_0px_2px_var(--color-border-default-primary)] pointer-events-none",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
const filledStyles = isFilled
|
||||||
|
? "font-medium leading-[20px]"
|
||||||
|
: "font-normal leading-[24px]";
|
||||||
|
// Default state uses primary border (matches Figma - border color same as background, so border is subtle)
|
||||||
|
return {
|
||||||
|
input: `bg-[var(--color-surface-default-secondary)] text-[var(--color-content-default-primary)] border border-solid border-[var(--color-border-default-primary)] ${filledStyles}`,
|
||||||
|
label: "text-[var(--color-content-default-secondary)]",
|
||||||
|
inputWrapper: "relative",
|
||||||
|
focusRing: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stateStyles = getStateStyles();
|
||||||
|
|
||||||
|
// Container classes (default label variant only)
|
||||||
|
const containerClasses = `flex flex-col ${sizeStyles.container}`;
|
||||||
|
|
||||||
|
const labelClasses = `${sizeStyles.label} font-inter`;
|
||||||
|
|
||||||
|
// Base classes without border (border is added in state styles)
|
||||||
|
const inputClasses = `
|
||||||
|
w-full transition-all duration-200 ease-in-out
|
||||||
|
focus:outline-none focus:ring-0
|
||||||
|
placeholder:text-[var(--color-content-default-tertiary,#b4b4b4)]
|
||||||
|
${sizeStyles.input}
|
||||||
|
${stateStyles.input}
|
||||||
|
${className}
|
||||||
|
`.trim();
|
||||||
|
|
||||||
|
// Text color for filled text (placeholder color is handled above)
|
||||||
|
const textColorClass = isFilled
|
||||||
|
? "text-[var(--color-content-default-primary)]"
|
||||||
|
: "text-[var(--color-content-default-tertiary,#b4b4b4)]";
|
||||||
|
|
||||||
|
// Form field handlers with disabled state handling
|
||||||
|
const { handleChange, handleBlur } = useFormField<HTMLInputElement>(disabled, {
|
||||||
|
onChange,
|
||||||
|
onBlur: (e) => {
|
||||||
|
if (shouldAutoManageFocus) {
|
||||||
|
setIsFocused(false);
|
||||||
|
setFocusMethod(null);
|
||||||
|
wasMouseDownRef.current = false;
|
||||||
|
}
|
||||||
|
onBlur?.(e);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle mouse down to detect mouse clicks
|
||||||
|
const handleMouseDown = () => {
|
||||||
|
if (!disabled && shouldAutoManageFocus) {
|
||||||
|
wasMouseDownRef.current = true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Custom focus handler to detect mouse vs keyboard
|
||||||
|
const handleFocus = (e: React.FocusEvent<HTMLInputElement>) => {
|
||||||
|
if (disabled) return;
|
||||||
|
|
||||||
|
// Detect if focus came from keyboard (Tab) or mouse (click)
|
||||||
|
// If mouseDown was detected before focus, it's a mouse click (active)
|
||||||
|
// Otherwise, it's keyboard navigation (focus)
|
||||||
|
const method = wasMouseDownRef.current ? "mouse" : "keyboard";
|
||||||
|
|
||||||
|
if (shouldAutoManageFocus) {
|
||||||
|
setIsFocused(true);
|
||||||
|
setFocusMethod(method);
|
||||||
|
// Reset mouse down flag after focus is processed
|
||||||
|
wasMouseDownRef.current = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
onFocus?.(e);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<TextInputView
|
||||||
|
ref={ref}
|
||||||
|
inputId={inputId}
|
||||||
|
labelId={labelId}
|
||||||
|
state={actualState}
|
||||||
|
disabled={disabled}
|
||||||
|
error={error}
|
||||||
|
label={label}
|
||||||
|
placeholder={placeholder}
|
||||||
|
value={value}
|
||||||
|
name={name}
|
||||||
|
type={type}
|
||||||
|
className={className}
|
||||||
|
containerClasses={containerClasses}
|
||||||
|
labelClasses={labelClasses}
|
||||||
|
inputClasses={`${inputClasses} ${textColorClass}`}
|
||||||
|
borderRadius={sizeStyles.radius}
|
||||||
|
handleChange={handleChange}
|
||||||
|
handleFocus={handleFocus}
|
||||||
|
handleBlur={handleBlur}
|
||||||
|
handleMouseDown={handleMouseDown}
|
||||||
|
showHelpIcon={showHelpIcon}
|
||||||
|
isFilled={isFilled}
|
||||||
|
inputWrapperClasses={stateStyles.inputWrapper}
|
||||||
|
focusRingClasses={stateStyles.focusRing}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
TextInputContainer.displayName = "TextInput";
|
||||||
|
|
||||||
|
export default memo(TextInputContainer);
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
export interface InputProps extends Omit<
|
export interface TextInputProps extends Omit<
|
||||||
React.InputHTMLAttributes<HTMLInputElement>,
|
React.InputHTMLAttributes<HTMLInputElement>,
|
||||||
"size" | "onChange" | "onFocus" | "onBlur"
|
"size" | "onChange" | "onFocus" | "onBlur"
|
||||||
> {
|
> {
|
||||||
size?: "small" | "medium" | "large";
|
|
||||||
labelVariant?: "default" | "horizontal";
|
|
||||||
state?: "default" | "active" | "hover" | "focus";
|
state?: "default" | "active" | "hover" | "focus";
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
error?: boolean;
|
error?: boolean;
|
||||||
@@ -14,13 +12,12 @@ export interface InputProps extends Omit<
|
|||||||
onFocus?: (_e: React.FocusEvent<HTMLInputElement>) => void;
|
onFocus?: (_e: React.FocusEvent<HTMLInputElement>) => void;
|
||||||
onBlur?: (_e: React.FocusEvent<HTMLInputElement>) => void;
|
onBlur?: (_e: React.FocusEvent<HTMLInputElement>) => void;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
showHelpIcon?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InputViewProps {
|
export interface TextInputViewProps {
|
||||||
inputId: string;
|
inputId: string;
|
||||||
labelId: string;
|
labelId: string;
|
||||||
size: "small" | "medium" | "large";
|
|
||||||
labelVariant: "default" | "horizontal";
|
|
||||||
state: "default" | "active" | "hover" | "focus";
|
state: "default" | "active" | "hover" | "focus";
|
||||||
disabled: boolean;
|
disabled: boolean;
|
||||||
error: boolean;
|
error: boolean;
|
||||||
@@ -37,4 +34,9 @@ export interface InputViewProps {
|
|||||||
handleChange: (_e: React.ChangeEvent<HTMLInputElement>) => void;
|
handleChange: (_e: React.ChangeEvent<HTMLInputElement>) => void;
|
||||||
handleFocus: (_e: React.FocusEvent<HTMLInputElement>) => void;
|
handleFocus: (_e: React.FocusEvent<HTMLInputElement>) => void;
|
||||||
handleBlur: (_e: React.FocusEvent<HTMLInputElement>) => void;
|
handleBlur: (_e: React.FocusEvent<HTMLInputElement>) => void;
|
||||||
|
handleMouseDown?: () => void;
|
||||||
|
showHelpIcon?: boolean;
|
||||||
|
isFilled?: boolean;
|
||||||
|
inputWrapperClasses?: string;
|
||||||
|
focusRingClasses?: string;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
import { forwardRef } from "react";
|
||||||
|
import { getAssetPath, ASSETS } from "../../../lib/assetUtils";
|
||||||
|
import type { TextInputViewProps } from "./TextInput.types";
|
||||||
|
|
||||||
|
export const TextInputView = forwardRef<HTMLInputElement, TextInputViewProps>(
|
||||||
|
(
|
||||||
|
{
|
||||||
|
inputId,
|
||||||
|
labelId,
|
||||||
|
label,
|
||||||
|
placeholder,
|
||||||
|
value,
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
disabled,
|
||||||
|
error: _error,
|
||||||
|
className: _className,
|
||||||
|
containerClasses,
|
||||||
|
labelClasses,
|
||||||
|
inputClasses,
|
||||||
|
borderRadius,
|
||||||
|
handleChange,
|
||||||
|
handleFocus,
|
||||||
|
handleBlur,
|
||||||
|
handleMouseDown,
|
||||||
|
showHelpIcon = true,
|
||||||
|
inputWrapperClasses = "relative",
|
||||||
|
focusRingClasses = "",
|
||||||
|
},
|
||||||
|
ref,
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
<div className={containerClasses}>
|
||||||
|
{label && (
|
||||||
|
<div className="flex flex-wrap gap-[var(--measures-spacing-200,4px_8px)] items-baseline pr-[var(--measures-spacing-100,4px)] relative shrink-0 w-full">
|
||||||
|
<div className="flex gap-[var(--measures-spacing-050,2px)] items-center relative shrink-0">
|
||||||
|
<label
|
||||||
|
id={labelId}
|
||||||
|
htmlFor={inputId}
|
||||||
|
className={`${labelClasses} font-inter font-medium text-[var(--color-content-default-primary)]`}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</label>
|
||||||
|
{showHelpIcon && (
|
||||||
|
<div className="relative shrink-0 size-[12px]">
|
||||||
|
<img
|
||||||
|
src={getAssetPath(ASSETS.ICON_HELP)}
|
||||||
|
alt="Help"
|
||||||
|
className="block max-w-none size-full"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className={inputWrapperClasses}>
|
||||||
|
<div className={disabled ? "opacity-40" : ""}>
|
||||||
|
<input
|
||||||
|
ref={ref}
|
||||||
|
id={inputId}
|
||||||
|
name={name}
|
||||||
|
type={type}
|
||||||
|
value={value}
|
||||||
|
placeholder={placeholder}
|
||||||
|
onChange={handleChange}
|
||||||
|
onFocus={handleFocus}
|
||||||
|
onBlur={handleBlur}
|
||||||
|
onMouseDown={handleMouseDown}
|
||||||
|
disabled={disabled}
|
||||||
|
className={inputClasses}
|
||||||
|
style={{ borderRadius }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{focusRingClasses && (
|
||||||
|
<div className={focusRingClasses} aria-hidden="true" />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
TextInputView.displayName = "TextInputView";
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
export { default } from "./TextInput.container";
|
||||||
|
export type { TextInputProps } from "./TextInput.types";
|
||||||
@@ -62,4 +62,7 @@ export const ASSETS = {
|
|||||||
|
|
||||||
// Tooltip icons
|
// Tooltip icons
|
||||||
ICON_POINTER: "assets/Icon_Pointer.svg",
|
ICON_POINTER: "assets/Icon_Pointer.svg",
|
||||||
|
|
||||||
|
// Help icon
|
||||||
|
ICON_HELP: "assets/Icon_Help.svg",
|
||||||
} as const;
|
} as const;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import Create from "../app/components/Create";
|
import Create from "../app/components/Create";
|
||||||
import Input from "../app/components/Input";
|
import TextInput from "../app/components/TextInput";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "Components/Create",
|
title: "Components/Create",
|
||||||
@@ -57,7 +57,7 @@ Default.args = {
|
|||||||
description: "You can also combine or add new approaches to the list",
|
description: "You can also combine or add new approaches to the list",
|
||||||
children: (
|
children: (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Input label="Label" placeholder="Policy name" value="" />
|
<TextInput label="Label" placeholder="Policy name" value="" />
|
||||||
<p className="text-[12px] text-[var(--color-content-default-tertiary)]">
|
<p className="text-[12px] text-[var(--color-content-default-tertiary)]">
|
||||||
0/48
|
0/48
|
||||||
</p>
|
</p>
|
||||||
@@ -77,7 +77,7 @@ WithStepper.args = {
|
|||||||
description: "You can also combine or add new approaches to the list",
|
description: "You can also combine or add new approaches to the list",
|
||||||
children: (
|
children: (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Input label="Label" placeholder="Policy name" value="" />
|
<TextInput label="Label" placeholder="Policy name" value="" />
|
||||||
<p className="text-[12px] text-[var(--color-content-default-tertiary)]">
|
<p className="text-[12px] text-[var(--color-content-default-tertiary)]">
|
||||||
0/48
|
0/48
|
||||||
</p>
|
</p>
|
||||||
@@ -155,7 +155,7 @@ NextButtonDisabled.args = {
|
|||||||
description: "You can also combine or add new approaches to the list",
|
description: "You can also combine or add new approaches to the list",
|
||||||
children: (
|
children: (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Input label="Label" placeholder="Policy name" value="" />
|
<TextInput label="Label" placeholder="Policy name" value="" />
|
||||||
<p className="text-[12px] text-[var(--color-content-default-tertiary)]">
|
<p className="text-[12px] text-[var(--color-content-default-tertiary)]">
|
||||||
0/48
|
0/48
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
import Select from "../app/components/Select";
|
import SelectInput from "../app/components/SelectInput";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "Forms/Select",
|
title: "Forms/SelectInput",
|
||||||
component: Select,
|
component: SelectInput,
|
||||||
argTypes: {
|
argTypes: {
|
||||||
size: {
|
size: {
|
||||||
control: { type: "select" },
|
control: { type: "select" },
|
||||||
@@ -35,10 +35,10 @@ export default {
|
|||||||
const Template = (args) => {
|
const Template = (args) => {
|
||||||
const [value, setValue] = useState("");
|
const [value, setValue] = useState("");
|
||||||
return (
|
return (
|
||||||
<Select
|
<SelectInput
|
||||||
{...args}
|
{...args}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={setValue}
|
onChange={(data) => setValue(data.target.value)}
|
||||||
options={[
|
options={[
|
||||||
{ value: "option1", label: "Option 1" },
|
{ value: "option1", label: "Option 1" },
|
||||||
{ value: "option2", label: "Option 2" },
|
{ value: "option2", label: "Option 2" },
|
||||||
@@ -50,27 +50,27 @@ const Template = (args) => {
|
|||||||
|
|
||||||
export const Default = Template.bind({});
|
export const Default = Template.bind({});
|
||||||
Default.args = {
|
Default.args = {
|
||||||
label: "Default Select",
|
label: "Default Select Input",
|
||||||
placeholder: "Select",
|
placeholder: "Select",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Small = Template.bind({});
|
export const Small = Template.bind({});
|
||||||
Small.args = {
|
Small.args = {
|
||||||
label: "Small Select",
|
label: "Small Select Input",
|
||||||
size: "small",
|
size: "small",
|
||||||
placeholder: "Select",
|
placeholder: "Select",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Medium = Template.bind({});
|
export const Medium = Template.bind({});
|
||||||
Medium.args = {
|
Medium.args = {
|
||||||
label: "Medium Select",
|
label: "Medium Select Input",
|
||||||
size: "medium",
|
size: "medium",
|
||||||
placeholder: "Select",
|
placeholder: "Select",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Large = Template.bind({});
|
export const Large = Template.bind({});
|
||||||
Large.args = {
|
Large.args = {
|
||||||
label: "Large Select",
|
label: "Large Select Input",
|
||||||
size: "large",
|
size: "large",
|
||||||
placeholder: "Select",
|
placeholder: "Select",
|
||||||
};
|
};
|
||||||
@@ -126,7 +126,7 @@ Disabled.args = {
|
|||||||
|
|
||||||
export const Interactive = Template.bind({});
|
export const Interactive = Template.bind({});
|
||||||
Interactive.args = {
|
Interactive.args = {
|
||||||
label: "Interactive Select",
|
label: "Interactive Select Input",
|
||||||
placeholder: "Choose an option",
|
placeholder: "Choose an option",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -138,39 +138,42 @@ export const AllSizes = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Select
|
<SelectInput
|
||||||
label="Small"
|
label="Small"
|
||||||
size="small"
|
size="small"
|
||||||
value={smallValue}
|
value={smallValue}
|
||||||
onChange={(e) => setSmallValue(e.target.value)}
|
onChange={(data) => setSmallValue(data.target.value)}
|
||||||
placeholder="Select"
|
placeholder="Select"
|
||||||
>
|
options={[
|
||||||
<option value="item1">Context Menu Item 1</option>
|
{ value: "item1", label: "Context Menu Item 1" },
|
||||||
<option value="item2">Context Menu Item 2</option>
|
{ value: "item2", label: "Context Menu Item 2" },
|
||||||
<option value="item3">Context Menu Item 3</option>
|
{ value: "item3", label: "Context Menu Item 3" },
|
||||||
</Select>
|
]}
|
||||||
<Select
|
/>
|
||||||
|
<SelectInput
|
||||||
label="Medium"
|
label="Medium"
|
||||||
size="medium"
|
size="medium"
|
||||||
value={mediumValue}
|
value={mediumValue}
|
||||||
onChange={(e) => setMediumValue(e.target.value)}
|
onChange={(data) => setMediumValue(data.target.value)}
|
||||||
placeholder="Select"
|
placeholder="Select"
|
||||||
>
|
options={[
|
||||||
<option value="item1">Context Menu Item 1</option>
|
{ value: "item1", label: "Context Menu Item 1" },
|
||||||
<option value="item2">Context Menu Item 2</option>
|
{ value: "item2", label: "Context Menu Item 2" },
|
||||||
<option value="item3">Context Menu Item 3</option>
|
{ value: "item3", label: "Context Menu Item 3" },
|
||||||
</Select>
|
]}
|
||||||
<Select
|
/>
|
||||||
|
<SelectInput
|
||||||
label="Large"
|
label="Large"
|
||||||
size="large"
|
size="large"
|
||||||
value={largeValue}
|
value={largeValue}
|
||||||
onChange={(e) => setLargeValue(e.target.value)}
|
onChange={(data) => setLargeValue(data.target.value)}
|
||||||
placeholder="Select"
|
placeholder="Select"
|
||||||
>
|
options={[
|
||||||
<option value="item1">Context Menu Item 1</option>
|
{ value: "item1", label: "Context Menu Item 1" },
|
||||||
<option value="item2">Context Menu Item 2</option>
|
{ value: "item2", label: "Context Menu Item 2" },
|
||||||
<option value="item3">Context Menu Item 3</option>
|
{ value: "item3", label: "Context Menu Item 3" },
|
||||||
</Select>
|
]}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -182,38 +185,41 @@ export const AllStates = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Select
|
<SelectInput
|
||||||
label="Default State"
|
label="Default State"
|
||||||
value={defaultValue}
|
value={defaultValue}
|
||||||
onChange={(e) => setDefaultValue(e.target.value)}
|
onChange={(data) => setDefaultValue(data.target.value)}
|
||||||
placeholder="Select"
|
placeholder="Select"
|
||||||
>
|
options={[
|
||||||
<option value="item1">Context Menu Item 1</option>
|
{ value: "item1", label: "Context Menu Item 1" },
|
||||||
<option value="item2">Context Menu Item 2</option>
|
{ value: "item2", label: "Context Menu Item 2" },
|
||||||
<option value="item3">Context Menu Item 3</option>
|
{ value: "item3", label: "Context Menu Item 3" },
|
||||||
</Select>
|
]}
|
||||||
<Select
|
/>
|
||||||
|
<SelectInput
|
||||||
label="Error State"
|
label="Error State"
|
||||||
error={true}
|
error={true}
|
||||||
value={errorValue}
|
value={errorValue}
|
||||||
onChange={(e) => setErrorValue(e.target.value)}
|
onChange={(data) => setErrorValue(data.target.value)}
|
||||||
placeholder="Select"
|
placeholder="Select"
|
||||||
>
|
options={[
|
||||||
<option value="item1">Context Menu Item 1</option>
|
{ value: "item1", label: "Context Menu Item 1" },
|
||||||
<option value="item2">Context Menu Item 2</option>
|
{ value: "item2", label: "Context Menu Item 2" },
|
||||||
<option value="item3">Context Menu Item 3</option>
|
{ value: "item3", label: "Context Menu Item 3" },
|
||||||
</Select>
|
]}
|
||||||
<Select
|
/>
|
||||||
|
<SelectInput
|
||||||
label="Disabled State"
|
label="Disabled State"
|
||||||
disabled={true}
|
disabled={true}
|
||||||
value={disabledValue}
|
value={disabledValue}
|
||||||
onChange={(e) => setDisabledValue(e.target.value)}
|
onChange={(data) => setDisabledValue(data.target.value)}
|
||||||
placeholder="Select"
|
placeholder="Select"
|
||||||
>
|
options={[
|
||||||
<option value="item1">Context Menu Item 1</option>
|
{ value: "item1", label: "Context Menu Item 1" },
|
||||||
<option value="item2">Context Menu Item 2</option>
|
{ value: "item2", label: "Context Menu Item 2" },
|
||||||
<option value="item3">Context Menu Item 3</option>
|
{ value: "item3", label: "Context Menu Item 3" },
|
||||||
</Select>
|
]}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Input from "../app/components/Input";
|
import TextInput from "../app/components/TextInput";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
title: "Forms/Input",
|
title: "Forms/TextInput",
|
||||||
component: Input,
|
component: TextInput,
|
||||||
parameters: {
|
parameters: {
|
||||||
layout: "centered",
|
layout: "centered",
|
||||||
},
|
},
|
||||||
@@ -38,12 +38,12 @@ export default {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const Template = (args) => <Input {...args} />;
|
const Template = (args) => <TextInput {...args} />;
|
||||||
|
|
||||||
// Default story
|
// Default story
|
||||||
export const Default = Template.bind({});
|
export const Default = Template.bind({});
|
||||||
Default.args = {
|
Default.args = {
|
||||||
label: "Default Input",
|
label: "Default Text Input",
|
||||||
placeholder: "Enter text...",
|
placeholder: "Enter text...",
|
||||||
size: "medium",
|
size: "medium",
|
||||||
labelVariant: "default",
|
labelVariant: "default",
|
||||||
@@ -53,7 +53,7 @@ Default.args = {
|
|||||||
// Size variants
|
// Size variants
|
||||||
export const Small = Template.bind({});
|
export const Small = Template.bind({});
|
||||||
Small.args = {
|
Small.args = {
|
||||||
label: "Small Input",
|
label: "Small Text Input",
|
||||||
placeholder: "Small size",
|
placeholder: "Small size",
|
||||||
size: "small",
|
size: "small",
|
||||||
labelVariant: "default",
|
labelVariant: "default",
|
||||||
@@ -62,7 +62,7 @@ Small.args = {
|
|||||||
|
|
||||||
export const Medium = Template.bind({});
|
export const Medium = Template.bind({});
|
||||||
Medium.args = {
|
Medium.args = {
|
||||||
label: "Medium Input",
|
label: "Medium Text Input",
|
||||||
placeholder: "Medium size",
|
placeholder: "Medium size",
|
||||||
size: "medium",
|
size: "medium",
|
||||||
labelVariant: "default",
|
labelVariant: "default",
|
||||||
@@ -71,7 +71,7 @@ Medium.args = {
|
|||||||
|
|
||||||
export const Large = Template.bind({});
|
export const Large = Template.bind({});
|
||||||
Large.args = {
|
Large.args = {
|
||||||
label: "Large Input",
|
label: "Large Text Input",
|
||||||
placeholder: "Large size",
|
placeholder: "Large size",
|
||||||
size: "large",
|
size: "large",
|
||||||
labelVariant: "default",
|
labelVariant: "default",
|
||||||
@@ -151,7 +151,7 @@ export const Interactive = (args) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Input
|
<TextInput
|
||||||
{...args}
|
{...args}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(e) => setValue(e.target.value)}
|
onChange={(e) => setValue(e.target.value)}
|
||||||
@@ -161,7 +161,7 @@ export const Interactive = (args) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
Interactive.args = {
|
Interactive.args = {
|
||||||
label: "Interactive Input",
|
label: "Interactive Text Input",
|
||||||
placeholder: "Type something...",
|
placeholder: "Type something...",
|
||||||
size: "medium",
|
size: "medium",
|
||||||
labelVariant: "default",
|
labelVariant: "default",
|
||||||
@@ -174,7 +174,7 @@ export const AllSizes = () => (
|
|||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-semibold mb-4">Small Size</h3>
|
<h3 className="text-lg font-semibold mb-4">Small Size</h3>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Input
|
<TextInput
|
||||||
label="Small Default"
|
label="Small Default"
|
||||||
placeholder="Small with top label"
|
placeholder="Small with top label"
|
||||||
size="small"
|
size="small"
|
||||||
@@ -186,13 +186,13 @@ export const AllSizes = () => (
|
|||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-semibold mb-4">Medium Size</h3>
|
<h3 className="text-lg font-semibold mb-4">Medium Size</h3>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Input
|
<TextInput
|
||||||
label="Medium Default"
|
label="Medium Default"
|
||||||
placeholder="Medium with top label"
|
placeholder="Medium with top label"
|
||||||
size="medium"
|
size="medium"
|
||||||
labelVariant="default"
|
labelVariant="default"
|
||||||
/>
|
/>
|
||||||
<Input
|
<TextInput
|
||||||
label="Medium Horizontal"
|
label="Medium Horizontal"
|
||||||
placeholder="Medium with left label"
|
placeholder="Medium with left label"
|
||||||
size="medium"
|
size="medium"
|
||||||
@@ -204,13 +204,13 @@ export const AllSizes = () => (
|
|||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-semibold mb-4">Large Size</h3>
|
<h3 className="text-lg font-semibold mb-4">Large Size</h3>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Input
|
<TextInput
|
||||||
label="Large Default"
|
label="Large Default"
|
||||||
placeholder="Large with top label"
|
placeholder="Large with top label"
|
||||||
size="large"
|
size="large"
|
||||||
labelVariant="default"
|
labelVariant="default"
|
||||||
/>
|
/>
|
||||||
<Input
|
<TextInput
|
||||||
label="Large Horizontal"
|
label="Large Horizontal"
|
||||||
placeholder="Large with left label"
|
placeholder="Large with left label"
|
||||||
size="large"
|
size="large"
|
||||||
@@ -225,39 +225,39 @@ export const AllSizes = () => (
|
|||||||
export const AllStates = () => (
|
export const AllStates = () => (
|
||||||
<div className="space-y-6">
|
<div className="space-y-6">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-semibold mb-4">Input States</h3>
|
<h3 className="text-lg font-semibold mb-4">Text Input States</h3>
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<Input
|
<TextInput
|
||||||
label="Default State"
|
label="Default State"
|
||||||
placeholder="Default input"
|
placeholder="Default input"
|
||||||
size="medium"
|
size="medium"
|
||||||
state="default"
|
state="default"
|
||||||
/>
|
/>
|
||||||
<Input
|
<TextInput
|
||||||
label="Active State"
|
label="Active State"
|
||||||
placeholder="Active input"
|
placeholder="Active input"
|
||||||
size="medium"
|
size="medium"
|
||||||
state="active"
|
state="active"
|
||||||
/>
|
/>
|
||||||
<Input
|
<TextInput
|
||||||
label="Hover State"
|
label="Hover State"
|
||||||
placeholder="Hover input"
|
placeholder="Hover input"
|
||||||
size="medium"
|
size="medium"
|
||||||
state="hover"
|
state="hover"
|
||||||
/>
|
/>
|
||||||
<Input
|
<TextInput
|
||||||
label="Focus State"
|
label="Focus State"
|
||||||
placeholder="Focused input"
|
placeholder="Focused input"
|
||||||
size="medium"
|
size="medium"
|
||||||
state="focus"
|
state="focus"
|
||||||
/>
|
/>
|
||||||
<Input
|
<TextInput
|
||||||
label="Error State"
|
label="Error State"
|
||||||
placeholder="Error input"
|
placeholder="Error input"
|
||||||
size="medium"
|
size="medium"
|
||||||
error={true}
|
error={true}
|
||||||
/>
|
/>
|
||||||
<Input
|
<TextInput
|
||||||
label="Disabled State"
|
label="Disabled State"
|
||||||
placeholder="Disabled input"
|
placeholder="Disabled input"
|
||||||
size="medium"
|
size="medium"
|
||||||
@@ -4,7 +4,7 @@ import { screen, fireEvent, waitFor } from "@testing-library/react";
|
|||||||
import "@testing-library/jest-dom/vitest";
|
import "@testing-library/jest-dom/vitest";
|
||||||
import { renderWithProviders } from "../utils/test-utils";
|
import { renderWithProviders } from "../utils/test-utils";
|
||||||
import Create from "../../app/components/Create";
|
import Create from "../../app/components/Create";
|
||||||
import Input from "../../app/components/Input";
|
import TextInput from "../../app/components/TextInput";
|
||||||
|
|
||||||
type CreateProps = React.ComponentProps<typeof Create>;
|
type CreateProps = React.ComponentProps<typeof Create>;
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ describe("Create", () => {
|
|||||||
it("traps focus within create dialog", async () => {
|
it("traps focus within create dialog", async () => {
|
||||||
renderWithProviders(
|
renderWithProviders(
|
||||||
<Create {...defaultProps}>
|
<Create {...defaultProps}>
|
||||||
<Input label="Test Input" />
|
<TextInput label="Test Input" />
|
||||||
</Create>,
|
</Create>,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Select from "../../app/components/Select";
|
import SelectInput from "../../app/components/SelectInput";
|
||||||
import { componentTestSuite } from "../utils/componentTestSuite";
|
import { componentTestSuite } from "../utils/componentTestSuite";
|
||||||
|
|
||||||
type SelectProps = React.ComponentProps<typeof Select>;
|
type SelectInputProps = React.ComponentProps<typeof SelectInput>;
|
||||||
|
|
||||||
componentTestSuite<SelectProps>({
|
componentTestSuite<SelectInputProps>({
|
||||||
component: Select,
|
component: SelectInput,
|
||||||
name: "Select",
|
name: "SelectInput",
|
||||||
props: {
|
props: {
|
||||||
label: "Test Select",
|
label: "Test Select Input",
|
||||||
placeholder: "Select an option",
|
placeholder: "Select an option",
|
||||||
options: [
|
options: [
|
||||||
{ value: "option1", label: "Option 1" },
|
{ value: "option1", label: "Option 1" },
|
||||||
{ value: "option2", label: "Option 2" },
|
{ value: "option2", label: "Option 2" },
|
||||||
],
|
],
|
||||||
} as SelectProps,
|
} as SelectInputProps,
|
||||||
requiredProps: ["options"],
|
requiredProps: ["options"],
|
||||||
optionalProps: {
|
optionalProps: {
|
||||||
size: "medium",
|
size: "medium",
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Input from "../../app/components/Input";
|
import TextInput from "../../app/components/TextInput";
|
||||||
import { componentTestSuite } from "../utils/componentTestSuite";
|
import { componentTestSuite } from "../utils/componentTestSuite";
|
||||||
|
|
||||||
type InputProps = React.ComponentProps<typeof Input>;
|
type TextInputProps = React.ComponentProps<typeof TextInput>;
|
||||||
|
|
||||||
componentTestSuite<InputProps>({
|
componentTestSuite<TextInputProps>({
|
||||||
component: Input,
|
component: TextInput,
|
||||||
name: "Input",
|
name: "TextInput",
|
||||||
props: {
|
props: {
|
||||||
label: "Test input",
|
label: "Test text input",
|
||||||
} as InputProps,
|
} as TextInputProps,
|
||||||
requiredProps: ["label"],
|
requiredProps: ["label"],
|
||||||
optionalProps: {
|
optionalProps: {
|
||||||
placeholder: "Enter value",
|
placeholder: "Enter value",
|
||||||
Reference in New Issue
Block a user