Compare commits

...

8 Commits

Author SHA1 Message Date
Sammii
4c39164dfe more linting 2025-08-15 15:36:20 +01:00
Sammii
570d82cf8f linting 2025-08-15 15:33:51 +01:00
Sammii
ede6c91016 reverting changes on form example 2025-08-15 15:31:26 +01:00
Sammii
82495a8406 Merge branch 'main' into feat/quint-checkbox 2025-08-15 15:20:49 +01:00
Sammii
c10ccc6140 removing unrelated changes 2025-08-15 15:14:10 +01:00
Sammii
0ee4a95754 updating input docs to show different types 2025-08-15 14:44:19 +01:00
Sammii
3ee43fa506 adding checkbox to design system 2025-08-15 14:42:35 +01:00
Sammii
903c70968e port quint to examples form 2025-08-15 14:38:24 +01:00
9 changed files with 379 additions and 29 deletions

View File

@@ -0,0 +1,87 @@
import { Checkbox } from "@/src/components/checkbox";
import Link from "next/link";
export default function CheckboxPage() {
return (
<div>
<h2 className="text-2xl font-bold">Checkbox</h2>
<p>
Checkboxes use the same intents and a subset of variants as the{" "}
<Link href="/docs/button">Button</Link> component.
</p>
<h3 className="text-lg font-bold">Sizes</h3>
<div className="flex flex-row gap-5 mb-3">
<div className="flex items-center gap-2">
<p className="text-sm font-medium">xs</p>
<Checkbox sizeStyle="xs" intent="default" />
</div>
<div className="flex items-center gap-2">
<p className="text-sm font-medium">sm</p>
<Checkbox sizeStyle="sm" intent="default" />
</div>
<div className="flex items-center gap-2">
<p className="text-sm font-medium">md</p>
<Checkbox sizeStyle="md" intent="default" />
</div>
<div className="flex items-center gap-2">
<p className="text-sm font-medium">lg</p>
<Checkbox sizeStyle="lg" intent="default" />
</div>
</div>
<h3 className="text-lg font-bold">Variants</h3>
<div className="flex flex-row gap-5 mb-3">
<div className="flex items-center gap-2">
<p className="text-sm font-medium">default</p>
<Checkbox variant="default" />
</div>
<div className="flex items-center gap-2">
<p className="text-sm font-medium">outline</p>
<Checkbox variant="outline" />
</div>
<div className="flex items-center gap-2">
<p className="text-sm font-medium">inverted</p>
<Checkbox variant="inverted" />
</div>
</div>
<h3 className="text-lg font-bold">Intents</h3>
<div className="flex flex-row gap-2 mb-3">
<Checkbox intent="default" />
<Checkbox intent="primary" />
<Checkbox intent="tip" />
<Checkbox intent="success" />
<Checkbox intent="warning" />
<Checkbox intent="danger" />
<Checkbox intent="info" />
<Checkbox intent="muted" />
<Checkbox intent="strong" />
</div>
<h3 className="text-lg font-bold">Intents and Variants</h3>
<div className="flex flex-row gap-2 mb-3">
<Checkbox intent="default" variant="outline" />
<Checkbox intent="primary" variant="outline" />
<Checkbox intent="tip" variant="outline" />
<Checkbox intent="success" variant="outline" />
<Checkbox intent="warning" variant="outline" />
<Checkbox intent="danger" variant="outline" />
<Checkbox intent="info" variant="outline" />
<Checkbox intent="muted" variant="outline" />
<Checkbox intent="strong" variant="outline" />
</div>
<div className="flex flex-row gap-2 mb-3">
<Checkbox intent="default" variant="inverted" />
<Checkbox intent="primary" variant="inverted" />
<Checkbox intent="tip" variant="inverted" />
<Checkbox intent="success" variant="inverted" />
<Checkbox intent="warning" variant="inverted" />
<Checkbox intent="danger" variant="inverted" />
<Checkbox intent="info" variant="inverted" />
<Checkbox intent="muted" variant="inverted" />
<Checkbox intent="strong" variant="inverted" />
</div>
</div>
);
}

View File

@@ -1,5 +1,4 @@
import { Input } from "@/src/components/input";
import { Label } from "@/src/components/label";
import { Input, Label } from "quint-ui";
import { SearchIcon } from "lucide-react";
export default function InputPage() {
@@ -11,38 +10,38 @@ export default function InputPage() {
intent and size props.
</p>
<div className="flex flex-row gap-2">
<Label htmlFor="input">Label</Label>
<Input id="input" />
<Label htmlFor="default">Label</Label>
<Input id="default" />
</div>
<div className="flex flex-col gap-2">
<Label htmlFor="input">Label</Label>
<Input id="input" intent="primary" />
<Label htmlFor="primary">Label</Label>
<Input id="primary" intent="primary" />
</div>
<div className="flex flex-row gap-2">
<Label htmlFor="input" size="sm">
<Label htmlFor="tip" size="sm">
Label
</Label>
<Input id="input" intent="tip" sizeStyle="sm" />
<Input id="tip" intent="tip" sizeStyle="sm" />
</div>
<div className="flex flex-col gap-2">
<Label htmlFor="input" size="sm">
<Label htmlFor="info" size="sm">
Label
</Label>
<Input id="input" intent="info" sizeStyle="sm" />
<Input id="info" intent="info" sizeStyle="sm" />
</div>
<div className="flex flex-row gap-2">
<Label htmlFor="input" size="lg">
<Label htmlFor="warning" size="lg">
Label
</Label>
<Input id="input" intent="warning" sizeStyle="lg" />
<Input id="warning" intent="warning" sizeStyle="lg" />
</div>
<div className="flex flex-col gap-2">
<Label htmlFor="input" size="lg">
<Label htmlFor="danger" size="lg">
Label
</Label>
<Input id="input" intent="danger" sizeStyle="lg" />
<Input id="danger" intent="danger" sizeStyle="lg" />
</div>
<p>
@@ -51,12 +50,51 @@ export default function InputPage() {
</p>
<div className="flex flex-row gap-2 items-center">
<Label htmlFor="input" isHiddenVisually>
<Label htmlFor="hidden" isHiddenVisually>
Label
</Label>
<SearchIcon />
<Input id="input" />
<Input id="hidden" />
</div>
<p>
All types of inputs are supported, including file, number, and date.
</p>
<div className="flex flex-row gap-2">
<Label htmlFor="email">Email</Label>
<Input id="email" type="email" />
</div>
<div className="flex flex-row gap-2">
<Label htmlFor="color">Color</Label>
<Input id="color" type="color" />
</div>
<div className="flex flex-row gap-2">
<Label htmlFor="password">Password</Label>
<Input id="password" type="password" />
</div>
<div className="flex flex-row gap-2">
<Label htmlFor="search">Search</Label>
<Input id="search" type="search" />
</div>
<div className="flex flex-row gap-2">
<Label htmlFor="file">File</Label>
<Input id="file" type="file" />
</div>
<div className="flex flex-row gap-2">
<Label htmlFor="number">Number</Label>
<Input id="number" type="number" />
</div>
<div className="flex flex-row gap-2">
<Label htmlFor="date">Date</Label>
<Input id="date" type="date" />
</div>
</div>
);

View File

@@ -9,6 +9,7 @@ export default function DocsPage() {
<Link href="/docs/button">Button</Link>
<Link href="/docs/icon">Icon</Link>
<Link href="/docs/input">Input</Link>
<Link href="/docs/checkbox">Checkbox</Link>
</li>
</ul>
</div>

View File

@@ -16,6 +16,8 @@ export default function RootLayout({
<Link href="/">Colors</Link>
<Link href="/docs/button">Button</Link>
<Link href="/docs/icons">Icons</Link>
<Link href="/docs/input">Input</Link>
<Link href="/docs/checkbox">Checkbox</Link>
</div>
<div className="container m-21">{children}</div>
</body>

View File

@@ -19,6 +19,7 @@
},
"dependencies": {
"@base-ui-components/react": "1.0.0-beta.1",
"@tailwindcss/forms": "^0.5.10",
"clsx": "^2.1.1",
"tailwind-merge": "^3.3.1",
"tailwind-variants": "^1.0.0",

View File

@@ -0,0 +1,206 @@
import { ComponentProps } from "react";
import { Checkbox as BaseUiCheckbox } from "@base-ui-components/react/checkbox";
import { tv, VariantProps } from "tailwind-variants";
import { CheckIcon } from "lucide-react";
interface CheckboxProps
extends ComponentProps<typeof BaseUiCheckbox.Root>,
VariantProps<typeof checkbox> {}
export function Checkbox({
sizeStyle,
intent,
variant,
value,
...props
}: CheckboxProps) {
return (
<BaseUiCheckbox.Root
{...props}
className={checkbox({ sizeStyle, intent, variant })}
>
<BaseUiCheckbox.Indicator>
<CheckIcon />
</BaseUiCheckbox.Indicator>
</BaseUiCheckbox.Root>
);
}
const checkbox = tv({
base: "text-white rounded-sm ",
variants: {
sizeStyle: {
xs: "w-3 h-3 [&>span>svg]:size-3",
sm: "w-4 h-4 [&>span>svg]:size-4",
md: "w-5 h-5 [&>span>svg]:size-5",
lg: "w-6 h-6 [&>span>svg]:size-6",
},
intent: {
default: "",
primary: "",
success: "",
warning: "",
danger: "",
info: "",
tip: "",
muted: "",
strong: "",
},
variant: {
default: "bg-gray-500",
outline:
"border bg-transparent box-border [&>span]:relative [&>span]:left-[-1px] [&>span]:top-[-1px]",
inverted: "shadow-sm",
},
disabled: {
true: "opacity-50",
},
},
compoundVariants: [
// Default Variants
{
intent: "default",
variant: "default",
className: "bg-gray-500",
},
{
intent: "primary",
variant: "default",
className: "bg-blue",
},
{
intent: "success",
variant: "default",
className: "bg-green",
},
{
intent: "warning",
variant: "default",
className: "bg-yellow",
},
{
intent: "danger",
variant: "default",
className: "bg-red",
},
{
intent: "info",
variant: "default",
className: "bg-blue",
},
{
intent: "tip",
variant: "default",
className: "bg-purple",
},
{
intent: "muted",
variant: "default",
className: "bg-muted",
},
{
intent: "strong",
variant: "default",
className: "bg-strong",
},
// Outline Variants
{
intent: "default",
variant: "outline",
className: "border border-gray-500 text-gray-500",
},
{
intent: "primary",
variant: "outline",
className: "border border-blue text-blue",
},
{
intent: "success",
variant: "outline",
className: "border border-green text-green",
},
{
intent: "danger",
variant: "outline",
className: "border border-red text-red",
},
{
intent: "warning",
variant: "outline",
className: "border border-yellow bg-transparent text-yellow",
},
{
intent: "info",
variant: "outline",
className: "border border-blue text-blue",
},
{
intent: "tip",
variant: "outline",
className: "border border-purple text-purple",
},
{
intent: "muted",
variant: "outline",
className: "border border-muted text-muted",
},
{
intent: "strong",
variant: "outline",
className: "border border-strong text-strong",
},
// Inverted Variants
{
intent: "default",
variant: "inverted",
className: "bg-transparent text-gray-500",
},
{
intent: "primary",
variant: "inverted",
className: "bg-blue/50 text-blue",
},
{
intent: "success",
variant: "inverted",
className: "bg-green/50 text-green",
},
{
intent: "warning",
variant: "inverted",
className: "bg-yellow/50 text-yellow",
},
{
intent: "danger",
variant: "inverted",
className: "bg-red/50 text-red",
},
{
intent: "info",
variant: "inverted",
className: "bg-cyan/50 text-cyan",
},
{
intent: "tip",
variant: "inverted",
className: "bg-purple/50 text-purple",
},
{
intent: "muted",
variant: "inverted",
className: "bg-gray-500/50 text-gray-500",
},
{
intent: "strong",
variant: "inverted",
className: "bg-strong/50 text-strong",
},
],
defaultVariants: {
sizeStyle: "md",
intent: "default",
variant: "default",
},
});

View File

@@ -1,5 +1,6 @@
@import "tailwindcss";
@import "tw-animate-css";
@plugin "@tailwindcss/forms";
/* Dark mode. If you want to use dark mode, you can add the dark class to the body/head element. */
@custom-variant dark (&:is(.dark *));

View File

@@ -3,6 +3,7 @@ export { Button } from "./components/button.js";
export { Icons } from "./components/icons.js";
export { Input } from "./components/input.js";
export { Label } from "./components/label.js";
export { Checkbox } from "./components/checkbox.js";
// UTILS
export { cn } from "./lib/utils.js";

39
pnpm-lock.yaml generated
View File

@@ -182,7 +182,7 @@ importers:
version: 0.510.0(react@19.1.0)
next:
specifier: 15.3.2
version: 15.3.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
version: 15.3.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react:
specifier: 19.1.0
version: 19.1.0
@@ -222,7 +222,7 @@ importers:
version: 19.1.0(@types/react@19.1.0)
react-email:
specifier: ^4.0.11
version: 4.0.13(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
version: 4.0.13(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
tailwindcss:
specifier: ^4
version: 4.1.10
@@ -888,6 +888,9 @@ importers:
jazz-tools:
specifier: workspace:*
version: link:../../packages/jazz-tools
quint-ui:
specifier: workspace:*
version: link:../../packages/quint-ui
react:
specifier: 19.1.0
version: 19.1.0
@@ -1040,7 +1043,7 @@ importers:
version: link:../../packages/jazz-tools
next:
specifier: 15.3.2
version: 15.3.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
version: 15.3.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react:
specifier: 19.1.0
version: 19.1.0
@@ -1587,7 +1590,7 @@ importers:
version: 0.525.0(react@19.1.0)
next:
specifier: 15.3.2
version: 15.3.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
version: 15.3.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next-themes:
specifier: ^0.4.6
version: 0.4.6(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
@@ -2281,6 +2284,9 @@ importers:
'@base-ui-components/react':
specifier: 1.0.0-beta.1
version: 1.0.0-beta.1(@types/react@19.1.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@tailwindcss/forms':
specifier: ^0.5.10
version: 0.5.10(tailwindcss@4.1.11)
clsx:
specifier: ^2.1.1
version: 2.1.1
@@ -2311,7 +2317,7 @@ importers:
version: 0.525.0(react@19.1.0)
next:
specifier: 15.4.2
version: 15.4.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
version: 15.4.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
react:
specifier: 19.1.0
version: 19.1.0
@@ -20491,6 +20497,11 @@ snapshots:
mini-svg-data-uri: 1.4.4
tailwindcss: 4.1.10
'@tailwindcss/forms@0.5.10(tailwindcss@4.1.11)':
dependencies:
mini-svg-data-uri: 1.4.4
tailwindcss: 4.1.11
'@tailwindcss/node@4.1.10':
dependencies:
'@ampproject/remapping': 2.3.0
@@ -21645,7 +21656,7 @@ snapshots:
sirv: 3.0.1
tinyglobby: 0.2.14
tinyrainbow: 2.0.0
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.5)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@17.4.4)(jiti@2.4.2)(jsdom@25.0.1)(lightningcss@1.30.1)(msw@2.10.4(@types/node@22.16.5)(typescript@5.6.2))(terser@5.37.0)(tsx@4.20.3)(yaml@2.6.1)
vitest: 3.2.4(@types/debug@4.1.12)(@types/node@22.16.5)(@vitest/browser@3.2.4)(@vitest/ui@3.2.4)(happy-dom@17.4.4)(jiti@2.4.2)(jsdom@25.0.1)(lightningcss@1.30.1)(msw@2.10.4(@types/node@22.16.5)(typescript@5.8.3))(terser@5.37.0)(tsx@4.20.3)(yaml@2.6.1)
'@vitest/utils@3.2.4':
dependencies:
@@ -26373,7 +26384,7 @@ snapshots:
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
next@15.3.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
next@15.3.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@next/env': 15.3.2
'@swc/counter': 0.1.3
@@ -26383,7 +26394,7 @@ snapshots:
postcss: 8.4.31
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
styled-jsx: 5.1.6(react@19.1.0)
styled-jsx: 5.1.6(@babel/core@7.27.1)(react@19.1.0)
optionalDependencies:
'@next/swc-darwin-arm64': 15.3.2
'@next/swc-darwin-x64': 15.3.2
@@ -26400,7 +26411,7 @@ snapshots:
- '@babel/core'
- babel-plugin-macros
next@15.4.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
next@15.4.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@next/env': 15.4.2
'@swc/helpers': 0.5.15
@@ -26408,7 +26419,7 @@ snapshots:
postcss: 8.4.31
react: 19.1.0
react-dom: 19.1.0(react@19.1.0)
styled-jsx: 5.1.6(react@19.1.0)
styled-jsx: 5.1.6(@babel/core@7.27.1)(react@19.1.0)
optionalDependencies:
'@next/swc-darwin-arm64': 15.4.2
'@next/swc-darwin-x64': 15.4.2
@@ -27399,7 +27410,7 @@ snapshots:
react: 19.1.0
scheduler: 0.26.0
react-email@4.0.13(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
react-email@4.0.13(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0):
dependencies:
'@babel/parser': 7.27.2
'@babel/traverse': 7.27.1
@@ -27411,7 +27422,7 @@ snapshots:
glob: 11.0.2
log-symbols: 7.0.0
mime-types: 3.0.1
next: 15.3.2(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
next: 15.3.2(@babel/core@7.27.1)(@opentelemetry/api@1.9.0)(@playwright/test@1.50.1)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
normalize-path: 3.0.0
ora: 8.2.0
socket.io: 4.8.1
@@ -28713,10 +28724,12 @@ snapshots:
structured-headers@0.4.1: {}
styled-jsx@5.1.6(react@19.1.0):
styled-jsx@5.1.6(@babel/core@7.27.1)(react@19.1.0):
dependencies:
client-only: 0.0.1
react: 19.1.0
optionalDependencies:
'@babel/core': 7.27.1
stylis@4.2.0: {}