@scattered-light/loomiere-mojave 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -1
- package/dist/exports/AGENTS.md +150 -0
- package/dist/exports/catalog.json +99 -1
- package/dist/exports/design-system/README.md +142 -0
- package/dist/exports/design-system/components/Accordion/README.md +97 -0
- package/dist/exports/design-system/components/Accordion/preview.html +19 -0
- package/dist/exports/design-system/components/AlertDialog/README.md +52 -0
- package/dist/exports/design-system/components/AlertDialog/preview.html +19 -0
- package/dist/exports/design-system/components/Autocomplete/README.md +68 -0
- package/dist/exports/design-system/components/Autocomplete/preview.html +19 -0
- package/dist/exports/design-system/components/Avatar/README.md +39 -0
- package/dist/exports/design-system/components/Avatar/preview.html +19 -0
- package/dist/exports/design-system/components/Button/README.md +27 -0
- package/dist/exports/design-system/components/Button/preview.html +23 -0
- package/dist/exports/design-system/components/Checkbox/README.md +39 -0
- package/dist/exports/design-system/components/Checkbox/preview.html +19 -0
- package/dist/exports/design-system/components/CheckboxGroup/README.md +56 -0
- package/dist/exports/design-system/components/CheckboxGroup/preview.html +19 -0
- package/dist/exports/design-system/components/Collapsible/README.md +48 -0
- package/dist/exports/design-system/components/Collapsible/preview.html +19 -0
- package/dist/exports/design-system/components/Combobox/README.md +105 -0
- package/dist/exports/design-system/components/Combobox/preview.html +19 -0
- package/dist/exports/design-system/components/ContextMenu/README.md +70 -0
- package/dist/exports/design-system/components/ContextMenu/preview.html +19 -0
- package/dist/exports/design-system/components/Cover/preview.html +39 -0
- package/dist/exports/design-system/components/Dialog/README.md +62 -0
- package/dist/exports/design-system/components/Dialog/preview.html +19 -0
- package/dist/exports/design-system/components/Drawer/README.md +32 -0
- package/dist/exports/design-system/components/Drawer/preview.html +19 -0
- package/dist/exports/design-system/components/Field/README.md +41 -0
- package/dist/exports/design-system/components/Field/preview.html +19 -0
- package/dist/exports/design-system/components/Fieldset/README.md +45 -0
- package/dist/exports/design-system/components/Fieldset/preview.html +19 -0
- package/dist/exports/design-system/components/Form/README.md +57 -0
- package/dist/exports/design-system/components/Form/preview.html +19 -0
- package/dist/exports/design-system/components/Input/README.md +38 -0
- package/dist/exports/design-system/components/Input/preview.html +19 -0
- package/dist/exports/design-system/components/Menu/README.md +58 -0
- package/dist/exports/design-system/components/Menu/preview.html +19 -0
- package/dist/exports/design-system/components/Menubar/README.md +105 -0
- package/dist/exports/design-system/components/Menubar/preview.html +19 -0
- package/dist/exports/design-system/components/Meter/README.md +43 -0
- package/dist/exports/design-system/components/Meter/preview.html +19 -0
- package/dist/exports/design-system/components/NavigationMenu/README.md +148 -0
- package/dist/exports/design-system/components/NavigationMenu/preview.html +19 -0
- package/dist/exports/design-system/components/NumberField/README.md +58 -0
- package/dist/exports/design-system/components/NumberField/preview.html +19 -0
- package/dist/exports/design-system/components/OTPField/README.md +39 -0
- package/dist/exports/design-system/components/OTPField/preview.html +19 -0
- package/dist/exports/design-system/components/Popover/README.md +56 -0
- package/dist/exports/design-system/components/Popover/preview.html +19 -0
- package/dist/exports/design-system/components/PreviewCard/README.md +74 -0
- package/dist/exports/design-system/components/PreviewCard/preview.html +19 -0
- package/dist/exports/design-system/components/Progress/README.md +58 -0
- package/dist/exports/design-system/components/Progress/preview.html +19 -0
- package/dist/exports/design-system/components/Radio/README.md +74 -0
- package/dist/exports/design-system/components/Radio/preview.html +19 -0
- package/dist/exports/design-system/components/ScrollArea/README.md +62 -0
- package/dist/exports/design-system/components/ScrollArea/preview.html +40 -0
- package/dist/exports/design-system/components/Select/README.md +84 -0
- package/dist/exports/design-system/components/Select/preview.html +19 -0
- package/dist/exports/design-system/components/Separator/README.md +37 -0
- package/dist/exports/design-system/components/Separator/preview.html +19 -0
- package/dist/exports/design-system/components/Slider/README.md +44 -0
- package/dist/exports/design-system/components/Slider/preview.html +19 -0
- package/dist/exports/design-system/components/Switch/README.md +34 -0
- package/dist/exports/design-system/components/Switch/preview.html +19 -0
- package/dist/exports/design-system/components/Tabs/README.md +56 -0
- package/dist/exports/design-system/components/Tabs/preview.html +19 -0
- package/dist/exports/design-system/components/Toast/README.md +78 -0
- package/dist/exports/design-system/components/Toast/preview.html +19 -0
- package/dist/exports/design-system/components/Toggle/README.md +32 -0
- package/dist/exports/design-system/components/Toggle/preview.html +19 -0
- package/dist/exports/design-system/components/ToggleGroup/README.md +40 -0
- package/dist/exports/design-system/components/ToggleGroup/preview.html +19 -0
- package/dist/exports/design-system/components/Toolbar/README.md +65 -0
- package/dist/exports/design-system/components/Toolbar/preview.html +19 -0
- package/dist/exports/design-system/components/Tooltip/README.md +46 -0
- package/dist/exports/design-system/components/Tooltip/preview.html +19 -0
- package/dist/exports/design-system/components/bundle.css +9881 -0
- package/dist/exports/design-system/components/bundle.js +5 -0
- package/dist/exports/design-system/components/index.d.ts +107 -0
- package/dist/exports/design-system/tokens.json +3063 -0
- package/dist/exports/shadcn.css +111 -0
- package/dist/exports/tailwind.css +1230 -36
- package/package.json +4 -2
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- @dsCard group="Forms" height=480 subtitle="Default / MultipleSelect / Grouped / Creatable" -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<style>
|
|
7
|
+
body { margin: 0; padding: var(--sl-space-4, 16px); background: var(--sl-surface-canvas); color: var(--sl-text-primary); }
|
|
8
|
+
#root { display: grid; gap: var(--sl-space-5, 20px); }
|
|
9
|
+
.ds-story-name { margin: 0 0 var(--sl-space-2, 8px); font: var(--sl-font-minimize-label-font, 500 10px sans-serif); color: var(--sl-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; }
|
|
10
|
+
</style>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
<script>
|
|
15
|
+
(()=>{var q=Object.create;var V=Object.defineProperty;var ee=Object.getOwnPropertyDescriptor;var oe=Object.getOwnPropertyNames;var ae=Object.getPrototypeOf,te=Object.prototype.hasOwnProperty;var O=(a,t)=>()=>(t||a((t={exports:{}}).exports,t),t.exports),se=(a,t)=>{for(var l in t)V(a,l,{get:t[l],enumerable:!0})},ne=(a,t,l,r)=>{if(t&&typeof t=="object"||typeof t=="function")for(let m of oe(t))!te.call(a,m)&&m!==l&&V(a,m,{get:()=>t[m],enumerable:!(r=ee(t,m))||r.enumerable});return a};var U=(a,t,l)=>(l=a!=null?q(ae(a)):{},ne(t||!a||!a.__esModule?V(l,"default",{value:a,enumerable:!0}):l,a));var $=O((he,G)=>{G.exports=window.React});var K=O((Ne,H)=>{H.exports=window.Loomiere.Base});var _=O((fe,W)=>{W.exports=window.Loomiere.Base});var j={};se(j,{AsyncSearchMultiple:()=>Ce,AsyncSearchSingle:()=>pe,Creatable:()=>be,Default:()=>re,Grouped:()=>ie,InputInsidePopup:()=>ue,MultipleSelect:()=>me,default:()=>B});var n=U($(),1),o=U(K(),1),v=U(_(),1);var k=window.React;function e(a,t,l){let{children:r,...m}=t||{};return l!==void 0&&(m.key=l),r===void 0?k.createElement(a,m):Array.isArray(r)?k.createElement(a,m,...r):k.createElement(a,m,r)}var ve=k.Fragment;var Q=["Apple","Banana","Cherry","Date","Elderberry","Fig","Grape","Honeydew","Kiwi","Lemon","Mango","Orange"],le={title:"Components/Combobox",parameters:{layout:"centered"},tags:["autodocs"]},B=le,re={render:()=>{let a=n.useId();return e("div",{className:"ComboboxRoot",style:{width:"400px"},children:e(o.Combobox.Root,{items:Q,children:[e("label",{htmlFor:a,className:"ComboboxLabel",children:["Choose a fruit",e("div",{className:"ComboboxInputWrapper",children:[e(o.Combobox.Input,{placeholder:"e.g. Apple",id:a,className:"ComboboxInput"}),e("div",{className:"ComboboxActionButtons",children:[e(o.Combobox.Clear,{className:"ComboboxClear","aria-label":"Clear selection",children:e("span",{className:"material-symbols-outlined ComboboxClearIcon",children:"close"})}),e(o.Combobox.Trigger,{className:"ComboboxTrigger","aria-label":"Open popup",children:e("span",{className:"material-symbols-outlined ComboboxTriggerIcon",children:"expand_more"})})]})]})]}),e(o.Combobox.Portal,{children:e(o.Combobox.Positioner,{className:"ComboboxPositioner",sideOffset:4,children:e(o.Combobox.Popup,{className:"ComboboxPopup",children:[e(o.Combobox.Empty,{className:"ComboboxEmpty",children:"No fruits found."}),e(o.Combobox.List,{className:"ComboboxList",children:t=>e(o.Combobox.Item,{value:t,className:"ComboboxItem",children:[e(o.Combobox.ItemIndicator,{className:"ComboboxItemIndicator",children:e("span",{className:"material-symbols-outlined ComboboxItemIndicatorIcon",children:"check"})}),e("div",{className:"ComboboxItemText",children:t})]},t)})]})})})]})})}},me={render:()=>{let a=n.useRef(null),t=n.useId();return e("div",{className:"ComboboxRoot",style:{width:"400px"},children:e(o.Combobox.Root,{items:Q,multiple:!0,children:[e("div",{className:"ComboboxContainer",children:[e("label",{className:"ComboboxLabel",htmlFor:t,children:"Choose fruits"}),e(o.Combobox.Chips,{className:"ComboboxChips",ref:a,children:e(o.Combobox.Value,{children:l=>e(n.Fragment,{children:[l.map(r=>e(o.Combobox.Chip,{className:"ComboboxChip","aria-label":r,children:[r,e(o.Combobox.ChipRemove,{className:"ComboboxChipRemove","aria-label":`Remove ${r}`,children:e("span",{className:"material-symbols-outlined ComboboxChipRemoveIcon",children:"close"})})]},r)),e(o.Combobox.Input,{id:t,placeholder:l.length>0?"":"e.g. Apple",className:"ComboboxInput"})]})})})]}),e(o.Combobox.Portal,{children:e(o.Combobox.Positioner,{className:"ComboboxPositioner",sideOffset:4,anchor:a,children:e(o.Combobox.Popup,{className:"ComboboxPopup",children:[e(o.Combobox.Empty,{className:"ComboboxEmpty",children:"No fruits found."}),e(o.Combobox.List,{className:"ComboboxList",children:l=>e(o.Combobox.Item,{value:l,className:"ComboboxItem",children:[e(o.Combobox.ItemIndicator,{className:"ComboboxItemIndicator",children:e("span",{className:"material-symbols-outlined ComboboxItemIndicatorIcon",children:"check"})}),e("div",{className:"ComboboxItemText",children:l})]},l)})]})})})]})})}},z=[{category:"Citrus",items:["Lemon","Lime","Orange","Grapefruit"]},{category:"Berries",items:["Strawberry","Blueberry","Raspberry","Blackberry"]},{category:"Tropical",items:["Mango","Pineapple","Papaya","Coconut"]}],ie={render:()=>{let a=n.useId(),t=z.flatMap(l=>l.items);return e("div",{className:"ComboboxRoot",style:{width:"400px"},children:e(o.Combobox.Root,{items:t,children:[e("label",{htmlFor:a,className:"ComboboxLabel",children:["Choose a fruit",e("div",{className:"ComboboxInputWrapper",children:[e(o.Combobox.Input,{placeholder:"Search fruits...",id:a,className:"ComboboxInput"}),e("div",{className:"ComboboxActionButtons",children:[e(o.Combobox.Clear,{className:"ComboboxClear","aria-label":"Clear selection",children:e("span",{className:"material-symbols-outlined ComboboxClearIcon",children:"close"})}),e(o.Combobox.Trigger,{className:"ComboboxTrigger","aria-label":"Open popup",children:e("span",{className:"material-symbols-outlined ComboboxTriggerIcon",children:"expand_more"})})]})]})]}),e(o.Combobox.Portal,{children:e(o.Combobox.Positioner,{className:"ComboboxPositioner",sideOffset:4,children:e(o.Combobox.Popup,{className:"ComboboxPopup",children:[e(o.Combobox.Empty,{className:"ComboboxEmpty",children:"No fruits found."}),z.map((l,r)=>e(n.Fragment,{children:[r>0&&e(o.Combobox.Separator,{className:"ComboboxSeparator"}),e(o.Combobox.Group,{className:"ComboboxGroup",children:[e(o.Combobox.GroupLabel,{className:"ComboboxGroupLabel",children:l.category}),l.items.map(m=>e(o.Combobox.Item,{value:m,className:"ComboboxItem",children:[e(o.Combobox.ItemIndicator,{className:"ComboboxItemIndicator",children:e("span",{className:"material-symbols-outlined ComboboxItemIndicatorIcon",children:"check"})}),e("div",{className:"ComboboxItemText",children:m})]},m))]})]},l.category))]})})})]})})}},ce=[{id:"bug",value:"bug"},{id:"docs",value:"documentation"},{id:"enhancement",value:"enhancement"},{id:"help-wanted",value:"help wanted"},{id:"good-first-issue",value:"good first issue"}],be={render:()=>{let a=n.useId(),[t,l]=n.useState(ce),[r,m]=n.useState([]),[R,g]=n.useState(""),[f,d]=n.useState(!1),p=n.useRef(null),y=n.useRef(null),h=n.useRef(null),I=n.useRef(""),N=n.useRef(void 0);function D(s){if(s.key!=="Enter"||N.current)return;let c=R.trim();if(c==="")return;let C=c.toLocaleLowerCase(),u=t.find(x=>x.value.trim().toLocaleLowerCase()===C);if(u){m(x=>x.some(F=>F.id===u.id)?x:[...x,u]),g("");return}I.current=c,d(!0)}function L(){let s=y.current||h.current,c=s?s.value.trim():"";if(!c)return;let C=c.toLocaleLowerCase(),u=C.replace(/\s+/g,"-"),x=t.find(b=>b.value.trim().toLocaleLowerCase()===C);if(x){m(b=>b.some(Y=>Y.id===x.id)?b:[...b,x]),d(!1),g("");return}let F=new Set(t.map(b=>b.id)),A=u;if(F.has(A)){let b=2;for(;F.has(`${u}-${b}`);)b+=1;A=`${u}-${b}`}let M={id:A,value:c};r.find(b=>b.id===M.id)||(l(b=>[...b,M]),m(b=>[...b,M])),d(!1),g("")}function P(s){s.preventDefault(),L()}let i=R.trim(),E=i.toLocaleLowerCase(),w=t.some(s=>s.value.trim().toLocaleLowerCase()===E),T=i!==""&&!w?[...t,{creatable:i,id:`create:${E}`,value:`Create "${i}"`}]:t;return e("div",{className:"ComboboxRoot",style:{width:"400px"},children:e(n.Fragment,{children:[e(o.Combobox.Root,{items:T,multiple:!0,onValueChange:s=>{let c=s.find(u=>u.creatable&&!r.some(x=>x.id===u.id));if(c&&c.creatable){I.current=c.creatable,d(!0);return}let C=s.filter(u=>!u.creatable);m(C),g("")},value:r,inputValue:R,onInputValueChange:g,onItemHighlighted:s=>{N.current=s},children:[e("div",{className:"ComboboxContainer",children:[e("label",{className:"ComboboxLabel",htmlFor:a,children:"Labels"}),e(o.Combobox.Chips,{className:"ComboboxChips",ref:p,children:e(o.Combobox.Value,{children:s=>e(n.Fragment,{children:[s.map(c=>e(o.Combobox.Chip,{className:"ComboboxChip","aria-label":c.value,children:[c.value,e(o.Combobox.ChipRemove,{className:"ComboboxChipRemove","aria-label":"Remove",children:e("span",{className:"material-symbols-outlined ComboboxChipRemoveIcon",children:"close"})})]},c.id)),e(o.Combobox.Input,{ref:h,id:a,placeholder:s.length>0?"":"e.g. bug",className:"ComboboxInput",onKeyDown:D})]})})})]}),e(o.Combobox.Portal,{children:e(o.Combobox.Positioner,{className:"ComboboxPositioner",sideOffset:4,anchor:p,children:e(o.Combobox.Popup,{className:"ComboboxPopup",children:[e(o.Combobox.Empty,{className:"ComboboxEmpty",children:"No labels found."}),e(o.Combobox.List,{className:"ComboboxList",children:s=>s.creatable?e(o.Combobox.Item,{className:"ComboboxItem",value:s,children:[e("span",{className:"ComboboxItemIndicator",children:e("span",{className:"material-symbols-outlined ComboboxItemIndicatorIcon",children:"add"})}),e("div",{className:"ComboboxItemText",children:['Create "',s.creatable,'"']})]},s.id):e(o.Combobox.Item,{className:"ComboboxItem",value:s,children:[e(o.Combobox.ItemIndicator,{className:"ComboboxItemIndicator",children:e("span",{className:"material-symbols-outlined ComboboxItemIndicatorIcon",children:"check"})}),e("div",{className:"ComboboxItemText",children:s.value})]},s.id)})]})})})]}),e(v.Dialog.Root,{open:f,onOpenChange:d,children:e(v.Dialog.Portal,{children:[e(v.Dialog.Backdrop,{className:"DialogBackdrop"}),e(v.Dialog.Popup,{className:"DialogPopup",initialFocus:y,children:[e(v.Dialog.Title,{className:"DialogTitle",children:"Create new label"}),e(v.Dialog.Description,{className:"DialogDescription",children:"Add a new label to select."}),e("form",{onSubmit:P,children:[e("input",{ref:y,className:"Input",placeholder:"Label name",defaultValue:I.current}),e("div",{className:"DialogActions",children:[e(v.Dialog.Close,{className:"Button","data-variant":"ghost",children:"Cancel"}),e("button",{type:"submit",className:"Button",children:"Create"})]})]})]})]})})]})})}},J=[{code:"",value:null,continent:"",label:"Select country"},{code:"af",value:"afghanistan",label:"Afghanistan",continent:"Asia"},{code:"au",value:"australia",label:"Australia",continent:"Oceania"},{code:"ca",value:"canada",label:"Canada",continent:"North America"},{code:"cn",value:"china",label:"China",continent:"Asia"},{code:"fr",value:"france",label:"France",continent:"Europe"},{code:"de",value:"germany",label:"Germany",continent:"Europe"},{code:"in",value:"india",label:"India",continent:"Asia"},{code:"jp",value:"japan",label:"Japan",continent:"Asia"},{code:"mx",value:"mexico",label:"Mexico",continent:"North America"},{code:"gb",value:"united-kingdom",label:"United Kingdom",continent:"Europe"},{code:"us",value:"united-states",label:"United States",continent:"North America"}],ue={render:()=>e("div",{className:"ComboboxRoot",style:{width:"400px"},children:e(o.Combobox.Root,{items:J,defaultValue:J[0],children:[e(o.Combobox.Trigger,{className:"ComboboxSelectTrigger",children:[e(o.Combobox.Value,{}),e(o.Combobox.Icon,{className:"ComboboxIcon",children:e("span",{className:"material-symbols-outlined",children:"unfold_more"})})]}),e(o.Combobox.Portal,{children:e(o.Combobox.Positioner,{className:"ComboboxPositioner",align:"start",sideOffset:4,children:e(o.Combobox.Popup,{className:"ComboboxPopup","aria-label":"Select country",children:[e("div",{className:"ComboboxInputContainer",children:e(o.Combobox.Input,{placeholder:"e.g. United Kingdom",className:"ComboboxInput"})}),e(o.Combobox.Empty,{className:"ComboboxEmpty",children:"No countries found."}),e(o.Combobox.List,{className:"ComboboxList",children:a=>e(o.Combobox.Item,{value:a,className:"ComboboxItem",children:[e(o.Combobox.ItemIndicator,{className:"ComboboxItemIndicator",children:e("span",{className:"material-symbols-outlined ComboboxItemIndicatorIcon",children:"check"})}),e("div",{className:"ComboboxItemText",children:a.label??a.value})]},a.code)})]})})})]})})},de=[{id:"leslie-alexander",name:"Leslie Alexander",username:"leslie",email:"leslie.alexander@example.com",title:"Product Manager"},{id:"kathryn-murphy",name:"Kathryn Murphy",username:"kathryn",email:"kathryn.murphy@example.com",title:"Marketing Lead"},{id:"courtney-henry",name:"Courtney Henry",username:"courtney",email:"courtney.henry@example.com",title:"Design Systems"},{id:"michael-foster",name:"Michael Foster",username:"michael",email:"michael.foster@example.com",title:"Engineering Manager"},{id:"lindsay-walton",name:"Lindsay Walton",username:"lindsay",email:"lindsay.walton@example.com",title:"Product Designer"},{id:"tom-cook",name:"Tom Cook",username:"tom",email:"tom.cook@example.com",title:"Frontend Engineer"},{id:"whitney-francis",name:"Whitney Francis",username:"whitney",email:"whitney.francis@example.com",title:"Customer Success"},{id:"jacob-jones",name:"Jacob Jones",username:"jacob",email:"jacob.jones@example.com",title:"Security Engineer"}];async function Z(a,t){return await new Promise(r=>{setTimeout(r,Math.random()*500+100)}),Math.random()<.01||a==="will_error"?{users:[],error:"Failed to fetch people. Please try again."}:{users:de.filter(r=>t(r.name,a)||t(r.username,a)||t(r.email,a)||t(r.title,a)),error:null}}var pe={render:()=>{let a=n.useId(),[t,l]=n.useState([]),[r,m]=n.useState(null),[R,g]=n.useState(""),[f,d]=n.useState(null),[p,y]=n.useTransition(),{contains:h}=o.Combobox.useFilter(),I=n.useRef(null),N=R.trim(),D=n.useMemo(()=>!r||t.some(i=>i.id===r.id)?t:[...t,r],[t,r]);function L(){return p?e(n.Fragment,{children:[e("span",{className:"ComboboxSpinner","aria-hidden":!0}),"Searching..."]}):f||(N===""?r?null:"Start typing to search people...":t.length===0?`No matches for "${N}".`:null)}function P(){return N===""||p||t.length>0||f?null:"Try a different search term."}return e("div",{className:"ComboboxRoot",style:{width:"400px"},children:e(o.Combobox.Root,{items:D,itemToStringLabel:i=>i.name,filter:null,onOpenChangeComplete:i=>{!i&&r&&l([r])},onValueChange:i=>{m(i),g(""),d(null)},onInputValueChange:(i,{reason:E})=>{g(i);let w=new AbortController;if(I.current?.abort(),I.current=w,i===""){l([]),d(null);return}E!=="item-press"&&y(()=>{(async()=>{d(null);let T=await Z(i,h);w.signal.aborted||y(()=>{l(T.users),d(T.error)})})()})},children:[e("div",{className:"ComboboxLabel",children:[e("label",{htmlFor:a,children:"Assign reviewer"}),e("div",{className:"ComboboxInputWrapper",children:[e(o.Combobox.Input,{id:a,placeholder:"e.g. Michael",className:"ComboboxInput"}),e("div",{className:"ComboboxActionButtons",children:[e(o.Combobox.Clear,{className:"ComboboxClear","aria-label":"Clear selection",children:e("span",{className:"material-symbols-outlined ComboboxClearIcon",children:"close"})}),e(o.Combobox.Trigger,{className:"ComboboxTrigger","aria-label":"Open popup",children:e("span",{className:"material-symbols-outlined ComboboxTriggerIcon",children:"expand_more"})})]})]})]}),e(o.Combobox.Portal,{children:e(o.Combobox.Positioner,{className:"ComboboxPositioner",sideOffset:4,children:e(o.Combobox.Popup,{className:"ComboboxPopup","aria-busy":p||void 0,children:[e(o.Combobox.Status,{className:"ComboboxStatus visually-hidden",children:L()}),e(o.Combobox.Empty,{className:"ComboboxEmpty",children:P()}),e(o.Combobox.List,{className:"ComboboxList",children:i=>e(o.Combobox.Item,{className:"ComboboxItem",value:i,children:[e(o.Combobox.ItemIndicator,{className:"ComboboxItemIndicator",children:e("span",{className:"material-symbols-outlined ComboboxItemIndicatorIcon",children:"check"})}),e("div",{className:"ComboboxItemText",children:[e("div",{className:"ComboboxItemTitle",children:i.name}),e("div",{className:"ComboboxItemSubtitle",children:[e("span",{className:"ComboboxItemUsername",children:["@",i.username]}),e("span",{children:i.title})]}),e("div",{className:"ComboboxItemEmail",children:i.email})]})]},i.id)})]})})})]})})}},Ce={render:()=>{let a=n.useId(),t=n.useRef(null),[l,r]=n.useState([]),[m,R]=n.useState([]),[g,f]=n.useState(""),[d,p]=n.useState(null),[y,h]=n.useState(!1),[I,N]=n.useTransition(),{contains:D}=o.Combobox.useFilter(),L=n.useRef(null),P=n.useRef([]),i=g.trim(),E=n.useMemo(()=>{if(m.length===0)return l;let s=[...l];return m.forEach(c=>{l.some(C=>C.id===c.id)||s.push(c)}),s},[l,m]);function w(){return I?e(n.Fragment,{children:[e("span",{className:"ComboboxSpinner","aria-hidden":!0}),"Searching..."]}):d||(i===""&&!y?m.length>0?null:"Start typing to search people...":l.length===0&&!y?`No matches for "${i}".`:null)}function T(){return i===""||I||l.length>0||d?null:"Try a different search term."}return e("div",{className:"ComboboxRoot",style:{width:"400px"},children:e(o.Combobox.Root,{items:E,itemToStringLabel:s=>s.name,multiple:!0,filter:null,onOpenChangeComplete:s=>{s||(r(P.current),h(!1))},onValueChange:s=>{P.current=s,R(s),f(""),p(null),s.length===0?(r([]),h(!1)):h(!0)},onInputValueChange:(s,{reason:c})=>{f(s);let C=new AbortController;if(L.current?.abort(),L.current=C,s===""){r(P.current),p(null),h(!1);return}c!=="item-press"&&N(()=>{(async()=>{p(null);let u=await Z(s,D);C.signal.aborted||N(()=>{r(u.users),p(u.error)})})()})},children:[e("div",{className:"ComboboxContainer",children:[e("label",{className:"ComboboxLabel",htmlFor:a,children:"Assign reviewers"}),e(o.Combobox.Chips,{className:"ComboboxChips",ref:t,children:e(o.Combobox.Value,{children:s=>e(n.Fragment,{children:[s.map(c=>e(o.Combobox.Chip,{className:"ComboboxChip","aria-label":c.name,children:[c.name,e(o.Combobox.ChipRemove,{className:"ComboboxChipRemove","aria-label":"Remove",children:e("span",{className:"material-symbols-outlined ComboboxChipRemoveIcon",children:"close"})})]},c.id)),e(o.Combobox.Input,{id:a,placeholder:s.length>0?"":"e.g. Michael",className:"ComboboxInput"})]})})})]}),e(o.Combobox.Portal,{children:e(o.Combobox.Positioner,{className:"ComboboxPositioner",anchor:t,sideOffset:4,children:e(o.Combobox.Popup,{className:"ComboboxPopup","aria-busy":I||void 0,children:[e(o.Combobox.Status,{className:"ComboboxStatus visually-hidden",children:w()}),e(o.Combobox.Empty,{className:"ComboboxEmpty",children:T()}),e(o.Combobox.List,{className:"ComboboxList",children:s=>e(o.Combobox.Item,{className:"ComboboxItem",value:s,children:[e(o.Combobox.ItemIndicator,{className:"ComboboxItemIndicator",children:e("span",{className:"material-symbols-outlined ComboboxItemIndicatorIcon",children:"check"})}),e("div",{className:"ComboboxItemText",children:[e("div",{className:"ComboboxItemTitle",children:s.name}),e("div",{className:"ComboboxItemSubtitle",children:[e("span",{className:"ComboboxItemUsername",children:["@",s.username]}),e("span",{children:s.title})]}),e("div",{className:"ComboboxItemEmail",children:s.email})]})]},s.id)})]})})})]})})}};var S=window.React,X=B||{},xe=["Default","MultipleSelect","Grouped","Creatable"];function ge({id:a}){let t=j[a],l={...X.args||{},...t.args||{}};return(t.render||(m=>S.createElement(X.component,m)))(l,{args:l,id:a,name:a})}var Ie=xe.map(a=>S.createElement("section",{key:a,className:"ds-story"},S.createElement("p",{className:"ds-story-name"},a.replace(/([a-z])([A-Z])/g,"$1 $2")),S.createElement("div",{className:"ds-story-body"},S.createElement(ge,{id:a}))));window.ReactDOM.createRoot(document.getElementById("root")).render(S.createElement(S.Fragment,null,Ie));})();
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# ContextMenu
|
|
2
|
+
|
|
3
|
+
The Base UI ContextMenu styled by the theme. No component tokens. Opens on right-click; the trigger area only sets the cursor. The popup is the popup concept, rows are item rows at the dense menu height, and group labels, separators and check slots are the shared list parts, so menus and listboxes read as one family.
|
|
4
|
+
|
|
5
|
+
Use `Loomiere.ContextMenu` (`import { ContextMenu } from '@base-ui/react/context-menu'` in an app) and give each part the class below; the styles target those classes, not Base UI's own markup.
|
|
6
|
+
|
|
7
|
+
Base UI docs: https://base-ui.com/react/components/context-menu
|
|
8
|
+
|
|
9
|
+
## Classes
|
|
10
|
+
|
|
11
|
+
| Class | Data attributes it answers to |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `ContextMenuTrigger` | |
|
|
14
|
+
| `ContextMenuPositioner` | |
|
|
15
|
+
| `ContextMenuPopup` | |
|
|
16
|
+
| `ContextMenuItem` | `data-highlighted`; `data-disabled` |
|
|
17
|
+
| `ContextMenuCheckboxItem` | `data-highlighted`; `data-disabled` |
|
|
18
|
+
| `ContextMenuRadioItem` | `data-highlighted`; `data-disabled`; `data-unchecked` |
|
|
19
|
+
| `ContextMenuSubmenuTrigger` | `data-highlighted`; `data-disabled` |
|
|
20
|
+
| `ContextMenuCheckboxItemIndicator` | |
|
|
21
|
+
| `ContextMenuRadioItemIndicator` | |
|
|
22
|
+
| `ContextMenuCheckboxItemIndicatorIcon` | |
|
|
23
|
+
| `ContextMenuRadioItemIndicatorIcon` | |
|
|
24
|
+
| `ContextMenuGroup` | |
|
|
25
|
+
| `ContextMenuGroupLabel` | |
|
|
26
|
+
| `ContextMenuSeparator` | |
|
|
27
|
+
| `ContextMenuArrow` | |
|
|
28
|
+
|
|
29
|
+
Base UI sets the state attributes (`data-checked`, `data-open`, `data-disabled`...) itself. Set `data-size`, `data-emphasis`, `data-variant` and `data-color` yourself; `data-color` takes any palette name (`primary`, `secondary`, `error`...) and repaints the part in it.
|
|
30
|
+
|
|
31
|
+
## Example
|
|
32
|
+
|
|
33
|
+
From the ContextMenu stories (`Default`):
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
export const Default: Story = {
|
|
37
|
+
render: () => (
|
|
38
|
+
<ContextMenu.Root>
|
|
39
|
+
<ContextMenu.Trigger className="ContextMenuTrigger">
|
|
40
|
+
<div style={{
|
|
41
|
+
width: '300px',
|
|
42
|
+
height: '200px',
|
|
43
|
+
display: 'flex',
|
|
44
|
+
alignItems: 'center',
|
|
45
|
+
justifyContent: 'center',
|
|
46
|
+
border: '2px dashed var(--sl-border-strong)',
|
|
47
|
+
borderRadius: '8px',
|
|
48
|
+
background: 'var(--sl-surface-overlay)',
|
|
49
|
+
cursor: 'context-menu'
|
|
50
|
+
}}>
|
|
51
|
+
Right-click here
|
|
52
|
+
</div>
|
|
53
|
+
</ContextMenu.Trigger>
|
|
54
|
+
<ContextMenu.Portal>
|
|
55
|
+
<ContextMenu.Positioner className="ContextMenuPositioner">
|
|
56
|
+
<ContextMenu.Popup className="ContextMenuPopup">
|
|
57
|
+
<ContextMenu.Item className="ContextMenuItem">Copy</ContextMenu.Item>
|
|
58
|
+
<ContextMenu.Item className="ContextMenuItem">Cut</ContextMenu.Item>
|
|
59
|
+
<ContextMenu.Item className="ContextMenuItem">Paste</ContextMenu.Item>
|
|
60
|
+
<ContextMenu.Separator className="ContextMenuSeparator" />
|
|
61
|
+
<ContextMenu.Item className="ContextMenuItem">Delete</ContextMenu.Item>
|
|
62
|
+
</ContextMenu.Popup>
|
|
63
|
+
</ContextMenu.Positioner>
|
|
64
|
+
</ContextMenu.Portal>
|
|
65
|
+
</ContextMenu.Root>
|
|
66
|
+
),
|
|
67
|
+
};
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The preview also shows `WithCheckboxes`, `WithRadioGroup`, `WithSubmenu`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- @dsCard group="Navigation" height=480 subtitle="Default / WithCheckboxes / WithRadioGroup / WithSubmenu" -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<style>
|
|
7
|
+
body { margin: 0; padding: var(--sl-space-4, 16px); background: var(--sl-surface-canvas); color: var(--sl-text-primary); }
|
|
8
|
+
#root { display: grid; gap: var(--sl-space-5, 20px); }
|
|
9
|
+
.ds-story-name { margin: 0 0 var(--sl-space-2, 8px); font: var(--sl-font-minimize-label-font, 500 10px sans-serif); color: var(--sl-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; }
|
|
10
|
+
</style>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
<script>
|
|
15
|
+
(()=>{var R=Object.create;var m=Object.defineProperty;var N=Object.getOwnPropertyDescriptor;var y=Object.getOwnPropertyNames;var k=Object.getPrototypeOf,P=Object.prototype.hasOwnProperty;var x=(o,n)=>()=>(n||o((n={exports:{}}).exports,n),n.exports),S=(o,n)=>{for(var a in n)m(o,a,{get:n[a],enumerable:!0})},f=(o,n,a,r)=>{if(n&&typeof n=="object"||typeof n=="function")for(let s of y(n))!P.call(o,s)&&s!==a&&m(o,s,{get:()=>n[s],enumerable:!(r=N(n,s))||r.enumerable});return o};var C=(o,n,a)=>(a=o!=null?R(k(o)):{},f(n||!o||!o.__esModule?m(a,"default",{value:o,enumerable:!0}):a,o));var p=x((W,I)=>{I.exports=window.React});var h=x((V,M)=>{M.exports=window.Loomiere.Base});var l={};S(l,{Default:()=>w,WithCheckboxes:()=>T,WithDisabledItems:()=>_,WithRadioGroup:()=>E,WithSubmenu:()=>L,default:()=>d});var u=C(p(),1),t=C(h(),1);var i=window.React;function e(o,n,a){let{children:r,...s}=n||{};return a!==void 0&&(s.key=a),r===void 0?i.createElement(o,s):Array.isArray(r)?i.createElement(o,s,...r):i.createElement(o,s,r)}var A=i.Fragment;var v={title:"Components/ContextMenu",component:t.ContextMenu.Root,parameters:{layout:"centered"},tags:["autodocs"]},d=v,w={render:()=>e(t.ContextMenu.Root,{children:[e(t.ContextMenu.Trigger,{className:"ContextMenuTrigger",children:e("div",{style:{width:"300px",height:"200px",display:"flex",alignItems:"center",justifyContent:"center",border:"2px dashed var(--sl-border-strong)",borderRadius:"8px",background:"var(--sl-surface-overlay)",cursor:"context-menu"},children:"Right-click here"})}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{className:"ContextMenuPositioner",children:e(t.ContextMenu.Popup,{className:"ContextMenuPopup",children:[e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"Copy"}),e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"Cut"}),e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"Paste"}),e(t.ContextMenu.Separator,{className:"ContextMenuSeparator"}),e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"Delete"})]})})})]})},T={render:()=>{let[o,n]=u.useState(!1),[a,r]=u.useState(!0),[s,g]=u.useState(!1);return e(t.ContextMenu.Root,{children:[e(t.ContextMenu.Trigger,{className:"ContextMenuTrigger",children:e("div",{style:{width:"300px",height:"200px",display:"flex",alignItems:"center",justifyContent:"center",border:"2px dashed var(--sl-border-strong)",borderRadius:"8px",background:"var(--sl-surface-overlay)",cursor:"context-menu"},children:"Right-click for view options"})}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{className:"ContextMenuPositioner",children:e(t.ContextMenu.Popup,{className:"ContextMenuPopup",children:[e(t.ContextMenu.CheckboxItem,{className:"ContextMenuCheckboxItem",checked:o,onCheckedChange:n,children:[e(t.ContextMenu.CheckboxItemIndicator,{className:"ContextMenuCheckboxItemIndicator",children:e("span",{className:"material-symbols-outlined ContextMenuCheckboxItemIndicatorIcon",children:"check"})}),"Show toolbar"]}),e(t.ContextMenu.CheckboxItem,{className:"ContextMenuCheckboxItem",checked:a,onCheckedChange:r,children:[e(t.ContextMenu.CheckboxItemIndicator,{className:"ContextMenuCheckboxItemIndicator",children:e("span",{className:"material-symbols-outlined ContextMenuCheckboxItemIndicatorIcon",children:"check"})}),"Show sidebar"]}),e(t.ContextMenu.CheckboxItem,{className:"ContextMenuCheckboxItem",checked:s,onCheckedChange:g,children:[e(t.ContextMenu.CheckboxItemIndicator,{className:"ContextMenuCheckboxItemIndicator",children:e("span",{className:"material-symbols-outlined ContextMenuCheckboxItemIndicatorIcon",children:"check"})}),"Show footer"]})]})})})]})}},E={render:()=>{let[o,n]=u.useState("light");return e(t.ContextMenu.Root,{children:[e(t.ContextMenu.Trigger,{className:"ContextMenuTrigger",children:e("div",{style:{width:"300px",height:"200px",display:"flex",alignItems:"center",justifyContent:"center",border:"2px dashed var(--sl-border-strong)",borderRadius:"8px",background:"var(--sl-surface-overlay)",cursor:"context-menu"},children:"Right-click to change theme"})}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{className:"ContextMenuPositioner",children:e(t.ContextMenu.Popup,{className:"ContextMenuPopup",children:e(t.ContextMenu.Group,{className:"ContextMenuGroup",children:[e(t.ContextMenu.GroupLabel,{className:"ContextMenuGroupLabel",children:"Theme"}),e(t.ContextMenu.RadioGroup,{value:o,onValueChange:n,children:[e(t.ContextMenu.RadioItem,{value:"light",className:"ContextMenuRadioItem",children:[e(t.ContextMenu.RadioItemIndicator,{className:"ContextMenuRadioItemIndicator",children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",style:{fontVariationSettings:'"FILL" 1'},children:"radio_button_checked"})}),e("span",{className:"ContextMenuRadioItemIndicator","data-unchecked":!0,children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",children:"radio_button_unchecked"})}),"Light"]}),e(t.ContextMenu.RadioItem,{value:"dark",className:"ContextMenuRadioItem",children:[e(t.ContextMenu.RadioItemIndicator,{className:"ContextMenuRadioItemIndicator",children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",style:{fontVariationSettings:'"FILL" 1'},children:"radio_button_checked"})}),e("span",{className:"ContextMenuRadioItemIndicator","data-unchecked":!0,children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",children:"radio_button_unchecked"})}),"Dark"]}),e(t.ContextMenu.RadioItem,{value:"system",className:"ContextMenuRadioItem",children:[e(t.ContextMenu.RadioItemIndicator,{className:"ContextMenuRadioItemIndicator",children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",style:{fontVariationSettings:'"FILL" 1'},children:"radio_button_checked"})}),e("span",{className:"ContextMenuRadioItemIndicator","data-unchecked":!0,children:e("span",{className:"material-symbols-outlined ContextMenuRadioItemIndicatorIcon",children:"radio_button_unchecked"})}),"System"]})]})]})})})})]})}},L={render:()=>e(t.ContextMenu.Root,{children:[e(t.ContextMenu.Trigger,{className:"ContextMenuTrigger",children:e("div",{style:{width:"300px",height:"200px",display:"flex",alignItems:"center",justifyContent:"center",border:"2px dashed var(--sl-border-strong)",borderRadius:"8px",background:"var(--sl-surface-overlay)",cursor:"context-menu"},children:"Right-click for nested menu"})}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{className:"ContextMenuPositioner",children:e(t.ContextMenu.Popup,{className:"ContextMenuPopup",children:[e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"New File"}),e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"New Folder"}),e(t.ContextMenu.Separator,{className:"ContextMenuSeparator"}),e(t.ContextMenu.SubmenuRoot,{children:[e(t.ContextMenu.SubmenuTrigger,{className:"ContextMenuSubmenuTrigger",children:"Share"}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{className:"ContextMenuPositioner",children:e(t.ContextMenu.Popup,{className:"ContextMenuPopup",children:[e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"Email"}),e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"Copy Link"}),e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"Social Media"})]})})})]})]})})})]})},_={render:()=>e(t.ContextMenu.Root,{children:[e(t.ContextMenu.Trigger,{className:"ContextMenuTrigger",children:e("div",{style:{width:"300px",height:"200px",display:"flex",alignItems:"center",justifyContent:"center",border:"2px dashed var(--sl-border-strong)",borderRadius:"8px",background:"var(--sl-surface-overlay)",cursor:"context-menu"},children:"Right-click here"})}),e(t.ContextMenu.Portal,{children:e(t.ContextMenu.Positioner,{className:"ContextMenuPositioner",children:e(t.ContextMenu.Popup,{className:"ContextMenuPopup",children:[e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"Copy"}),e(t.ContextMenu.Item,{className:"ContextMenuItem",disabled:!0,children:"Cut (disabled)"}),e(t.ContextMenu.Item,{className:"ContextMenuItem",disabled:!0,children:"Paste (disabled)"}),e(t.ContextMenu.Separator,{className:"ContextMenuSeparator"}),e(t.ContextMenu.Item,{className:"ContextMenuItem",children:"Delete"})]})})})]})};var c=window.React,b=d||{},F=["Default","WithCheckboxes","WithRadioGroup","WithSubmenu"];function G({id:o}){let n=l[o],a={...b.args||{},...n.args||{}};return(n.render||(s=>c.createElement(b.component,s)))(a,{args:a,id:o,name:o})}var j=F.map(o=>c.createElement("section",{key:o,className:"ds-story"},c.createElement("p",{className:"ds-story-name"},o.replace(/([a-z])([A-Z])/g,"$1 $2")),c.createElement("div",{className:"ds-story-body"},c.createElement(G,{id:o}))));window.ReactDOM.createRoot(document.getElementById("root")).render(c.createElement(c.Fragment,null,j));})();
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
<!-- @dsCard height=288 -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<style>
|
|
7
|
+
body { margin: 0; background: var(--sl-surface-canvas); }
|
|
8
|
+
.cover { position: relative; width: 960px; height: 288px; overflow: hidden; }
|
|
9
|
+
svg { position: absolute; inset: 0; }
|
|
10
|
+
.accent { fill: var(--sl-color-primary-600); }
|
|
11
|
+
.second { fill: var(--sl-color-secondary-600); }
|
|
12
|
+
.ink { fill: var(--sl-surface-inverse); }
|
|
13
|
+
.tint { fill: var(--sl-color-primary-100); }
|
|
14
|
+
.dune { fill: none; stroke: var(--sl-color-tertiary-300); stroke-width: var(--sl-stroke-thick); }
|
|
15
|
+
.text { position: absolute; left: var(--sl-space-10); bottom: var(--sl-space-10); max-width: 440px; }
|
|
16
|
+
h1 { margin: 0; font-family: var(--sl-font-family-display); font-weight: 600; font-size: 120px; line-height: 0.92; color: var(--sl-text-primary); }
|
|
17
|
+
p { margin: var(--sl-space-3) 0 0; font-family: var(--sl-font-family-body); font-size: 14px; line-height: 1.4; color: var(--sl-text-secondary); }
|
|
18
|
+
</style>
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
<div class="cover">
|
|
22
|
+
<svg width="960" height="288" viewBox="0 0 960 288" aria-hidden="true">
|
|
23
|
+
<!-- blocks: accent primary-600 slab 192x288, secondary-600 288x144, surface-inverse 144x144, primary-100 tint 144x144
|
|
24
|
+
arrangement: one tall slab with a band and two squares beside it, bleeding off the top, right and bottom
|
|
25
|
+
pattern: dunes, concentric half-rings in tertiary-300; the brand is a desert, so its motif is the dune
|
|
26
|
+
scales: 36px (space-9) ring pitch, 144px (space-36) modules, stroke-thick rings, square corners (radius-minimal) -->
|
|
27
|
+
<rect class="accent" x="480" y="0" width="192" height="288"/>
|
|
28
|
+
<rect class="second" x="672" y="0" width="288" height="144"/>
|
|
29
|
+
<rect class="ink" x="672" y="144" width="144" height="144"/>
|
|
30
|
+
<rect class="tint" x="816" y="144" width="144" height="144"/>
|
|
31
|
+
<path class="dune" d="M636 288 a36 36 0 0 1 72 0 M600 288 a72 72 0 0 1 144 0 M564 288 a108 108 0 0 1 216 0"/>
|
|
32
|
+
</svg>
|
|
33
|
+
<div class="text">
|
|
34
|
+
<h1>Mojave</h1>
|
|
35
|
+
<p>Warm desert neutrals with a violet primary and ember accent.</p>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
</body>
|
|
39
|
+
</html>
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Dialog
|
|
2
|
+
|
|
3
|
+
The Base UI Dialog styled by the theme. Both are centered modals built from the modal concept (tokens/semantic/modal.json): the modal-surface and modal-backdrop patterns, the maximize-xl heading and base description. Alert dialog shares every rule here; AlertDialog.css adds nothing of its own. Action buttons are plain .Button elements, so they follow the emphasis levels.
|
|
4
|
+
|
|
5
|
+
Use `Loomiere.Dialog` (`import { Dialog } from '@base-ui/react/dialog'` in an app) and give each part the class below; the styles target those classes, not Base UI's own markup.
|
|
6
|
+
|
|
7
|
+
Base UI docs: https://base-ui.com/react/components/dialog
|
|
8
|
+
|
|
9
|
+
## Classes
|
|
10
|
+
|
|
11
|
+
| Class | Data attributes it answers to |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `DialogBackdrop` | `data-starting-style`; `data-ending-style` |
|
|
14
|
+
| `AlertDialogBackdrop` | `data-starting-style`; `data-ending-style` |
|
|
15
|
+
| `DialogPopup` | `data-starting-style`; `data-ending-style` |
|
|
16
|
+
| `AlertDialogPopup` | `data-starting-style`; `data-ending-style` |
|
|
17
|
+
| `DialogClose` | |
|
|
18
|
+
| `DialogTitle` | |
|
|
19
|
+
| `AlertDialogTitle` | |
|
|
20
|
+
| `DialogDescription` | |
|
|
21
|
+
| `AlertDialogDescription` | |
|
|
22
|
+
| `DialogContent` | |
|
|
23
|
+
| `Form` | |
|
|
24
|
+
| `DialogActions` | |
|
|
25
|
+
| `AlertDialogActions` | |
|
|
26
|
+
|
|
27
|
+
Base UI sets the state attributes (`data-checked`, `data-open`, `data-disabled`...) itself. Set `data-size`, `data-emphasis`, `data-variant` and `data-color` yourself; `data-color` takes any palette name (`primary`, `secondary`, `error`...) and repaints the part in it.
|
|
28
|
+
|
|
29
|
+
## Example
|
|
30
|
+
|
|
31
|
+
From the Dialog stories (`Default`):
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
export const Default: Story = {
|
|
35
|
+
render: () => (
|
|
36
|
+
<Dialog.Root>
|
|
37
|
+
<Dialog.Trigger className="Button">
|
|
38
|
+
Open Dialog
|
|
39
|
+
</Dialog.Trigger>
|
|
40
|
+
<Dialog.Portal>
|
|
41
|
+
<Dialog.Backdrop className="DialogBackdrop" />
|
|
42
|
+
<Dialog.Popup className="DialogPopup">
|
|
43
|
+
<Dialog.Title className="DialogTitle">Dialog Title</Dialog.Title>
|
|
44
|
+
<Dialog.Description className="DialogDescription">
|
|
45
|
+
This is a description of the dialog. It provides context about what the dialog is for.
|
|
46
|
+
</Dialog.Description>
|
|
47
|
+
<div className="DialogActions">
|
|
48
|
+
<Dialog.Close className="Button" data-variant="ghost">
|
|
49
|
+
Cancel
|
|
50
|
+
</Dialog.Close>
|
|
51
|
+
<Dialog.Close className="Button">
|
|
52
|
+
Confirm
|
|
53
|
+
</Dialog.Close>
|
|
54
|
+
</div>
|
|
55
|
+
</Dialog.Popup>
|
|
56
|
+
</Dialog.Portal>
|
|
57
|
+
</Dialog.Root>
|
|
58
|
+
),
|
|
59
|
+
};
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The preview also shows `WithForm`, `Nested`, `LongContent`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- @dsCard group="Overlays" height=480 subtitle="Default / WithForm / Nested / LongContent" -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<style>
|
|
7
|
+
body { margin: 0; padding: var(--sl-space-4, 16px); background: var(--sl-surface-canvas); color: var(--sl-text-primary); }
|
|
8
|
+
#root { display: grid; gap: var(--sl-space-5, 20px); }
|
|
9
|
+
.ds-story-name { margin: 0 0 var(--sl-space-2, 8px); font: var(--sl-font-minimize-label-font, 500 10px sans-serif); color: var(--sl-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; }
|
|
10
|
+
</style>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
<script>
|
|
15
|
+
(()=>{var C=Object.create;var c=Object.defineProperty;var P=Object.getOwnPropertyDescriptor;var h=Object.getOwnPropertyNames;var y=Object.getPrototypeOf,B=Object.prototype.hasOwnProperty;var d=(a,t)=>()=>(t||a((t={exports:{}}).exports,t),t.exports),R=(a,t)=>{for(var i in t)c(a,i,{get:t[i],enumerable:!0})},b=(a,t,i,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let l of h(t))!B.call(a,l)&&l!==i&&c(a,l,{get:()=>t[l],enumerable:!(s=P(t,l))||s.enumerable});return a};var u=(a,t,i)=>(i=a!=null?C(y(a)):{},b(t||!a||!a.__esModule?c(i,"default",{value:a,enumerable:!0}):i,a));var N=d((I,D)=>{D.exports=window.React});var f=d((L,v)=>{v.exports=window.Loomiere.Base});var g={};R(g,{Default:()=>F,LongContent:()=>E,Nested:()=>q,WithForm:()=>S,default:()=>p});var m=u(N(),1),e=u(f(),1);var n=window.React;function o(a,t,i){let{children:s,...l}=t||{};return i!==void 0&&(l.key=i),s===void 0?n.createElement(a,l):Array.isArray(s)?n.createElement(a,l,...s):n.createElement(a,l,s)}var j=n.Fragment;var x={title:"Components/Dialog",component:e.Dialog.Root,parameters:{layout:"centered"},tags:["autodocs"]},p=x,F={render:()=>o(e.Dialog.Root,{children:[o(e.Dialog.Trigger,{className:"Button",children:"Open Dialog"}),o(e.Dialog.Portal,{children:[o(e.Dialog.Backdrop,{className:"DialogBackdrop"}),o(e.Dialog.Popup,{className:"DialogPopup",children:[o(e.Dialog.Title,{className:"DialogTitle",children:"Dialog Title"}),o(e.Dialog.Description,{className:"DialogDescription",children:"This is a description of the dialog. It provides context about what the dialog is for."}),o("div",{className:"DialogActions",children:[o(e.Dialog.Close,{className:"Button","data-variant":"ghost",children:"Cancel"}),o(e.Dialog.Close,{className:"Button",children:"Confirm"})]})]})]})]})},S={render:()=>{let a=m.useId(),t=m.useId(),i=s=>{s.preventDefault(),console.log("Form submitted")};return o(e.Dialog.Root,{children:[o(e.Dialog.Trigger,{className:"Button",children:"Open Form Dialog"}),o(e.Dialog.Portal,{children:[o(e.Dialog.Backdrop,{className:"DialogBackdrop"}),o(e.Dialog.Popup,{className:"DialogPopup",children:[o(e.Dialog.Title,{className:"DialogTitle",children:"Contact Information"}),o(e.Dialog.Description,{className:"DialogDescription",children:"Please provide your contact details."}),o("form",{className:"Form",onSubmit:i,children:[o("div",{className:"FieldRoot",children:[o("label",{htmlFor:a,className:"FieldLabel",children:"Name"}),o("input",{id:a,type:"text",className:"FieldControl",placeholder:"John Doe"})]}),o("div",{className:"FieldRoot",children:[o("label",{htmlFor:t,className:"FieldLabel",children:"Email"}),o("input",{id:t,type:"email",className:"FieldControl",placeholder:"you@example.com"})]})]}),o("div",{className:"DialogActions",children:[o(e.Dialog.Close,{className:"Button","data-variant":"ghost",children:"Cancel"}),o(e.Dialog.Close,{className:"Button",children:"Submit"})]})]})]})]})}},q={render:()=>o(e.Dialog.Root,{children:[o(e.Dialog.Trigger,{className:"Button",children:"Open First Dialog"}),o(e.Dialog.Portal,{children:[o(e.Dialog.Backdrop,{className:"DialogBackdrop"}),o(e.Dialog.Popup,{className:"DialogPopup",children:[o(e.Dialog.Title,{className:"DialogTitle",children:"First Dialog"}),o(e.Dialog.Description,{className:"DialogDescription",children:"This is the first dialog. You can open another dialog from here."}),o("div",{className:"DialogActions",children:[o(e.Dialog.Root,{children:[o(e.Dialog.Trigger,{className:"Button","data-variant":"outline",children:"Open Second Dialog"}),o(e.Dialog.Portal,{children:[o(e.Dialog.Backdrop,{className:"DialogBackdrop"}),o(e.Dialog.Popup,{className:"DialogPopup",children:[o(e.Dialog.Title,{className:"DialogTitle",children:"Second Dialog"}),o(e.Dialog.Description,{className:"DialogDescription",children:"This is a nested dialog opened from the first one."}),o("div",{className:"DialogActions",children:o(e.Dialog.Close,{className:"Button",children:"Close"})})]})]})]}),o(e.Dialog.Close,{className:"Button","data-variant":"ghost",children:"Close"})]})]})]})]})},E={render:()=>o(e.Dialog.Root,{children:[o(e.Dialog.Trigger,{className:"Button",children:"Open Long Dialog"}),o(e.Dialog.Portal,{children:[o(e.Dialog.Backdrop,{className:"DialogBackdrop"}),o(e.Dialog.Popup,{className:"DialogPopup",children:[o(e.Dialog.Title,{className:"DialogTitle",children:"Terms and Conditions"}),o(e.Dialog.Description,{className:"DialogDescription",children:"Please read and accept our terms and conditions."}),o("div",{className:"DialogContent",children:[o("p",{children:"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat."}),o("p",{children:"Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."}),o("p",{children:"Sed ut perspiciatis unde omnis iste natus error sit voluptatem accusantium doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo inventore veritatis et quasi architecto beatae vitae dicta sunt explicabo."}),o("p",{children:"Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt."})]}),o("div",{className:"DialogActions",children:[o(e.Dialog.Close,{className:"Button","data-variant":"ghost",children:"Decline"}),o(e.Dialog.Close,{className:"Button",children:"Accept"})]})]})]})]})};var r=window.React,T=p||{},k=["Default","WithForm","Nested","LongContent"];function w({id:a}){let t=g[a],i={...T.args||{},...t.args||{}};return(t.render||(l=>r.createElement(T.component,l)))(i,{args:i,id:a,name:a})}var A=k.map(a=>r.createElement("section",{key:a,className:"ds-story"},r.createElement("p",{className:"ds-story-name"},a.replace(/([a-z])([A-Z])/g,"$1 $2")),r.createElement("div",{className:"ds-story-body"},r.createElement(w,{id:a}))));window.ReactDOM.createRoot(document.getElementById("root")).render(r.createElement(r.Fragment,null,A));})();
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Drawer
|
|
2
|
+
|
|
3
|
+
The Base UI Drawer styled by the theme. The surface, scrim, heading and motion are the modal concept's (--sl-modal-*), so a drawer reads as a dialog's sibling; only its size and grab bar are its own (--sl-drawer-*). Base UI supplies the swipe through --drawer-swipe-movement-x/y and data-swipe-direction on the popup.
|
|
4
|
+
|
|
5
|
+
Use `Loomiere.Drawer` (`import { Drawer } from '@base-ui/react/drawer'` in an app) and give each part the class below; the styles target those classes, not Base UI's own markup.
|
|
6
|
+
|
|
7
|
+
Base UI docs: https://base-ui.com/react/components/drawer
|
|
8
|
+
|
|
9
|
+
## Classes
|
|
10
|
+
|
|
11
|
+
| Class | Data attributes it answers to |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `DrawerBackdrop` | `data-starting-style`; `data-ending-style` |
|
|
14
|
+
| `DrawerViewport` | |
|
|
15
|
+
| `DrawerPopup` | `data-swipe-direction`: `down`, `up`, `right`, `left`; `data-starting-style`; `data-ending-style`; `data-swiping` |
|
|
16
|
+
| `DrawerContent` | |
|
|
17
|
+
| `DrawerTitle` | |
|
|
18
|
+
| `DrawerDescription` | |
|
|
19
|
+
|
|
20
|
+
Base UI sets the state attributes (`data-checked`, `data-open`, `data-disabled`...) itself. Set `data-size`, `data-emphasis`, `data-variant` and `data-color` yourself; `data-color` takes any palette name (`primary`, `secondary`, `error`...) and repaints the part in it.
|
|
21
|
+
|
|
22
|
+
## Example
|
|
23
|
+
|
|
24
|
+
From the Drawer stories (`Default`):
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
export const Default: Story = {
|
|
28
|
+
render: () => <Panel side="down" />,
|
|
29
|
+
};
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The preview also shows `Sides`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- @dsCard group="Overlays" height=240 subtitle="Default / Sides" -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<style>
|
|
7
|
+
body { margin: 0; padding: var(--sl-space-4, 16px); background: var(--sl-surface-canvas); color: var(--sl-text-primary); }
|
|
8
|
+
#root { display: grid; gap: var(--sl-space-5, 20px); }
|
|
9
|
+
.ds-story-name { margin: 0 0 var(--sl-space-2, 8px); font: var(--sl-font-minimize-label-font, 500 10px sans-serif); color: var(--sl-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; }
|
|
10
|
+
</style>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
<script>
|
|
15
|
+
(()=>{var y=Object.create;var p=Object.defineProperty;var f=Object.getOwnPropertyDescriptor;var g=Object.getOwnPropertyNames;var E=Object.getPrototypeOf,h=Object.prototype.hasOwnProperty;var N=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),R=(e,t)=>{for(var o in t)p(e,o,{get:t[o],enumerable:!0})},S=(e,t,o,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let a of g(t))!h.call(e,a)&&a!==o&&p(e,a,{get:()=>t[a],enumerable:!(n=f(t,a))||n.enumerable});return e};var x=(e,t,o)=>(o=e!=null?y(E(e)):{},S(t||!e||!e.__esModule?p(o,"default",{value:e,enumerable:!0}):o,e));var w=N((j,d)=>{d.exports=window.Loomiere.Base});var m={};R(m,{Default:()=>B,Sides:()=>b,default:()=>i});var s=x(w(),1);var l=window.React;function r(e,t,o){let{children:n,...a}=t||{};return o!==void 0&&(a.key=o),n===void 0?l.createElement(e,a):Array.isArray(n)?l.createElement(e,a,...n):l.createElement(e,a,n)}var V=l.Fragment;var T={title:"Components/Drawer",component:s.Drawer.Root,parameters:{layout:"centered"},tags:["autodocs"]},i=T,D=({side:e})=>r(s.Drawer.Root,{swipeDirection:e,children:[r(s.Drawer.Trigger,{className:"Button","data-emphasis":"standard",children:[e==="down"?"Bottom":e==="up"?"Top":e==="left"?"Left":"Right"," drawer"]}),r(s.Drawer.Portal,{children:[r(s.Drawer.Backdrop,{className:"DrawerBackdrop"}),r(s.Drawer.Viewport,{className:"DrawerViewport",children:r(s.Drawer.Popup,{className:"DrawerPopup",children:[r(s.Drawer.Title,{className:"DrawerTitle",children:"Trail notes"}),r(s.Drawer.Description,{className:"DrawerDescription",children:"Swipe it away, press Escape, or use the button."}),r(s.Drawer.Content,{className:"DrawerContent",children:r("p",{children:"Three sites logged at dusk. Wind from the southwest, sand moving east."})}),r(s.Drawer.Close,{className:"Button","data-emphasis":"bold",children:"Done"})]})})]})]}),B={render:()=>r(D,{side:"down"})},b={render:()=>r("div",{style:{display:"flex",gap:"var(--sl-space-2)"},children:["down","right","left","up"].map(e=>r(D,{side:e},e))})};var c=window.React,u=i||{},k=["Default","Sides"];function C({id:e}){let t=m[e],o={...u.args||{},...t.args||{}};return(t.render||(a=>c.createElement(u.component,a)))(o,{args:o,id:e,name:e})}var P=k.map(e=>c.createElement("section",{key:e,className:"ds-story"},c.createElement("p",{className:"ds-story-name"},e.replace(/([a-z])([A-Z])/g,"$1 $2")),c.createElement("div",{className:"ds-story-body"},c.createElement(C,{id:e}))));window.ReactDOM.createRoot(document.getElementById("root")).render(c.createElement(c.Fragment,null,P));})();
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Field
|
|
2
|
+
|
|
3
|
+
The Base UI Field styled by the theme. Label, control, description and error. No component tokens: spacing is the field concept (tokens/semantic/field.json) and text is whole text styles. Field.Control is styled with Input (Input.css). Number field's label, description and error are the same parts, so they share these rules.
|
|
4
|
+
|
|
5
|
+
Use `Loomiere.Field`, this package's wrapper: it puts the class names on for you (`import { Field } from '@scattered-light/loomiere-base-ui'` in an app). The bare Base UI part is `Loomiere.Base.Field`.
|
|
6
|
+
|
|
7
|
+
Base UI docs: https://base-ui.com/react/components/field
|
|
8
|
+
|
|
9
|
+
## Classes
|
|
10
|
+
|
|
11
|
+
| Class | Data attributes it answers to |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `FieldRoot` | `data-disabled` |
|
|
14
|
+
| `FieldLabel` | |
|
|
15
|
+
| `NumberFieldLabel` | |
|
|
16
|
+
| `FieldDescription` | |
|
|
17
|
+
| `NumberFieldDescription` | |
|
|
18
|
+
| `FieldError` | |
|
|
19
|
+
| `NumberFieldError` | |
|
|
20
|
+
| `FieldControl` | |
|
|
21
|
+
|
|
22
|
+
Base UI sets the state attributes (`data-checked`, `data-open`, `data-disabled`...) itself. Set `data-size`, `data-emphasis`, `data-variant` and `data-color` yourself; `data-color` takes any palette name (`primary`, `secondary`, `error`...) and repaints the part in it.
|
|
23
|
+
|
|
24
|
+
## Example
|
|
25
|
+
|
|
26
|
+
From the Field stories (`Default`):
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
export const Default: Story = {
|
|
30
|
+
render: () => (
|
|
31
|
+
<div style={{ width: '400px' }}>
|
|
32
|
+
<Field.Root name="email">
|
|
33
|
+
<Field.Label>Email address</Field.Label>
|
|
34
|
+
<Field.Control type="email" placeholder="you@example.com" />
|
|
35
|
+
</Field.Root>
|
|
36
|
+
</div>
|
|
37
|
+
),
|
|
38
|
+
};
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The preview also shows `WithDescription`, `WithError`, `Required`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- @dsCard group="Forms" height=480 subtitle="Default / WithDescription / WithError / Required" -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<style>
|
|
7
|
+
body { margin: 0; padding: var(--sl-space-4, 16px); background: var(--sl-surface-canvas); color: var(--sl-text-primary); }
|
|
8
|
+
#root { display: grid; gap: var(--sl-space-5, 20px); }
|
|
9
|
+
.ds-story-name { margin: 0 0 var(--sl-space-2, 8px); font: var(--sl-font-minimize-label-font, 500 10px sans-serif); color: var(--sl-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; }
|
|
10
|
+
</style>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
<script>
|
|
15
|
+
(()=>{var x=Object.create;var d=Object.defineProperty;var h=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var F=Object.getPrototypeOf,R=Object.prototype.hasOwnProperty;var f=(t,r)=>()=>(r||t((r={exports:{}}).exports,r),r.exports),E=(t,r)=>{for(var a in r)d(t,a,{get:r[a],enumerable:!0})},w=(t,r,a,l)=>{if(r&&typeof r=="object"||typeof r=="function")for(let n of b(r))!R.call(t,n)&&n!==a&&d(t,n,{get:()=>r[n],enumerable:!(l=h(r,n))||l.enumerable});return t};var v=(t,r,a)=>(a=t!=null?x(F(t)):{},w(r||!t||!t.__esModule?d(a,"default",{value:t,enumerable:!0}):a,t));var y=f((O,p)=>{p.exports=window.Loomiere});var m={};E(m,{Default:()=>L,Disabled:()=>j,Required:()=>C,Textarea:()=>M,WithDescription:()=>g,WithError:()=>S,default:()=>c});var o=v(y(),1);var i=window.React;function e(t,r,a){let{children:l,...n}=r||{};return a!==void 0&&(n.key=a),l===void 0?i.createElement(t,n):Array.isArray(l)?i.createElement(t,n,...l):i.createElement(t,n,l)}var U=i.Fragment;var D={title:"Components/Lib/Field",parameters:{layout:"centered"},tags:["autodocs","ds:lib"]},c=D,L={render:()=>e("div",{style:{width:"400px"},children:e(o.Field.Root,{name:"email",children:[e(o.Field.Label,{children:"Email address"}),e(o.Field.Control,{type:"email",placeholder:"you@example.com"})]})})},g={render:()=>e("div",{style:{width:"400px"},children:e(o.Field.Root,{name:"username",children:[e(o.Field.Label,{children:"Username"}),e(o.Field.Control,{type:"text",placeholder:"johndoe"}),e(o.Field.Description,{children:"Choose a unique username for your account"})]})})},S={render:()=>e("div",{style:{width:"400px"},children:e(o.Field.Root,{name:"username",invalid:!0,children:[e(o.Field.Label,{children:"Username"}),e(o.Field.Control,{type:"text",placeholder:"johndoe","aria-invalid":"true",defaultValue:"john"}),e(o.Field.Error,{children:"Username must be at least 5 characters"})]})})},C={render:()=>e("div",{style:{width:"400px"},children:e(o.Field.Root,{name:"fullName",children:[e(o.Field.Label,{children:["Full name ",e("span",{style:{color:"var(--sl-status-warning)"},children:"*"})]}),e(o.Field.Control,{type:"text",placeholder:"John Doe",required:!0})]})})},j={render:()=>e("div",{style:{width:"400px"},children:e(o.Field.Root,{name:"email",disabled:!0,children:[e(o.Field.Label,{children:"Email address"}),e(o.Field.Control,{type:"email",placeholder:"you@example.com",disabled:!0}),e(o.Field.Description,{children:"This field is currently disabled"})]})})},M={render:()=>e("div",{style:{width:"400px"},children:e(o.Field.Root,{name:"message",children:[e(o.Field.Label,{children:"Message"}),e(o.Field.Control,{render:e("textarea",{rows:4,placeholder:"Enter your message..."})}),e(o.Field.Description,{children:"Maximum 500 characters"})]})})};var s=window.React,u=c||{},q=["Default","WithDescription","WithError","Required"];function N({id:t}){let r=m[t],a={...u.args||{},...r.args||{}};return(r.render||(n=>s.createElement(u.component,n)))(a,{args:a,id:t,name:t})}var W=q.map(t=>s.createElement("section",{key:t,className:"ds-story"},s.createElement("p",{className:"ds-story-name"},t.replace(/([a-z])([A-Z])/g,"$1 $2")),s.createElement("div",{className:"ds-story-body"},s.createElement(N,{id:t}))));window.ReactDOM.createRoot(document.getElementById("root")).render(s.createElement(s.Fragment,null,W));})();
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Fieldset
|
|
2
|
+
|
|
3
|
+
The Base UI Fieldset styled by the theme. No component tokens: a titled group of fields, spaced by the stack gaps, with whole text styles.
|
|
4
|
+
|
|
5
|
+
Use `Loomiere.Fieldset`, this package's wrapper: it puts the class names on for you (`import { Fieldset } from '@scattered-light/loomiere-base-ui'` in an app). The bare Base UI part is `Loomiere.Base.Fieldset`.
|
|
6
|
+
|
|
7
|
+
Base UI docs: https://base-ui.com/react/components/fieldset
|
|
8
|
+
|
|
9
|
+
## Classes
|
|
10
|
+
|
|
11
|
+
| Class | Data attributes it answers to |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `Fieldset` | |
|
|
14
|
+
| `FieldsetLegend` | |
|
|
15
|
+
| `FieldsetDescription` | |
|
|
16
|
+
|
|
17
|
+
Base UI sets the state attributes (`data-checked`, `data-open`, `data-disabled`...) itself. Set `data-size`, `data-emphasis`, `data-variant` and `data-color` yourself; `data-color` takes any palette name (`primary`, `secondary`, `error`...) and repaints the part in it.
|
|
18
|
+
|
|
19
|
+
## Example
|
|
20
|
+
|
|
21
|
+
From the Fieldset stories (`Default`):
|
|
22
|
+
|
|
23
|
+
```tsx
|
|
24
|
+
export const Default: Story = {
|
|
25
|
+
render: () => (
|
|
26
|
+
<div style={{ width: '400px' }}>
|
|
27
|
+
<Fieldset.Root>
|
|
28
|
+
<Fieldset.Legend>Personal Information</Fieldset.Legend>
|
|
29
|
+
|
|
30
|
+
<Field.Root name="firstName">
|
|
31
|
+
<Field.Label>First name</Field.Label>
|
|
32
|
+
<Field.Control type="text" placeholder="John" />
|
|
33
|
+
</Field.Root>
|
|
34
|
+
|
|
35
|
+
<Field.Root name="lastName">
|
|
36
|
+
<Field.Label>Last name</Field.Label>
|
|
37
|
+
<Field.Control type="text" placeholder="Doe" />
|
|
38
|
+
</Field.Root>
|
|
39
|
+
</Fieldset.Root>
|
|
40
|
+
</div>
|
|
41
|
+
),
|
|
42
|
+
};
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
The preview also shows `WithDescription`, `WithValidation`, `Disabled`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- @dsCard group="Forms" height=480 subtitle="Default / WithDescription / WithValidation / Disabled" -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<style>
|
|
7
|
+
body { margin: 0; padding: var(--sl-space-4, 16px); background: var(--sl-surface-canvas); color: var(--sl-text-primary); }
|
|
8
|
+
#root { display: grid; gap: var(--sl-space-5, 20px); }
|
|
9
|
+
.ds-story-name { margin: 0 0 var(--sl-space-2, 8px); font: var(--sl-font-minimize-label-font, 500 10px sans-serif); color: var(--sl-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; }
|
|
10
|
+
</style>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
<script>
|
|
15
|
+
(()=>{var L=Object.create;var s=Object.defineProperty;var R=Object.getOwnPropertyDescriptor;var b=Object.getOwnPropertyNames;var h=Object.getPrototypeOf,u=Object.prototype.hasOwnProperty;var x=(o,l)=>()=>(l||o((l={exports:{}}).exports,l),l.exports),f=(o,l)=>{for(var a in l)s(o,a,{get:l[a],enumerable:!0})},g=(o,l,a,r)=>{if(l&&typeof l=="object"||typeof l=="function")for(let n of b(l))!u.call(o,n)&&n!==a&&s(o,n,{get:()=>l[n],enumerable:!(r=R(l,n))||r.enumerable});return o};var D=(o,l,a)=>(a=o!=null?L(h(o)):{},g(l||!o||!o.__esModule?s(a,"default",{value:o,enumerable:!0}):a,o));var F=x((A,p)=>{p.exports=window.Loomiere});var c={};f(c,{Default:()=>v,Disabled:()=>N,MultipleFieldsets:()=>S,WithDescription:()=>C,WithValidation:()=>E,default:()=>m});var t=D(F(),1);var d=window.React;function e(o,l,a){let{children:r,...n}=l||{};return a!==void 0&&(n.key=a),r===void 0?d.createElement(o,n):Array.isArray(r)?d.createElement(o,n,...r):d.createElement(o,n,r)}var J=d.Fragment;var w={title:"Components/Lib/Fieldset",parameters:{layout:"centered"},tags:["autodocs","ds:lib"]},m=w,v={render:()=>e("div",{style:{width:"400px"},children:e(t.Fieldset.Root,{children:[e(t.Fieldset.Legend,{children:"Personal Information"}),e(t.Field.Root,{name:"firstName",children:[e(t.Field.Label,{children:"First name"}),e(t.Field.Control,{type:"text",placeholder:"John"})]}),e(t.Field.Root,{name:"lastName",children:[e(t.Field.Label,{children:"Last name"}),e(t.Field.Control,{type:"text",placeholder:"Doe"})]})]})})},C={render:()=>e("div",{style:{width:"400px"},children:e(t.Fieldset.Root,{children:[e(t.Fieldset.Legend,{children:"Contact Information"}),e(t.FieldsetDescription,{children:"We'll use this information to contact you about your order."}),e(t.Field.Root,{name:"email",children:[e(t.Field.Label,{children:"Email address"}),e(t.Field.Control,{type:"email",placeholder:"you@example.com"})]}),e(t.Field.Root,{name:"phone",children:[e(t.Field.Label,{children:"Phone number"}),e(t.Field.Control,{type:"tel",placeholder:"(555) 123-4567"})]})]})})},E={render:()=>e("div",{style:{width:"400px"},children:e(t.Fieldset.Root,{children:[e(t.Fieldset.Legend,{children:"Account Details"}),e(t.Field.Root,{name:"firstName",children:[e(t.Field.Label,{children:"First name"}),e(t.Field.Control,{type:"text",placeholder:"John"})]}),e(t.Field.Root,{name:"lastName",children:[e(t.Field.Label,{children:"Last name"}),e(t.Field.Control,{type:"text",placeholder:"Doe"})]}),e(t.Field.Root,{name:"email",invalid:!0,children:[e(t.Field.Label,{children:["Email address ",e("span",{style:{color:"var(--sl-status-warning)"},children:"*"})]}),e(t.Field.Control,{type:"email",placeholder:"you@example.com","aria-invalid":"true",defaultValue:"invalid-email"}),e(t.Field.Error,{children:"Please enter a valid email address"})]})]})})},N={render:()=>e("div",{style:{width:"400px"},children:e(t.Fieldset.Root,{disabled:!0,children:[e(t.Fieldset.Legend,{children:"Personal Information"}),e(t.FieldsetDescription,{children:"This section is currently disabled."}),e(t.Field.Root,{name:"firstName",children:[e(t.Field.Label,{children:"First name"}),e(t.Field.Control,{type:"text",placeholder:"John"})]}),e(t.Field.Root,{name:"lastName",children:[e(t.Field.Label,{children:"Last name"}),e(t.Field.Control,{type:"text",placeholder:"Doe"})]})]})})},S={render:()=>e("div",{style:{width:"400px",display:"flex",flexDirection:"column",gap:"32px"},children:[e(t.Fieldset.Root,{children:[e(t.Fieldset.Legend,{children:"Personal Information"}),e(t.Field.Root,{name:"firstName",children:[e(t.Field.Label,{children:"First name"}),e(t.Field.Control,{type:"text",placeholder:"John"})]}),e(t.Field.Root,{name:"lastName",children:[e(t.Field.Label,{children:"Last name"}),e(t.Field.Control,{type:"text",placeholder:"Doe"})]})]}),e(t.Fieldset.Root,{children:[e(t.Fieldset.Legend,{children:"Contact Information"}),e(t.FieldsetDescription,{children:"How can we reach you?"}),e(t.Field.Root,{name:"email2",children:[e(t.Field.Label,{children:"Email address"}),e(t.Field.Control,{type:"email",placeholder:"you@example.com"})]}),e(t.Field.Root,{name:"phone2",children:[e(t.Field.Label,{children:"Phone number"}),e(t.Field.Control,{type:"tel",placeholder:"(555) 123-4567"})]})]})]})};var i=window.React,y=m||{},I=["Default","WithDescription","WithValidation","Disabled"];function P({id:o}){let l=c[o],a={...y.args||{},...l.args||{}};return(l.render||(n=>i.createElement(y.component,n)))(a,{args:a,id:o,name:o})}var W=I.map(o=>i.createElement("section",{key:o,className:"ds-story"},i.createElement("p",{className:"ds-story-name"},o.replace(/([a-z])([A-Z])/g,"$1 $2")),i.createElement("div",{className:"ds-story-body"},i.createElement(P,{id:o}))));window.ReactDOM.createRoot(document.getElementById("root")).render(i.createElement(i.Fragment,null,W));})();
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Form
|
|
2
|
+
|
|
3
|
+
The Base UI Form styled by the theme. No component tokens: fields stack with the large block space, and the action buttons sit in a row after them.
|
|
4
|
+
|
|
5
|
+
Use `Loomiere.Form`, this package's wrapper: it puts the class names on for you (`import { Form } from '@scattered-light/loomiere-base-ui'` in an app). The bare Base UI part is `Loomiere.Base.Form`.
|
|
6
|
+
|
|
7
|
+
Base UI docs: https://base-ui.com/react/components/form
|
|
8
|
+
|
|
9
|
+
## Classes
|
|
10
|
+
|
|
11
|
+
| Class | Data attributes it answers to |
|
|
12
|
+
|---|---|
|
|
13
|
+
| `Form` | |
|
|
14
|
+
| `FormActions` | |
|
|
15
|
+
|
|
16
|
+
Base UI sets the state attributes (`data-checked`, `data-open`, `data-disabled`...) itself. Set `data-size`, `data-emphasis`, `data-variant` and `data-color` yourself; `data-color` takes any palette name (`primary`, `secondary`, `error`...) and repaints the part in it.
|
|
17
|
+
|
|
18
|
+
## Example
|
|
19
|
+
|
|
20
|
+
From the Form stories (`Default`):
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
export const Default: Story = {
|
|
24
|
+
render: () => {
|
|
25
|
+
const handleSubmit = (formValues: Record<string, unknown>) => {
|
|
26
|
+
console.log('Form submitted', formValues);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<div style={{ width: '400px' }}>
|
|
31
|
+
<Form onFormSubmit={handleSubmit}>
|
|
32
|
+
<Field.Root name="name">
|
|
33
|
+
<Field.Label>Name</Field.Label>
|
|
34
|
+
<Field.Control type="text" placeholder="John Doe" required />
|
|
35
|
+
</Field.Root>
|
|
36
|
+
|
|
37
|
+
<Field.Root name="email">
|
|
38
|
+
<Field.Label>Email</Field.Label>
|
|
39
|
+
<Field.Control type="email" placeholder="you@example.com" required />
|
|
40
|
+
</Field.Root>
|
|
41
|
+
|
|
42
|
+
<FormActions>
|
|
43
|
+
<Button type="submit" data-variant="solid">
|
|
44
|
+
Submit
|
|
45
|
+
</Button>
|
|
46
|
+
<Button type="reset" data-variant="outline">
|
|
47
|
+
Reset
|
|
48
|
+
</Button>
|
|
49
|
+
</FormActions>
|
|
50
|
+
</Form>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
The preview also shows `WithFieldsets`, `WithValidation`, `ActionsAlignedRight`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
<!-- @dsCard group="Forms" height=480 subtitle="Default / WithFieldsets / WithValidation / ActionsAlignedRight" -->
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html>
|
|
4
|
+
<head>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<style>
|
|
7
|
+
body { margin: 0; padding: var(--sl-space-4, 16px); background: var(--sl-surface-canvas); color: var(--sl-text-primary); }
|
|
8
|
+
#root { display: grid; gap: var(--sl-space-5, 20px); }
|
|
9
|
+
.ds-story-name { margin: 0 0 var(--sl-space-2, 8px); font: var(--sl-font-minimize-label-font, 500 10px sans-serif); color: var(--sl-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; }
|
|
10
|
+
</style>
|
|
11
|
+
</head>
|
|
12
|
+
<body>
|
|
13
|
+
<div id="root"></div>
|
|
14
|
+
<script>
|
|
15
|
+
(()=>{var L=Object.create;var d=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var x=Object.getOwnPropertyNames;var S=Object.getPrototypeOf,v=Object.prototype.hasOwnProperty;var u=(o,a)=>()=>(a||o((a={exports:{}}).exports,a),a.exports),f=(o,a)=>{for(var r in a)d(o,r,{get:a[r],enumerable:!0})},C=(o,a,r,l)=>{if(a&&typeof a=="object"||typeof a=="function")for(let n of x(a))!v.call(o,n)&&n!==r&&d(o,n,{get:()=>a[n],enumerable:!(l=w(a,n))||l.enumerable});return o};var p=(o,a,r)=>(r=o!=null?L(S(o)):{},C(a||!o||!o.__esModule?d(r,"default",{value:o,enumerable:!0}):r,o));var b=u((W,F)=>{F.exports=window.React});var h=u((V,y)=>{y.exports=window.Loomiere});var c={};f(c,{ActionsAlignedRight:()=>B,Default:()=>A,WithFieldsets:()=>q,WithValidation:()=>D,default:()=>m});var R=p(b(),1),t=p(h(),1);var s=window.React;function e(o,a,r){let{children:l,...n}=a||{};return r!==void 0&&(n.key=r),l===void 0?s.createElement(o,n):Array.isArray(l)?s.createElement(o,n,...l):s.createElement(o,n,l)}var I=s.Fragment;var E={title:"Components/Lib/Form",parameters:{layout:"centered"},tags:["autodocs","ds:lib"]},m=E,A={render:()=>e("div",{style:{width:"400px"},children:e(t.Form,{onFormSubmit:a=>{console.log("Form submitted",a)},children:[e(t.Field.Root,{name:"name",children:[e(t.Field.Label,{children:"Name"}),e(t.Field.Control,{type:"text",placeholder:"John Doe",required:!0})]}),e(t.Field.Root,{name:"email",children:[e(t.Field.Label,{children:"Email"}),e(t.Field.Control,{type:"email",placeholder:"you@example.com",required:!0})]}),e(t.FormActions,{children:[e(t.Button,{type:"submit","data-variant":"solid",children:"Submit"}),e(t.Button,{type:"reset","data-variant":"outline",children:"Reset"})]})]})})},q={render:()=>e("div",{style:{width:"400px"},children:e(t.Form,{onFormSubmit:a=>{console.log("Form submitted",a)},children:[e(t.Fieldset.Root,{children:[e(t.Fieldset.Legend,{children:"Personal Information"}),e(t.Field.Root,{name:"firstName",children:[e(t.Field.Label,{children:"First name"}),e(t.Field.Control,{type:"text",placeholder:"John",required:!0})]}),e(t.Field.Root,{name:"lastName",children:[e(t.Field.Label,{children:"Last name"}),e(t.Field.Control,{type:"text",placeholder:"Doe",required:!0})]})]}),e(t.Fieldset.Root,{children:[e(t.Fieldset.Legend,{children:"Contact Information"}),e(t.Field.Root,{name:"email",children:[e(t.Field.Label,{children:"Email address"}),e(t.Field.Control,{type:"email",placeholder:"you@example.com",required:!0})]}),e(t.Field.Root,{name:"phone",children:[e(t.Field.Label,{children:"Phone number"}),e(t.Field.Control,{type:"tel",placeholder:"(555) 123-4567"})]})]}),e(t.Field.Root,{name:"message",children:[e(t.Field.Label,{children:"Message"}),e(t.Field.Control,{render:e("textarea",{placeholder:"Enter your message..."}),required:!0})]}),e(t.FormActions,{children:[e(t.Button,{type:"submit","data-variant":"solid",children:"Submit"}),e(t.Button,{type:"reset","data-variant":"outline",children:"Cancel"})]})]})})},D={render:()=>{let[o]=R.useState({username:!0,email:!1});return e("div",{style:{width:"400px"},children:e(t.Form,{onFormSubmit:r=>{console.log("Form submitted",r)},children:[e(t.Field.Root,{name:"username",invalid:o.username,children:[e(t.Field.Label,{children:["Username ",e("span",{style:{color:"var(--sl-status-warning)"},children:"*"})]}),e(t.Field.Control,{type:"text",placeholder:"johndoe","aria-invalid":o.username,defaultValue:"john",required:!0}),o.username&&e(t.Field.Error,{children:"Username must be at least 5 characters"})]}),e(t.Field.Root,{name:"email",children:[e(t.Field.Label,{children:["Email address ",e("span",{style:{color:"var(--sl-status-warning)"},children:"*"})]}),e(t.Field.Control,{type:"email",placeholder:"you@example.com",required:!0}),e(t.Field.Description,{children:"We'll never share your email with anyone else"})]}),e(t.Field.Root,{name:"password",children:[e(t.Field.Label,{children:["Password ",e("span",{style:{color:"var(--sl-status-warning)"},children:"*"})]}),e(t.Field.Control,{type:"password",placeholder:"Enter password",required:!0}),e(t.Field.Description,{children:"Must be at least 8 characters"})]}),e(t.FormActions,{children:[e(t.Button,{type:"submit","data-variant":"solid",children:"Create Account"}),e(t.Button,{type:"button","data-variant":"ghost",children:"Cancel"})]})]})})}},B={render:()=>e("div",{style:{width:"400px"},children:e(t.Form,{onFormSubmit:a=>{console.log("Form submitted",a)},children:[e(t.Field.Root,{name:"name",children:[e(t.Field.Label,{children:"Name"}),e(t.Field.Control,{type:"text",placeholder:"John Doe",required:!0})]}),e(t.Field.Root,{name:"email",children:[e(t.Field.Label,{children:"Email"}),e(t.Field.Control,{type:"email",placeholder:"you@example.com",required:!0})]}),e(t.FormActions,{style:{justifyContent:"flex-end"},children:[e(t.Button,{type:"button","data-variant":"ghost",children:"Cancel"}),e(t.Button,{type:"submit","data-variant":"solid",children:"Save"})]})]})})};var i=window.React,g=m||{},j=["Default","WithFieldsets","WithValidation","ActionsAlignedRight"];function N({id:o}){let a=c[o],r={...g.args||{},...a.args||{}};return(a.render||(n=>i.createElement(g.component,n)))(r,{args:r,id:o,name:o})}var k=j.map(o=>i.createElement("section",{key:o,className:"ds-story"},i.createElement("p",{className:"ds-story-name"},o.replace(/([a-z])([A-Z])/g,"$1 $2")),i.createElement("div",{className:"ds-story-body"},i.createElement(N,{id:o}))));window.ReactDOM.createRoot(document.getElementById("root")).render(i.createElement(i.Fragment,null,k));})();
|
|
16
|
+
|
|
17
|
+
</script>
|
|
18
|
+
</body>
|
|
19
|
+
</html>
|