File upload
منطقة إسقاط وقائمة ملفات.
- المتصفحات
- Chrome 123+Firefox 121+Safari 17.5+
- الفئة
- 1
- الحجم المضغوط
- 2.27 kB
- ميزانية التخطيط القسري
- 0 ms
- ميزانية axe
- 0
- متوافق مع SSR
- نعم
- العقد المنشور
- بيئة الاختبار
المختبر
File upload
Attachments
"use client";
import { FileUpload } from "@gunkin/uiify";
export default function Example() {
return (
<FileUpload.Root multiple maxFiles={3} maxSize={5000000} className="">
<FileUpload.HiddenInput name="attachments" aria-label="Attachments" />
<FileUpload.Trigger as="button" className="">
Choose files
</FileUpload.Trigger>
<FileUpload.Dropzone className="">Drop files here</FileUpload.Dropzone>
<FileUpload.List className="">
{(files) =>
files.map((file, index) => (
<FileUpload.Item key={file.name} index={index} className="">
<span>
{file.name} · {(file.size / 1024).toFixed(1)} KB
</span>
<FileUpload.ItemRemove index={index} aria-label={"Remove " + file.name}>
×
</FileUpload.ItemRemove>
</FileUpload.Item>
))
}
</FileUpload.List>
</FileUpload.Root>
);
}/* File upload — trigger button with dashed dropzone. */
@layer components {
[data-uiify-file-upload] {
display: grid;
gap: var(--space-md);
inline-size: 100%;
max-inline-size: 24rem;
}
[data-uiify-file-upload] [data-part="dropzone"] {
display: flex;
align-items: center;
justify-content: center;
min-block-size: 8rem;
padding: var(--space-lg);
border: 2px dashed var(--input);
border-radius: var(--radius-xl);
corner-shape: squircle;
background-color: var(--secondary);
color: var(--muted-foreground);
font-size: var(--text-sm);
text-align: center;
transition: var(--transition-colors);
}
[data-uiify-file-upload] [data-part="dropzone"]:hover,
[data-uiify-file-upload] [data-part="dropzone"][data-dragging] {
border-color: var(--primary);
background-color: color-mix(in oklch, var(--primary) 8%, transparent);
color: var(--foreground);
}
[data-uiify-file-upload] [data-part="dropzone"][data-disabled] {
opacity: 0.5;
cursor: not-allowed;
}
[data-uiify-file-upload] [data-part="list"] {
display: grid;
gap: var(--space-xs);
margin: 0;
padding: 0;
list-style: none;
}
[data-uiify-file-upload] [data-part="item"] {
display: flex;
align-items: center;
gap: var(--space-sm);
padding: var(--space-sm) var(--space-md);
border: var(--border-width) solid var(--border);
border-radius: var(--radius-lg);
corner-shape: squircle;
background-color: var(--card);
font-size: var(--text-sm);
}
}
@layer components {
[data-uiify-file-upload] [data-part="file-info"] {
display: grid;
gap: 0.25rem;
min-inline-size: 0;
flex: 1;
overflow-wrap: anywhere;
}
[data-uiify-file-upload] small {
color: var(--muted-foreground);
}
[data-uiify-file-upload] [data-part="remove"] {
display: grid;
place-items: center;
flex: none;
inline-size: 2rem;
block-size: 2rem;
margin-inline-start: auto;
border: 0;
border-radius: 50%;
background: var(--secondary);
color: var(--foreground);
font-size: 1.25rem;
line-height: 1;
cursor: pointer;
}
[data-uiify-file-upload] [data-part="remove"]:hover {
background: var(--accent);
}
[data-uiify-file-upload] [data-part="remove"]:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
}
}"use client";
import { FileUpload } from "@gunkin/uiify";
export default function Example() {
return (
<FileUpload.Root
multiple
maxFiles={3}
maxSize={5000000}
className="
grid gap-md [inline-size:100%] [max-inline-size:24rem] [&_[data-part=dropzone]]:flex
[&_[data-part=dropzone]]:items-center [&_[data-part=dropzone]]:justify-center
[&_[data-part=dropzone]]:[min-block-size:8rem] [&_[data-part=dropzone]]:p-lg
[&_[data-part=dropzone]]:[border-width:2px] [&_[data-part=dropzone]]:[border-style:dashed]
[&_[data-part=dropzone]]:border-input [&_[data-part=dropzone]]:rounded-xl
[&_[data-part=dropzone]]:[corner-shape:squircle] [&_[data-part=dropzone]]:bg-secondary
[&_[data-part=dropzone]]:text-muted-foreground [&_[data-part=dropzone]]:text-sm
[&_[data-part=dropzone]]:text-center [&_[data-part=dropzone]]:[transition:var(--transition-colors)]
[&_[data-part=dropzone]:hover]:border-primary
[&_[data-part=dropzone]:hover]:[background-color:color-mix(in_oklch,_var(--primary)_8%,_transparent)]
[&_[data-part=dropzone]:hover]:text-foreground [&_[data-part=dropzone][data-dragging]]:border-primary
[&_[data-part=dropzone][data-dragging]]:[background-color:color-mix(in_oklch,_var(--primary)_8%,_transparent)]
[&_[data-part=dropzone][data-dragging]]:text-foreground [&_[data-part=dropzone][data-disabled]]:opacity-50
[&_[data-part=dropzone][data-disabled]]:cursor-not-allowed [&_[data-part=list]]:grid [&_[data-part=list]]:gap-xs
[&_[data-part=list]]:m-0 [&_[data-part=list]]:p-0 [&_[data-part=list]]:list-none [&_[data-part=item]]:flex
[&_[data-part=item]]:items-center [&_[data-part=item]]:gap-sm
[&_[data-part=item]]:[padding:var(--space-sm)_var(--space-md)]
[&_[data-part=item]]:border-[length:var(--border-width)] [&_[data-part=item]]:border-solid
[&_[data-part=item]]:border-border [&_[data-part=item]]:rounded-lg [&_[data-part=item]]:[corner-shape:squircle]
[&_[data-part=item]]:bg-card [&_[data-part=item]]:text-sm [&_[data-part=file-info]]:grid
[&_[data-part=file-info]]:[gap:0.25rem] [&_[data-part=file-info]]:[min-inline-size:0]
[&_[data-part=file-info]]:[flex:1] [&_[data-part=file-info]]:[overflow-wrap:anywhere]
[&_small]:text-muted-foreground [&_[data-part=remove]]:grid [&_[data-part=remove]]:place-items-center
[&_[data-part=remove]]:flex-none [&_[data-part=remove]]:[inline-size:2rem]
[&_[data-part=remove]]:[block-size:2rem] [&_[data-part=remove]]:[margin-inline-start:auto]
[&_[data-part=remove]]:border-0 [&_[data-part=remove]]:border-current [&_[data-part=remove]]:border-none
[&_[data-part=remove]]:rounded-[50%] [&_[data-part=remove]]:bg-secondary [&_[data-part=remove]]:text-foreground
[&_[data-part=remove]]:[font-size:1.25rem] [&_[data-part=remove]]:leading-none
[&_[data-part=remove]]:cursor-pointer [&_[data-part=remove]:hover]:bg-accent
[&_[data-part=remove]:focus-visible]:[outline:2px_solid_var(--ring)]
[&_[data-part=remove]:focus-visible]:[outline-offset:2px]
"
>
<FileUpload.HiddenInput name="attachments" aria-label="Attachments" />
<FileUpload.Trigger
as="button"
className={
"focus-visible:[outline:none] focus-visible:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--" +
"ring)_16%,_transparent)] [--uiify-button-rim:rgb(255_255_255_/_20%)] [--uiify-button-wash:light-dark(rgb(" +
"255_255_255_/_15%),_rgb(255_255_255_/_30%))] relative isolate inline-flex items-center justify-center [ga" +
"p:0.375rem] [min-block-size:44px] [min-inline-size:44px] py-0 [padding-inline:1.25rem] border-[length:var" +
"(--border-width)] border-solid border-transparent rounded-[var(--radius-full)] bg-foreground bg-clip-padd" +
"ing text-background text-base font-[number:var(--weight-medium)] leading-6 no-underline cursor-pointer [t" +
"ransition:var(--transition-colors)] before:content-[''] before:absolute before:inset-0 before:z-[-1] befo" +
"re:[border-radius:inherit] before:pointer-events-none after:content-[''] after:absolute after:inset-0 aft" +
"er:z-[-1] after:[border-radius:inherit] after:pointer-events-none before:[background-color:var(--uiify-bu" +
"tton-wash)] before:[filter:blur(10px)] before:[translate:0_-50%] before:[clip-path:inset(50%_0_-50%_0_rou" +
"nd_var(--radius-full))] after:[padding:0.5px] after:[background-image:linear-gradient(to_bottom,_var(--ui" +
"ify-button-rim),_transparent_75%)] after:[mask:linear-gradient(#fff_0_0)_content-box_exclude,_linear-grad" +
"ient(#fff_0_0)] [&:is([data-size=sm],[data-size=icon-sm])]:[min-block-size:32px] [&:is([data-size=sm],[da" +
"ta-size=icon-sm])]:[min-inline-size:32px] [&:is([data-size=sm],[data-size=icon-sm])]:[padding-inline:0.75" +
"rem] [&:is([data-size=sm],[data-size=icon-sm])]:[gap:0.25rem] [&:is([data-size=sm],[data-size=icon-sm])]:" +
"text-sm [&:is([data-size=sm],[data-size=icon-sm])]:leading-5 [&:is([data-size=lg],[data-size=icon-lg])]:[" +
"min-block-size:56px] [&:is([data-size=lg],[data-size=icon-lg])]:[min-inline-size:56px] [&:is([data-size=l" +
"g],[data-size=icon-lg])]:[padding-inline:1.75rem] [&:is([data-size=lg],[data-size=icon-lg])]:text-lg [&:i" +
"s([data-size=lg],[data-size=icon-lg])]:leading-7 [&[data-size^=icon]]:px-0 [@media_(any-hover:_hover)_and" +
"_(any-pointer:_fine)]:hover:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(" +
"--foreground)_90%,_var(--background))] active:[&:not(:disabled,[data-disabled])]:[background-color:color-" +
"mix(in_oklch,_var(--foreground)_80%,_var(--background))] disabled:opacity-50 disabled:cursor-not-allowed " +
"data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed data-[variant=secondary]:[&:where(:not(:che" +
"cked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:[--uiify-button-rim:light-dark(rgb(0_0_" +
"0_/_5%),_rgb(255_255_255_/_10%))] data-[variant=secondary]:[&:where(:not(:checked+*,[data-selected],[aria" +
"-pressed=true],[aria-current=page]))]:[--uiify-button-wash:light-dark(rgb(255_255_255_/_20%),_rgb(255_255" +
"_255_/_5%))] data-[variant=secondary]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-" +
"current=page]))]:[background-color:color-mix(in_oklch,_var(--foreground)_10%,_transparent)] data-[variant" +
"=secondary]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:text-fore" +
"ground data-[variant=outline]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=" +
"page]))]:[--uiify-button-rim:color-mix(in_oklch,_var(--foreground)_25%,_transparent)] data-[variant=outli" +
"ne]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:[border-color:col" +
"or-mix(in_oklch,_var(--foreground)_20%,_transparent)] data-[variant=outline]:[&:where(:not(:checked+*,[da" +
"ta-selected],[aria-pressed=true],[aria-current=page]))]:bg-transparent data-[variant=outline]:[&:where(:n" +
"ot(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:text-foreground data-[variant=ou" +
"tline]:before:content-none data-[variant=outline]:after:[inset:calc(-1_*_var(--border-width))] data-[vari" +
"ant=outline]:after:[padding:var(--border-width)] data-[variant=outline]:[&:where(:not(:checked+*,[data-se" +
"lected],[aria-pressed=true],[aria-current=page]))]:active:[&:not(:disabled,[data-disabled])]:[background-" +
"color:color-mix(in_oklch,_var(--foreground)_16%,_transparent)] data-[variant=ghost]:[&:where(:not(:checke" +
"d+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:bg-transparent data-[variant=ghost]:[&:whe" +
"re(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:text-foreground data-[varia" +
"nt=ghost]:before:content-none data-[variant=ghost]:after:content-none data-[variant=ghost]:[&:where(:not(" +
":checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:active:[&:not(:disabled,[data-disab" +
"led])]:[background-color:color-mix(in_oklch,_var(--foreground)_16%,_transparent)] data-[variant=secondary" +
"]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:active:[&:not(:disa" +
"bled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_26%,_transparent)] data-[v" +
"ariant=destructive]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:[" +
"--uiify-button-wash:rgb(255_255_255_/_15%)] data-[variant=destructive]:[&:where(:not(:checked+*,[data-sel" +
"ected],[aria-pressed=true],[aria-current=page]))]:bg-destructive data-[variant=destructive]:text-destruct" +
"ive-foreground data-[variant=destructive]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[a" +
"ria-current=page]))]:active:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(" +
"--destructive),_black_20%)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=outline]:[&" +
":where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:hover:[&:not(:disabled," +
"[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_10%,_transparent)] [@media_(any" +
"-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=ghost]:[&:where(:not(:checked+*,[data-selected],[ar" +
"ia-pressed=true],[aria-current=page]))]:hover:[&:not(:disabled,[data-disabled])]:[background-color:color-" +
"mix(in_oklch,_var(--foreground)_10%,_transparent)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:da" +
"ta-[variant=secondary]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))" +
"]:hover:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_20%,_t" +
"ransparent)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=destructive]:[&:where(:not" +
"(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:hover:[&:not(:disabled,[data-disab" +
"led])]:[background-color:color-mix(in_oklch,_var(--destructive),_black_12%)] [&:is([data-selected],[aria-" +
"pressed=true],[aria-current=page])]:[--uiify-button-rim:rgb(255_255_255_/_20%)] [&:is([data-selected],[ar" +
"ia-pressed=true],[aria-current=page])]:[--uiify-button-wash:rgb(255_255_255_/_15%)] [&:is([data-selected]" +
",[aria-pressed=true],[aria-current=page])]:border-transparent [&:is([data-selected],[aria-pressed=true],[" +
"aria-current=page])]:bg-primary [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:text-prim" +
"ary-foreground [:checked+&]:[--uiify-button-rim:rgb(255_255_255_/_20%)] [:checked+&]:[--uiify-button-wash" +
":rgb(255_255_255_/_15%)] [:checked+&]:border-transparent [:checked+&]:bg-primary [:checked+&]:text-primar" +
"y-foreground [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[&:is([data-selected],[aria-pressed=true" +
"],[aria-current=page]):hover:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--" +
"primary)_88%,_var(--primary-foreground))] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[:checked:n" +
"ot(:disabled)+&:hover]:[background-color:color-mix(in_oklch,_var(--primary)_88%,_var(--primary-foreground" +
"))] [:disabled+&]:opacity-50 [:disabled+&]:cursor-not-allowed [&[hidden]]:hidden data-[variant=link]:px-0" +
" data-[variant=link]:border-0 data-[variant=link]:border-current data-[variant=link]:border-none data-[va" +
"riant=link]:rounded-none data-[variant=link]:bg-transparent data-[variant=link]:text-primary data-[varian" +
"t=link]:underline data-[variant=link]:[text-underline-offset:0.2em] data-[variant=link]:active:px-0 data-" +
"[variant=link]:active:border-0 data-[variant=link]:active:border-current data-[variant=link]:active:borde" +
"r-none data-[variant=link]:active:rounded-none data-[variant=link]:active:bg-transparent data-[variant=li" +
"nk]:active:text-primary data-[variant=link]:active:underline data-[variant=link]:active:[text-underline-o" +
"ffset:0.2em] data-[variant=link]:[min-inline-size:0] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:" +
"data-[variant=link]:hover:px-0 [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:ho" +
"ver:border-0 [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:border-current" +
" [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:border-none [@media_(any-h" +
"over:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:rounded-none [@media_(any-hover:_hover)_a" +
"nd_(any-pointer:_fine)]:data-[variant=link]:hover:bg-transparent [@media_(any-hover:_hover)_and_(any-poin" +
"ter:_fine)]:data-[variant=link]:hover:text-primary [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:da" +
"ta-[variant=link]:hover:underline [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]" +
":hover:[text-underline-offset:0.2em] data-[variant=link]:before:content-none data-[variant=link]:after:co" +
"ntent-none data-[variant=link]:focus-visible:[outline:2px_solid_var(--ring)] data-[variant=link]:focus-vi" +
"sible:[outline-offset:3px] [[data-uiify-toggle]>input:focus-visible+&]:[box-shadow:0_0_0_var(--ring-width" +
")_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [[data-uiify-toggle-group]_[data-part=item]>input:fo" +
"cus-visible+&]:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [[d" +
"ata-uiify-modal][data-part=close]&]:border-transparent [[data-uiify-modal][data-part=close]&]:[background" +
"-color:color-mix(in_oklch,_var(--foreground)_8%,_transparent)] [[data-uiify-modal][data-part=close]&]:tex" +
"t-foreground [[data-uiify-modal][data-part=close]&:hover]:[background-color:color-mix(in_oklch,_var(--for" +
"eground)_14%,_transparent)] [[data-uiify-modal][data-part=close]&:active]:[background-color:color-mix(in_" +
"oklch,_var(--foreground)_20%,_transparent)] [[data-uiify-pagination]_span&:not([data-disabled])]:cursor-d" +
"efault [[data-uiify-input-group]>[data-part=addon]>&]:[min-inline-size:0] [[data-uiify-input-group]>[data" +
"-part=addon]>&]:[max-inline-size:100%] [[data-uiify-input-group]>[data-part=addon]>&]:whitespace-normal [" +
"[data-uiify-input-group]>[data-part=addon]>&]:[overflow-wrap:anywhere] [[data-uiify-item-content]>&]:[jus" +
"tify-self:start]"
}
>
Choose files
</FileUpload.Trigger>
<FileUpload.Dropzone className="">Drop files here</FileUpload.Dropzone>
<FileUpload.List className="">
{(files) =>
files.map((file, index) => (
<FileUpload.Item key={file.name} index={index} className="">
<span>
{file.name} · {(file.size / 1024).toFixed(1)} KB
</span>
<FileUpload.ItemRemove index={index} aria-label={"Remove " + file.name}>
×
</FileUpload.ItemRemove>
</FileUpload.Item>
))
}
</FileUpload.List>
</FileUpload.Root>
);
}/* app.css */
@layer reset, ui, app, tokens, base, demo, components, utilities, theme;
@import "@gunkin/uiify/styles/reset";
@import "@gunkin/uiify/components/behavior.css";
@import "@gunkin/uiify/styles/tokens";
@import "@gunkin/uiify/styles/tailwind";
@import "tailwindcss/utilities.css";
@theme { --spacing: 0.25rem; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; }
@source inline('grid gap-md [inline-size:100%] [max-inline-size:24rem] [&_[data-part=dropzone]]:flex [&_[data-part=dropzone]]:items-center [&_[data-part=dropzone]]:justify-center [&_[data-part=dropzone]]:[min-block-size:8rem] [&_[data-part=dropzone]]:p-lg [&_[data-part=dropzone]]:[border-width:2px] [&_[data-part=dropzone]]:[border-style:dashed] [&_[data-part=dropzone]]:border-input [&_[data-part=dropzone]]:rounded-xl [&_[data-part=dropzone]]:[corner-shape:squircle] [&_[data-part=dropzone]]:bg-secondary [&_[data-part=dropzone]]:text-muted-foreground [&_[data-part=dropzone]]:text-sm [&_[data-part=dropzone]]:text-center [&_[data-part=dropzone]]:[transition:var(--transition-colors)] [&_[data-part=dropzone]:hover]:border-primary [&_[data-part=dropzone]:hover]:[background-color:color-mix(in_oklch,_var(--primary)_8%,_transparent)] [&_[data-part=dropzone]:hover]:text-foreground [&_[data-part=dropzone][data-dragging]]:border-primary [&_[data-part=dropzone][data-dragging]]:[background-color:color-mix(in_oklch,_var(--primary)_8%,_transparent)] [&_[data-part=dropzone][data-dragging]]:text-foreground [&_[data-part=dropzone][data-disabled]]:opacity-50 [&_[data-part=dropzone][data-disabled]]:cursor-not-allowed [&_[data-part=list]]:grid [&_[data-part=list]]:gap-xs [&_[data-part=list]]:m-0 [&_[data-part=list]]:p-0 [&_[data-part=list]]:list-none [&_[data-part=item]]:flex [&_[data-part=item]]:items-center [&_[data-part=item]]:gap-sm [&_[data-part=item]]:[padding:var(--space-sm)_var(--space-md)] [&_[data-part=item]]:border-[length:var(--border-width)] [&_[data-part=item]]:border-solid [&_[data-part=item]]:border-border [&_[data-part=item]]:rounded-lg [&_[data-part=item]]:[corner-shape:squircle] [&_[data-part=item]]:bg-card [&_[data-part=item]]:text-sm [&_[data-part=file-info]]:grid [&_[data-part=file-info]]:[gap:0.25rem] [&_[data-part=file-info]]:[min-inline-size:0] [&_[data-part=file-info]]:[flex:1] [&_[data-part=file-info]]:[overflow-wrap:anywhere] [&_small]:text-muted-foreground [&_[data-part=remove]]:grid [&_[data-part=remove]]:place-items-center [&_[data-part=remove]]:flex-none [&_[data-part=remove]]:[inline-size:2rem] [&_[data-part=remove]]:[block-size:2rem] [&_[data-part=remove]]:[margin-inline-start:auto] [&_[data-part=remove]]:border-0 [&_[data-part=remove]]:border-current [&_[data-part=remove]]:border-none [&_[data-part=remove]]:rounded-[50%] [&_[data-part=remove]]:bg-secondary [&_[data-part=remove]]:text-foreground [&_[data-part=remove]]:[font-size:1.25rem] [&_[data-part=remove]]:leading-none [&_[data-part=remove]]:cursor-pointer [&_[data-part=remove]:hover]:bg-accent [&_[data-part=remove]:focus-visible]:[outline:2px_solid_var(--ring)] [&_[data-part=remove]:focus-visible]:[outline-offset:2px] focus-visible:[outline:none] focus-visible:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [--uiify-button-rim:rgb(255_255_255_/_20%)] [--uiify-button-wash:light-dark(rgb(255_255_255_/_15%),_rgb(255_255_255_/_30%))] relative isolate inline-flex items-center justify-center [gap:0.375rem] [min-block-size:44px] [min-inline-size:44px] py-0 [padding-inline:1.25rem] border-[length:var(--border-width)] border-solid border-transparent rounded-[var(--radius-full)] bg-foreground bg-clip-padding text-background text-base font-[number:var(--weight-medium)] leading-6 no-underline cursor-pointer [transition:var(--transition-colors)] before:absolute before:inset-0 before:z-[-1] before:[border-radius:inherit] before:pointer-events-none after:absolute after:inset-0 after:z-[-1] after:[border-radius:inherit] after:pointer-events-none before:[background-color:var(--uiify-button-wash)] before:[filter:blur(10px)] before:[translate:0_-50%] before:[clip-path:inset(50%_0_-50%_0_round_var(--radius-full))] after:[padding:0.5px] after:[background-image:linear-gradient(to_bottom,_var(--uiify-button-rim),_transparent_75%)] after:[mask:linear-gradient(#fff_0_0)_content-box_exclude,_linear-gradient(#fff_0_0)] [&:is([data-size=sm],[data-size=icon-sm])]:[min-block-size:32px] [&:is([data-size=sm],[data-size=icon-sm])]:[min-inline-size:32px] [&:is([data-size=sm],[data-size=icon-sm])]:[padding-inline:0.75rem] [&:is([data-size=sm],[data-size=icon-sm])]:[gap:0.25rem] [&:is([data-size=sm],[data-size=icon-sm])]:text-sm [&:is([data-size=sm],[data-size=icon-sm])]:leading-5 [&:is([data-size=lg],[data-size=icon-lg])]:[min-block-size:56px] [&:is([data-size=lg],[data-size=icon-lg])]:[min-inline-size:56px] [&:is([data-size=lg],[data-size=icon-lg])]:[padding-inline:1.75rem] [&:is([data-size=lg],[data-size=icon-lg])]:text-lg [&:is([data-size=lg],[data-size=icon-lg])]:leading-7 [&[data-size^=icon]]:px-0 [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:hover:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_90%,_var(--background))] active:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_80%,_var(--background))] disabled:opacity-50 disabled:cursor-not-allowed data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed data-[variant=secondary]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:[--uiify-button-rim:light-dark(rgb(0_0_0_/_5%),_rgb(255_255_255_/_10%))] data-[variant=secondary]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:[--uiify-button-wash:light-dark(rgb(255_255_255_/_20%),_rgb(255_255_255_/_5%))] data-[variant=secondary]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:[background-color:color-mix(in_oklch,_var(--foreground)_10%,_transparent)] data-[variant=secondary]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:text-foreground data-[variant=outline]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:[--uiify-button-rim:color-mix(in_oklch,_var(--foreground)_25%,_transparent)] data-[variant=outline]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:[border-color:color-mix(in_oklch,_var(--foreground)_20%,_transparent)] data-[variant=outline]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:bg-transparent data-[variant=outline]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:text-foreground data-[variant=outline]:before:content-none data-[variant=outline]:after:[inset:calc(-1_*_var(--border-width))] data-[variant=outline]:after:[padding:var(--border-width)] data-[variant=outline]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:active:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_16%,_transparent)] data-[variant=ghost]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:bg-transparent data-[variant=ghost]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:text-foreground data-[variant=ghost]:before:content-none data-[variant=ghost]:after:content-none data-[variant=ghost]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:active:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_16%,_transparent)] data-[variant=secondary]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:active:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_26%,_transparent)] data-[variant=destructive]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:[--uiify-button-wash:rgb(255_255_255_/_15%)] data-[variant=destructive]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:bg-destructive data-[variant=destructive]:text-destructive-foreground data-[variant=destructive]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:active:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--destructive),_black_20%)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=outline]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:hover:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_10%,_transparent)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=ghost]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:hover:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_10%,_transparent)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=secondary]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:hover:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--foreground)_20%,_transparent)] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=destructive]:[&:where(:not(:checked+*,[data-selected],[aria-pressed=true],[aria-current=page]))]:hover:[&:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--destructive),_black_12%)] [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:[--uiify-button-rim:rgb(255_255_255_/_20%)] [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:[--uiify-button-wash:rgb(255_255_255_/_15%)] [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:border-transparent [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:bg-primary [&:is([data-selected],[aria-pressed=true],[aria-current=page])]:text-primary-foreground [:checked+&]:[--uiify-button-rim:rgb(255_255_255_/_20%)] [:checked+&]:[--uiify-button-wash:rgb(255_255_255_/_15%)] [:checked+&]:border-transparent [:checked+&]:bg-primary [:checked+&]:text-primary-foreground [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[&:is([data-selected],[aria-pressed=true],[aria-current=page]):hover:not(:disabled,[data-disabled])]:[background-color:color-mix(in_oklch,_var(--primary)_88%,_var(--primary-foreground))] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:[:checked:not(:disabled)+&:hover]:[background-color:color-mix(in_oklch,_var(--primary)_88%,_var(--primary-foreground))] [:disabled+&]:opacity-50 [:disabled+&]:cursor-not-allowed [&[hidden]]:hidden data-[variant=link]:px-0 data-[variant=link]:border-0 data-[variant=link]:border-current data-[variant=link]:border-none data-[variant=link]:rounded-none data-[variant=link]:bg-transparent data-[variant=link]:text-primary data-[variant=link]:underline data-[variant=link]:[text-underline-offset:0.2em] data-[variant=link]:active:px-0 data-[variant=link]:active:border-0 data-[variant=link]:active:border-current data-[variant=link]:active:border-none data-[variant=link]:active:rounded-none data-[variant=link]:active:bg-transparent data-[variant=link]:active:text-primary data-[variant=link]:active:underline data-[variant=link]:active:[text-underline-offset:0.2em] data-[variant=link]:[min-inline-size:0] [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:px-0 [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:border-0 [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:border-current [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:border-none [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:rounded-none [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:bg-transparent [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:text-primary [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:underline [@media_(any-hover:_hover)_and_(any-pointer:_fine)]:data-[variant=link]:hover:[text-underline-offset:0.2em] data-[variant=link]:before:content-none data-[variant=link]:after:content-none data-[variant=link]:focus-visible:[outline:2px_solid_var(--ring)] data-[variant=link]:focus-visible:[outline-offset:3px] [[data-uiify-toggle]>input:focus-visible+&]:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [[data-uiify-toggle-group]_[data-part=item]>input:focus-visible+&]:[box-shadow:0_0_0_var(--ring-width)_color-mix(in_oklch,_var(--ring)_16%,_transparent)] [[data-uiify-modal][data-part=close]&]:border-transparent [[data-uiify-modal][data-part=close]&]:[background-color:color-mix(in_oklch,_var(--foreground)_8%,_transparent)] [[data-uiify-modal][data-part=close]&]:text-foreground [[data-uiify-modal][data-part=close]&:hover]:[background-color:color-mix(in_oklch,_var(--foreground)_14%,_transparent)] [[data-uiify-modal][data-part=close]&:active]:[background-color:color-mix(in_oklch,_var(--foreground)_20%,_transparent)] [[data-uiify-pagination]_span&:not([data-disabled])]:cursor-default [[data-uiify-input-group]>[data-part=addon]>&]:[min-inline-size:0] [[data-uiify-input-group]>[data-part=addon]>&]:[max-inline-size:100%] [[data-uiify-input-group]>[data-part=addon]>&]:whitespace-normal [[data-uiify-input-group]>[data-part=addon]>&]:[overflow-wrap:anywhere] [[data-uiify-item-content]>&]:[justify-self:start]');
@source inline("before:content-[''] after:content-['']");
@layer base { :root { --uiify-control-text: var(--text-sm); } @media (pointer: coarse) { :root { --uiify-control-text: var(--text-base); } } }
/* Authored animation and registered properties used by the Tailwind skin.
* Visual rules belong in utility recipes; only at-rule definitions live here. */
@layer components {
@keyframes uiify-presence-in {
from {
opacity: 0;
scale: var(--presence-scale);
}
}
}
@layer components {
@keyframes uiify-presence-out {
to {
opacity: 0;
scale: var(--presence-scale);
}
}
}
@property --uiify-spinner-tail {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
@property --uiify-spinner-length {
syntax: "<angle>";
inherits: false;
initial-value: 36deg;
}
@layer components {
@keyframes uiify-spinner-rotate {
to {
transform: rotate(360deg);
}
}
}
@layer components {
@keyframes uiify-spinner-orbit {
0% {
--uiify-spinner-tail: 0deg;
--uiify-spinner-length: 36deg;
}
50% {
--uiify-spinner-tail: 90deg;
--uiify-spinner-length: 324deg;
}
100% {
--uiify-spinner-tail: 360deg;
--uiify-spinner-length: 36deg;
}
}
}
@layer components {
@keyframes uiify-skeleton-pulse {
50% {
opacity: 0.45;
}
}
}
@layer components {
@keyframes uiify-skeleton-shimmer {
to {
background-position: -200% 0;
}
}
}
@layer components {
@keyframes uiify-skeleton-reveal {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
@property --candle-body-height {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-body-top {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --candle-slot {
syntax: "<percentage>";
inherits: true;
initial-value: 100%;
}
@property --candle-wick-height {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-wick-top {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --candle-x {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-scale {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
@property --line-y {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --line-prev-y {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --line-count {
syntax: "<integer>";
inherits: false;
initial-value: 1;
}
@property --line-scale {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
@layer components {
@keyframes uiify-otp-input-caret-blink {
50% {
opacity: 0;
}
}
}API
FileUpload.Root
| الخاصية | النوع | افتراضي | الوصف |
|---|---|---|---|
children | ReactNode | — | أجزاء رفع الملفات: المدخل المخفي وزر التفعيل ومنطقة الإسقاط والقائمة. |
value | readonly File[] | — | الملفات الحالية، وتجعل المكوّن متحكّمًا به. |
defaultValue | readonly File[] | [] | الملفات الأولية للمكوّن غير المتحكّم به. |
onValueChange | (files: File[]) => void | — | تُستدعى بالملفات المقبولة كلما تغيّر التحديد. |
onReject | (rejections: FileRejection[]) => void | — | تُستدعى بالملفات التي أخفقت في التحقق وأسباب الإخفاق. |
accept | string[] | [] | أنواع الملفات المقبولة، كامتدادات أو أنواع MIME. |
maxFiles | number | — | أقصى عدد ملفات يمكن الاحتفاظ بها في الوقت نفسه. |
maxSize | number | — | أقصى حجم مقبول للملف بالبايت. |
minSize | number | — | أدنى حجم مقبول للملف بالبايت. |
multiple | boolean | false | يتيح للمنتقي تحديد أكثر من ملف واحد. |
disabled | boolean | false | يعطّل المنتقي ومنطقة الإسقاط وأزرار الإزالة. |
FileUpload.HiddenInput
| الخاصية | النوع | افتراضي | الوصف |
|---|---|---|---|
className | string | — | الفئة المطبّقة على مدخل الملف الأصلي. |
FileUpload.Trigger
| الخاصية | النوع | افتراضي | الوصف |
|---|---|---|---|
children | ReactNode | — | محتوى عنصر التحكم الذي يفتح منتقي الملفات. |
className | string | — | الفئة المطبّقة على عنصر التفعيل. |
render | ReactElement | ((props, state) => ReactElement) | — | استبدل العنصر المعروض مع الحفاظ على توصيلات السلوك وإمكانية الوصول. |
FileUpload.Dropzone
| الخاصية | النوع | افتراضي | الوصف |
|---|---|---|---|
children | ReactNode | — | محتوى هدف الإسقاط. |
className | string | — | الفئة المطبّقة على عنصر منطقة الإسقاط. |
render | ReactElement | ((props, state) => ReactElement) | — | استبدل العنصر المعروض مع الحفاظ على توصيلات السلوك وإمكانية الوصول. |
FileUpload.List
| الخاصية | النوع | افتراضي | الوصف |
|---|---|---|---|
children | ReactNode | ((files: readonly File[]) => ReactNode) | — | اعرض الملفات المقبولة من القائمة الحية. تنعكس تغييرات القيمة المتحكّم بها وإعادة الضبط الخارجية فورًا. |
className | string | — | الفئة المطبّقة على عنصر القائمة. |
FileUpload.Item
| الخاصية | النوع | افتراضي | الوصف |
|---|---|---|---|
children | ReactNode | — | محتوى يصف الملف، مثل اسمه وحجمه. |
className | string | — | الفئة المطبّقة على العنصر. |
index* | number | — | موضع الملف الذي يمثّله هذا العنصر. |
render | ReactElement | ((props, state) => ReactElement) | — | استبدل العنصر المعروض مع الحفاظ على توصيلات السلوك وإمكانية الوصول. |
FileUpload.ItemRemove
| الخاصية | النوع | افتراضي | الوصف |
|---|---|---|---|
className | string | — | الفئة المطبّقة على زر الإزالة. |
index* | number | — | موضع الملف الذي يزيله هذا الزر. |
FileRejection
| الخاصية | النوع | افتراضي | الوصف |
|---|---|---|---|
file* | File | — | الملف الذي لم يُقبل. |
reason* | "accept" | "max-size" | "max-files" | — | القاعدة التي أخفق الملف في استيفائها. |
لوحة المفاتيح
| المفتاح | الإجراء |
|---|---|
| Enter / Space | فتح منتقي الملفات من Trigger أو إزالة ملف مركّز |
| Tab | التنقل بين زر تفعيل المنتقي وعناصر تحكم إزالة الملفات |
إمكانية الوصول
وفّر لـ HiddenInput تسمية للتقنيات المساعدة. تتلقى List الملفات المقبولة وتعرض أسماءها وأحجامها وأزرار إزالتها ذات التسميات. يدعم Root قيمة متحكّمًا بها والتحقق التراكمي من maxFiles وmaxSize وaccept؛ ويبلّغ onReject عن الملفات المرفوضة. تمنع الجذور المعطّلة إجراءات المنتقي والإسقاط والإزالة. تتطلب معالجة الملفات الإماهة.
نقاط التنسيق
data-uiify-file-uploaddata-partdata-disableddata-state