@usememos/ui 26.10.5 → 26.11.1

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 CHANGED
@@ -3,7 +3,7 @@
3
3
  The Memos UI design system: tokens, foundation styles and React components for memos, the website, the web clipper and future usememos projects.
4
4
 
5
5
  - Calm, dense and tactile: pure grays, ink for emphasis, and a little depth that shows what holds a value and what you can press.
6
- - Light, Dark and High contrast themes, all from CSS custom properties.
6
+ - Light and Dark themes, all from CSS custom properties. Apps can add their own.
7
7
  - One package, `@usememos/ui`. ESM only, for React 18 or later, with behavior from [Base UI](https://base-ui.com).
8
8
 
9
9
  The package ships the tokens, the foundation styles and 28 components, each with a page in [docs/components](docs/components/README.md). Versions follow memos' CalVer (`26.10.0`, `26.10.1`) and do not signal breaking changes, so pin an exact version. [docs/](docs/README.md) is the design system and the source of truth for the package.
@@ -79,7 +79,7 @@ The package ships `llms.txt`, an index of the docs, and `llms-full.txt`, every d
79
79
 
80
80
  ### Themes
81
81
 
82
- Set `data-theme="light"`, `"dark"` or `"contrast"` on the root element, or on any element to theme its subtree. Without the attribute the tokens are Light. The package does not read `prefers-color-scheme`; the app does, so a saved preference can win over the system setting.
82
+ Set `data-theme="light"` or `"dark"` on the root element, or on any element to theme its subtree. Without the attribute the tokens are Light. The package does not read `prefers-color-scheme`; the app does, so a saved preference can win over the system setting.
83
83
 
84
84
  An app can add its own themes and fonts by setting the color, shadow and font tokens; every other token is internal. See [What an app can change](docs/color.md#what-an-app-can-change).
85
85
 
@@ -1,3 +1,3 @@
1
1
  'use client';
2
- import{X as b}from"lucide-react";import{forwardRef as s}from"react";import{cx as n,withClass as l}from"../../internal/class-name.js";import{Button as C}from"../button/index.js";import{jsx as i,jsxs as u}from"react/jsx-runtime";function v(t,p,g){let c=s(function({className:o,...e},r){return i(t.Trigger,{ref:r,...e,className:l(`mu-${p}-trigger`,o)})}),m=s(function({container:o,sheet:e=!0,closeLabel:r="Close",className:T,children:x,...H},L){return u(t.Portal,{container:o,children:[i(t.Backdrop,{className:"mu-dialog-backdrop"}),i(t.Viewport,{className:n("mu-dialog-viewport",e&&"mu-dialog-sheet"),children:u(t.Popup,{ref:L,...H,className:l(`mu-dialog-popup mu-${p}-popup mu-popup mu-base mu-s-md`,T),children:[x,g?i(t.Close,{className:"mu-dialog-x",render:i(C,{variant:"ghost",size:"sm",icon:i(b,{}),"aria-label":r})}):null]})})]})}),P=s(function({className:o,...e},r){return i(t.Title,{ref:r,...e,className:l("mu-dialog-title mu-title",o)})}),f=s(function({className:o,...e},r){return i(t.Description,{ref:r,...e,className:l("mu-dialog-description mu-body",o)})}),D=s(function({className:o,...e},r){return i(t.Close,{ref:r,...e,className:l(`mu-${p}-close`,o)})}),d=s(function({className:o,...e},r){return i("div",{ref:r,...e,className:n("mu-dialog-footer",o)})});return{Root:t.Root,Trigger:c,Popup:m,Title:P,Description:f,Close:D,Footer:d}}export{v as createDialogParts};
2
+ import{X as L}from"lucide-react";import{forwardRef as s}from"react";import{cx as n,withClass as l}from"../../internal/class-name.js";import{SizeContext as b}from"../../internal/size.js";import{Button as v}from"../button/index.js";import{jsx as t,jsxs as u}from"react/jsx-runtime";function w(i,p,g){let c=s(function({className:o,...e},r){return t(i.Trigger,{ref:r,...e,className:l(`mu-${p}-trigger`,o)})}),m=s(function({container:o,sheet:e=!0,closeLabel:r="Close",className:T,children:x,...C},H){return u(i.Portal,{container:o,children:[t(i.Backdrop,{className:"mu-dialog-backdrop"}),t(i.Viewport,{className:n("mu-dialog-viewport",e&&"mu-dialog-sheet"),children:u(i.Popup,{ref:H,...C,className:l(`mu-dialog-popup mu-${p}-popup mu-popup mu-base mu-s-md`,T),children:[t(b.Provider,{value:"md",children:x}),g?t(i.Close,{className:"mu-dialog-x",render:t(v,{variant:"ghost",size:"sm",icon:t(L,{}),"aria-label":r})}):null]})})]})}),P=s(function({className:o,...e},r){return t(i.Title,{ref:r,...e,className:l("mu-dialog-title mu-title",o)})}),f=s(function({className:o,...e},r){return t(i.Description,{ref:r,...e,className:l("mu-dialog-description mu-body",o)})}),d=s(function({className:o,...e},r){return t(i.Close,{ref:r,...e,className:l(`mu-${p}-close`,o)})}),D=s(function({className:o,...e},r){return t("div",{ref:r,...e,className:n("mu-dialog-footer",o)})});return{Root:i.Root,Trigger:c,Popup:m,Title:P,Description:f,Close:d,Footer:D}}export{w as createDialogParts};
3
3
  //# sourceMappingURL=parts.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/dialog/parts.tsx"],
4
- "sourcesContent": ["import { Dialog as BaseDialog } from '@base-ui/react/dialog';\nimport { X } from 'lucide-react';\nimport { forwardRef, type HTMLAttributes } from 'react';\nimport { cx, withClass } from '../../internal/class-name';\nimport { Button } from '../button';\n\nexport type RootProps = BaseDialog.Root.Props;\nexport interface TriggerProps extends BaseDialog.Trigger.Props {}\nexport interface PopupProps extends BaseDialog.Popup.Props {\n /** Where the dialog is portaled to. Default `document.body`. */\n container?: BaseDialog.Portal.Props['container'];\n /** Below `breakpoint-sm` the dialog becomes a sheet from the bottom. `false` keeps it centered. Default true. */\n sheet?: boolean;\n}\nexport interface TitleProps extends BaseDialog.Title.Props {}\nexport interface DescriptionProps extends BaseDialog.Description.Props {}\nexport interface CloseProps extends BaseDialog.Close.Props {}\nexport interface FooterProps extends HTMLAttributes<HTMLDivElement> {}\n\n/**\n * Builds the styled parts on Base UI's Dialog or AlertDialog, which share\n * their anatomy. `closeButton` adds the X at the top right of the popup.\n */\nexport function createDialogParts(Base: typeof BaseDialog, name: 'dialog' | 'alert-dialog', closeButton: boolean) {\n const Trigger = forwardRef<HTMLButtonElement, TriggerProps>(function DialogTrigger({ className, ...props }, ref) {\n return <Base.Trigger ref={ref} {...props} className={withClass(`mu-${name}-trigger`, className)} />;\n });\n\n const Popup = forwardRef<HTMLDivElement, PopupProps & { closeLabel?: string }>(function DialogPopup(\n { container, sheet = true, closeLabel = 'Close', className, children, ...props },\n ref,\n ) {\n return (\n <Base.Portal container={container}>\n <Base.Backdrop className=\"mu-dialog-backdrop\" />\n <Base.Viewport className={cx('mu-dialog-viewport', sheet && 'mu-dialog-sheet')}>\n <Base.Popup ref={ref} {...props} className={withClass(`mu-dialog-popup mu-${name}-popup mu-popup mu-base mu-s-md`, className)}>\n {children}\n {closeButton ? (\n <Base.Close className=\"mu-dialog-x\" render={<Button variant=\"ghost\" size=\"sm\" icon={<X />} aria-label={closeLabel} />} />\n ) : null}\n </Base.Popup>\n </Base.Viewport>\n </Base.Portal>\n );\n });\n\n const Title = forwardRef<HTMLHeadingElement, TitleProps>(function DialogTitle({ className, ...props }, ref) {\n return <Base.Title ref={ref} {...props} className={withClass('mu-dialog-title mu-title', className)} />;\n });\n\n const Description = forwardRef<HTMLParagraphElement, DescriptionProps>(function DialogDescription({ className, ...props }, ref) {\n return <Base.Description ref={ref} {...props} className={withClass('mu-dialog-description mu-body', className)} />;\n });\n\n const Close = forwardRef<HTMLButtonElement, CloseProps>(function DialogClose({ className, ...props }, ref) {\n return <Base.Close ref={ref} {...props} className={withClass(`mu-${name}-close`, className)} />;\n });\n\n const Footer = forwardRef<HTMLDivElement, FooterProps>(function DialogFooter({ className, ...props }, ref) {\n return <div ref={ref} {...props} className={cx('mu-dialog-footer', className)} />;\n });\n\n return { Root: Base.Root, Trigger, Popup, Title, Description, Close, Footer };\n}\n"],
5
- "mappings": ";AACA,OAAS,KAAAA,MAAS,eAClB,OAAS,cAAAC,MAAuC,QAChD,OAAS,MAAAC,EAAI,aAAAC,MAAiB,+BAC9B,OAAS,UAAAC,MAAc,qBAqBZ,cAAAC,EAWD,QAAAC,MAXC,oBAFJ,SAASC,EAAkBC,EAAyBC,EAAiCC,EAAsB,CAChH,IAAMC,EAAUV,EAA4C,SAAuB,CAAE,UAAAW,EAAW,GAAGC,CAAM,EAAGC,EAAK,CAC/G,OAAOT,EAACG,EAAK,QAAL,CAAa,IAAKM,EAAM,GAAGD,EAAO,UAAWV,EAAU,MAAMM,CAAI,WAAYG,CAAS,EAAG,CACnG,CAAC,EAEKG,EAAQd,EAAiE,SAC7E,CAAE,UAAAe,EAAW,MAAAC,EAAQ,GAAM,WAAAC,EAAa,QAAS,UAAAN,EAAW,SAAAO,EAAU,GAAGN,CAAM,EAC/EC,EACA,CACA,OACER,EAACE,EAAK,OAAL,CAAY,UAAWQ,EACtB,UAAAX,EAACG,EAAK,SAAL,CAAc,UAAU,qBAAqB,EAC9CH,EAACG,EAAK,SAAL,CAAc,UAAWN,EAAG,qBAAsBe,GAAS,iBAAiB,EAC3E,SAAAX,EAACE,EAAK,MAAL,CAAW,IAAKM,EAAM,GAAGD,EAAO,UAAWV,EAAU,sBAAsBM,CAAI,kCAAmCG,CAAS,EACzH,UAAAO,EACAT,EACCL,EAACG,EAAK,MAAL,CAAW,UAAU,cAAc,OAAQH,EAACD,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,KAAMC,EAACL,EAAA,EAAE,EAAI,aAAYkB,EAAY,EAAI,EACrH,MACN,EACF,GACF,CAEJ,CAAC,EAEKE,EAAQnB,EAA2C,SAAqB,CAAE,UAAAW,EAAW,GAAGC,CAAM,EAAGC,EAAK,CAC1G,OAAOT,EAACG,EAAK,MAAL,CAAW,IAAKM,EAAM,GAAGD,EAAO,UAAWV,EAAU,2BAA4BS,CAAS,EAAG,CACvG,CAAC,EAEKS,EAAcpB,EAAmD,SAA2B,CAAE,UAAAW,EAAW,GAAGC,CAAM,EAAGC,EAAK,CAC9H,OAAOT,EAACG,EAAK,YAAL,CAAiB,IAAKM,EAAM,GAAGD,EAAO,UAAWV,EAAU,gCAAiCS,CAAS,EAAG,CAClH,CAAC,EAEKU,EAAQrB,EAA0C,SAAqB,CAAE,UAAAW,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACzG,OAAOT,EAACG,EAAK,MAAL,CAAW,IAAKM,EAAM,GAAGD,EAAO,UAAWV,EAAU,MAAMM,CAAI,SAAUG,CAAS,EAAG,CAC/F,CAAC,EAEKW,EAAStB,EAAwC,SAAsB,CAAE,UAAAW,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACzG,OAAOT,EAAC,OAAI,IAAKS,EAAM,GAAGD,EAAO,UAAWX,EAAG,mBAAoBU,CAAS,EAAG,CACjF,CAAC,EAED,MAAO,CAAE,KAAMJ,EAAK,KAAM,QAAAG,EAAS,MAAAI,EAAO,MAAAK,EAAO,YAAAC,EAAa,MAAAC,EAAO,OAAAC,CAAO,CAC9E",
6
- "names": ["X", "forwardRef", "cx", "withClass", "Button", "jsx", "jsxs", "createDialogParts", "Base", "name", "closeButton", "Trigger", "className", "props", "ref", "Popup", "container", "sheet", "closeLabel", "children", "Title", "Description", "Close", "Footer"]
4
+ "sourcesContent": ["import { Dialog as BaseDialog } from '@base-ui/react/dialog';\nimport { X } from 'lucide-react';\nimport { forwardRef, type HTMLAttributes } from 'react';\nimport { cx, withClass } from '../../internal/class-name';\nimport { SizeContext } from '../../internal/size';\nimport { Button } from '../button';\n\nexport type RootProps = BaseDialog.Root.Props;\nexport interface TriggerProps extends BaseDialog.Trigger.Props {}\nexport interface PopupProps extends BaseDialog.Popup.Props {\n /** Where the dialog is portaled to. Default `document.body`. */\n container?: BaseDialog.Portal.Props['container'];\n /** Below `breakpoint-sm` the dialog becomes a sheet from the bottom. `false` keeps it centered. Default true. */\n sheet?: boolean;\n}\nexport interface TitleProps extends BaseDialog.Title.Props {}\nexport interface DescriptionProps extends BaseDialog.Description.Props {}\nexport interface CloseProps extends BaseDialog.Close.Props {}\nexport interface FooterProps extends HTMLAttributes<HTMLDivElement> {}\n\n/**\n * Builds the styled parts on Base UI's Dialog or AlertDialog, which share\n * their anatomy. `closeButton` adds the X at the top right of the popup.\n */\nexport function createDialogParts(Base: typeof BaseDialog, name: 'dialog' | 'alert-dialog', closeButton: boolean) {\n const Trigger = forwardRef<HTMLButtonElement, TriggerProps>(function DialogTrigger({ className, ...props }, ref) {\n return <Base.Trigger ref={ref} {...props} className={withClass(`mu-${name}-trigger`, className)} />;\n });\n\n const Popup = forwardRef<HTMLDivElement, PopupProps & { closeLabel?: string }>(function DialogPopup(\n { container, sheet = true, closeLabel = 'Close', className, children, ...props },\n ref,\n ) {\n return (\n <Base.Portal container={container}>\n <Base.Backdrop className=\"mu-dialog-backdrop\" />\n <Base.Viewport className={cx('mu-dialog-viewport', sheet && 'mu-dialog-sheet')}>\n <Base.Popup ref={ref} {...props} className={withClass(`mu-dialog-popup mu-${name}-popup mu-popup mu-base mu-s-md`, className)}>\n {/* A dialog is md wherever it is declared: React context crosses the portal, so a size set by a parent Root (a sm Table) would leak in. */}\n <SizeContext.Provider value=\"md\">{children}</SizeContext.Provider>\n {closeButton ? (\n <Base.Close className=\"mu-dialog-x\" render={<Button variant=\"ghost\" size=\"sm\" icon={<X />} aria-label={closeLabel} />} />\n ) : null}\n </Base.Popup>\n </Base.Viewport>\n </Base.Portal>\n );\n });\n\n const Title = forwardRef<HTMLHeadingElement, TitleProps>(function DialogTitle({ className, ...props }, ref) {\n return <Base.Title ref={ref} {...props} className={withClass('mu-dialog-title mu-title', className)} />;\n });\n\n const Description = forwardRef<HTMLParagraphElement, DescriptionProps>(function DialogDescription({ className, ...props }, ref) {\n return <Base.Description ref={ref} {...props} className={withClass('mu-dialog-description mu-body', className)} />;\n });\n\n const Close = forwardRef<HTMLButtonElement, CloseProps>(function DialogClose({ className, ...props }, ref) {\n return <Base.Close ref={ref} {...props} className={withClass(`mu-${name}-close`, className)} />;\n });\n\n const Footer = forwardRef<HTMLDivElement, FooterProps>(function DialogFooter({ className, ...props }, ref) {\n return <div ref={ref} {...props} className={cx('mu-dialog-footer', className)} />;\n });\n\n return { Root: Base.Root, Trigger, Popup, Title, Description, Close, Footer };\n}\n"],
5
+ "mappings": ";AACA,OAAS,KAAAA,MAAS,eAClB,OAAS,cAAAC,MAAuC,QAChD,OAAS,MAAAC,EAAI,aAAAC,MAAiB,+BAC9B,OAAS,eAAAC,MAAmB,yBAC5B,OAAS,UAAAC,MAAc,qBAqBZ,cAAAC,EAWD,QAAAC,MAXC,oBAFJ,SAASC,EAAkBC,EAAyBC,EAAiCC,EAAsB,CAChH,IAAMC,EAAUX,EAA4C,SAAuB,CAAE,UAAAY,EAAW,GAAGC,CAAM,EAAGC,EAAK,CAC/G,OAAOT,EAACG,EAAK,QAAL,CAAa,IAAKM,EAAM,GAAGD,EAAO,UAAWX,EAAU,MAAMO,CAAI,WAAYG,CAAS,EAAG,CACnG,CAAC,EAEKG,EAAQf,EAAiE,SAC7E,CAAE,UAAAgB,EAAW,MAAAC,EAAQ,GAAM,WAAAC,EAAa,QAAS,UAAAN,EAAW,SAAAO,EAAU,GAAGN,CAAM,EAC/EC,EACA,CACA,OACER,EAACE,EAAK,OAAL,CAAY,UAAWQ,EACtB,UAAAX,EAACG,EAAK,SAAL,CAAc,UAAU,qBAAqB,EAC9CH,EAACG,EAAK,SAAL,CAAc,UAAWP,EAAG,qBAAsBgB,GAAS,iBAAiB,EAC3E,SAAAX,EAACE,EAAK,MAAL,CAAW,IAAKM,EAAM,GAAGD,EAAO,UAAWX,EAAU,sBAAsBO,CAAI,kCAAmCG,CAAS,EAE1H,UAAAP,EAACF,EAAY,SAAZ,CAAqB,MAAM,KAAM,SAAAgB,EAAS,EAC1CT,EACCL,EAACG,EAAK,MAAL,CAAW,UAAU,cAAc,OAAQH,EAACD,EAAA,CAAO,QAAQ,QAAQ,KAAK,KAAK,KAAMC,EAACN,EAAA,EAAE,EAAI,aAAYmB,EAAY,EAAI,EACrH,MACN,EACF,GACF,CAEJ,CAAC,EAEKE,EAAQpB,EAA2C,SAAqB,CAAE,UAAAY,EAAW,GAAGC,CAAM,EAAGC,EAAK,CAC1G,OAAOT,EAACG,EAAK,MAAL,CAAW,IAAKM,EAAM,GAAGD,EAAO,UAAWX,EAAU,2BAA4BU,CAAS,EAAG,CACvG,CAAC,EAEKS,EAAcrB,EAAmD,SAA2B,CAAE,UAAAY,EAAW,GAAGC,CAAM,EAAGC,EAAK,CAC9H,OAAOT,EAACG,EAAK,YAAL,CAAiB,IAAKM,EAAM,GAAGD,EAAO,UAAWX,EAAU,gCAAiCU,CAAS,EAAG,CAClH,CAAC,EAEKU,EAAQtB,EAA0C,SAAqB,CAAE,UAAAY,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACzG,OAAOT,EAACG,EAAK,MAAL,CAAW,IAAKM,EAAM,GAAGD,EAAO,UAAWX,EAAU,MAAMO,CAAI,SAAUG,CAAS,EAAG,CAC/F,CAAC,EAEKW,EAASvB,EAAwC,SAAsB,CAAE,UAAAY,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACzG,OAAOT,EAAC,OAAI,IAAKS,EAAM,GAAGD,EAAO,UAAWZ,EAAG,mBAAoBW,CAAS,EAAG,CACjF,CAAC,EAED,MAAO,CAAE,KAAMJ,EAAK,KAAM,QAAAG,EAAS,MAAAI,EAAO,MAAAK,EAAO,YAAAC,EAAa,MAAAC,EAAO,OAAAC,CAAO,CAC9E",
6
+ "names": ["X", "forwardRef", "cx", "withClass", "SizeContext", "Button", "jsx", "jsxs", "createDialogParts", "Base", "name", "closeButton", "Trigger", "className", "props", "ref", "Popup", "container", "sheet", "closeLabel", "children", "Title", "Description", "Close", "Footer"]
7
7
  }
@@ -1,3 +1,3 @@
1
1
  'use client';
2
- import{Popover as s}from"@base-ui/react/popover";import{forwardRef as p}from"react";import{withClass as i}from"../../internal/class-name.js";import{splitPositioner as f}from"../../internal/popup.js";import{popoverClasses as m}from"./classes.js";import{jsx as t}from"react/jsx-runtime";var P=m(),d=s.Root,B=p(function({className:o,...e},r){return t(s.Trigger,{ref:r,...e,className:i("mu-popover-trigger",o)})}),C=p(function({container:o,className:e,...r},a){let[c,l]=f(r);return t(s.Portal,{container:o,children:t(s.Positioner,{sideOffset:6,...c,className:"mu-positioner",children:t(s.Popup,{ref:a,...l,className:i(P.popup,e)})})})}),D=p(function({className:o,...e},r){return t(s.Title,{ref:r,...e,className:i(P.title,o)})}),H=p(function({className:o,...e},r){return t(s.Description,{ref:r,...e,className:i(P.description,o)})}),M=p(function({className:o,...e},r){return t(s.Close,{ref:r,...e,className:i("mu-popover-close",o)})});export{M as Close,H as Description,C as Popup,d as Root,D as Title,B as Trigger};
2
+ import{Popover as s}from"@base-ui/react/popover";import{forwardRef as p}from"react";import{withClass as i}from"../../internal/class-name.js";import{splitPositioner as v}from"../../internal/popup.js";import{SizeContext as f}from"../../internal/size.js";import{popoverClasses as u}from"./classes.js";import{jsx as t}from"react/jsx-runtime";var P=u(),D=s.Root,H=p(function({className:o,...e},r){return t(s.Trigger,{ref:r,...e,className:i("mu-popover-trigger",o)})}),M=p(function({container:o,className:e,children:r,...a},c){let[l,m]=v(a);return t(s.Portal,{container:o,children:t(s.Positioner,{sideOffset:6,...l,className:"mu-positioner",children:t(s.Popup,{ref:c,...m,className:i(P.popup,e),children:t(f.Provider,{value:"md",children:r})})})})}),N=p(function({className:o,...e},r){return t(s.Title,{ref:r,...e,className:i(P.title,o)})}),h=p(function({className:o,...e},r){return t(s.Description,{ref:r,...e,className:i(P.description,o)})}),E=p(function({className:o,...e},r){return t(s.Close,{ref:r,...e,className:i("mu-popover-close",o)})});export{E as Close,h as Description,M as Popup,D as Root,N as Title,H as Trigger};
3
3
  //# sourceMappingURL=index.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/components/popover/index.tsx"],
4
- "sourcesContent": ["import { Popover as BasePopover } from '@base-ui/react/popover';\nimport { forwardRef } from 'react';\nimport { withClass } from '../../internal/class-name';\nimport { splitPositioner } from '../../internal/popup';\nimport { popoverClasses } from './classes';\n\nconst classes = /* @__PURE__ */ popoverClasses();\n\nexport type RootProps = BasePopover.Root.Props;\n\n/** Groups a trigger and its popover. */\nexport const Root = BasePopover.Root;\n\nexport interface TriggerProps extends BasePopover.Trigger.Props {}\n\n/** Opens the popover. Usually `render={<Button />}`. */\nexport const Trigger = forwardRef<HTMLButtonElement, TriggerProps>(function PopoverTrigger({ className, ...props }, ref) {\n return <BasePopover.Trigger ref={ref} {...props} className={withClass('mu-popover-trigger', className)} />;\n});\n\ntype PositionerProps = Pick<\n BasePopover.Positioner.Props,\n 'side' | 'align' | 'collisionAvoidance' | 'collisionBoundary' | 'sticky' | 'anchor' | 'positionMethod' | 'disableAnchorTracking'\n>;\n\nexport interface PopupProps extends BasePopover.Popup.Props, PositionerProps {\n /** Where the popover is portaled to. Default `document.body`. */\n container?: BasePopover.Portal.Props['container'];\n}\n\n/** The panel: a surface with `shadow-pop`, `popover-width` wide. */\nexport const Popup = forwardRef<HTMLDivElement, PopupProps>(function PopoverPopup({ container, className, ...props }, ref) {\n const [positioner, rest] = splitPositioner(props);\n return (\n <BasePopover.Portal container={container}>\n <BasePopover.Positioner sideOffset={6} {...positioner} className=\"mu-positioner\">\n <BasePopover.Popup ref={ref} {...rest} className={withClass(classes.popup, className)} />\n </BasePopover.Positioner>\n </BasePopover.Portal>\n );\n});\n\nexport interface TitleProps extends BasePopover.Title.Props {}\n\n/** The popover's heading, an `<h2>`. Names the popup for screen readers. */\nexport const Title = forwardRef<HTMLHeadingElement, TitleProps>(function PopoverTitle({ className, ...props }, ref) {\n return <BasePopover.Title ref={ref} {...props} className={withClass(classes.title, className)} />;\n});\n\nexport interface DescriptionProps extends BasePopover.Description.Props {}\n\n/** One line under the title, a `<p>`. */\nexport const Description = forwardRef<HTMLParagraphElement, DescriptionProps>(function PopoverDescription({ className, ...props }, ref) {\n return <BasePopover.Description ref={ref} {...props} className={withClass(classes.description, className)} />;\n});\n\nexport interface CloseProps extends BasePopover.Close.Props {}\n\n/** Closes the popover. Usually `render={<Button />}`. */\nexport const Close = forwardRef<HTMLButtonElement, CloseProps>(function PopoverClose({ className, ...props }, ref) {\n return <BasePopover.Close ref={ref} {...props} className={withClass('mu-popover-close', className)} />;\n});\n"],
5
- "mappings": ";AAAA,OAAS,WAAWA,MAAmB,yBACvC,OAAS,cAAAC,MAAkB,QAC3B,OAAS,aAAAC,MAAiB,+BAC1B,OAAS,mBAAAC,MAAuB,0BAChC,OAAS,kBAAAC,MAAsB,eAatB,cAAAC,MAAA,oBAXT,IAAMC,EAA0BF,EAAe,EAKlCG,EAAOP,EAAY,KAKnBQ,EAAUP,EAA4C,SAAwB,CAAE,UAAAQ,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACvH,OAAON,EAACL,EAAY,QAAZ,CAAoB,IAAKW,EAAM,GAAGD,EAAO,UAAWR,EAAU,qBAAsBO,CAAS,EAAG,CAC1G,CAAC,EAaYG,EAAQX,EAAuC,SAAsB,CAAE,UAAAY,EAAW,UAAAJ,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACzH,GAAM,CAACG,EAAYC,CAAI,EAAIZ,EAAgBO,CAAK,EAChD,OACEL,EAACL,EAAY,OAAZ,CAAmB,UAAWa,EAC7B,SAAAR,EAACL,EAAY,WAAZ,CAAuB,WAAY,EAAI,GAAGc,EAAY,UAAU,gBAC/D,SAAAT,EAACL,EAAY,MAAZ,CAAkB,IAAKW,EAAM,GAAGI,EAAM,UAAWb,EAAUI,EAAQ,MAAOG,CAAS,EAAG,EACzF,EACF,CAEJ,CAAC,EAKYO,EAAQf,EAA2C,SAAsB,CAAE,UAAAQ,EAAW,GAAGC,CAAM,EAAGC,EAAK,CAClH,OAAON,EAACL,EAAY,MAAZ,CAAkB,IAAKW,EAAM,GAAGD,EAAO,UAAWR,EAAUI,EAAQ,MAAOG,CAAS,EAAG,CACjG,CAAC,EAKYQ,EAAchB,EAAmD,SAA4B,CAAE,UAAAQ,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACtI,OAAON,EAACL,EAAY,YAAZ,CAAwB,IAAKW,EAAM,GAAGD,EAAO,UAAWR,EAAUI,EAAQ,YAAaG,CAAS,EAAG,CAC7G,CAAC,EAKYS,EAAQjB,EAA0C,SAAsB,CAAE,UAAAQ,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACjH,OAAON,EAACL,EAAY,MAAZ,CAAkB,IAAKW,EAAM,GAAGD,EAAO,UAAWR,EAAU,mBAAoBO,CAAS,EAAG,CACtG,CAAC",
6
- "names": ["BasePopover", "forwardRef", "withClass", "splitPositioner", "popoverClasses", "jsx", "classes", "Root", "Trigger", "className", "props", "ref", "Popup", "container", "positioner", "rest", "Title", "Description", "Close"]
4
+ "sourcesContent": ["import { Popover as BasePopover } from '@base-ui/react/popover';\nimport { forwardRef } from 'react';\nimport { withClass } from '../../internal/class-name';\nimport { splitPositioner } from '../../internal/popup';\nimport { SizeContext } from '../../internal/size';\nimport { popoverClasses } from './classes';\n\nconst classes = /* @__PURE__ */ popoverClasses();\n\nexport type RootProps = BasePopover.Root.Props;\n\n/** Groups a trigger and its popover. */\nexport const Root = BasePopover.Root;\n\nexport interface TriggerProps extends BasePopover.Trigger.Props {}\n\n/** Opens the popover. Usually `render={<Button />}`. */\nexport const Trigger = forwardRef<HTMLButtonElement, TriggerProps>(function PopoverTrigger({ className, ...props }, ref) {\n return <BasePopover.Trigger ref={ref} {...props} className={withClass('mu-popover-trigger', className)} />;\n});\n\ntype PositionerProps = Pick<\n BasePopover.Positioner.Props,\n 'side' | 'align' | 'collisionAvoidance' | 'collisionBoundary' | 'sticky' | 'anchor' | 'positionMethod' | 'disableAnchorTracking'\n>;\n\nexport interface PopupProps extends BasePopover.Popup.Props, PositionerProps {\n /** Where the popover is portaled to. Default `document.body`. */\n container?: BasePopover.Portal.Props['container'];\n}\n\n/** The panel: a surface with `shadow-pop`, `popover-width` wide. */\nexport const Popup = forwardRef<HTMLDivElement, PopupProps>(function PopoverPopup({ container, className, children, ...props }, ref) {\n const [positioner, rest] = splitPositioner(props);\n return (\n <BasePopover.Portal container={container}>\n <BasePopover.Positioner sideOffset={6} {...positioner} className=\"mu-positioner\">\n <BasePopover.Popup ref={ref} {...rest} className={withClass(classes.popup, className)}>\n {/* The panel is md wherever it is declared: React context crosses the portal, so a sm toolbar's size would leak in. */}\n <SizeContext.Provider value=\"md\">{children}</SizeContext.Provider>\n </BasePopover.Popup>\n </BasePopover.Positioner>\n </BasePopover.Portal>\n );\n});\n\nexport interface TitleProps extends BasePopover.Title.Props {}\n\n/** The popover's heading, an `<h2>`. Names the popup for screen readers. */\nexport const Title = forwardRef<HTMLHeadingElement, TitleProps>(function PopoverTitle({ className, ...props }, ref) {\n return <BasePopover.Title ref={ref} {...props} className={withClass(classes.title, className)} />;\n});\n\nexport interface DescriptionProps extends BasePopover.Description.Props {}\n\n/** One line under the title, a `<p>`. */\nexport const Description = forwardRef<HTMLParagraphElement, DescriptionProps>(function PopoverDescription({ className, ...props }, ref) {\n return <BasePopover.Description ref={ref} {...props} className={withClass(classes.description, className)} />;\n});\n\nexport interface CloseProps extends BasePopover.Close.Props {}\n\n/** Closes the popover. Usually `render={<Button />}`. */\nexport const Close = forwardRef<HTMLButtonElement, CloseProps>(function PopoverClose({ className, ...props }, ref) {\n return <BasePopover.Close ref={ref} {...props} className={withClass('mu-popover-close', className)} />;\n});\n"],
5
+ "mappings": ";AAAA,OAAS,WAAWA,MAAmB,yBACvC,OAAS,cAAAC,MAAkB,QAC3B,OAAS,aAAAC,MAAiB,+BAC1B,OAAS,mBAAAC,MAAuB,0BAChC,OAAS,eAAAC,MAAmB,yBAC5B,OAAS,kBAAAC,MAAsB,eAatB,cAAAC,MAAA,oBAXT,IAAMC,EAA0BF,EAAe,EAKlCG,EAAOR,EAAY,KAKnBS,EAAUR,EAA4C,SAAwB,CAAE,UAAAS,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACvH,OAAON,EAACN,EAAY,QAAZ,CAAoB,IAAKY,EAAM,GAAGD,EAAO,UAAWT,EAAU,qBAAsBQ,CAAS,EAAG,CAC1G,CAAC,EAaYG,EAAQZ,EAAuC,SAAsB,CAAE,UAAAa,EAAW,UAAAJ,EAAW,SAAAK,EAAU,GAAGJ,CAAM,EAAGC,EAAK,CACnI,GAAM,CAACI,EAAYC,CAAI,EAAId,EAAgBQ,CAAK,EAChD,OACEL,EAACN,EAAY,OAAZ,CAAmB,UAAWc,EAC7B,SAAAR,EAACN,EAAY,WAAZ,CAAuB,WAAY,EAAI,GAAGgB,EAAY,UAAU,gBAC/D,SAAAV,EAACN,EAAY,MAAZ,CAAkB,IAAKY,EAAM,GAAGK,EAAM,UAAWf,EAAUK,EAAQ,MAAOG,CAAS,EAElF,SAAAJ,EAACF,EAAY,SAAZ,CAAqB,MAAM,KAAM,SAAAW,EAAS,EAC7C,EACF,EACF,CAEJ,CAAC,EAKYG,EAAQjB,EAA2C,SAAsB,CAAE,UAAAS,EAAW,GAAGC,CAAM,EAAGC,EAAK,CAClH,OAAON,EAACN,EAAY,MAAZ,CAAkB,IAAKY,EAAM,GAAGD,EAAO,UAAWT,EAAUK,EAAQ,MAAOG,CAAS,EAAG,CACjG,CAAC,EAKYS,EAAclB,EAAmD,SAA4B,CAAE,UAAAS,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACtI,OAAON,EAACN,EAAY,YAAZ,CAAwB,IAAKY,EAAM,GAAGD,EAAO,UAAWT,EAAUK,EAAQ,YAAaG,CAAS,EAAG,CAC7G,CAAC,EAKYU,EAAQnB,EAA0C,SAAsB,CAAE,UAAAS,EAAW,GAAGC,CAAM,EAAGC,EAAK,CACjH,OAAON,EAACN,EAAY,MAAZ,CAAkB,IAAKY,EAAM,GAAGD,EAAO,UAAWT,EAAU,mBAAoBQ,CAAS,EAAG,CACtG,CAAC",
6
+ "names": ["BasePopover", "forwardRef", "withClass", "splitPositioner", "SizeContext", "popoverClasses", "jsx", "classes", "Root", "Trigger", "className", "props", "ref", "Popup", "container", "children", "positioner", "rest", "Title", "Description", "Close"]
7
7
  }
package/dist/styles.css CHANGED
@@ -1 +1 @@
1
- @layer mu{.mu-s-xs{--mu-row-height: var(--mu-control-xs);--mu-row-padding: 6px;--mu-row-padding-icon: var(--mu-space-1);--mu-row-font-size: 12px;--mu-row-line-height: 16px;--mu-row-radius: var(--mu-radius-sm);--mu-row-gap: var(--mu-space-1);--mu-row-icon: var(--mu-icon-xs);--mu-row-icon-stroke: 1.25px;--mu-row-check-box: 14px}.mu-s-sm{--mu-row-height: var(--mu-control-sm);--mu-row-padding: var(--mu-space-2);--mu-row-padding-icon: 6px;--mu-row-font-size: 13px;--mu-row-line-height: 18px;--mu-row-radius: var(--mu-radius-sm);--mu-row-gap: var(--mu-space-1);--mu-row-icon: var(--mu-icon-sm);--mu-row-icon-stroke: 1.25px;--mu-row-check-box: 16px}.mu-s-md{--mu-row-height: var(--mu-control-md);--mu-row-padding: var(--mu-space-3);--mu-row-padding-icon: 10px;--mu-row-font-size: 14px;--mu-row-line-height: 20px;--mu-row-radius: var(--mu-radius-md);--mu-row-gap: 6px;--mu-row-icon: var(--mu-icon-md);--mu-row-icon-stroke: 1.5px;--mu-row-check-box: 18px}.mu-recessed{background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track)}.mu-raised{background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),rgba(255,255,255,0) 60%);box-shadow:var(--mu-shadow-raised)}.mu-key{background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),rgba(255,255,255,0) 60%);box-shadow:var(--mu-shadow-key)}.mu-popup{background:var(--mu-surface);box-shadow:var(--mu-shadow-pop);border-radius:var(--mu-radius-xl)}.mu-positioner{z-index:var(--mu-layer-popup);outline:0}.mu-popup-motion{transition:opacity var(--mu-duration-fade) var(--mu-ease-out),translate var(--mu-duration-fade) var(--mu-ease-out)}.mu-popup-motion[data-starting-style],.mu-popup-motion[data-ending-style]{opacity:0;translate:0 var(--mu-space-1)}.mu-popup-motion[data-instant]{transition:none}@media(prefers-reduced-motion:reduce){.mu-popup-motion[data-starting-style],.mu-popup-motion[data-ending-style]{translate:none}}.mu-base{font-family:var(--mu-font-sans);font-size:var(--mu-row-font-size, 14px);line-height:var(--mu-row-line-height, 20px);font-weight:500;letter-spacing:0;color:var(--mu-ink);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:transparent}.mu-base ::selection,.mu-base::selection{background:var(--mu-selection)}.mu-visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.mu-focus:focus-visible{outline:var(--mu-focus-width) solid var(--mu-focus);outline-offset:var(--mu-focus-width)}.mu-hit{position:relative}@media(pointer:coarse){.mu-hit:after{content:"";position:absolute;left:50%;top:50%;width:max(100%,var(--mu-hit-area));height:max(100%,var(--mu-hit-area));transform:translate(-50%,-50%)}}.mu-icon,.mu-base svg.lucide,.mu-prose svg.lucide{width:var(--mu-row-icon, 16px);height:var(--mu-row-icon, 16px);flex:none;display:block;stroke-width:var(--mu-row-icon-stroke, 1.5px)}.mu-icon *,.mu-base svg.lucide *,.mu-prose svg.lucide *{vector-effect:non-scaling-stroke}.mu-label-xs{font-family:var(--mu-font-sans);font-size:12px;line-height:16px;font-weight:500}.mu-caption{font-family:var(--mu-font-sans);font-size:13px;line-height:18px;font-weight:400}.mu-label-sm{font-family:var(--mu-font-sans);font-size:13px;line-height:18px;font-weight:500}.mu-body{font-family:var(--mu-font-sans);font-size:14px;line-height:20px;font-weight:400}.mu-label{font-family:var(--mu-font-sans);font-size:14px;line-height:20px;font-weight:500}.mu-title{font-family:var(--mu-font-display);font-size:16px;line-height:24px;font-weight:500}.mu-heading{font-family:var(--mu-font-display);font-size:20px;line-height:28px;font-weight:500}.mu-display{font-family:var(--mu-font-display);font-size:32px;line-height:40px;font-weight:500;letter-spacing:-.02em}.mu-prose{--prose-fs: 16px;--prose-lh: 24px;--prose-h1: 20px;--prose-h1-lh: 28px;--prose-h2: 16px;--prose-h2-lh: 24px;--prose-head: 13px;--prose-head-lh: 18px}.mu-prose-sm{--prose-fs: 14px;--prose-lh: 22px}}@layer mu{.mu-spinner{display:inline-block;flex:none;box-sizing:border-box;width:var(--mu-row-icon);height:var(--mu-row-icon);border:var(--mu-row-icon-stroke) solid currentColor;border-top-color:transparent;border-radius:var(--mu-radius-full);animation:mu-spin var(--mu-duration-spin) linear infinite}@keyframes mu-spin{to{rotate:1turn}}}@layer mu{.mu-button{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:var(--mu-row-gap);box-sizing:border-box;height:var(--mu-row-height);margin:0;padding:0 var(--mu-row-padding);border:0;border-radius:var(--mu-row-radius);color:var(--mu-ink);background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),transparent 60%);box-shadow:var(--mu-shadow-raised);white-space:nowrap;text-decoration:none;cursor:pointer;user-select:none;transition-property:background-color,box-shadow,color,translate;transition-duration:var(--mu-duration-press);transition-timing-function:var(--mu-ease-out)}.mu-button:where(:has(>svg:first-child)){padding-inline-start:var(--mu-row-padding-icon)}.mu-button.mu-button-icon{width:var(--mu-row-height);padding:0}.mu-button-label{min-width:0;overflow:hidden;text-overflow:ellipsis}@media(hover:hover){.mu-button:hover:not([data-disabled]){background-color:var(--mu-key-hover)}.mu-button-primary:hover:not([data-disabled]){background-color:var(--mu-primary-hover)}.mu-button-danger:hover:not([data-disabled]){background-color:var(--mu-danger-key);filter:brightness(1.08)}.mu-button-ghost:hover:not([data-disabled]){background-color:var(--mu-hover);color:var(--mu-ink)}}.mu-button:active:not([data-disabled]){translate:0 .5px;box-shadow:var(--mu-shadow-pressed)}.mu-button-primary{color:var(--mu-on-primary);background-color:var(--mu-primary)}.mu-button-danger{color:var(--mu-on-danger);background-color:var(--mu-danger-key)}.mu-button-ghost{color:var(--mu-ink-muted);background-color:transparent;background-image:none;box-shadow:none}.mu-button-ghost[data-popup-open]{background-color:var(--mu-hover);color:var(--mu-ink)}.mu-button-ghost:active:not([data-disabled]){translate:none;background-color:var(--mu-well);box-shadow:var(--mu-shadow-track)}.mu-button[data-disabled]:not([data-loading]){opacity:.45;cursor:not-allowed}.mu-button[data-loading]{cursor:progress}.mu-button[data-loading]>:not(.mu-spinner){opacity:0}.mu-button>.mu-spinner{position:absolute;inset:0;margin:auto}@media(prefers-reduced-motion:reduce){.mu-button:active:not([data-disabled]){translate:none}}}@layer mu{.mu-kbd{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:var(--mu-control-xs);height:var(--mu-control-xs);padding:0 var(--mu-space-1);border-radius:var(--mu-radius-sm);color:var(--mu-ink-muted);background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),transparent 60%);box-shadow:var(--mu-shadow-raised);white-space:nowrap}}@layer mu{.mu-separator{flex:none;align-self:stretch;margin:0;border:0;background-color:var(--mu-line)}.mu-separator[data-orientation=horizontal]{height:1px}.mu-separator[data-orientation=vertical]{width:1px}}@layer mu{.mu-badge{display:inline-flex;align-items:center;gap:var(--mu-space-1);box-sizing:border-box;height:var(--mu-control-xs);padding:0 var(--mu-row-padding);border-radius:var(--mu-radius-sm);white-space:nowrap;vertical-align:middle}.mu-badge-neutral{color:var(--mu-ink);background-color:var(--mu-well)}.mu-badge-outline{color:var(--mu-ink-muted);box-shadow:inset 0 0 0 1px var(--mu-edge)}.mu-badge-success{color:var(--mu-success);background-color:var(--mu-success-soft)}.mu-badge-warning{color:var(--mu-warning);background-color:var(--mu-warning-soft)}.mu-badge-danger{color:var(--mu-danger);background-color:var(--mu-danger-soft)}}@layer mu{.mu-avatar-root{display:inline-flex;flex:none;align-items:center;justify-content:center;overflow:hidden;box-sizing:border-box;width:var(--mu-row-height);height:var(--mu-row-height);border-radius:var(--mu-radius-full);color:var(--mu-ink-muted);background-color:var(--mu-well);vertical-align:middle;user-select:none}.mu-avatar-image{width:100%;height:100%;object-fit:cover}.mu-avatar-fallback{display:flex;align-items:center;justify-content:center;width:100%;height:100%}}@layer mu{.mu-link{color:var(--mu-accent);text-decoration:none;text-underline-offset:.2em;border-radius:var(--mu-radius-xs);cursor:pointer}.mu-link:hover,.mu-link:focus-visible,.mu-link-underline{text-decoration:underline}[data-theme=contrast] .mu-link{text-decoration:underline}.mu-link-muted{color:var(--mu-ink-muted)}.mu-link-muted:hover{color:var(--mu-ink)}.mu-link>.mu-icon{display:inline-block;width:.85em;height:.85em;margin-inline-start:.1em;vertical-align:-.05em}}@layer mu{.mu-skeleton{box-sizing:border-box;width:100%;height:var(--mu-row-line-height);border-radius:var(--mu-radius-sm);background-color:var(--mu-well);background-image:linear-gradient(90deg,transparent 0%,var(--mu-hover) 50%,transparent 100%);background-size:200% 100%;background-repeat:no-repeat;animation:mu-shimmer var(--mu-duration-shimmer) ease-in-out infinite}.mu-skeleton-round{width:var(--mu-row-height);height:var(--mu-row-height);border-radius:var(--mu-radius-full)}@keyframes mu-shimmer{0%{background-position:150% 0}to{background-position:-50% 0}}@media(prefers-reduced-motion:reduce){.mu-skeleton{animation:none;background-image:none}}}@layer mu{.mu-field-root{display:flex;flex-direction:column;gap:var(--mu-space-1);min-width:0}.mu-field-label{color:var(--mu-ink)}.mu-field-item{display:flex}.mu-field-label:where(:has(>.mu-checkbox,>.mu-switch,>.mu-radio)){display:inline-flex;align-items:center;gap:var(--mu-space-2);font-weight:400;cursor:pointer}.mu-field-label[data-disabled]{opacity:.45;cursor:not-allowed}.mu-field-description{margin:0;color:var(--mu-ink-muted)}.mu-field-root[data-invalid]>.mu-field-description{display:none}.mu-field-error{display:flex;align-items:flex-start;gap:var(--mu-space-1);color:var(--mu-danger)}.mu-field-error>.mu-icon{--mu-row-icon: var(--mu-icon-sm);margin-block:calc((1lh - var(--mu-icon-sm)) / 2)}.mu-fieldset-root{display:flex;flex-direction:column;gap:var(--mu-space-3);min-width:0;margin:0;padding:0;border:0}.mu-fieldset-legend{margin-bottom:var(--mu-space-1);padding:0;color:var(--mu-ink)}}@layer mu{.mu-input-root{display:flex;align-items:center;gap:var(--mu-row-gap);box-sizing:border-box;width:100%;min-width:0;height:var(--mu-row-height);padding:0 var(--mu-row-padding);border-radius:var(--mu-row-radius);color:var(--mu-ink);background-color:var(--mu-surface);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);cursor:text;transition:box-shadow var(--mu-duration-fade) var(--mu-ease-out)}.mu-input-root:where(:has(>.mu-input-prefix)){padding-inline-start:var(--mu-row-padding-icon)}.mu-input-root:where(:has(>.mu-input-suffix)){padding-inline-end:var(--mu-row-padding-icon)}@media(hover:hover){.mu-input-root:hover:not([data-disabled],[aria-disabled=true],:has(>[data-disabled])){box-shadow:inset 0 0 0 1px var(--mu-ink-muted),var(--mu-shadow-track)}}.mu-input-root:where(:has(>.mu-input:focus)),.mu-input-root:where(:not(:has(>.mu-input))):focus-within{outline:var(--mu-focus-width) solid var(--mu-focus);outline-offset:var(--mu-focus-width)}.mu-input-root:is([data-invalid],[aria-invalid=true],:has(>[data-invalid])){box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-track)}.mu-input-root:is([data-disabled],[aria-disabled=true],:has(>[data-disabled])){opacity:.45;cursor:not-allowed}.mu-input{flex:1;min-width:0;height:100%;margin:0;padding:0;border:0;outline:none;color:inherit;background:none;font:inherit;font-weight:400}.mu-input::placeholder{color:var(--mu-ink-muted);opacity:1}.mu-input[data-disabled]{cursor:not-allowed}.mu-input-prefix,.mu-input-suffix{display:flex;flex:none;align-items:center;gap:var(--mu-space-1);color:var(--mu-ink-muted)}}@layer mu{.mu-textarea{display:block;box-sizing:border-box;width:100%;min-height:var(--mu-row-height);margin:0;padding:calc((var(--mu-row-height) - var(--mu-row-line-height)) / 2) var(--mu-row-padding);border:0;border-radius:var(--mu-row-radius);color:var(--mu-ink);background-color:var(--mu-surface);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);font-weight:400;resize:vertical;transition:box-shadow var(--mu-duration-fade) var(--mu-ease-out)}.mu-textarea::placeholder{color:var(--mu-ink-muted);opacity:1}@media(hover:hover){.mu-textarea:hover:not([data-disabled],[aria-disabled=true]){box-shadow:inset 0 0 0 1px var(--mu-ink-muted),var(--mu-shadow-track)}}.mu-textarea:focus{outline:var(--mu-focus-width) solid var(--mu-focus);outline-offset:var(--mu-focus-width)}.mu-textarea:is([data-invalid],[aria-invalid=true]){box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-track)}.mu-textarea:is([data-disabled],[aria-disabled=true]){opacity:.45;cursor:not-allowed}}@layer mu{.mu-checkbox{display:inline-flex;flex:none;align-items:center;justify-content:center;box-sizing:border-box;width:var(--mu-row-check-box);height:var(--mu-row-check-box);border-radius:var(--mu-radius-sm);color:var(--mu-on-primary);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);cursor:pointer;transition-property:background-color,box-shadow,scale;transition-duration:var(--mu-duration-press);transition-timing-function:var(--mu-ease-out)}.mu-checkbox[data-checked],.mu-checkbox[data-indeterminate]{background-color:var(--mu-primary);box-shadow:none}.mu-checkbox[data-invalid]{box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-track)}.mu-checkbox:active:not([data-disabled],[data-readonly]){scale:.94}.mu-checkbox[data-disabled]{opacity:.45;cursor:not-allowed}.mu-checkbox-indicator{display:flex;transition:opacity var(--mu-duration-fade) var(--mu-ease-out) var(--mu-duration-press),scale var(--mu-duration-fade) var(--mu-ease-out) var(--mu-duration-press)}.mu-checkbox-indicator[data-starting-style],.mu-checkbox-indicator[data-ending-style]{opacity:0;scale:.6}.mu-checkbox-indicator>svg{width:calc(var(--mu-row-check-box) - 2 * var(--mu-inset));height:calc(var(--mu-row-check-box) - 2 * var(--mu-inset));stroke-width:2}.mu-checkbox-indicator>svg *{vector-effect:non-scaling-stroke}@media(prefers-reduced-motion:reduce){.mu-checkbox:active:not([data-disabled],[data-readonly]){scale:none}.mu-checkbox-indicator[data-starting-style],.mu-checkbox-indicator[data-ending-style]{scale:none}}}@layer mu{.mu-switch{--switch-h: calc(var(--mu-row-check-box) + var(--mu-inset));--switch-w: calc(var(--switch-h) * 1.7);--knob: calc(var(--switch-h) - 2 * var(--mu-inset));position:relative;display:inline-flex;flex:none;align-items:center;box-sizing:border-box;width:var(--switch-w);height:var(--switch-h);padding:var(--mu-inset);border-radius:var(--mu-radius-full);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);cursor:pointer;transition:background-color var(--mu-duration-settle) var(--mu-ease-settle),box-shadow var(--mu-duration-settle) var(--mu-ease-settle)}.mu-switch[data-checked]{background-color:var(--mu-primary);box-shadow:inset 0 0 0 1px var(--mu-primary)}.mu-switch[data-invalid]{box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-track)}.mu-switch[data-disabled]{opacity:.45;cursor:not-allowed}.mu-switch-thumb{display:block;width:var(--knob);height:var(--knob);border-radius:var(--mu-radius-full);background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),transparent 60%);box-shadow:var(--mu-shadow-key);transition:translate var(--mu-duration-settle) var(--mu-ease-settle),scale var(--mu-duration-press) var(--mu-ease-out),background-color var(--mu-duration-settle) var(--mu-ease-settle)}.mu-switch-thumb[data-checked]{translate:calc(var(--switch-w) - var(--switch-h)) 0;background-color:var(--mu-on-primary)}.mu-switch:active:not([data-disabled],[data-readonly])>.mu-switch-thumb{scale:1.1}@media(prefers-reduced-motion:reduce){.mu-switch-thumb{transition-property:background-color}.mu-switch:active:not([data-disabled],[data-readonly])>.mu-switch-thumb{scale:none}}}@layer mu{.mu-radio-group{display:flex;flex-direction:column;align-items:flex-start;gap:var(--mu-space-3)}.mu-radio-group[data-orientation=horizontal]{flex-direction:row;flex-wrap:wrap;gap:var(--mu-space-3) var(--mu-space-4)}.mu-radio-group[data-orientation=horizontal]>.mu-fieldset-legend{flex-basis:100%}.mu-radio{display:inline-flex;flex:none;align-items:center;justify-content:center;box-sizing:border-box;width:var(--mu-row-check-box);height:var(--mu-row-check-box);border-radius:var(--mu-radius-full);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);cursor:pointer;transition-property:background-color,box-shadow,scale;transition-duration:var(--mu-duration-press);transition-timing-function:var(--mu-ease-out)}.mu-radio[data-checked]{background-color:var(--mu-primary);box-shadow:none}.mu-radio[data-invalid]{box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-track)}.mu-radio:active:not([data-disabled],[data-readonly]){scale:.94}.mu-radio[data-disabled]{opacity:.45;cursor:not-allowed}.mu-radio-indicator{width:calc(var(--mu-row-check-box) / 2.5);height:calc(var(--mu-row-check-box) / 2.5);border-radius:var(--mu-radius-full);background-color:var(--mu-on-primary);transition:opacity var(--mu-duration-fade) var(--mu-ease-out) var(--mu-duration-press),scale var(--mu-duration-fade) var(--mu-ease-out) var(--mu-duration-press)}.mu-radio-indicator[data-starting-style],.mu-radio-indicator[data-ending-style]{opacity:0;scale:.4}@media(prefers-reduced-motion:reduce){.mu-radio:active:not([data-disabled],[data-readonly]){scale:none}.mu-radio-indicator[data-starting-style],.mu-radio-indicator[data-ending-style]{scale:none}}}@layer mu{.mu-toggle{position:relative;display:inline-flex;flex:none;align-items:center;justify-content:center;gap:var(--mu-row-gap);box-sizing:border-box;height:var(--mu-row-height);margin:0;padding:0 var(--mu-row-padding);border:0;border-radius:var(--mu-row-radius);color:var(--mu-ink-muted);background-color:transparent;white-space:nowrap;cursor:pointer;user-select:none;transition-property:background-color,box-shadow,color;transition-duration:var(--mu-duration-press);transition-timing-function:var(--mu-ease-out)}.mu-toggle:where(:has(>svg:first-child)){padding-inline-start:var(--mu-row-padding-icon)}.mu-toggle.mu-toggle-icon{width:var(--mu-row-height);padding:0}@media(hover:hover){.mu-toggle:hover:not([data-disabled]){color:var(--mu-ink);background-color:var(--mu-hover)}}.mu-toggle[data-pressed],.mu-toggle:active:not([data-disabled]){color:var(--mu-ink);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track)}.mu-toggle[data-disabled]{opacity:.45;cursor:not-allowed}}@layer mu{.mu-segmented{position:relative;display:inline-flex;align-items:stretch;gap:0;box-sizing:border-box;height:var(--mu-row-height);padding:var(--mu-inset);border-radius:var(--mu-row-radius);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track)}.mu-segmented-key{position:absolute;top:var(--mu-inset);left:0;width:var(--key-width);height:calc(var(--mu-row-height) - 2 * var(--mu-inset));translate:var(--key-left) 0;border-radius:calc(var(--mu-row-radius) - var(--mu-inset));background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),transparent 60%);box-shadow:var(--mu-shadow-key);transition:translate var(--mu-duration-settle) var(--mu-ease-settle),width var(--mu-duration-settle) var(--mu-ease-settle)}.mu-toggle-group.mu-segmented:not([data-keyed])>.mu-segmented-key{display:none}.mu-tabs-indicator{--key-left: var(--active-tab-left);--key-width: var(--active-tab-width)}.mu-segmented-item,.mu-segmented>.mu-toggle{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:var(--mu-row-gap);box-sizing:border-box;height:100%;margin:0;padding:0 calc(var(--mu-row-padding) - var(--mu-inset));border:0;border-radius:calc(var(--mu-row-radius) - var(--mu-inset));color:var(--mu-ink-muted);background:none;box-shadow:none;font:inherit;white-space:nowrap;cursor:pointer;user-select:none;transition:color var(--mu-duration-fade) var(--mu-ease-out)}.mu-segmented>.mu-toggle.mu-toggle-icon{width:calc(var(--mu-row-height) - 2 * var(--mu-inset));padding:0}@media(hover:hover){.mu-segmented-item:hover:not([data-disabled]),.mu-segmented>.mu-toggle:hover:not([data-disabled]){color:var(--mu-ink);background:none}}.mu-segmented-item[data-active],.mu-segmented>.mu-toggle[data-pressed],.mu-segmented>.mu-toggle:active:not([data-disabled]){color:var(--mu-ink);background:none;box-shadow:none}.mu-segmented-item[data-disabled]{opacity:.45;cursor:not-allowed}.mu-tabs-root{display:flex;flex-direction:column;gap:var(--mu-space-4)}.mu-tabs-list{align-self:flex-start}.mu-tabs-panel{border-radius:var(--mu-radius-sm)}@media(prefers-reduced-motion:reduce){.mu-segmented-key{transition:none}}}@layer mu{.mu-toggle-group{display:inline-flex;align-items:center;gap:var(--mu-inset)}.mu-toggle-group>.mu-separator{align-self:center;height:max(var(--mu-space-2),calc(var(--mu-row-height) - 2 * var(--mu-space-2)));margin-inline:var(--mu-space-1)}}@layer mu{.mu-tooltip-popup{display:flex;align-items:center;gap:var(--mu-space-2);box-sizing:border-box;max-width:var(--mu-tooltip-width);padding:var(--mu-space-1) var(--mu-space-2);border-radius:var(--mu-radius-md);color:var(--mu-on-primary);background-color:var(--mu-primary);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.mu-tooltip-shortcut{opacity:.65}}@layer mu{.mu-popover-popup{display:flex;flex-direction:column;gap:var(--mu-space-3);box-sizing:border-box;width:var(--mu-popover-width);max-width:var(--available-width);padding:var(--mu-space-4);outline:0}.mu-popover-title{margin:0;color:var(--mu-ink)}.mu-popover-description{margin:calc(-1 * var(--mu-space-2)) 0 0;color:var(--mu-ink-muted)}}@layer mu{.mu-menu-popup{box-sizing:border-box;min-width:var(--mu-menu-width);max-height:var(--available-height);overflow-y:auto;padding:var(--mu-space-1);outline:0}.mu-menu-item{display:flex;align-items:center;gap:var(--mu-space-2);box-sizing:border-box;height:var(--mu-row-height);padding:0 var(--mu-row-padding);border-radius:calc(var(--mu-radius-xl) - var(--mu-space-1));color:var(--mu-ink);font-weight:400;white-space:nowrap;cursor:default;user-select:none;outline:0}.mu-menu-item:where(:has(>svg:first-child)){padding-inline-start:var(--mu-row-padding-icon)}.mu-menu-item>svg{color:var(--mu-ink-muted)}.mu-menu-item[data-highlighted],.mu-menu-submenu-trigger[data-popup-open]{background-color:var(--mu-hover)}.mu-menu-item[data-disabled]{opacity:.45}.mu-menu-item-danger,.mu-menu-item-danger>svg{color:var(--mu-danger)}.mu-menu-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.mu-menu-shortcut{margin-inline-start:var(--mu-space-4);color:var(--mu-ink-muted)}.mu-menu-indicator{display:grid;flex:none;place-items:center;width:var(--mu-row-icon);height:var(--mu-row-icon);margin-inline-start:var(--mu-space-2)}.mu-menu-indicator>svg{color:var(--mu-ink)}.mu-menu-chevron{margin-inline-end:calc(var(--mu-row-padding-icon) - var(--mu-row-padding));color:var(--mu-ink-muted)}.mu-menu-group-label{padding:var(--mu-space-2) var(--mu-row-padding) var(--mu-space-1);color:var(--mu-ink-muted)}.mu-menu-separator{height:1px;margin:var(--mu-space-1) calc(-1 * var(--mu-space-1));background-color:var(--mu-line)}}@layer mu{.mu-select-trigger{justify-content:space-between;min-width:0;padding-inline-end:var(--mu-row-padding-icon);text-align:start}.mu-select-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mu-select-value[data-placeholder]{color:var(--mu-ink-muted);font-weight:400}.mu-select-icon{display:flex;flex:none;color:var(--mu-ink-muted)}.mu-select-trigger[data-invalid]{box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-key)}.mu-select-positioner{outline:0}.mu-select-popup{box-sizing:border-box;min-width:max(var(--mu-menu-width),var(--anchor-width));max-height:var(--available-height);padding:var(--mu-space-1);outline:0}.mu-select-list{overflow-y:auto;max-height:var(--available-height);scroll-padding-block:var(--mu-space-1);outline:0}.mu-select-item{display:flex;align-items:center;gap:var(--mu-space-2);box-sizing:border-box;height:var(--mu-row-height);padding:0 var(--mu-row-padding);border-radius:calc(var(--mu-radius-xl) - var(--mu-space-1));color:var(--mu-ink);font-weight:400;white-space:nowrap;cursor:default;user-select:none;outline:0}.mu-select-item:where(:has(>svg:first-child)){padding-inline-start:var(--mu-row-padding-icon)}.mu-select-item>svg{color:var(--mu-ink-muted)}.mu-select-item[data-highlighted]{background-color:var(--mu-hover)}.mu-select-item[data-disabled]{opacity:.45}.mu-select-item-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.mu-select-indicator{display:grid;flex:none;place-items:center;width:var(--mu-row-icon);height:var(--mu-row-icon);margin-inline-start:var(--mu-space-2);color:var(--mu-ink)}.mu-select-group-label{padding:var(--mu-space-2) var(--mu-row-padding) var(--mu-space-1);color:var(--mu-ink-muted)}.mu-select-separator{height:1px;margin:var(--mu-space-1) calc(-1 * var(--mu-space-1));background-color:var(--mu-line)}.mu-select-scroll-arrow{display:grid;place-items:center;height:var(--mu-space-4);color:var(--mu-ink-muted)}}@layer mu{.mu-dialog-backdrop{position:fixed;inset:0;z-index:var(--mu-layer-overlay);background-color:var(--mu-overlay);transition:opacity var(--mu-duration-settle) var(--mu-ease-out)}.mu-dialog-backdrop[data-starting-style],.mu-dialog-backdrop[data-ending-style]{opacity:0}.mu-dialog-viewport{position:fixed;inset:0;z-index:var(--mu-layer-overlay);display:grid;place-items:safe center;box-sizing:border-box;padding:var(--mu-space-6) var(--mu-space-4);overflow-y:auto}.mu-dialog-popup{position:relative;display:flex;flex-direction:column;gap:var(--mu-space-4);box-sizing:border-box;width:var(--mu-dialog-width);max-width:100%;padding:var(--mu-space-5);border-radius:var(--mu-radius-2xl);outline:0;transition:opacity var(--mu-duration-settle) var(--mu-ease-out),translate var(--mu-duration-settle) var(--mu-ease-out)}.mu-dialog-popup[data-starting-style],.mu-dialog-popup[data-ending-style]{opacity:0;translate:0 var(--mu-space-1)}.mu-dialog-popup:where(:has(>.mu-dialog-x))>.mu-dialog-title{padding-inline-end:var(--mu-space-6)}.mu-dialog-title{margin:0;color:var(--mu-ink)}.mu-dialog-description{margin:calc(-1 * var(--mu-space-2)) 0 0;color:var(--mu-ink-muted)}.mu-dialog-x{position:absolute;top:var(--mu-space-4);right:var(--mu-space-4)}.mu-dialog-footer{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--mu-space-2);margin-top:var(--mu-space-2)}@media(max-width:639.98px){.mu-dialog-sheet{place-items:end stretch;padding:var(--mu-space-6) 0 0}.mu-dialog-sheet>.mu-dialog-popup{width:100%;padding-bottom:max(var(--mu-space-5),env(safe-area-inset-bottom));border-end-start-radius:0;border-end-end-radius:0}.mu-dialog-sheet>.mu-dialog-popup[data-starting-style],.mu-dialog-sheet>.mu-dialog-popup[data-ending-style]{translate:0 var(--mu-space-6)}.mu-dialog-sheet .mu-dialog-footer{flex-direction:column-reverse}.mu-dialog-sheet .mu-dialog-footer>*{width:100%}}@media(prefers-reduced-motion:reduce){.mu-dialog-popup[data-starting-style],.mu-dialog-popup[data-ending-style],.mu-dialog-sheet>.mu-dialog-popup[data-starting-style],.mu-dialog-sheet>.mu-dialog-popup[data-ending-style]{translate:none}}}@layer mu{.mu-toast-viewport{position:fixed;right:var(--mu-space-6);bottom:var(--mu-space-6);z-index:var(--mu-layer-toast);width:var(--mu-toast-width);outline:0}@media(max-width:639.98px){.mu-toast-viewport{right:var(--mu-space-4);bottom:var(--mu-space-4);left:var(--mu-space-4);width:auto}}.mu-toast{--mu-row-gap: var(--mu-space-3);--peek: var(--mu-space-2);--scale: max(0, 1 - var(--toast-index) * .05);--shrink: calc(1 - var(--scale));--height: var(--toast-frontmost-height, var(--toast-height));--offset-y: calc(var(--toast-offset-y) * -1 - var(--toast-index) * var(--mu-row-gap) + var(--toast-swipe-movement-y));position:absolute;right:0;bottom:0;z-index:calc(var(--mu-layer-toast) - var(--toast-index));box-sizing:border-box;width:100%;height:var(--height);transform-origin:bottom center;translate:var(--toast-swipe-movement-x) calc(var(--toast-swipe-movement-y) - var(--toast-index) * var(--peek) - var(--shrink) * var(--height));scale:var(--scale);user-select:none;outline:0;transition:translate var(--mu-duration-settle) var(--mu-ease-settle),scale var(--mu-duration-settle) var(--mu-ease-settle),opacity var(--mu-duration-settle) var(--mu-ease-out),height var(--mu-duration-fade) var(--mu-ease-out)}.mu-toast[data-expanded]{height:var(--toast-height);translate:var(--toast-swipe-movement-x) var(--offset-y);scale:1}.mu-toast[data-starting-style],.mu-toast[data-ending-style]{translate:0 150%}.mu-toast[data-ending-style]{opacity:0}.mu-toast[data-ending-style][data-swipe-direction=up]{translate:0 calc(var(--toast-swipe-movement-y) - 150%)}.mu-toast[data-ending-style][data-swipe-direction=down]{translate:0 calc(var(--toast-swipe-movement-y) + 150%)}.mu-toast[data-ending-style][data-swipe-direction=left]{translate:calc(var(--toast-swipe-movement-x) - 150%) var(--offset-y)}.mu-toast[data-ending-style][data-swipe-direction=right]{translate:calc(var(--toast-swipe-movement-x) + 150%) var(--offset-y)}.mu-toast[data-limited]{opacity:0}.mu-toast:focus-visible{outline:var(--mu-focus-width) solid var(--mu-focus);outline-offset:var(--mu-focus-width)}.mu-toast:after{content:"";position:absolute;top:100%;left:0;width:100%;height:calc(var(--mu-row-gap) + 1px)}.mu-toast-content{display:flex;align-items:flex-start;gap:var(--mu-space-3);box-sizing:border-box;height:100%;padding:var(--mu-space-3) var(--mu-space-3) var(--mu-space-3) var(--mu-space-4);overflow:hidden;transition:opacity var(--mu-duration-settle) var(--mu-ease-out)}.mu-toast-content[data-behind]{opacity:0}.mu-toast-content[data-expanded]{opacity:1}.mu-toast-icon{margin-block:calc((var(--mu-row-height) - var(--mu-row-icon)) / 2);color:var(--mu-ink-muted)}.mu-toast-success .mu-toast-icon{color:var(--mu-success)}.mu-toast-warning .mu-toast-icon{color:var(--mu-warning)}.mu-toast-danger .mu-toast-icon{color:var(--mu-danger)}.mu-toast-text{display:flex;flex:1;flex-direction:column;min-width:0;padding-block:calc((var(--mu-row-height) - var(--mu-row-line-height)) / 2)}.mu-toast-title{margin:0;color:var(--mu-ink)}.mu-toast-description{margin:0;color:var(--mu-ink-muted)}.mu-toast-action,.mu-toast-close{margin-block:calc((var(--mu-control-md) - var(--mu-control-sm)) / 2)}@media(prefers-reduced-motion:reduce){.mu-toast{transition-property:opacity,height}.mu-toast[data-starting-style],.mu-toast[data-ending-style]{translate:var(--toast-swipe-movement-x) var(--offset-y)}}}@layer mu{.mu-input-root.mu-combobox-input-root{padding-inline-end:calc(var(--mu-row-padding-icon) - var(--mu-space-1))}.mu-combobox-trigger{display:grid;place-items:center;width:calc(var(--mu-row-icon) + var(--mu-space-2));height:calc(var(--mu-row-icon) + var(--mu-space-2));margin:0;padding:0;border:0;border-radius:var(--mu-radius-sm);color:var(--mu-ink-muted);background:none;cursor:pointer}.mu-combobox-trigger:hover:not([data-disabled]){color:var(--mu-ink)}.mu-combobox-trigger[data-disabled]{cursor:not-allowed}.mu-combobox-popup{box-sizing:border-box;width:var(--anchor-width);min-width:var(--mu-menu-width);max-width:var(--available-width);outline:0}.mu-combobox-list{box-sizing:border-box;max-height:min(var(--mu-list-height),var(--available-height));overflow-y:auto;overscroll-behavior:contain;padding:var(--mu-space-1);scroll-padding-block:var(--mu-space-1);outline:0}.mu-combobox-list[data-empty]{padding:0}.mu-combobox-item{display:flex;align-items:center;gap:var(--mu-space-2);box-sizing:border-box;height:var(--mu-row-height);padding:0 var(--mu-row-padding);border-radius:calc(var(--mu-radius-xl) - var(--mu-space-1));color:var(--mu-ink);font-weight:400;white-space:nowrap;cursor:default;user-select:none;outline:0}.mu-combobox-item:where(:has(>svg:first-child)){padding-inline-start:var(--mu-row-padding-icon)}.mu-combobox-item>svg{color:var(--mu-ink-muted)}.mu-combobox-item[data-highlighted]{background-color:var(--mu-hover)}.mu-combobox-item[data-disabled]{opacity:.45}.mu-combobox-item-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.mu-combobox-indicator{display:grid;flex:none;place-items:center;width:var(--mu-row-icon);height:var(--mu-row-icon);margin-inline-start:var(--mu-space-2);color:var(--mu-ink)}.mu-combobox-empty:not(:empty){padding:var(--mu-space-3) var(--mu-space-4);color:var(--mu-ink-muted)}.mu-combobox-group-label{padding:var(--mu-space-2) var(--mu-row-padding) var(--mu-space-1);color:var(--mu-ink-muted)}.mu-combobox-separator{height:1px;margin:var(--mu-space-1) calc(-1 * var(--mu-space-1));background-color:var(--mu-line)}}@layer mu{.mu-button.mu-collapsible-trigger{margin-inline-start:calc(-1 * var(--mu-row-padding));padding-inline-end:var(--mu-row-padding-icon)}.mu-collapsible-chevron{color:var(--mu-ink-muted);transition:rotate var(--mu-duration-settle) var(--mu-ease-settle)}.mu-collapsible-trigger[data-panel-open]>.mu-collapsible-chevron{rotate:180deg}.mu-collapsible-panel{transition:opacity var(--mu-duration-fade) var(--mu-ease-out),translate var(--mu-duration-fade) var(--mu-ease-out)}.mu-collapsible-panel[data-starting-style],.mu-collapsible-panel[data-ending-style]{opacity:0;translate:0 var(--mu-space-1)}@media(prefers-reduced-motion:reduce){.mu-collapsible-chevron{transition:none}.mu-collapsible-panel[data-starting-style],.mu-collapsible-panel[data-ending-style]{translate:none}}}@layer mu{.mu-table-scroll{overflow-x:auto;max-width:100%}.mu-table{width:100%;border-collapse:collapse;color:var(--mu-ink);font-variant-numeric:tabular-nums;text-align:start}.mu-table-head,.mu-table-cell{padding:0 var(--mu-row-padding);text-align:start;vertical-align:middle}.mu-table-head{height:var(--mu-row-height);color:var(--mu-ink-muted);white-space:nowrap;border-bottom:1px solid var(--mu-line)}.mu-table-cell{padding-block:calc((var(--mu-row-height) - var(--mu-row-line-height)) / 2 + var(--mu-space-1))}.mu-table-body>.mu-table-row+.mu-table-row>.mu-table-cell{border-top:1px solid var(--mu-line)}.mu-table-body>.mu-table-row:hover>.mu-table-cell{background-color:var(--mu-hover)}.mu-table-cell>.mu-button{margin-block:calc((var(--mu-row-line-height) - var(--mu-row-height)) / 2);vertical-align:top}.mu-table-num{text-align:end}.mu-table-muted{color:var(--mu-ink-muted)}.mu-table-caption{caption-side:bottom;padding:var(--mu-space-2) var(--mu-row-padding) 0;color:var(--mu-ink-muted);text-align:start}}@layer mu{.mu-prose{color:var(--mu-ink);font-family:var(--mu-font-sans);font-size:var(--prose-fs);line-height:var(--prose-lh);font-weight:400;overflow-wrap:break-word;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.mu-prose ::selection{background:var(--mu-selection)}.mu-prose :where(p,ul,ol,pre,blockquote,table,figure,img,video,hr){margin:0 0 var(--mu-space-3)}.mu-prose :where(h1,h2,h3,h4,h5,h6){margin:var(--mu-space-5) 0 var(--mu-space-2);font-family:var(--mu-font-display);font-weight:600;letter-spacing:0}.mu-prose>:first-child{margin-top:0}.mu-prose>:last-child{margin-bottom:0}.mu-prose h1{font-size:var(--prose-h1);line-height:var(--prose-h1-lh)}.mu-prose :where(h2,h3,h4,h5,h6){font-size:var(--prose-h2);line-height:var(--prose-h2-lh)}.mu-prose :where(strong,b){font-weight:600}.mu-prose del{color:var(--mu-ink-muted)}.mu-prose a{color:var(--mu-accent);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.2em;border-radius:var(--mu-radius-xs)}.mu-prose a:focus-visible{outline:var(--mu-focus-width) solid var(--mu-focus);outline-offset:var(--mu-focus-width)}.mu-prose :where(ul,ol){padding-inline-start:var(--mu-space-6)}.mu-prose li+li{margin-top:var(--mu-space-1)}.mu-prose li>:where(ul,ol){margin:var(--mu-space-1) 0 0}.mu-prose li>p{margin:0}.mu-prose li::marker{color:var(--mu-ink-muted)}.mu-prose li:where(:has(>input[type=checkbox]:first-child)){position:relative;list-style:none}.mu-prose li>input[type=checkbox]:first-child{appearance:none;position:absolute;inset-inline-start:calc(-1 * (var(--mu-space-4) + var(--mu-space-2)));top:calc((var(--prose-lh) - var(--mu-space-4)) / 2);box-sizing:border-box;width:var(--mu-space-4);height:var(--mu-space-4);margin:0;border-radius:var(--mu-radius-sm);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);cursor:pointer}.mu-prose li>input[type=checkbox]:first-child:disabled{cursor:default}.mu-prose li>input[type=checkbox]:first-child:focus-visible{outline:var(--mu-focus-width) solid var(--mu-focus);outline-offset:var(--mu-focus-width)}.mu-prose li>input[type=checkbox]:first-child:checked{background-color:var(--mu-primary);box-shadow:none}.mu-prose li>input[type=checkbox]:first-child:checked:after{content:"";position:absolute;inset:var(--mu-inset);background-color:var(--mu-on-primary);mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat}.mu-prose li:where(:has(>input[type=checkbox]:first-child:checked)){color:var(--mu-ink-muted);text-decoration:line-through}.mu-prose :where(code,kbd,samp,pre){font-family:var(--mu-font-mono);font-size:.875em}.mu-prose :not(pre)>code{padding:.1em .3em;border-radius:var(--mu-radius-xs);background-color:var(--mu-well)}.mu-prose pre{overflow-x:auto;padding:var(--mu-space-3) var(--mu-space-4);border-radius:var(--mu-radius-md);background-color:var(--mu-well);line-height:1.6}.mu-prose pre>code{font-size:inherit}.mu-prose blockquote{margin-inline:0;padding-inline-start:var(--mu-space-4);border-inline-start:var(--mu-inset) solid var(--mu-edge);color:var(--mu-ink-muted)}.mu-prose hr{height:1px;margin-block:var(--mu-space-5);border:0;background-color:var(--mu-line)}.mu-prose :where(img,video){display:block;max-width:100%;height:auto;border-radius:var(--mu-radius-lg)}.mu-prose table{display:block;width:max-content;max-width:100%;overflow-x:auto;border-collapse:collapse;font-variant-numeric:tabular-nums}.mu-prose :where(th,td){padding:var(--mu-space-2) var(--mu-space-3);text-align:start;vertical-align:top}.mu-prose th{color:var(--mu-ink-muted);font-size:var(--prose-head);line-height:var(--prose-head-lh);font-weight:500;white-space:nowrap;border-bottom:1px solid var(--mu-line)}.mu-prose tr+tr>td{border-top:1px solid var(--mu-line)}.mu-prose-tag{padding:0 .25em;border-radius:var(--mu-radius-xs);color:var(--mu-ink-muted);background-color:var(--mu-well)}}
1
+ @layer mu{.mu-s-xs{--mu-row-height: var(--mu-control-xs);--mu-row-padding: 6px;--mu-row-padding-icon: var(--mu-space-1);--mu-row-font-size: 12px;--mu-row-line-height: 16px;--mu-row-radius: var(--mu-radius-sm);--mu-row-gap: var(--mu-space-1);--mu-row-icon: var(--mu-icon-xs);--mu-row-icon-stroke: 1.25px;--mu-row-check-box: 14px}.mu-s-sm{--mu-row-height: var(--mu-control-sm);--mu-row-padding: var(--mu-space-2);--mu-row-padding-icon: 6px;--mu-row-font-size: 13px;--mu-row-line-height: 18px;--mu-row-radius: var(--mu-radius-sm);--mu-row-gap: var(--mu-space-1);--mu-row-icon: var(--mu-icon-sm);--mu-row-icon-stroke: 1.25px;--mu-row-check-box: 16px}.mu-s-md{--mu-row-height: var(--mu-control-md);--mu-row-padding: var(--mu-space-3);--mu-row-padding-icon: 10px;--mu-row-font-size: 14px;--mu-row-line-height: 20px;--mu-row-radius: var(--mu-radius-md);--mu-row-gap: 6px;--mu-row-icon: var(--mu-icon-md);--mu-row-icon-stroke: 1.5px;--mu-row-check-box: 18px}.mu-recessed{background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track)}.mu-raised{background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),rgba(255,255,255,0) 60%);box-shadow:var(--mu-shadow-raised)}.mu-key{background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),rgba(255,255,255,0) 60%);box-shadow:var(--mu-shadow-key)}.mu-popup{background:var(--mu-surface);box-shadow:var(--mu-shadow-pop);border-radius:var(--mu-radius-xl)}.mu-positioner{z-index:var(--mu-layer-popup);outline:0}.mu-popup-motion{transition:opacity var(--mu-duration-fade) var(--mu-ease-out),translate var(--mu-duration-fade) var(--mu-ease-out)}.mu-popup-motion[data-starting-style],.mu-popup-motion[data-ending-style]{opacity:0;translate:0 var(--mu-space-1)}.mu-popup-motion[data-instant]{transition:none}@media(prefers-reduced-motion:reduce){.mu-popup-motion[data-starting-style],.mu-popup-motion[data-ending-style]{translate:none}}.mu-base{font-family:var(--mu-font-sans);font-size:var(--mu-row-font-size, 14px);line-height:var(--mu-row-line-height, 20px);font-weight:500;letter-spacing:0;color:var(--mu-ink);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-tap-highlight-color:transparent}.mu-base ::selection,.mu-base::selection{background:var(--mu-selection)}.mu-visually-hidden{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.mu-focus:focus-visible{outline:var(--mu-focus-width) solid var(--mu-focus);outline-offset:var(--mu-focus-offset)}.mu-hit{position:relative}@media(pointer:coarse){.mu-hit:after{content:"";position:absolute;left:50%;top:50%;width:max(100%,var(--mu-hit-area));height:max(100%,var(--mu-hit-area));transform:translate(-50%,-50%)}}.mu-icon,.mu-base svg.lucide,.mu-prose svg.lucide{width:var(--mu-row-icon, 16px);height:var(--mu-row-icon, 16px);flex:none;display:block;stroke-width:var(--mu-row-icon-stroke, 1.5px)}.mu-icon *,.mu-base svg.lucide *,.mu-prose svg.lucide *{vector-effect:non-scaling-stroke}.mu-label-xs{font-family:var(--mu-font-sans);font-size:12px;line-height:16px;font-weight:500}.mu-caption{font-family:var(--mu-font-sans);font-size:13px;line-height:18px;font-weight:400}.mu-label-sm{font-family:var(--mu-font-sans);font-size:13px;line-height:18px;font-weight:500}.mu-body{font-family:var(--mu-font-sans);font-size:14px;line-height:20px;font-weight:400}.mu-label{font-family:var(--mu-font-sans);font-size:14px;line-height:20px;font-weight:500}.mu-title{font-family:var(--mu-font-display);font-size:16px;line-height:24px;font-weight:500}.mu-heading{font-family:var(--mu-font-display);font-size:20px;line-height:28px;font-weight:500}.mu-display{font-family:var(--mu-font-display);font-size:32px;line-height:40px;font-weight:500;letter-spacing:-.02em}.mu-prose{--prose-fs: 16px;--prose-lh: 24px;--prose-h1: 20px;--prose-h1-lh: 28px;--prose-h2: 16px;--prose-h2-lh: 24px;--prose-head: 13px;--prose-head-lh: 18px}.mu-prose-sm{--prose-fs: 14px;--prose-lh: 22px}}@layer mu{.mu-spinner{display:inline-block;flex:none;box-sizing:border-box;width:var(--mu-row-icon);height:var(--mu-row-icon);border:var(--mu-row-icon-stroke) solid currentColor;border-top-color:transparent;border-radius:var(--mu-radius-full);animation:mu-spin var(--mu-duration-spin) linear infinite}@keyframes mu-spin{to{rotate:1turn}}}@layer mu{.mu-button{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:var(--mu-row-gap);box-sizing:border-box;height:var(--mu-row-height);margin:0;padding:0 var(--mu-row-padding);border:0;border-radius:var(--mu-row-radius);color:var(--mu-ink);background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),transparent 60%);box-shadow:var(--mu-shadow-raised);white-space:nowrap;text-decoration:none;cursor:pointer;user-select:none;transition-property:background-color,box-shadow,color,translate;transition-duration:var(--mu-duration-press);transition-timing-function:var(--mu-ease-out)}.mu-button:where(:has(>svg:first-child)){padding-inline-start:var(--mu-row-padding-icon)}.mu-button.mu-button-icon{width:var(--mu-row-height);padding:0}.mu-button-label{min-width:0;overflow:hidden;text-overflow:ellipsis}@media(hover:hover){.mu-button:hover:not([data-disabled]){background-color:var(--mu-key-hover)}.mu-button-primary:hover:not([data-disabled]){background-color:var(--mu-primary-hover)}.mu-button-danger:hover:not([data-disabled]){background-color:var(--mu-danger-key);filter:brightness(1.08)}.mu-button-ghost:hover:not([data-disabled]){background-color:var(--mu-hover);color:var(--mu-ink)}}.mu-button:active:not([data-disabled]){translate:0 .5px;box-shadow:var(--mu-shadow-pressed)}.mu-button-primary{color:var(--mu-on-primary);background-color:var(--mu-primary)}.mu-button-danger{color:var(--mu-on-danger);background-color:var(--mu-danger-key)}.mu-button-ghost{color:var(--mu-ink-muted);background-color:transparent;background-image:none;box-shadow:none}.mu-button-ghost[data-popup-open]{background-color:var(--mu-hover);color:var(--mu-ink)}.mu-button-ghost:active:not([data-disabled]){translate:none;background-color:var(--mu-well);box-shadow:var(--mu-shadow-track)}.mu-button[data-disabled]:not([data-loading]){opacity:.45;cursor:not-allowed}.mu-button[data-loading]{cursor:progress}.mu-button[data-loading]>:not(.mu-spinner){opacity:0}.mu-button>.mu-spinner{position:absolute;inset:0;margin:auto}@media(prefers-reduced-motion:reduce){.mu-button:active:not([data-disabled]){translate:none}}}@layer mu{.mu-kbd{display:inline-flex;align-items:center;justify-content:center;box-sizing:border-box;min-width:var(--mu-control-xs);height:var(--mu-control-xs);padding:0 var(--mu-space-1);border-radius:var(--mu-radius-sm);color:var(--mu-ink-muted);background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),transparent 60%);box-shadow:var(--mu-shadow-raised);white-space:nowrap}}@layer mu{.mu-separator{flex:none;align-self:stretch;margin:0;border:0;background-color:var(--mu-line)}.mu-separator[data-orientation=horizontal]{height:1px}.mu-separator[data-orientation=vertical]{width:1px}}@layer mu{.mu-badge{display:inline-flex;align-items:center;gap:var(--mu-space-1);box-sizing:border-box;height:var(--mu-control-xs);padding:0 var(--mu-row-padding);border-radius:var(--mu-radius-sm);white-space:nowrap;vertical-align:middle}.mu-badge-neutral{color:var(--mu-ink);background-color:var(--mu-well)}.mu-badge-outline{color:var(--mu-ink-muted);box-shadow:inset 0 0 0 1px var(--mu-edge)}.mu-badge-success{color:var(--mu-success);background-color:var(--mu-success-soft)}.mu-badge-warning{color:var(--mu-warning);background-color:var(--mu-warning-soft)}.mu-badge-danger{color:var(--mu-danger);background-color:var(--mu-danger-soft)}}@layer mu{.mu-avatar-root{display:inline-flex;flex:none;align-items:center;justify-content:center;overflow:hidden;box-sizing:border-box;width:var(--mu-row-height);height:var(--mu-row-height);border-radius:var(--mu-radius-full);color:var(--mu-ink-muted);background-color:var(--mu-well);vertical-align:middle;user-select:none}.mu-avatar-image{width:100%;height:100%;object-fit:cover}.mu-avatar-fallback{display:flex;align-items:center;justify-content:center;width:100%;height:100%}}@layer mu{.mu-link{color:var(--mu-accent);text-decoration:none;text-underline-offset:.2em;border-radius:var(--mu-radius-xs);cursor:pointer}.mu-link:hover,.mu-link:focus-visible,.mu-link-underline{text-decoration:underline}.mu-link-muted{color:var(--mu-ink-muted)}.mu-link-muted:hover{color:var(--mu-ink)}.mu-link>.mu-icon{display:inline-block;width:.85em;height:.85em;margin-inline-start:.1em;vertical-align:-.05em}}@layer mu{.mu-skeleton{box-sizing:border-box;width:100%;height:var(--mu-row-line-height);border-radius:var(--mu-radius-sm);background-color:var(--mu-well);background-image:linear-gradient(90deg,transparent 0%,var(--mu-hover) 50%,transparent 100%);background-size:200% 100%;background-repeat:no-repeat;animation:mu-shimmer var(--mu-duration-shimmer) ease-in-out infinite}.mu-skeleton-round{width:var(--mu-row-height);height:var(--mu-row-height);border-radius:var(--mu-radius-full)}@keyframes mu-shimmer{0%{background-position:150% 0}to{background-position:-50% 0}}@media(prefers-reduced-motion:reduce){.mu-skeleton{animation:none;background-image:none}}}@layer mu{.mu-field-root{display:flex;flex-direction:column;gap:var(--mu-space-1);min-width:0}.mu-field-label{color:var(--mu-ink)}.mu-field-item{display:flex}.mu-field-label:where(:has(>.mu-checkbox,>.mu-switch,>.mu-radio)){display:inline-flex;align-items:center;gap:var(--mu-space-2);font-weight:400;cursor:pointer}.mu-field-label[data-disabled]{opacity:.45;cursor:not-allowed}.mu-field-description{margin:0;color:var(--mu-ink-muted)}.mu-field-root[data-invalid]>.mu-field-description{display:none}.mu-field-error{display:flex;align-items:flex-start;gap:var(--mu-space-1);color:var(--mu-danger)}.mu-field-error>.mu-icon{--mu-row-icon: var(--mu-icon-sm);margin-block:calc((1lh - var(--mu-icon-sm)) / 2)}.mu-fieldset-root{display:flex;flex-direction:column;gap:var(--mu-space-3);min-width:0;margin:0;padding:0;border:0}.mu-fieldset-legend{margin-bottom:var(--mu-space-1);padding:0;color:var(--mu-ink)}}@layer mu{.mu-input-root{display:flex;align-items:center;gap:var(--mu-row-gap);box-sizing:border-box;width:100%;min-width:0;height:var(--mu-row-height);padding:0 var(--mu-row-padding);border-radius:var(--mu-row-radius);color:var(--mu-ink);background-color:var(--mu-surface);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);cursor:text;transition:box-shadow var(--mu-duration-fade) var(--mu-ease-out)}.mu-input-root:where(:has(>.mu-input-prefix)){padding-inline-start:var(--mu-row-padding-icon)}.mu-input-root:where(:has(>.mu-input-suffix)){padding-inline-end:var(--mu-row-padding-icon)}@media(hover:hover){.mu-input-root:hover:not([data-disabled],[aria-disabled=true],:has(>[data-disabled]),:focus-within){box-shadow:inset 0 0 0 1px var(--mu-ink-muted),var(--mu-shadow-track)}}.mu-input-root:where(:has(>.mu-input:focus)),.mu-input-root:where(:not(:has(>.mu-input))):focus-within{box-shadow:inset 0 0 0 var(--mu-focus-edge-width) var(--mu-focus-edge),var(--mu-shadow-track);outline:var(--mu-focus-width) solid transparent;outline-offset:calc(-1 * var(--mu-focus-width))}.mu-input-root:is([data-invalid],[aria-invalid=true],:has(>[data-invalid])){box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-track)}.mu-input-root:is([data-invalid],[aria-invalid=true],:has(>[data-invalid])):where(:has(>.mu-input:focus),:not(:has(>.mu-input)):focus-within){box-shadow:inset 0 0 0 var(--mu-focus-edge-width) var(--mu-danger),var(--mu-shadow-track)}.mu-input-root:is([data-disabled],[aria-disabled=true],:has(>[data-disabled])){opacity:.45;cursor:not-allowed}.mu-input{flex:1;min-width:0;height:100%;margin:0;padding:0;border:0;outline:none;color:inherit;background:none;font:inherit;font-weight:400}.mu-input::placeholder{color:var(--mu-ink-muted);opacity:1}.mu-input[data-disabled]{cursor:not-allowed}.mu-input-prefix,.mu-input-suffix{display:flex;flex:none;align-items:center;gap:var(--mu-space-1);color:var(--mu-ink-muted)}}@layer mu{.mu-textarea{display:block;box-sizing:border-box;width:100%;min-height:var(--mu-row-height);margin:0;padding:calc((var(--mu-row-height) - var(--mu-row-line-height)) / 2) var(--mu-row-padding);border:0;border-radius:var(--mu-row-radius);color:var(--mu-ink);background-color:var(--mu-surface);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);font-weight:400;resize:vertical;transition:box-shadow var(--mu-duration-fade) var(--mu-ease-out)}.mu-textarea::placeholder{color:var(--mu-ink-muted);opacity:1}@media(hover:hover){.mu-textarea:hover:not([data-disabled],[aria-disabled=true],:focus-within){box-shadow:inset 0 0 0 1px var(--mu-ink-muted),var(--mu-shadow-track)}}.mu-textarea:focus-within{box-shadow:inset 0 0 0 var(--mu-focus-edge-width) var(--mu-focus-edge),var(--mu-shadow-track);outline:var(--mu-focus-width) solid transparent;outline-offset:calc(-1 * var(--mu-focus-width))}.mu-textarea:is([data-invalid],[aria-invalid=true]){box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-track)}.mu-textarea:is([data-invalid],[aria-invalid=true]):focus-within{box-shadow:inset 0 0 0 var(--mu-focus-edge-width) var(--mu-danger),var(--mu-shadow-track)}.mu-textarea:is([data-disabled],[aria-disabled=true]){opacity:.45;cursor:not-allowed}}@layer mu{.mu-checkbox{display:inline-flex;flex:none;align-items:center;justify-content:center;box-sizing:border-box;width:var(--mu-row-check-box);height:var(--mu-row-check-box);border-radius:var(--mu-radius-sm);color:var(--mu-on-primary);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);cursor:pointer;transition-property:background-color,box-shadow,scale;transition-duration:var(--mu-duration-press);transition-timing-function:var(--mu-ease-out)}.mu-checkbox[data-checked],.mu-checkbox[data-indeterminate]{background-color:var(--mu-primary);box-shadow:none}.mu-checkbox[data-invalid]{box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-track)}.mu-checkbox:active:not([data-disabled],[data-readonly]){scale:.94}.mu-checkbox[data-disabled]{opacity:.45;cursor:not-allowed}.mu-checkbox-indicator{display:flex;transition:opacity var(--mu-duration-fade) var(--mu-ease-out) var(--mu-duration-press),scale var(--mu-duration-fade) var(--mu-ease-out) var(--mu-duration-press)}.mu-checkbox-indicator[data-starting-style],.mu-checkbox-indicator[data-ending-style]{opacity:0;scale:.6}.mu-checkbox-indicator>svg{width:calc(var(--mu-row-check-box) - 2 * var(--mu-inset));height:calc(var(--mu-row-check-box) - 2 * var(--mu-inset));stroke-width:2}.mu-checkbox-indicator>svg *{vector-effect:non-scaling-stroke}@media(prefers-reduced-motion:reduce){.mu-checkbox:active:not([data-disabled],[data-readonly]){scale:none}.mu-checkbox-indicator[data-starting-style],.mu-checkbox-indicator[data-ending-style]{scale:none}}}@layer mu{.mu-switch{--switch-h: calc(var(--mu-row-check-box) + var(--mu-inset));--switch-w: calc(var(--switch-h) * 1.7);--knob: calc(var(--switch-h) - 2 * var(--mu-inset));position:relative;display:inline-flex;flex:none;align-items:center;box-sizing:border-box;width:var(--switch-w);height:var(--switch-h);padding:var(--mu-inset);border-radius:var(--mu-radius-full);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);cursor:pointer;transition:background-color var(--mu-duration-settle) var(--mu-ease-settle),box-shadow var(--mu-duration-settle) var(--mu-ease-settle)}.mu-switch[data-checked]{background-color:var(--mu-primary);box-shadow:inset 0 0 0 1px var(--mu-primary)}.mu-switch[data-invalid]{box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-track)}.mu-switch[data-disabled]{opacity:.45;cursor:not-allowed}.mu-switch-thumb{display:block;width:var(--knob);height:var(--knob);border-radius:var(--mu-radius-full);background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),transparent 60%);box-shadow:var(--mu-shadow-key);transition:translate var(--mu-duration-settle) var(--mu-ease-settle),scale var(--mu-duration-press) var(--mu-ease-out),background-color var(--mu-duration-settle) var(--mu-ease-settle)}.mu-switch-thumb[data-checked]{translate:calc(var(--switch-w) - var(--switch-h)) 0;background-color:var(--mu-on-primary)}.mu-switch:active:not([data-disabled],[data-readonly])>.mu-switch-thumb{scale:1.1}@media(prefers-reduced-motion:reduce){.mu-switch-thumb{transition-property:background-color}.mu-switch:active:not([data-disabled],[data-readonly])>.mu-switch-thumb{scale:none}}}@layer mu{.mu-radio-group{display:flex;flex-direction:column;align-items:flex-start;gap:var(--mu-space-3)}.mu-radio-group[data-orientation=horizontal]{flex-direction:row;flex-wrap:wrap;gap:var(--mu-space-3) var(--mu-space-4)}.mu-radio-group[data-orientation=horizontal]>.mu-fieldset-legend{flex-basis:100%}.mu-radio{display:inline-flex;flex:none;align-items:center;justify-content:center;box-sizing:border-box;width:var(--mu-row-check-box);height:var(--mu-row-check-box);border-radius:var(--mu-radius-full);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);cursor:pointer;transition-property:background-color,box-shadow,scale;transition-duration:var(--mu-duration-press);transition-timing-function:var(--mu-ease-out)}.mu-radio[data-checked]{background-color:var(--mu-primary);box-shadow:none}.mu-radio[data-invalid]{box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-track)}.mu-radio:active:not([data-disabled],[data-readonly]){scale:.94}.mu-radio[data-disabled]{opacity:.45;cursor:not-allowed}.mu-radio-indicator{width:calc(var(--mu-row-check-box) / 2.5);height:calc(var(--mu-row-check-box) / 2.5);border-radius:var(--mu-radius-full);background-color:var(--mu-on-primary);transition:opacity var(--mu-duration-fade) var(--mu-ease-out) var(--mu-duration-press),scale var(--mu-duration-fade) var(--mu-ease-out) var(--mu-duration-press)}.mu-radio-indicator[data-starting-style],.mu-radio-indicator[data-ending-style]{opacity:0;scale:.4}@media(prefers-reduced-motion:reduce){.mu-radio:active:not([data-disabled],[data-readonly]){scale:none}.mu-radio-indicator[data-starting-style],.mu-radio-indicator[data-ending-style]{scale:none}}}@layer mu{.mu-toggle{position:relative;display:inline-flex;flex:none;align-items:center;justify-content:center;gap:var(--mu-row-gap);box-sizing:border-box;height:var(--mu-row-height);margin:0;padding:0 var(--mu-row-padding);border:0;border-radius:var(--mu-row-radius);color:var(--mu-ink-muted);background-color:transparent;white-space:nowrap;cursor:pointer;user-select:none;transition-property:background-color,box-shadow,color;transition-duration:var(--mu-duration-press);transition-timing-function:var(--mu-ease-out)}.mu-toggle:where(:has(>svg:first-child)){padding-inline-start:var(--mu-row-padding-icon)}.mu-toggle.mu-toggle-icon{width:var(--mu-row-height);padding:0}@media(hover:hover){.mu-toggle:hover:not([data-disabled]){color:var(--mu-ink);background-color:var(--mu-hover)}}.mu-toggle[data-pressed],.mu-toggle:active:not([data-disabled]){color:var(--mu-ink);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track)}.mu-toggle[data-disabled]{opacity:.45;cursor:not-allowed}}@layer mu{.mu-segmented{position:relative;display:inline-flex;align-items:stretch;gap:0;box-sizing:border-box;height:var(--mu-row-height);padding:var(--mu-inset);border-radius:var(--mu-row-radius);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track)}.mu-segmented-key{position:absolute;top:var(--mu-inset);left:0;width:var(--key-width);height:calc(var(--mu-row-height) - 2 * var(--mu-inset));translate:var(--key-left) 0;border-radius:calc(var(--mu-row-radius) - var(--mu-inset));background-color:var(--mu-key);background-image:linear-gradient(180deg,var(--mu-key-sheen),transparent 60%);box-shadow:var(--mu-shadow-key);transition:translate var(--mu-duration-settle) var(--mu-ease-settle),width var(--mu-duration-settle) var(--mu-ease-settle)}.mu-toggle-group.mu-segmented:not([data-keyed])>.mu-segmented-key{display:none}.mu-tabs-indicator{--key-left: var(--active-tab-left);--key-width: var(--active-tab-width)}.mu-segmented-item,.mu-segmented>.mu-toggle{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:var(--mu-row-gap);box-sizing:border-box;height:100%;margin:0;padding:0 calc(var(--mu-row-padding) - var(--mu-inset));border:0;border-radius:calc(var(--mu-row-radius) - var(--mu-inset));color:var(--mu-ink-muted);background:none;box-shadow:none;font:inherit;white-space:nowrap;cursor:pointer;user-select:none;transition:color var(--mu-duration-fade) var(--mu-ease-out)}.mu-segmented>.mu-toggle.mu-toggle-icon{width:calc(var(--mu-row-height) - 2 * var(--mu-inset));padding:0}@media(hover:hover){.mu-segmented-item:hover:not([data-disabled]),.mu-segmented>.mu-toggle:hover:not([data-disabled]){color:var(--mu-ink);background:none}}.mu-segmented-item[data-active],.mu-segmented>.mu-toggle[data-pressed],.mu-segmented>.mu-toggle:active:not([data-disabled]){color:var(--mu-ink);background:none;box-shadow:none}.mu-segmented-item[data-disabled]{opacity:.45;cursor:not-allowed}.mu-tabs-root{display:flex;flex-direction:column;gap:var(--mu-space-4)}.mu-tabs-list{align-self:flex-start}.mu-tabs-panel{border-radius:var(--mu-radius-sm)}@media(prefers-reduced-motion:reduce){.mu-segmented-key{transition:none}}}@layer mu{.mu-toggle-group{display:inline-flex;align-items:center;gap:var(--mu-inset)}.mu-toggle-group>.mu-separator{align-self:center;height:max(var(--mu-space-2),calc(var(--mu-row-height) - 2 * var(--mu-space-2)));margin-inline:var(--mu-space-1)}}@layer mu{.mu-tooltip-popup{display:flex;align-items:center;gap:var(--mu-space-2);box-sizing:border-box;max-width:var(--mu-tooltip-width);padding:var(--mu-space-1) var(--mu-space-2);border-radius:var(--mu-radius-md);color:var(--mu-on-primary);background-color:var(--mu-primary);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.mu-tooltip-shortcut{opacity:.65}}@layer mu{.mu-popover-popup{display:flex;flex-direction:column;gap:var(--mu-space-3);box-sizing:border-box;width:var(--mu-popover-width);max-width:var(--available-width);padding:var(--mu-space-4);outline:0}.mu-popover-title{margin:0;color:var(--mu-ink)}.mu-popover-description{margin:calc(-1 * var(--mu-space-2)) 0 0;color:var(--mu-ink-muted)}}@layer mu{.mu-menu-popup{box-sizing:border-box;min-width:var(--mu-menu-width);max-height:var(--available-height);overflow-y:auto;padding:var(--mu-space-1);outline:0}.mu-menu-item{display:flex;align-items:center;gap:var(--mu-space-2);box-sizing:border-box;height:var(--mu-row-height);padding:0 var(--mu-row-padding);border-radius:calc(var(--mu-radius-xl) - var(--mu-space-1));color:var(--mu-ink);font-weight:400;white-space:nowrap;cursor:default;user-select:none;outline:0}.mu-menu-item:where(:has(>svg:first-child)){padding-inline-start:var(--mu-row-padding-icon)}.mu-menu-item>svg{color:var(--mu-ink-muted)}.mu-menu-item[data-highlighted],.mu-menu-submenu-trigger[data-popup-open]{background-color:var(--mu-hover)}.mu-menu-item[data-disabled]{opacity:.45}.mu-menu-item-danger,.mu-menu-item-danger>svg{color:var(--mu-danger)}.mu-menu-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.mu-menu-shortcut{margin-inline-start:var(--mu-space-4);color:var(--mu-ink-muted)}.mu-menu-indicator{display:grid;flex:none;place-items:center;width:var(--mu-row-icon);height:var(--mu-row-icon);margin-inline-start:var(--mu-space-2)}.mu-menu-indicator>svg{color:var(--mu-ink)}.mu-menu-chevron{margin-inline-end:calc(var(--mu-row-padding-icon) - var(--mu-row-padding));color:var(--mu-ink-muted)}.mu-menu-group-label{padding:var(--mu-space-2) var(--mu-row-padding) var(--mu-space-1);color:var(--mu-ink-muted)}.mu-menu-separator{height:1px;margin:var(--mu-space-1) calc(-1 * var(--mu-space-1));background-color:var(--mu-line)}}@layer mu{.mu-select-trigger{justify-content:space-between;min-width:0;padding-inline-end:var(--mu-row-padding-icon);text-align:start}.mu-select-value{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.mu-select-value[data-placeholder]{color:var(--mu-ink-muted);font-weight:400}.mu-select-icon{display:flex;flex:none;color:var(--mu-ink-muted)}.mu-select-trigger[data-invalid]{box-shadow:inset 0 0 0 1px var(--mu-danger),var(--mu-shadow-key)}.mu-select-positioner{outline:0}.mu-select-popup{box-sizing:border-box;min-width:max(var(--mu-menu-width),var(--anchor-width));max-height:var(--available-height);padding:var(--mu-space-1);outline:0}.mu-select-list{overflow-y:auto;max-height:var(--available-height);scroll-padding-block:var(--mu-space-1);outline:0}.mu-select-item{display:flex;align-items:center;gap:var(--mu-space-2);box-sizing:border-box;height:var(--mu-row-height);padding:0 var(--mu-row-padding);border-radius:calc(var(--mu-radius-xl) - var(--mu-space-1));color:var(--mu-ink);font-weight:400;white-space:nowrap;cursor:default;user-select:none;outline:0}.mu-select-item:where(:has(>svg:first-child)){padding-inline-start:var(--mu-row-padding-icon)}.mu-select-item>svg{color:var(--mu-ink-muted)}.mu-select-item[data-highlighted]{background-color:var(--mu-hover)}.mu-select-item[data-disabled]{opacity:.45}.mu-select-item-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.mu-select-indicator{display:grid;flex:none;place-items:center;width:var(--mu-row-icon);height:var(--mu-row-icon);margin-inline-start:var(--mu-space-2);color:var(--mu-ink)}.mu-select-group-label{padding:var(--mu-space-2) var(--mu-row-padding) var(--mu-space-1);color:var(--mu-ink-muted)}.mu-select-separator{height:1px;margin:var(--mu-space-1) calc(-1 * var(--mu-space-1));background-color:var(--mu-line)}.mu-select-scroll-arrow{display:grid;place-items:center;height:var(--mu-space-4);color:var(--mu-ink-muted)}}@layer mu{.mu-dialog-backdrop{position:fixed;inset:0;z-index:var(--mu-layer-overlay);background-color:var(--mu-overlay);transition:opacity var(--mu-duration-settle) var(--mu-ease-out)}.mu-dialog-backdrop[data-starting-style],.mu-dialog-backdrop[data-ending-style]{opacity:0}.mu-dialog-viewport{position:fixed;inset:0;z-index:var(--mu-layer-overlay);display:grid;place-items:safe center;box-sizing:border-box;padding:var(--mu-space-6) var(--mu-space-4);overflow-y:auto}.mu-dialog-popup{position:relative;display:flex;flex-direction:column;gap:var(--mu-space-4);box-sizing:border-box;width:var(--mu-dialog-width);max-width:100%;padding:var(--mu-space-5);border-radius:var(--mu-radius-2xl);outline:0;transition:opacity var(--mu-duration-settle) var(--mu-ease-out),translate var(--mu-duration-settle) var(--mu-ease-out)}.mu-dialog-popup[data-starting-style],.mu-dialog-popup[data-ending-style]{opacity:0;translate:0 var(--mu-space-1)}.mu-dialog-popup:where(:has(>.mu-dialog-x))>.mu-dialog-title{padding-inline-end:var(--mu-space-6)}.mu-dialog-title{margin:0;color:var(--mu-ink)}.mu-dialog-description{margin:calc(-1 * var(--mu-space-2)) 0 0;color:var(--mu-ink-muted)}.mu-dialog-x{position:absolute;top:var(--mu-space-4);right:var(--mu-space-4)}.mu-dialog-footer{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:var(--mu-space-2);margin-top:var(--mu-space-2)}@media(max-width:639.98px){.mu-dialog-sheet{place-items:end stretch;padding:var(--mu-space-6) 0 0}.mu-dialog-sheet>.mu-dialog-popup{width:100%;padding-bottom:max(var(--mu-space-5),env(safe-area-inset-bottom));border-end-start-radius:0;border-end-end-radius:0}.mu-dialog-sheet>.mu-dialog-popup[data-starting-style],.mu-dialog-sheet>.mu-dialog-popup[data-ending-style]{translate:0 var(--mu-space-6)}.mu-dialog-sheet .mu-dialog-footer{flex-direction:column-reverse}.mu-dialog-sheet .mu-dialog-footer>*{width:100%}}@media(prefers-reduced-motion:reduce){.mu-dialog-popup[data-starting-style],.mu-dialog-popup[data-ending-style],.mu-dialog-sheet>.mu-dialog-popup[data-starting-style],.mu-dialog-sheet>.mu-dialog-popup[data-ending-style]{translate:none}}}@layer mu{.mu-toast-viewport{position:fixed;right:var(--mu-space-6);bottom:var(--mu-space-6);z-index:var(--mu-layer-toast);width:var(--mu-toast-width);outline:0}@media(max-width:639.98px){.mu-toast-viewport{right:var(--mu-space-4);bottom:var(--mu-space-4);left:var(--mu-space-4);width:auto}}.mu-toast{--mu-row-gap: var(--mu-space-3);--peek: var(--mu-space-2);--scale: max(0, 1 - var(--toast-index) * .05);--shrink: calc(1 - var(--scale));--height: var(--toast-frontmost-height, var(--toast-height));--offset-y: calc(var(--toast-offset-y) * -1 - var(--toast-index) * var(--mu-row-gap) + var(--toast-swipe-movement-y));position:absolute;right:0;bottom:0;z-index:calc(var(--mu-layer-toast) - var(--toast-index));box-sizing:border-box;width:100%;height:var(--height);transform-origin:bottom center;translate:var(--toast-swipe-movement-x) calc(var(--toast-swipe-movement-y) - var(--toast-index) * var(--peek) - var(--shrink) * var(--height));scale:var(--scale);user-select:none;outline:0;transition:translate var(--mu-duration-settle) var(--mu-ease-settle),scale var(--mu-duration-settle) var(--mu-ease-settle),opacity var(--mu-duration-settle) var(--mu-ease-out),height var(--mu-duration-fade) var(--mu-ease-out)}.mu-toast[data-expanded]{height:var(--toast-height);translate:var(--toast-swipe-movement-x) var(--offset-y);scale:1}.mu-toast[data-starting-style],.mu-toast[data-ending-style]{translate:0 150%}.mu-toast[data-ending-style]{opacity:0}.mu-toast[data-ending-style][data-swipe-direction=up]{translate:0 calc(var(--toast-swipe-movement-y) - 150%)}.mu-toast[data-ending-style][data-swipe-direction=down]{translate:0 calc(var(--toast-swipe-movement-y) + 150%)}.mu-toast[data-ending-style][data-swipe-direction=left]{translate:calc(var(--toast-swipe-movement-x) - 150%) var(--offset-y)}.mu-toast[data-ending-style][data-swipe-direction=right]{translate:calc(var(--toast-swipe-movement-x) + 150%) var(--offset-y)}.mu-toast[data-limited]{opacity:0}.mu-toast:focus-visible{outline:var(--mu-focus-width) solid var(--mu-focus);outline-offset:var(--mu-focus-offset)}.mu-toast:after{content:"";position:absolute;top:100%;left:0;width:100%;height:calc(var(--mu-row-gap) + 1px)}.mu-toast-content{display:flex;align-items:flex-start;gap:var(--mu-space-3);box-sizing:border-box;height:100%;padding:var(--mu-space-3) var(--mu-space-3) var(--mu-space-3) var(--mu-space-4);overflow:hidden;transition:opacity var(--mu-duration-settle) var(--mu-ease-out)}.mu-toast-content[data-behind]{opacity:0}.mu-toast-content[data-expanded]{opacity:1}.mu-toast-icon{margin-block:calc((var(--mu-row-height) - var(--mu-row-icon)) / 2);color:var(--mu-ink-muted)}.mu-toast-success .mu-toast-icon{color:var(--mu-success)}.mu-toast-warning .mu-toast-icon{color:var(--mu-warning)}.mu-toast-danger .mu-toast-icon{color:var(--mu-danger)}.mu-toast-text{display:flex;flex:1;flex-direction:column;min-width:0;padding-block:calc((var(--mu-row-height) - var(--mu-row-line-height)) / 2)}.mu-toast-title{margin:0;color:var(--mu-ink)}.mu-toast-description{margin:0;color:var(--mu-ink-muted)}.mu-toast-action,.mu-toast-close{margin-block:calc((var(--mu-control-md) - var(--mu-control-sm)) / 2)}@media(prefers-reduced-motion:reduce){.mu-toast{transition-property:opacity,height}.mu-toast[data-starting-style],.mu-toast[data-ending-style]{translate:var(--toast-swipe-movement-x) var(--offset-y)}}}@layer mu{.mu-input-root.mu-combobox-input-root{padding-inline-end:calc(var(--mu-row-padding-icon) - var(--mu-space-1))}.mu-combobox-trigger{display:grid;place-items:center;width:calc(var(--mu-row-icon) + var(--mu-space-2));height:calc(var(--mu-row-icon) + var(--mu-space-2));margin:0;padding:0;border:0;border-radius:var(--mu-radius-sm);color:var(--mu-ink-muted);background:none;cursor:pointer}.mu-combobox-trigger:hover:not([data-disabled]){color:var(--mu-ink)}.mu-combobox-trigger[data-disabled]{cursor:not-allowed}.mu-combobox-popup{box-sizing:border-box;width:var(--anchor-width);min-width:var(--mu-menu-width);max-width:var(--available-width);outline:0}.mu-combobox-list{box-sizing:border-box;max-height:min(var(--mu-list-height),var(--available-height));overflow-y:auto;overscroll-behavior:contain;padding:var(--mu-space-1);scroll-padding-block:var(--mu-space-1);outline:0}.mu-combobox-list[data-empty]{padding:0}.mu-combobox-item{display:flex;align-items:center;gap:var(--mu-space-2);box-sizing:border-box;height:var(--mu-row-height);padding:0 var(--mu-row-padding);border-radius:calc(var(--mu-radius-xl) - var(--mu-space-1));color:var(--mu-ink);font-weight:400;white-space:nowrap;cursor:default;user-select:none;outline:0}.mu-combobox-item:where(:has(>svg:first-child)){padding-inline-start:var(--mu-row-padding-icon)}.mu-combobox-item>svg{color:var(--mu-ink-muted)}.mu-combobox-item[data-highlighted]{background-color:var(--mu-hover)}.mu-combobox-item[data-disabled]{opacity:.45}.mu-combobox-item-text{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis}.mu-combobox-indicator{display:grid;flex:none;place-items:center;width:var(--mu-row-icon);height:var(--mu-row-icon);margin-inline-start:var(--mu-space-2);color:var(--mu-ink)}.mu-combobox-empty:not(:empty){padding:var(--mu-space-3) var(--mu-space-4);color:var(--mu-ink-muted)}.mu-combobox-group-label{padding:var(--mu-space-2) var(--mu-row-padding) var(--mu-space-1);color:var(--mu-ink-muted)}.mu-combobox-separator{height:1px;margin:var(--mu-space-1) calc(-1 * var(--mu-space-1));background-color:var(--mu-line)}}@layer mu{.mu-button.mu-collapsible-trigger{margin-inline-start:calc(-1 * var(--mu-row-padding));padding-inline-end:var(--mu-row-padding-icon)}.mu-collapsible-chevron{color:var(--mu-ink-muted);transition:rotate var(--mu-duration-settle) var(--mu-ease-settle)}.mu-collapsible-trigger[data-panel-open]>.mu-collapsible-chevron{rotate:180deg}.mu-collapsible-panel{transition:opacity var(--mu-duration-fade) var(--mu-ease-out),translate var(--mu-duration-fade) var(--mu-ease-out)}.mu-collapsible-panel[data-starting-style],.mu-collapsible-panel[data-ending-style]{opacity:0;translate:0 var(--mu-space-1)}@media(prefers-reduced-motion:reduce){.mu-collapsible-chevron{transition:none}.mu-collapsible-panel[data-starting-style],.mu-collapsible-panel[data-ending-style]{translate:none}}}@layer mu{.mu-table-scroll{overflow-x:auto;max-width:100%}.mu-table{width:100%;border-collapse:collapse;color:var(--mu-ink);font-variant-numeric:tabular-nums;text-align:start}.mu-table-head,.mu-table-cell{padding:0 var(--mu-row-padding);text-align:start;vertical-align:middle}.mu-table-head{height:var(--mu-row-height);color:var(--mu-ink-muted);white-space:nowrap;border-bottom:1px solid var(--mu-line)}.mu-table-cell{padding-block:calc((var(--mu-row-height) - var(--mu-row-line-height)) / 2 + var(--mu-space-1))}.mu-table-body>.mu-table-row+.mu-table-row>.mu-table-cell{border-top:1px solid var(--mu-line)}.mu-table-body>.mu-table-row:hover>.mu-table-cell{background-color:var(--mu-hover)}.mu-table-cell>.mu-button{margin-block:calc((var(--mu-row-line-height) - var(--mu-row-height)) / 2);vertical-align:top}.mu-table-num{text-align:end}.mu-table-muted{color:var(--mu-ink-muted)}.mu-table-caption{caption-side:bottom;padding:var(--mu-space-2) var(--mu-row-padding) 0;color:var(--mu-ink-muted);text-align:start}}@layer mu{.mu-prose{color:var(--mu-ink);font-family:var(--mu-font-sans);font-size:var(--prose-fs);line-height:var(--prose-lh);font-weight:400;overflow-wrap:break-word;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.mu-prose ::selection{background:var(--mu-selection)}.mu-prose :where(p,ul,ol,pre,blockquote,table,figure,img,video,hr){margin:0 0 var(--mu-space-3)}.mu-prose :where(h1,h2,h3,h4,h5,h6){margin:var(--mu-space-5) 0 var(--mu-space-2);font-family:var(--mu-font-display);font-weight:600;letter-spacing:0}.mu-prose>:first-child{margin-top:0}.mu-prose>:last-child{margin-bottom:0}.mu-prose h1{font-size:var(--prose-h1);line-height:var(--prose-h1-lh)}.mu-prose :where(h2,h3,h4,h5,h6){font-size:var(--prose-h2);line-height:var(--prose-h2-lh)}.mu-prose :where(strong,b){font-weight:600}.mu-prose del{color:var(--mu-ink-muted)}.mu-prose a{color:var(--mu-accent);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.2em;border-radius:var(--mu-radius-xs)}.mu-prose a:focus-visible{outline:var(--mu-focus-width) solid var(--mu-focus);outline-offset:var(--mu-focus-offset)}.mu-prose :where(ul,ol){padding-inline-start:var(--mu-space-6)}.mu-prose li+li{margin-top:var(--mu-space-1)}.mu-prose li>:where(ul,ol){margin:var(--mu-space-1) 0 0}.mu-prose li>p{margin:0}.mu-prose li::marker{color:var(--mu-ink-muted)}.mu-prose li:where(:has(>input[type=checkbox]:first-child)){position:relative;list-style:none}.mu-prose li>input[type=checkbox]:first-child{appearance:none;position:absolute;inset-inline-start:calc(-1 * (var(--mu-space-4) + var(--mu-space-2)));top:calc((var(--prose-lh) - var(--mu-space-4)) / 2);box-sizing:border-box;width:var(--mu-space-4);height:var(--mu-space-4);margin:0;border-radius:var(--mu-radius-sm);background-color:var(--mu-well);box-shadow:inset 0 0 0 1px var(--mu-edge),var(--mu-shadow-track);cursor:pointer}.mu-prose li>input[type=checkbox]:first-child:disabled{cursor:default}.mu-prose li>input[type=checkbox]:first-child:focus-visible{outline:var(--mu-focus-width) solid var(--mu-focus);outline-offset:var(--mu-focus-offset)}.mu-prose li>input[type=checkbox]:first-child:checked{background-color:var(--mu-primary);box-shadow:none}.mu-prose li>input[type=checkbox]:first-child:checked:after{content:"";position:absolute;inset:var(--mu-inset);background-color:var(--mu-on-primary);mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / contain no-repeat}.mu-prose li:where(:has(>input[type=checkbox]:first-child:checked)){color:var(--mu-ink-muted);text-decoration:line-through}.mu-prose :where(code,kbd,samp,pre){font-family:var(--mu-font-mono);font-size:.875em}.mu-prose :not(pre)>code{padding:.1em .3em;border-radius:var(--mu-radius-xs);background-color:var(--mu-well)}.mu-prose pre{overflow-x:auto;padding:var(--mu-space-3) var(--mu-space-4);border-radius:var(--mu-radius-md);background-color:var(--mu-well);line-height:1.6}.mu-prose pre>code{font-size:inherit}.mu-prose blockquote{margin-inline:0;padding-inline-start:var(--mu-space-4);border-inline-start:var(--mu-inset) solid var(--mu-edge);color:var(--mu-ink-muted)}.mu-prose hr{height:1px;margin-block:var(--mu-space-5);border:0;background-color:var(--mu-line)}.mu-prose :where(img,video){display:block;max-width:100%;height:auto;border-radius:var(--mu-radius-lg)}.mu-prose table{display:block;width:max-content;max-width:100%;overflow-x:auto;border-collapse:collapse;font-variant-numeric:tabular-nums}.mu-prose :where(th,td){padding:var(--mu-space-2) var(--mu-space-3);text-align:start;vertical-align:top}.mu-prose th{color:var(--mu-ink-muted);font-size:var(--prose-head);line-height:var(--prose-head-lh);font-weight:500;white-space:nowrap;border-bottom:1px solid var(--mu-line)}.mu-prose tr+tr>td{border-top:1px solid var(--mu-line)}.mu-prose-tag{padding:0 .25em;border-radius:var(--mu-radius-xs);color:var(--mu-ink-muted);background-color:var(--mu-well)}}
package/dist/tailwind.css CHANGED
@@ -34,6 +34,7 @@
34
34
  --color-mu-accent: var(--mu-accent);
35
35
  --color-mu-selection: var(--mu-selection);
36
36
  --color-mu-focus: var(--mu-focus);
37
+ --color-mu-focus-edge: var(--mu-focus-edge);
37
38
  --color-mu-success: var(--mu-success);
38
39
  --color-mu-success-soft: var(--mu-success-soft);
39
40
  --color-mu-warning: var(--mu-warning);
@@ -1,3 +1,3 @@
1
1
  'use client';
2
- var m=["--mu-canvas","--mu-surface","--mu-well","--mu-hover","--mu-key","--mu-key-hover","--mu-key-sheen","--mu-edge","--mu-line","--mu-overlay","--mu-ink","--mu-ink-muted","--mu-primary","--mu-primary-hover","--mu-on-primary","--mu-accent","--mu-selection","--mu-focus","--mu-success","--mu-success-soft","--mu-warning","--mu-warning-soft","--mu-danger","--mu-danger-key","--mu-danger-soft","--mu-on-danger","--mu-shadow-track","--mu-shadow-key","--mu-shadow-raised","--mu-shadow-pressed","--mu-shadow-pop"];export{m as themeTokens};
2
+ var u=["--mu-canvas","--mu-surface","--mu-well","--mu-hover","--mu-key","--mu-key-hover","--mu-key-sheen","--mu-edge","--mu-line","--mu-overlay","--mu-ink","--mu-ink-muted","--mu-primary","--mu-primary-hover","--mu-on-primary","--mu-accent","--mu-selection","--mu-focus","--mu-focus-edge","--mu-success","--mu-success-soft","--mu-warning","--mu-warning-soft","--mu-danger","--mu-danger-key","--mu-danger-soft","--mu-on-danger","--mu-shadow-track","--mu-shadow-key","--mu-shadow-raised","--mu-shadow-pressed","--mu-shadow-pop"];export{u as themeTokens};
3
3
  //# sourceMappingURL=theme-tokens.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/theme-tokens.ts"],
4
- "sourcesContent": ["/**\n * The custom properties an app theme sets: the 26 color tokens in\n * docs/color.md and the five shadow tokens in docs/depth.md. A token a theme\n * leaves out keeps its Light value, so an app's tests can check its theme\n * against this list. See docs/color.md#app-themes.\n */\nexport const themeTokens = [\n '--mu-canvas',\n '--mu-surface',\n '--mu-well',\n '--mu-hover',\n '--mu-key',\n '--mu-key-hover',\n '--mu-key-sheen',\n '--mu-edge',\n '--mu-line',\n '--mu-overlay',\n '--mu-ink',\n '--mu-ink-muted',\n '--mu-primary',\n '--mu-primary-hover',\n '--mu-on-primary',\n '--mu-accent',\n '--mu-selection',\n '--mu-focus',\n '--mu-success',\n '--mu-success-soft',\n '--mu-warning',\n '--mu-warning-soft',\n '--mu-danger',\n '--mu-danger-key',\n '--mu-danger-soft',\n '--mu-on-danger',\n '--mu-shadow-track',\n '--mu-shadow-key',\n '--mu-shadow-raised',\n '--mu-shadow-pressed',\n '--mu-shadow-pop',\n] as const;\n"],
5
- "mappings": ";AAMO,IAAMA,EAAc,CACzB,cACA,eACA,YACA,aACA,WACA,iBACA,iBACA,YACA,YACA,eACA,WACA,iBACA,eACA,qBACA,kBACA,cACA,iBACA,aACA,eACA,oBACA,eACA,oBACA,cACA,kBACA,mBACA,iBACA,oBACA,kBACA,qBACA,sBACA,iBACF",
4
+ "sourcesContent": ["/**\n * The custom properties an app theme sets: the 26 color tokens in\n * docs/color.md and the five shadow tokens in docs/depth.md. A token a theme\n * leaves out keeps its Light value, so an app's tests can check its theme\n * against this list. See docs/color.md#app-themes.\n */\nexport const themeTokens = [\n '--mu-canvas',\n '--mu-surface',\n '--mu-well',\n '--mu-hover',\n '--mu-key',\n '--mu-key-hover',\n '--mu-key-sheen',\n '--mu-edge',\n '--mu-line',\n '--mu-overlay',\n '--mu-ink',\n '--mu-ink-muted',\n '--mu-primary',\n '--mu-primary-hover',\n '--mu-on-primary',\n '--mu-accent',\n '--mu-selection',\n '--mu-focus',\n '--mu-focus-edge',\n '--mu-success',\n '--mu-success-soft',\n '--mu-warning',\n '--mu-warning-soft',\n '--mu-danger',\n '--mu-danger-key',\n '--mu-danger-soft',\n '--mu-on-danger',\n '--mu-shadow-track',\n '--mu-shadow-key',\n '--mu-shadow-raised',\n '--mu-shadow-pressed',\n '--mu-shadow-pop',\n] as const;\n"],
5
+ "mappings": ";AAMO,IAAMA,EAAc,CACzB,cACA,eACA,YACA,aACA,WACA,iBACA,iBACA,YACA,YACA,eACA,WACA,iBACA,eACA,qBACA,kBACA,cACA,iBACA,aACA,kBACA,eACA,oBACA,eACA,oBACA,cACA,kBACA,mBACA,iBACA,oBACA,kBACA,qBACA,sBACA,iBACF",
6
6
  "names": ["themeTokens"]
7
7
  }
package/dist/tokens.css CHANGED
@@ -1 +1 @@
1
- @layer mu{:where(:root,:host,.mu-root:not([data-theme] *)),[data-theme=light]{color-scheme:light;--mu-canvas: #f9f9f9;--mu-surface: #ffffff;--mu-well: #e4e4e4;--mu-hover: #ededed;--mu-key: #ffffff;--mu-key-hover: #fbfbfb;--mu-key-sheen: rgba(255,255,255,.18);--mu-edge: #d0d0d0;--mu-line: #e0e0e0;--mu-overlay: rgba(0,0,0,.32);--mu-ink: #1a1a1a;--mu-ink-muted: #5e5e5e;--mu-primary: #1f1f1f;--mu-primary-hover: #333333;--mu-on-primary: #ffffff;--mu-accent: oklch(.5 .13 255);--mu-selection: rgba(40,99,171,.18);--mu-success: oklch(.52 .13 150);--mu-success-soft: #e9f4ec;--mu-warning: oklch(.5 .11 70);--mu-warning-soft: #fbf1df;--mu-danger: oklch(.53 .19 27);--mu-danger-key: oklch(.53 .19 27);--mu-danger-soft: #fbeaea;--mu-on-danger: #ffffff;--mu-focus: var(--mu-accent);--mu-shadow-track: inset 0 1px 2px rgba(0,0,0,.1);--mu-shadow-key: 0 1px 2px rgba(0,0,0,.16), 0 2px 6px rgba(0,0,0,.08), inset 0 1px 0 rgba(255,255,255,.9), inset 0 -1px 0 rgba(0,0,0,.05);--mu-shadow-raised: inset 0 1px 0 rgba(255,255,255,.25), inset 0 -1px 0 rgba(0,0,0,.1), 0 0 0 .5px rgba(0,0,0,.12), 0 1px 2px rgba(0,0,0,.12);--mu-shadow-pressed: inset 0 1px 3px rgba(0,0,0,.22), 0 0 0 .5px rgba(0,0,0,.12);--mu-shadow-pop: 0 8px 24px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.08), 0 0 0 .5px rgba(0,0,0,.08), inset 0 1px 0 rgba(255,255,255,.8)}[data-theme=dark]{--mu-canvas: #0f0f0f;--mu-surface: #1a1a1a;--mu-well: #262626;--mu-hover: #242424;--mu-key: #343434;--mu-key-hover: #3c3c3c;--mu-key-sheen: rgba(255,255,255,.08);--mu-edge: #353535;--mu-line: #262626;--mu-overlay: rgba(0,0,0,.6);--mu-ink: #ededed;--mu-ink-muted: #adadad;--mu-primary: #e6e6e6;--mu-primary-hover: #f5f5f5;--mu-on-primary: #111111;--mu-accent: oklch(.78 .11 255);--mu-selection: rgba(135,186,253,.28);--mu-success: oklch(.78 .14 150);--mu-success-soft: #14261a;--mu-warning: oklch(.8 .13 75);--mu-warning-soft: #2a2112;--mu-danger: oklch(.72 .16 25);--mu-danger-key: oklch(.55 .17 25);--mu-danger-soft: #2c1616;--mu-on-danger: #ffffff;--mu-focus: var(--mu-accent);--mu-shadow-track: inset 0 1px 2px rgba(0,0,0,.55), inset 0 -.5px 0 rgba(255,255,255,.06);--mu-shadow-key: 0 1px 2px rgba(0,0,0,.6), 0 2px 6px rgba(0,0,0,.3), inset 0 1px 0 rgba(255,255,255,.1);--mu-shadow-raised: inset 0 1px 0 rgba(255,255,255,.1), inset 0 -1px 0 rgba(0,0,0,.25), 0 0 0 .5px rgba(0,0,0,.6), 0 1px 2px rgba(0,0,0,.5);--mu-shadow-pressed: inset 0 1px 3px rgba(0,0,0,.6), 0 0 0 .5px rgba(0,0,0,.6);--mu-shadow-pop: 0 8px 24px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.06), inset 0 1px 0 rgba(255,255,255,.06);color-scheme:dark}[data-theme=contrast]{color-scheme:light;--mu-canvas: #ffffff;--mu-surface: #ffffff;--mu-well: #e6e6e6;--mu-hover: #d9d9d9;--mu-key: #ffffff;--mu-key-hover: #f2f2f2;--mu-key-sheen: #ffffff00;--mu-edge: #6b6b6b;--mu-line: #6b6b6b;--mu-overlay: rgba(0,0,0,.6);--mu-ink: #000000;--mu-ink-muted: #333333;--mu-primary: #000000;--mu-primary-hover: #262626;--mu-on-primary: #ffffff;--mu-accent: oklch(.42 .14 255);--mu-selection: rgba(0,75,151,.25);--mu-success: oklch(.42 .12 150);--mu-success-soft: #e9f4ec;--mu-warning: oklch(.45 .11 70);--mu-warning-soft: #fbf1df;--mu-danger: oklch(.45 .18 27);--mu-danger-key: oklch(.45 .18 27);--mu-danger-soft: #fbeaea;--mu-on-danger: #ffffff;--mu-focus: var(--mu-accent);--mu-shadow-track: 0 0 0 0 rgba(0,0,0,0);--mu-shadow-key: 0 0 0 1px #6b6b6b;--mu-shadow-raised: 0 0 0 1px #000000;--mu-shadow-pressed: inset 0 0 0 2px #000000;--mu-shadow-pop: 0 0 0 1px #000000}:where(:root,:host,.mu-root){--mu-space-1: 4px;--mu-space-2: 8px;--mu-space-3: 12px;--mu-space-4: 16px;--mu-space-5: 20px;--mu-space-6: 24px;--mu-space-8: 32px;--mu-space-12: 48px;--mu-space-16: 64px;--mu-radius-xs: 2px;--mu-radius-sm: 4px;--mu-radius-md: 6px;--mu-radius-lg: 8px;--mu-radius-xl: 12px;--mu-radius-2xl: 16px;--mu-radius-full: 9999px;--mu-control-xs: 20px;--mu-control-sm: 24px;--mu-control-md: 32px;--mu-inset: 2px;--mu-hit-area: 44px;--mu-focus-width: 2px;--mu-icon-xs: 12px;--mu-icon-sm: 14px;--mu-icon-md: 16px;--mu-content-width: 720px;--mu-sidebar-width: 240px;--mu-menu-width: 200px;--mu-list-height: 240px;--mu-popover-width: 280px;--mu-tooltip-width: 240px;--mu-toast-width: 360px;--mu-dialog-width: 440px;--mu-layer-popup: 50;--mu-layer-overlay: 50;--mu-layer-toast: 60;--mu-duration-press: 80ms;--mu-duration-settle: .15s;--mu-duration-fade: .1s;--mu-duration-spin: .8s;--mu-duration-shimmer: 1.4s;--mu-ease-settle: cubic-bezier(.2, .9, .3, 1);--mu-ease-out: cubic-bezier(.2, 0, 0, 1);--mu-font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--mu-font-display: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--mu-font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace}}
1
+ @layer mu{:where(:root,:host,.mu-root:not([data-theme] *)),[data-theme=light]{color-scheme:light;--mu-canvas: #fafafa;--mu-surface: #ffffff;--mu-well: #e4e4e4;--mu-hover: #ececec;--mu-key: #ffffff;--mu-key-hover: #fafafa;--mu-key-sheen: rgba(255,255,255,.18);--mu-edge: #d0d0d0;--mu-line: #dedede;--mu-overlay: rgba(0,0,0,.32);--mu-ink: #1a1a1a;--mu-ink-muted: #5e5e5e;--mu-primary: #1a1a1a;--mu-primary-hover: #333333;--mu-on-primary: #ffffff;--mu-accent: oklch(.5 .13 255);--mu-selection: rgba(40,99,171,.18);--mu-success: oklch(.52 .13 150);--mu-success-soft: #e9f4ec;--mu-warning: oklch(.5 .11 70);--mu-warning-soft: #fbf1df;--mu-danger: oklch(.53 .19 27);--mu-danger-key: oklch(.53 .19 27);--mu-danger-soft: #fbeaea;--mu-on-danger: #ffffff;--mu-focus: var(--mu-primary);--mu-focus-edge: var(--mu-ink);--mu-shadow-track: inset 0 1px 2px rgba(0,0,0,.1);--mu-shadow-key: 0 1px 2px rgba(0,0,0,.16), 0 2px 6px rgba(0,0,0,.08), inset 0 1px 0 rgba(255,255,255,.9), inset 0 -1px 0 rgba(0,0,0,.05);--mu-shadow-raised: inset 0 1px 0 rgba(255,255,255,.25), inset 0 -1px 0 rgba(0,0,0,.1), 0 0 0 .5px rgba(0,0,0,.12), 0 1px 2px rgba(0,0,0,.12);--mu-shadow-pressed: inset 0 1px 3px rgba(0,0,0,.22), 0 0 0 .5px rgba(0,0,0,.12);--mu-shadow-pop: 0 8px 24px rgba(0,0,0,.1), 0 1px 3px rgba(0,0,0,.08), 0 0 0 .5px rgba(0,0,0,.08), inset 0 1px 0 rgba(255,255,255,.8)}[data-theme=dark]{--mu-canvas: #0f0f0f;--mu-surface: #1a1a1a;--mu-well: #252525;--mu-hover: #252525;--mu-key: #343434;--mu-key-hover: #3c3c3c;--mu-key-sheen: rgba(255,255,255,.08);--mu-edge: #343434;--mu-line: #252525;--mu-overlay: rgba(0,0,0,.6);--mu-ink: #ededed;--mu-ink-muted: #adadad;--mu-primary: #e6e6e6;--mu-primary-hover: #ffffff;--mu-on-primary: #0f0f0f;--mu-accent: oklch(.78 .11 255);--mu-selection: rgba(135,186,253,.28);--mu-success: oklch(.78 .14 150);--mu-success-soft: #14261a;--mu-warning: oklch(.8 .13 75);--mu-warning-soft: #2a2112;--mu-danger: oklch(.72 .16 25);--mu-danger-key: oklch(.55 .17 25);--mu-danger-soft: #2c1616;--mu-on-danger: #ffffff;--mu-focus: var(--mu-primary);--mu-focus-edge: var(--mu-ink);--mu-shadow-track: inset 0 1px 2px rgba(0,0,0,.55), inset 0 -.5px 0 rgba(255,255,255,.06);--mu-shadow-key: 0 1px 2px rgba(0,0,0,.6), 0 2px 6px rgba(0,0,0,.3), inset 0 1px 0 rgba(255,255,255,.1);--mu-shadow-raised: inset 0 1px 0 rgba(255,255,255,.1), inset 0 -1px 0 rgba(0,0,0,.25), 0 0 0 .5px rgba(0,0,0,.6), 0 1px 2px rgba(0,0,0,.5);--mu-shadow-pressed: inset 0 1px 3px rgba(0,0,0,.6), 0 0 0 .5px rgba(0,0,0,.6);--mu-shadow-pop: 0 8px 24px rgba(0,0,0,.6), 0 0 0 1px rgba(255,255,255,.06), inset 0 1px 0 rgba(255,255,255,.06);color-scheme:dark}:where(:root,:host,.mu-root){--mu-space-1: 4px;--mu-space-2: 8px;--mu-space-3: 12px;--mu-space-4: 16px;--mu-space-5: 20px;--mu-space-6: 24px;--mu-space-8: 32px;--mu-space-12: 48px;--mu-space-16: 64px;--mu-radius-xs: 2px;--mu-radius-sm: 4px;--mu-radius-md: 6px;--mu-radius-lg: 8px;--mu-radius-xl: 12px;--mu-radius-2xl: 16px;--mu-radius-full: 9999px;--mu-control-xs: 20px;--mu-control-sm: 24px;--mu-control-md: 32px;--mu-inset: 2px;--mu-hit-area: 44px;--mu-focus-width: 2px;--mu-focus-offset: 1px;--mu-focus-edge-width: 1.5px;--mu-icon-xs: 12px;--mu-icon-sm: 14px;--mu-icon-md: 16px;--mu-content-width: 720px;--mu-sidebar-width: 240px;--mu-menu-width: 200px;--mu-list-height: 240px;--mu-popover-width: 280px;--mu-tooltip-width: 240px;--mu-toast-width: 360px;--mu-dialog-width: 440px;--mu-layer-popup: 50;--mu-layer-overlay: 50;--mu-layer-toast: 60;--mu-duration-press: 80ms;--mu-duration-settle: .15s;--mu-duration-fade: .1s;--mu-duration-spin: .8s;--mu-duration-shimmer: 1.4s;--mu-ease-settle: cubic-bezier(.2, .9, .3, 1);--mu-ease-out: cubic-bezier(.2, 0, 0, 1);--mu-font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--mu-font-display: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;--mu-font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace}}
@@ -4,4 +4,4 @@
4
4
  * leaves out keeps its Light value, so an app's tests can check its theme
5
5
  * against this list. See docs/color.md#app-themes.
6
6
  */
7
- export declare const themeTokens: readonly ["--mu-canvas", "--mu-surface", "--mu-well", "--mu-hover", "--mu-key", "--mu-key-hover", "--mu-key-sheen", "--mu-edge", "--mu-line", "--mu-overlay", "--mu-ink", "--mu-ink-muted", "--mu-primary", "--mu-primary-hover", "--mu-on-primary", "--mu-accent", "--mu-selection", "--mu-focus", "--mu-success", "--mu-success-soft", "--mu-warning", "--mu-warning-soft", "--mu-danger", "--mu-danger-key", "--mu-danger-soft", "--mu-on-danger", "--mu-shadow-track", "--mu-shadow-key", "--mu-shadow-raised", "--mu-shadow-pressed", "--mu-shadow-pop"];
7
+ export declare const themeTokens: readonly ["--mu-canvas", "--mu-surface", "--mu-well", "--mu-hover", "--mu-key", "--mu-key-hover", "--mu-key-sheen", "--mu-edge", "--mu-line", "--mu-overlay", "--mu-ink", "--mu-ink-muted", "--mu-primary", "--mu-primary-hover", "--mu-on-primary", "--mu-accent", "--mu-selection", "--mu-focus", "--mu-focus-edge", "--mu-success", "--mu-success-soft", "--mu-warning", "--mu-warning-soft", "--mu-danger", "--mu-danger-key", "--mu-danger-soft", "--mu-on-danger", "--mu-shadow-track", "--mu-shadow-key", "--mu-shadow-raised", "--mu-shadow-pressed", "--mu-shadow-pop"];
package/llms-full.txt CHANGED
@@ -18,7 +18,7 @@ It is not a general-purpose UI library for outside developers. Components are ge
18
18
  | Doc | What it covers |
19
19
  | --- | --- |
20
20
  | [Principles and voice](principles.md) | The taste in six rules, and how interface text is written |
21
- | [Color](color.md) | Color roles, every color token in Light, Dark and High contrast, and how themes are chosen |
21
+ | [Color](color.md) | Color roles, every color token in Light and Dark, and how themes are chosen |
22
22
  | [Depth](depth.md) | The tactile model: recessed, key, raised, popup and flat; shadow tokens |
23
23
  | [Typography](typography.md) | The system font, the type scale and text rules |
24
24
  | [Size, spacing and layout](layout.md) | Control sizes, the 4px scale, radius, layout widths, breakpoints and layers |
@@ -26,6 +26,7 @@ It is not a general-purpose UI library for outside developers. Components are ge
26
26
  | [States](states.md) | Hover, pressed, loading, disabled, invalid and focus |
27
27
  | [Icons](icons.md) | Lucide, sizes, fixed stroke widths and accessibility |
28
28
  | [Components](components/README.md) | The 28 components, what was left out, and one page per component |
29
+ | [Using the components](usage.md) | Which component to pick (overlays, controls, feedback), recipes for combining them, size, emphasis, an accessibility checklist, common mistakes and a map from other UI kits |
29
30
  | [Patterns](patterns.md) | Page, form, entry, confirmation, loading, empty state and mobile |
30
31
  | [Building on it](building.md) | Base UI, loading the CSS, scoping inside a host page, theme selection and API conventions |
31
32
  | [Building your own component](custom-components.md) | How an app builds a part the package doesn't ship: Base UI, class functions, public classes, row variables and Tailwind CSS |
@@ -34,9 +35,9 @@ It is not a general-purpose UI library for outside developers. Components are ge
34
35
 
35
36
  - **Behavior from Base UI.** Focus management, keyboard support, ARIA, portals and positioning come from [Base UI](https://base-ui.com). Styling, tokens and the component API are our own.
36
37
  - **No shadcn.** No shadcn dependency, no copied shadcn code, and no shadcn-compatible component or token names (`card`, `muted`, `destructive`, `foreground` and so on are not used).
37
- - **Light, tactile by default.** Restrained depth that shows behavior. Light is the default theme; Dark and High contrast ship with it.
38
+ - **Light, tactile by default.** Restrained depth that shows behavior. Light is the default theme; Dark ships with it.
38
39
  - **Ink is the accent.** The primary action and every on state use `primary`: near-black in Light, near-white in Dark.
39
- - **One quiet hue.** `accent` is a quiet blue used only for focus rings, links and text selection, never as a fill.
40
+ - **One quiet hue.** `accent` is a quiet blue used only for links and text selection, never as a fill. Focus is ink.
40
41
  - **Status colors only for status.** Green means success, amber means warning, red means danger or error. None of them is used for emphasis.
41
42
  - **Lucide icons** at a fixed screen-pixel stroke: 1.5px at md, 1.25px at xs, sm and in badges.
42
43
  - **The system UI font** for all text. The package ships no font files.
@@ -79,7 +80,7 @@ It is not a general-purpose UI library for outside developers. Components are ge
79
80
 
80
81
  # Color
81
82
 
82
- Memos UI is ink on paper: pure-gray neutrals, `primary` ink for emphasis, one quiet blue for focus, links and selection, and status colors only when there is a status.
83
+ Memos UI is ink on paper: pure-gray neutrals, `primary` ink for emphasis, one quiet blue for links and selection, and status colors only when there is a status.
83
84
 
84
85
  ## Roles
85
86
 
@@ -89,16 +90,17 @@ Memos UI is ink on paper: pure-gray neutrals, `primary` ink for emphasis, one qu
89
90
  | Wells | `well`, `edge` | Switch, tab, checkbox and radio wells, pressed toggles, inline code. `edge` is the 1px border of wells and inputs |
90
91
  | Hover | `hover` | Rows, ghost buttons, the highlighted menu row. About 4% ink over surface |
91
92
  | Keys | `key`, `key-hover`, `key-sheen` | Neutral buttons, select triggers, the selected tab, switch knobs, kbd |
92
- | Text | `ink`, `ink-muted` | Primary and secondary text. Both pass 4.5:1 on every surface, well and key in every theme |
93
+ | Text | `ink`, `ink-muted` | Primary and secondary text. Both pass 4.5:1 on every surface, well and key in both themes |
93
94
  | Emphasis | `primary`, `primary-hover`, `on-primary` | Primary button, checked checkbox and radio, switch when on, tooltip |
94
- | Meta | `accent`, `selection`, `focus` | Links, focus ring, text selection. Never a fill |
95
+ | Meta | `accent`, `selection`, `focus`, `focus-edge` | Links and text selection (`accent`); the keyboard focus ring and the focused field edge (`focus`, `focus-edge`, both ink). Never a fill |
95
96
  | Status | `success`, `warning`, `danger` and their `-soft` pairs; `danger-key`, `on-danger` | Toasts, badges, field errors, danger buttons |
96
97
  | Lines | `line` | Separators, table rules, menu dividers |
97
98
 
98
99
  ## Rules
99
100
 
100
101
  - Neutrals are pure gray, never tinted.
101
- - `accent` is a quiet blue used only for links, focus and selection. If a screen has blue on it at rest, apart from links, something is wrong.
102
+ - `accent` is a quiet blue used only for links and selection. If a screen has blue on it at rest, apart from links, something is wrong.
103
+ - Focus is ink, not blue. A focused field darkens its own edge to `focus-edge`; a control reached by keyboard gets a 2px `focus` ring 1px outside its edge. See [States](states.md).
102
104
  - Status colors appear only when there is a status. Red is for destructive actions and errors, never for emphasis.
103
105
  - `danger` is tuned for text. `danger-key` is the danger button's fill; it is darker in Dark so the button is not the loudest thing on screen.
104
106
  - Always pair a status color with a word or an icon.
@@ -106,15 +108,15 @@ Memos UI is ink on paper: pure-gray neutrals, `primary` ink for emphasis, one qu
106
108
 
107
109
  ## Themes
108
110
 
109
- There are three themes: **Light** (the default), **Dark** and **High contrast**.
111
+ There are two themes: **Light** (the default) and **Dark**.
110
112
 
111
113
  - Each theme sets every color token and every shadow token to an explicit value. Nothing is derived at runtime. The package's tests check the values against the tables on this page and in [Depth](depth.md), and check the contrast promised here.
112
114
  - Dark keeps the same depth model. Wells go darker than `canvas`, keys go lighter, `key-sheen` drops to 8%, and `primary` flips to near-white with a dark `on-primary`.
113
- - Non-text contrast: `edge` is about 1.5:1 in Light and Dark. That is the soft border people expect from a calm interface, and it is below WCAG's 3:1 for control boundaries. High contrast raises `edge` to 5.3:1 and outlines every key. Offer High contrast wherever the theme is chosen.
115
+ - Non-text contrast: `edge` is about 1.5:1 in Light and Dark. That is the soft border people expect from a calm interface, and it is below WCAG's 3:1 for control boundaries. An app that needs 3:1 boundaries defines its own [app theme](#app-themes) with a darker `edge` and outlined keys.
114
116
 
115
117
  ### Choosing a theme
116
118
 
117
- Set `data-theme="light" | "dark" | "contrast"` on the root element, or on any `.mu-root` element. Without the attribute the tokens are Light.
119
+ Set `data-theme="light" | "dark"` on the root element, or on any `.mu-root` element. Without the attribute the tokens are Light.
118
120
 
119
121
  The package does not read `prefers-color-scheme` itself. The app does, so that a saved preference wins over the system setting. Dark sets `color-scheme: dark`, so native scrollbars and form controls follow.
120
122
 
@@ -122,7 +124,7 @@ The package does not read `prefers-color-scheme` itself. The app does, so that a
122
124
 
123
125
  An app sets only these tokens:
124
126
 
125
- - the 26 color tokens in the [table below](#color-tokens),
127
+ - the 27 color tokens in the [table below](#color-tokens),
126
128
  - the five shadow tokens in [Depth](depth.md#shadow-tokens),
127
129
  - the three font tokens in [Typography](typography.md#fonts): `font-sans`, `font-display` and `font-mono`.
128
130
 
@@ -132,7 +134,7 @@ Internal rules are not private classes. An app applies the [public classes](cust
132
134
 
133
135
  ### App themes
134
136
 
135
- An app can offer more themes than the three the package ships, such as a warm Paper theme in memos. An app theme is a rule that sets the color and shadow tokens under its own `data-theme` value:
137
+ An app can offer more themes than the two the package ships, such as a warm Paper theme in memos. An app theme is a rule that sets the color and shadow tokens under its own `data-theme` value:
136
138
 
137
139
  ```css
138
140
  [data-theme="paper"] {
@@ -144,7 +146,7 @@ An app can offer more themes than the three the package ships, such as a warm Pa
144
146
  ```
145
147
 
146
148
  - Set every color token in the table below and the five shadow tokens in [Depth](depth.md). A token the theme leaves out keeps its Light value, so a partial theme mixes two palettes.
147
- - The package exports `themeTokens`, the custom property names of those 31 tokens (`--mu-canvas` to `--mu-shadow-pop`). Check in the app's tests that its theme sets each one:
149
+ - The package exports `themeTokens`, the custom property names of those 32 tokens (`--mu-canvas` to `--mu-shadow-pop`). Check in the app's tests that its theme sets each one:
148
150
 
149
151
  ```ts
150
152
  import { themeTokens } from "@usememos/ui";
@@ -154,43 +156,44 @@ An app can offer more themes than the three the package ships, such as a warm Pa
154
156
  expect(themeTokens.filter((name) => !paper.includes(`${name}:`))).toEqual([]);
155
157
  });
156
158
  ```
157
- - Keep the rules on this page: `primary` stays ink, not a brand hue; `accent` is only for focus, links and selection; status colors only for status.
158
- - The app owns the theme's contrast. Check in the app's own tests that every text and background pair named in the Usage column below keeps 4.5:1 or more. The package's tests and screenshots cover only Light, Dark and High contrast.
159
+ - Keep the rules on this page: `primary` stays ink, not a brand hue; `accent` is only for links and selection; focus is ink; status colors only for status.
160
+ - The app owns the theme's contrast. Check in the app's own tests that every text and background pair named in the Usage column below keeps 4.5:1 or more. The package's tests and screenshots cover only Light and Dark.
159
161
  - The tokens sit in the `mu` [cascade layer](building.md#cascade-layer), so an unlayered app theme wins over them at any specificity.
160
162
  - An app theme is a choice the user makes. It is not a way to restyle the package per product: an app's default theme is Light or Dark.
161
163
 
162
164
  ## Color tokens
163
165
 
164
- | Token | Light | Dark | High contrast | Usage |
165
- | --- | --- | --- | --- | --- |
166
- | `canvas` | `#f9f9f9` | `#0f0f0f` | `#ffffff` | Page background |
167
- | `surface` | `#ffffff` | `#1a1a1a` | `#ffffff` | One lightness step above canvas: inputs, menus, popovers, dialogs, toasts, table headers |
168
- | `well` | `#e4e4e4` | `#262626` | `#e6e6e6` | Recessed parts that hold a state: switch, tab, checkbox and radio wells, pressed toggles, inline code. Paired with `edge` and `shadow-track`. Not for text entry |
169
- | `hover` | `#ededed` | `#242424` | `#d9d9d9` | Hover on rows, ghost buttons and wells; the highlighted row in menus and selects |
170
- | `key` | `#ffffff` | `#343434` | `#ffffff` | Raised parts you press: neutral buttons, select triggers, the selected tab, switch knobs, kbd. Paired with `shadow-key` or `shadow-raised` |
171
- | `key-hover` | `#fbfbfb` | `#3c3c3c` | `#f2f2f2` | Hover on a neutral key |
172
- | `key-sheen` | `rgba(255,255,255,0.18)` | `rgba(255,255,255,0.08)` | `#ffffff00` | Top light on keys: a gradient from `key-sheen` at the top edge to clear at 60% of the height |
173
- | `edge` | `#d0d0d0` | `#353535` | `#6b6b6b` | 1px border of inputs and wells. About 1.5:1 on canvas in Light and Dark; 5.3:1 in High contrast, where it also outlines keys |
174
- | `line` | `#e0e0e0` | `#262626` | `#6b6b6b` | Separators, table rules and menu dividers. 1.25:1 in Light, so structural lines also need spacing or a heading |
175
- | `overlay` | `rgba(0,0,0,0.32)` | `rgba(0,0,0,0.6)` | `rgba(0,0,0,0.6)` | Backdrop behind dialogs and sheets |
176
- | `ink` | `#1a1a1a` | `#ededed` | `#000000` | Primary text and icons on canvas, surface, well and key (13:1 or more in every theme) |
177
- | `ink-muted` | `#5e5e5e` | `#adadad` | `#333333` | Secondary text: descriptions, placeholders, unselected tabs and toggles, shortcuts, timestamps (4.9:1 or more on every surface) |
178
- | `primary` | `#1f1f1f` | `#e6e6e6` | `#000000` | The one emphasized action and every on state: primary buttons, checked boxes and radios, switches when on, tooltips. Ink, not a hue |
179
- | `primary-hover` | `#333333` | `#f5f5f5` | `#262626` | Hover on a primary key |
180
- | `on-primary` | `#ffffff` | `#111111` | `#ffffff` | Text, icons and the switch knob on `primary` (16:1 Light, 15:1 Dark) |
181
- | `accent` | `oklch(0.5 0.13 255)` | `oklch(0.78 0.11 255)` | `oklch(0.42 0.14 255)` | The only hue at rest: focus rings, links, the text cursor and selection. 5.8:1 on canvas in Light. Never a fill |
182
- | `selection` | `rgba(40,99,171,0.18)` | `rgba(135,186,253,0.28)` | `rgba(0,75,151,0.25)` | Text selection and the selected range in an editor |
183
- | `focus` | `var(--mu-accent)` | `var(--mu-accent)` | `var(--mu-accent)` | Focus ring: 2px outline, 2px offset, on `:focus-visible` only |
184
- | `success` | `oklch(0.52 0.13 150)` | `oklch(0.78 0.14 150)` | `oklch(0.42 0.12 150)` | Success text and icons on `surface` or `success-soft` (4.6:1 or more). Always with a word or icon |
185
- | `success-soft` | `#e9f4ec` | `#14261a` | `#e9f4ec` | Background of success badges and toasts |
186
- | `warning` | `oklch(0.5 0.11 70)` | `oklch(0.8 0.13 75)` | `oklch(0.45 0.11 70)` | Warning text and icons on `surface` or `warning-soft` (5.5:1 or more) |
187
- | `warning-soft` | `#fbf1df` | `#2a2112` | `#fbf1df` | Background of warning badges and toasts |
188
- | `danger` | `oklch(0.53 0.19 27)` | `oklch(0.72 0.16 25)` | `oklch(0.45 0.18 27)` | Danger text and icons: field errors, delete menu items, danger badges (5.0:1 or more on `surface` and `danger-soft`) |
189
- | `danger-key` | `oklch(0.53 0.19 27)` | `oklch(0.55 0.17 25)` | `oklch(0.45 0.18 27)` | Fill of a danger button. 5.3:1 or more with `on-danger` |
190
- | `danger-soft` | `#fbeaea` | `#2c1616` | `#fbeaea` | Background of danger badges and error toasts |
191
- | `on-danger` | `#ffffff` | `#ffffff` | `#ffffff` | Text on a danger key |
192
-
193
- Every text and background pair in this table keeps at least 4.5:1 in every theme. Depth (see [Depth](depth.md)) is added on top and never lowers contrast.
166
+ | Token | Light | Dark | Usage |
167
+ | --- | --- | --- | --- |
168
+ | `canvas` | `#fafafa` | `#0f0f0f` | Page background |
169
+ | `surface` | `#ffffff` | `#1a1a1a` | One lightness step above canvas: inputs, menus, popovers, dialogs, toasts, table headers |
170
+ | `well` | `#e4e4e4` | `#252525` | Recessed parts that hold a state: switch, tab, checkbox and radio wells, pressed toggles, inline code. Paired with `edge` and `shadow-track`. Not for text entry |
171
+ | `hover` | `#ececec` | `#252525` | Hover on rows, ghost buttons and wells; the highlighted row in menus and selects |
172
+ | `key` | `#ffffff` | `#343434` | Raised parts you press: neutral buttons, select triggers, the selected tab, switch knobs, kbd. Paired with `shadow-key` or `shadow-raised` |
173
+ | `key-hover` | `#fafafa` | `#3c3c3c` | Hover on a neutral key |
174
+ | `key-sheen` | `rgba(255,255,255,0.18)` | `rgba(255,255,255,0.08)` | Top light on keys: a gradient from `key-sheen` at the top edge to clear at 60% of the height |
175
+ | `edge` | `#d0d0d0` | `#343434` | 1px border of inputs and wells. About 1.5:1 on canvas |
176
+ | `line` | `#dedede` | `#252525` | Separators, table rules and menu dividers. 1.25:1 in Light, so structural lines also need spacing or a heading |
177
+ | `overlay` | `rgba(0,0,0,0.32)` | `rgba(0,0,0,0.6)` | Backdrop behind dialogs and sheets |
178
+ | `ink` | `#1a1a1a` | `#ededed` | Primary text and icons on canvas, surface, well and key (13:1 or more in both themes) |
179
+ | `ink-muted` | `#5e5e5e` | `#adadad` | Secondary text: descriptions, placeholders, unselected tabs and toggles, shortcuts, timestamps (4.9:1 or more on every surface) |
180
+ | `primary` | `#1a1a1a` | `#e6e6e6` | The one emphasized action and every on state: primary buttons, checked boxes and radios, switches when on, tooltips. Ink, not a hue |
181
+ | `primary-hover` | `#333333` | `#ffffff` | Hover on a primary key |
182
+ | `on-primary` | `#ffffff` | `#0f0f0f` | Text, icons and the switch knob on `primary` (16:1 Light, 15:1 Dark) |
183
+ | `accent` | `oklch(0.5 0.13 255)` | `oklch(0.78 0.11 255)` | The only hue at rest: links, the text cursor and selection. 5.8:1 on canvas in Light. Never a fill |
184
+ | `selection` | `rgba(40,99,171,0.18)` | `rgba(135,186,253,0.28)` | Text selection and the selected range in an editor |
185
+ | `focus` | `var(--mu-primary)` | `var(--mu-primary)` | Keyboard focus ring: 2px outline, 1px offset, on `:focus-visible` only |
186
+ | `focus-edge` | `var(--mu-ink)` | `var(--mu-ink)` | Edge of a focused field (Input, Textarea, Combobox): 1.5px on any focus, in place of the 1px `edge` |
187
+ | `success` | `oklch(0.52 0.13 150)` | `oklch(0.78 0.14 150)` | Success text and icons on `surface` or `success-soft` (4.6:1 or more). Always with a word or icon |
188
+ | `success-soft` | `#e9f4ec` | `#14261a` | Background of success badges and toasts |
189
+ | `warning` | `oklch(0.5 0.11 70)` | `oklch(0.8 0.13 75)` | Warning text and icons on `surface` or `warning-soft` (5.5:1 or more) |
190
+ | `warning-soft` | `#fbf1df` | `#2a2112` | Background of warning badges and toasts |
191
+ | `danger` | `oklch(0.53 0.19 27)` | `oklch(0.72 0.16 25)` | Danger text and icons: field errors, delete menu items, danger badges (5.0:1 or more on `surface` and `danger-soft`) |
192
+ | `danger-key` | `oklch(0.53 0.19 27)` | `oklch(0.55 0.17 25)` | Fill of a danger button. 5.3:1 or more with `on-danger` |
193
+ | `danger-soft` | `#fbeaea` | `#2c1616` | Background of danger badges and error toasts |
194
+ | `on-danger` | `#ffffff` | `#ffffff` | Text on a danger key |
195
+
196
+ Every text and background pair in this table keeps at least 4.5:1 in both themes. Depth (see [Depth](depth.md)) is added on top and never lowers contrast.
194
197
 
195
198
  <!-- docs/depth.md -->
196
199
 
@@ -225,7 +228,6 @@ Each depth class applies a whole role in one class. Use them for new parts befor
225
228
  - **One rule for "selected".** A single choice among peers (tabs, a segmented filter) is a raised key sliding in a well. An on/off state (a toolbar toggle) is pressed into a well. Never mix the two in one row.
226
229
  - Content areas are flat. There is no card component: group content with spacing, a heading and a `Separator`.
227
230
  - No textures, no glass or blur behind text, and no neumorphism. Every fill and text pair keeps its contrast, and depth is added on top.
228
- - In High contrast, depth turns into outlines on every well and key, and `shadow-pressed` becomes an inner ring.
229
231
 
230
232
  ## Shadow tokens
231
233
 
@@ -257,16 +259,6 @@ Each depth class applies a whole role in one class. Use them for new parts befor
257
259
  --mu-shadow-pop: 0 8px 24px rgba(0,0,0,0.6), 0 0 0 1px rgba(255,255,255,0.06), inset 0 1px 0 rgba(255,255,255,0.06);
258
260
  ```
259
261
 
260
- ### High contrast
261
-
262
- ```css
263
- --mu-shadow-track: 0 0 0 0 rgba(0,0,0,0);
264
- --mu-shadow-key: 0 0 0 1px #6b6b6b;
265
- --mu-shadow-raised: 0 0 0 1px #000000;
266
- --mu-shadow-pressed: inset 0 0 0 2px #000000;
267
- --mu-shadow-pop: 0 0 0 1px #000000;
268
- ```
269
-
270
262
  <!-- docs/typography.md -->
271
263
 
272
264
  # Typography
@@ -406,7 +398,9 @@ Buttons, inputs and badges are never pills.
406
398
  | `control-md` | 32px | Default control height |
407
399
  | `inset` | 2px | Well-to-key inset at every size |
408
400
  | `hit-area` | 44px | Minimum touch target on `pointer: coarse`, added invisibly around a control |
409
- | `focus-width` | 2px | Width and offset of the focus ring |
401
+ | `focus-width` | 2px | Width of the keyboard focus ring |
402
+ | `focus-offset` | 1px | Gap between a control's edge and its focus ring, so the ring stays visible on ink fills |
403
+ | `focus-edge-width` | 1.5px | Edge width of a focused field |
410
404
  | `icon-xs` | 12px | Icons in xs controls and badges |
411
405
  | `icon-sm` | 14px | Icons in sm controls |
412
406
  | `icon-md` | 16px | Icons in md controls and nav rows |
@@ -495,13 +489,18 @@ Every interactive component handles these states the same way.
495
489
  | Loading | The control keeps its size, hides its label and shows a Spinner. It is inert while loading |
496
490
  | Disabled | 45% opacity, `cursor: not-allowed`, and no hover or press response |
497
491
  | Invalid | A `danger` edge on the field, plus an error line with an icon under it |
498
- | Focus | A 2px `focus` outline with a 2px offset, on `:focus-visible` only |
492
+ | Focus (field) | The edge darkens from 1px `edge` to 1.5px `focus-edge` (ink), on click and keyboard alike. No ring around it. An invalid field's `danger` edge thickens the same way |
493
+ | Focus (everything else) | A 2px ink `focus` ring 1px outside the edge, on `:focus-visible` (keyboard) only |
494
+ | Focus (inside a widget) | Menu items and options take the `hover` fill. No ring |
499
495
 
500
496
  ## Rules
501
497
 
502
498
  - Hover never changes size, weight or layout.
503
499
  - An input never changes its background on hover or focus, so it never looks disabled.
504
- - Focus rings show for keyboard focus only (`:focus-visible`), never on mouse click.
500
+ - Focus rings show for keyboard focus only (`:focus-visible`), never on mouse click. Fields are the exception: a clicked field is focused for typing, so its edge darkens, but it still gets no ring.
501
+ - Focus is ink, never blue, and never a ring floating away from the control.
502
+ - Popups, dialogs and panels never show a focus ring when they open and take focus.
503
+ - Every focus style survives forced-colors mode: rings are outlines, and fields add a transparent outline that the system paints.
505
504
  - Disabled controls stay in place. Prefer explaining why something is unavailable over hiding it.
506
505
  - Loading never shows a spinner for less than about 300ms; short waits pass silently.
507
506
 
@@ -583,6 +582,8 @@ Components follow the [API conventions](../building.md#api-conventions): parts w
583
582
 
584
583
  ## Choosing between similar components
585
584
 
585
+ The short version. [Using the components](../usage.md) has the full decision guides, recipes and common mistakes.
586
+
586
587
  | Need | Use |
587
588
  | --- | --- |
588
589
  | Start an action | Button |
@@ -837,7 +838,8 @@ Base UI's props pass through: `open`, `defaultOpen`, `onOpenChange`, `modal` on
837
838
  - Act in `onClick`. Labels are verbs in sentence case.
838
839
  - Put destructive items last, after a Separator, with `danger`. Confirm them with an [AlertDialog](dialog.md).
839
840
  - CheckboxItems and RadioItems stay open on click, so people can change several.
840
- - For picking a value saved with a form, use [Select](select.md).
841
+ - For picking a value saved with a form, use [Select](select.md). For content that stays open while people use it (inputs, text, several controls), use [Popover](popover.md). See [Menu or Popover](../usage.md#menu-or-popover).
842
+ - To open a Dialog from an item, keep the Dialog outside the Menu and control its `open`. See [the recipe](../usage.md#a-menu-item-that-opens-a-dialog).
841
843
  - Arrow keys move the highlight; typing jumps to an item; Escape and an outside click close it; focus returns to the trigger.
842
844
  - An app's own floating list, such as an editor's suggestion list, takes `menuClasses()`: `popup` on the list, `item` on each row, and `data-highlighted` on the active row. See [Class functions](../custom-components.md#class-functions).
843
845
 
@@ -887,7 +889,6 @@ Provide `href` and `children`.
887
889
  ## Style
888
890
 
889
891
  - `accent` text that underlines on hover: the one place the hue appears at rest. `muted` uses `ink-muted`.
890
- - High contrast underlines every link.
891
892
 
892
893
  <!-- docs/components/field.md -->
893
894
 
@@ -993,13 +994,13 @@ Wraps Base UI's [Input](https://base-ui.com/react/components/input), so inside a
993
994
  - Provide a `Field.Label` or `aria-label`. Never a placeholder alone.
994
995
  - `prefix` and `suffix` hold an icon, a short word or a small ghost Button.
995
996
  - `sm` for filters inside panels, `md` everywhere else.
996
- - An app's own one-line field, such as a tag input around a native `<input>`, takes `inputClasses()` on its box: focus anywhere inside shows the ring, and `aria-invalid="true"` or `aria-disabled="true"` on the box show those states. See [Class functions](../custom-components.md#class-functions).
997
+ - An app's own one-line field, such as a tag input around a native `<input>`, takes `inputClasses()` on its box: focus anywhere inside darkens the edge, and `aria-invalid="true"` or `aria-disabled="true"` on the box show those states. See [Class functions](../custom-components.md#class-functions).
997
998
 
998
999
  ## Style
999
1000
 
1000
1001
  - Flat `surface` with a 1px `edge` and a faint inner shadow from the top. Never a gray well, so it never reads as disabled.
1001
1002
  - Typed text weight 400; placeholder `ink-muted`.
1002
- - Hover darkens the edge to `ink-muted`; focus adds the ring. The background never changes.
1003
+ - Hover darkens the edge to `ink-muted`; focus turns it into a 1.5px `focus-edge` (ink), on click and keyboard alike. There is no ring around the field. The background never changes.
1003
1004
  - The side with a prefix or suffix has 2px less padding.
1004
1005
 
1005
1006
  <!-- docs/components/textarea.md -->
@@ -1036,7 +1037,7 @@ Base UI has no textarea part, so this renders Base UI's `Field.Control` as a `<t
1036
1037
 
1037
1038
  - Provide a `Field.Label` or `aria-label`.
1038
1039
  - Rich content is not a textarea: use the editor (`@usememos/editor`) with [Prose](prose.md).
1039
- - An app's own multi-line field, such as a content-editable editor, takes `textareaClasses()`: focus shows the ring, and `aria-invalid="true"` or `aria-disabled="true"` show those states. See [Class functions](../custom-components.md#class-functions).
1040
+ - An app's own multi-line field, such as a content-editable editor, takes `textareaClasses()`: focus darkens the edge, and `aria-invalid="true"` or `aria-disabled="true"` show those states. See [Class functions](../custom-components.md#class-functions).
1040
1041
 
1041
1042
  ## Style
1042
1043
 
@@ -1193,7 +1194,7 @@ Base UI's props pass through: `items`, `value`, `defaultValue`, `onValueChange`,
1193
1194
 
1194
1195
  ## Style
1195
1196
 
1196
- - The box is an [Input](input.md): flat `surface`, `edge`, focus ring on the box. The search icon and chevron are `ink-muted`; the chevron turns `ink` on hover.
1197
+ - The box is an [Input](input.md): flat `surface`, `edge`, and the focused edge on the box. The search icon and chevron are `ink-muted`; the chevron turns `ink` on hover.
1197
1198
  - List: `mu-popup`, `space-1` padding, as wide as the input and at least `menu-width`, at most `list-height` (240px) tall, then it scrolls.
1198
1199
  - Rows are a control height, text weight 400; the highlighted row uses `hover`; the chosen row has a check at the end.
1199
1200
  - Empty text: `body` in `ink-muted`, `space-3` by `space-4` padding.
@@ -1511,6 +1512,7 @@ Base UI's props pass through: `open`, `defaultOpen`, `onOpenChange`, `modal`, `d
1511
1512
  - Use AlertDialog for confirmations; see the [confirmation pattern](../patterns.md#confirmation). Open it from a Menu item with `open` and `onOpenChange`.
1512
1513
  - Escape and a backdrop click close a Dialog. While a form has unsaved input, keep it open from `onOpenChange`.
1513
1514
  - Focus moves into the dialog and returns to the trigger on close.
1515
+ - The panel is always md: controls inside it ignore the size of a Root the Dialog is declared in (a sm Table). Pass `size` to a control inside only when it should differ.
1514
1516
 
1515
1517
  ## Style
1516
1518
 
@@ -1568,6 +1570,7 @@ Base UI's props pass through: `open`, `defaultOpen`, `onOpenChange`, `modal` on
1568
1570
 
1569
1571
  - Use it for a few controls that belong to one thing. For a list of actions, use [Menu](menu.md). For a decision that blocks the page, use [Dialog](dialog.md).
1570
1572
  - Give it a `Popover.Title`, or `aria-label` on the popup.
1573
+ - The panel is always md: controls inside it ignore the size of the Root around the Popover (a sm toolbar). Pass `size` to a control inside only when it should differ.
1571
1574
  - It closes on Escape and on a click outside; focus returns to the trigger.
1572
1575
  - An app's own floating panel, such as an emoji picker, takes `popoverClasses()`. See [Class functions](../custom-components.md#class-functions).
1573
1576
 
@@ -1627,6 +1630,7 @@ Base UI's props pass through: `open`, `defaultOpen`, `onOpenChange`, `disabled`
1627
1630
  - Never put essential information only in a tooltip: it doesn't open on touch screens.
1628
1631
  - For text that explains something, use a [Popover](popover.md) instead.
1629
1632
  - Wrap a toolbar, or the whole app, in one `Tooltip.Provider`.
1633
+ - On a trigger that also opens a Menu, Popover or Dialog, stack the triggers: `<Tooltip.Trigger render={<Menu.Trigger render={<Button … />} />} />`. See [the recipe](../usage.md#an-icon-only-button-with-a-tooltip-and-a-menu).
1630
1634
 
1631
1635
  ## Style
1632
1636
 
@@ -2058,6 +2062,377 @@ Every native attribute passes through.
2058
2062
  - Tags: `ink-muted` on `well`, `radius-xs`. They read as words, not badges.
2059
2063
  - Sizes are custom properties set on `.mu-prose` in the foundation (`--prose-fs`, `--prose-lh`, heading sizes).
2060
2064
 
2065
+ <!-- docs/usage.md -->
2066
+
2067
+ # Using the components
2068
+
2069
+ How to pick the right component for a screen and put components together. Read it before building or migrating a screen in an app. Each component's own page has its props and rules; this page decides between them.
2070
+
2071
+ ## Before you build a screen
2072
+
2073
+ 1. Find the [pattern](patterns.md) the screen follows: page, form, entry, confirmation, loading, empty state, mobile. Follow it before choosing components.
2074
+ 2. Pick each component with the guides below. When two seem to fit, the first row that matches wins.
2075
+ 3. Import components from `@usememos/ui` and icons from `lucide-react`. Don't wrap a component to restyle it.
2076
+ 4. Use `className` and `style` for layout only: width, margin, grid or flex placement. Don't change a component's color, height, padding, radius, shadow, font size or focus style. If the look is wrong, the component or its page is wrong; change the package, not the screen.
2077
+ 5. A part the package doesn't ship is built with [Building your own component](custom-components.md), never by copying a component's CSS.
2078
+
2079
+ ## Picking something that floats
2080
+
2081
+ The most common mistake is reaching for the wrong overlay. Decide by what the floating thing holds and how it closes.
2082
+
2083
+ | Component | Holds | Opens on | Closes when | Blocks the page | Use it for |
2084
+ | --- | --- | --- | --- | --- | --- |
2085
+ | [Tooltip](components/tooltip.md) | Two or three words of text, and a shortcut | Hover or keyboard focus | The pointer or focus leaves | No | Naming an icon-only control |
2086
+ | [Menu](components/menu.md) | A list of commands | Click on its trigger | One command is picked, Escape, a click outside | No | Actions on one thing: "Pin", "Copy link", "Delete" |
2087
+ | [Select](components/select.md), [Combobox](components/combobox.md) | A list of values | Click or typing | One value is picked | No | Choosing a value that a form or setting keeps |
2088
+ | [Popover](components/popover.md) | Any small content: text, a few controls | Click on its trigger | Escape, a click outside, or its own Close | No | A share panel, a link editor, a filter panel, an explanation |
2089
+ | [Dialog](components/dialog.md) | A short form or a decision | An action | Its buttons, Escape, a backdrop click | Yes | Creating something, editing settings of one thing |
2090
+ | [AlertDialog](components/dialog.md) | A question and two buttons | An action | Only its buttons | Yes | Confirming a destructive or irreversible action |
2091
+ | [Toast](components/toast.md) | A sentence about what happened, at most one action | The app, after something happened | A timeout, its X, or its action | No | "Note archived" with Undo; "Couldn't sync" |
2092
+
2093
+ ### Menu or Popover
2094
+
2095
+ - **Menu: picking an item runs a command and closes the menu.** Items are verbs. Arrow keys move between items; typing jumps to one. Nothing inside a Menu takes text or holds focus.
2096
+ - **Popover: the content stays open while people use it.** It can hold text, inputs, buttons, a list of toggles. People tab through it like a small page.
2097
+ - An input, a checkbox list with an Apply button, or explanatory text inside a Menu means it should be a Popover.
2098
+ - A Popover whose content is only a list of actions should be a Menu.
2099
+ - A Menu may hold `Menu.CheckboxItem`s and `Menu.RadioItem`s for view options ("Show archived", "Sort by"). They stay open on click. Use them only for options of the view the menu belongs to, not for form values.
2100
+
2101
+ ### Menu or Select
2102
+
2103
+ - **Menu runs commands; Select keeps a value.** A Select's trigger shows the chosen value, it sits in a [Field](components/field.md) with a label, and its value is submitted with a form.
2104
+ - A "Sort by" control in a toolbar that changes a view is a Menu with a `Menu.RadioGroup`, or a [ToggleGroup](components/toggle-group.md) when the options fit in a row.
2105
+ - A "Visibility" field in a form is a Select.
2106
+
2107
+ ### Popover, Dialog or a page
2108
+
2109
+ - **Popover**: one to three controls about the thing next to it, changes that apply as they are made or are trivial to undo.
2110
+ - **Dialog**: more than three controls, a Save or Create button, or a decision that must be made before going on.
2111
+ - **A page**: more than about six fields, sections, or content people need to link to.
2112
+ - Don't open a Dialog from a Dialog. Replace the content, or close the first one. The one exception is an AlertDialog that confirms discarding the first one's input.
2113
+
2114
+ ### Tooltip or Popover
2115
+
2116
+ - **Tooltip**: a label for a control. It has no interactive content and never opens on touch screens, so it must never be the only place a fact appears.
2117
+ - **Popover**: anything people need to read, anything with a link or a button, or anything that must work on touch. For a hover card ("show the person on hover"), use a Popover with `openOnHover` on its trigger, and make sure a click shows the same thing.
2118
+
2119
+ ### Dialog or AlertDialog
2120
+
2121
+ - **AlertDialog** for "Are you sure?": deleting, discarding unsaved input, revoking a token. It has no X and ignores the backdrop, so people must answer.
2122
+ - **Dialog** for everything else. A Dialog with a form keeps itself open while it has unsaved input (see [Recipes](#form-in-a-dialog)).
2123
+ - Don't confirm actions that can be undone. Run them and show a Toast with Undo instead.
2124
+
2125
+ ### Toast or an inline message
2126
+
2127
+ - **Toast**: the result of an action people just took, when the screen doesn't already show it. "Note archived" (the note disappeared), "Link copied" (nothing else changed).
2128
+ - **Inline**: anything tied to a place on the screen. A field's error goes in `Field.Error` under the field. A page that fails to load says so in the page, with a Retry button.
2129
+ - Don't toast what the screen already shows. A saved setting whose Switch moved needs no toast.
2130
+ - A toast never asks a question. A decision is an AlertDialog.
2131
+
2132
+ ## Picking a control
2133
+
2134
+ ### Starting an action or going somewhere
2135
+
2136
+ | Need | Use | Not |
2137
+ | --- | --- | --- |
2138
+ | Run an action | [Button](components/button.md) | A Link with an `onClick` |
2139
+ | Go to another page | [Link](components/link.md) | A Button with `navigate()` in `onClick` |
2140
+ | Go to another page, styled as an action ("Get started") | An `<a>` (or router link) with `buttonClasses()` | `Button` with `render={<a />}` |
2141
+ | Several actions on one thing | A ghost Button that opens a [Menu](components/menu.md) | A row of icon buttons for rare actions |
2142
+ | Turn one option on or off in a toolbar | [Toggle](components/toggle.md) | A Button that changes its own label |
2143
+
2144
+ ### Choosing a value
2145
+
2146
+ Answer in order; the first yes decides.
2147
+
2148
+ 1. **Does it save the moment it changes (a settings page)?** On or off: [Switch](components/switch.md). One of a few: [Select](components/select.md) that saves in `onValueChange`.
2149
+ 2. **Is it on or off, saved with a form?** [Checkbox](components/checkbox.md).
2150
+ 3. **Is it one of 2 or 3 options, with room to show them or each needing a description?** [RadioGroup](components/radio-group.md).
2151
+ 4. **Is it one of up to about 10 options?** [Select](components/select.md).
2152
+ 5. **Is it one of a long list, or do people know what they're looking for and type it?** [Combobox](components/combobox.md).
2153
+ 6. **Is it several of a few options?** Checkboxes in a [Fieldset](components/field.md).
2154
+ 7. **Is it a view or filter on the current page, not a stored value?** One choice: [ToggleGroup](components/toggle-group.md) without `multiple`. Stacking filters: [Toggle](components/toggle.md)s, or a ToggleGroup with `multiple`.
2155
+ 8. **Is it text?** One line: [Input](components/input.md). A few plain lines: [Textarea](components/textarea.md). Formatted content: the editor (`@usememos/editor`) with [Prose](components/prose.md).
2156
+ 9. **Is it a number?** An Input with `type="number"` and `inputMode="numeric"`, or a Select of the sensible values. There is no Slider or Stepper.
2157
+
2158
+ ### Grouping and moving between sections
2159
+
2160
+ | Need | Use | Not |
2161
+ | --- | --- | --- |
2162
+ | Sections of one page (Account, Notifications) | [Tabs](components/tabs.md) | ToggleGroup |
2163
+ | A view or filter of the same content (All, Pinned, Archived) | [ToggleGroup](components/toggle-group.md) without `multiple` | Tabs |
2164
+ | Navigation between pages | [Link](components/link.md)s in the app's sidebar | Tabs |
2165
+ | Details or advanced settings people rarely need | [Collapsible](components/collapsible.md) | A Dialog |
2166
+ | Several sections, one open at a time | Collapsibles, controlled together | A third-party accordion |
2167
+ | Separating groups of content | `space-6` of whitespace, then a section title, then a [Separator](components/separator.md) if still unclear | A box, border or card |
2168
+ | Data with columns (tokens, users, webhooks) | [Table](components/table.md) | A list of boxes |
2169
+ | A list of content (notes, comments) | [Entries](patterns.md#entry) | A Table |
2170
+
2171
+ ## Picking feedback
2172
+
2173
+ | Situation | Use |
2174
+ | --- | --- |
2175
+ | A button's action is waiting on a server | The Button's `loading`, with `loadingLabel` ("Saving") |
2176
+ | A list or page is loading | [Skeleton](components/skeleton.md)s in the shape of the content, and `aria-busy` on the region |
2177
+ | Something short is running with no control to put it in | [Spinner](components/spinner.md) with a `label` |
2178
+ | An action finished and the screen doesn't show it | [Toast](components/toast.md), neutral or `success` |
2179
+ | An action failed | Toast with `type: "danger"` and `timeout: 0`; a field's own error in `Field.Error` instead |
2180
+ | A field's value is wrong | `invalid` on `Field.Root` and a `Field.Error` that says how to fix it |
2181
+ | A thing has a status (Synced, Expired) | [Badge](components/badge.md) with a tone and a word |
2182
+ | A list is empty | The [empty state](patterns.md#empty-state) pattern |
2183
+ | An action is about to destroy something | [AlertDialog](components/dialog.md), then a Toast after it runs |
2184
+
2185
+ Waits under about 300ms show nothing. Status colors (`success`, `warning`, `danger`) appear only with words or an icon, never as the only signal.
2186
+
2187
+ ## Recipes
2188
+
2189
+ ### Trigger through `render`
2190
+
2191
+ Every `Trigger` and `Close` renders the element given in `render`. Pass the Button there; don't put it inside.
2192
+
2193
+ ```tsx
2194
+ // Do: one <button>
2195
+ <Menu.Trigger render={<Button variant="ghost" icon={<Ellipsis />} aria-label="More actions" />} />
2196
+
2197
+ // Don't: a <button> inside a <button>
2198
+ <Menu.Trigger><Button variant="ghost" icon={<Ellipsis />} aria-label="More actions" /></Menu.Trigger>
2199
+ ```
2200
+
2201
+ ### An icon-only button with a tooltip and a menu
2202
+
2203
+ Stack the triggers with `render`. One `<button>` gets both behaviors.
2204
+
2205
+ ```tsx
2206
+ <Menu.Root>
2207
+ <Tooltip.Root>
2208
+ <Tooltip.Trigger
2209
+ render={<Menu.Trigger render={<Button variant="ghost" icon={<Ellipsis />} aria-label="More actions" />} />}
2210
+ />
2211
+ <Tooltip.Popup>More actions</Tooltip.Popup>
2212
+ </Tooltip.Root>
2213
+ <Menu.Popup align="end">…</Menu.Popup>
2214
+ </Menu.Root>
2215
+ ```
2216
+
2217
+ The same works for a Dialog or Popover trigger: `<Tooltip.Trigger render={<Popover.Trigger render={<Button … />} />} />`.
2218
+
2219
+ ### A menu item that opens a dialog
2220
+
2221
+ Keep the Dialog outside the Menu and control it with `open`. The Menu closes when the item is picked, so a Dialog inside `Menu.Popup` would unmount with it.
2222
+
2223
+ ```tsx
2224
+ const [confirming, setConfirming] = useState(false);
2225
+
2226
+ <Menu.Root>
2227
+ <Menu.Trigger render={<Button variant="ghost" icon={<Ellipsis />} aria-label="More actions" />} />
2228
+ <Menu.Popup align="end">
2229
+ <Menu.Item icon={<Pin />} onClick={pin}>Pin</Menu.Item>
2230
+ <Menu.Separator />
2231
+ <Menu.Item icon={<Trash2 />} danger onClick={() => setConfirming(true)}>Delete</Menu.Item>
2232
+ </Menu.Popup>
2233
+ </Menu.Root>
2234
+
2235
+ <AlertDialog.Root open={confirming} onOpenChange={setConfirming}>
2236
+ <AlertDialog.Popup>
2237
+ <AlertDialog.Title>Delete this note?</AlertDialog.Title>
2238
+ <AlertDialog.Description>It moves to the trash for 30 days.</AlertDialog.Description>
2239
+ <AlertDialog.Footer>
2240
+ <AlertDialog.Close render={<Button variant="ghost">Cancel</Button>} />
2241
+ <Button variant="danger" loading={deleting} loadingLabel="Deleting" onClick={remove}>Delete note</Button>
2242
+ </AlertDialog.Footer>
2243
+ </AlertDialog.Popup>
2244
+ </AlertDialog.Root>
2245
+ ```
2246
+
2247
+ `remove` closes the dialog with `setConfirming(false)` once the server answers, then shows a Toast. Use `AlertDialog.Close render={<Button variant="danger" />}` only when the action can't fail.
2248
+
2249
+ ### Form in a dialog
2250
+
2251
+ ```tsx
2252
+ <Dialog.Root
2253
+ open={open}
2254
+ onOpenChange={(next) => {
2255
+ if (!next && dirty) return; // keep unsaved input; Cancel resets and closes
2256
+ setOpen(next);
2257
+ }}
2258
+ >
2259
+ <Dialog.Trigger render={<Button>Create access token</Button>} />
2260
+ <Dialog.Popup>
2261
+ <Dialog.Title>Create access token</Dialog.Title>
2262
+ <Dialog.Description>Use it to call the API from scripts.</Dialog.Description>
2263
+ <form id="create-token" onSubmit={create}>
2264
+ <Field.Root invalid={!!error}>
2265
+ <Field.Label>Description</Field.Label>
2266
+ <Input value={description} onValueChange={setDescription} />
2267
+ <Field.Error match>{error}</Field.Error>
2268
+ </Field.Root>
2269
+ </form>
2270
+ <Dialog.Footer>
2271
+ <Button variant="ghost" onClick={cancel}>Cancel</Button>
2272
+ <Button variant="primary" type="submit" form="create-token" loading={saving} loadingLabel="Creating">Create</Button>
2273
+ </Dialog.Footer>
2274
+ </Dialog.Popup>
2275
+ </Dialog.Root>
2276
+ ```
2277
+
2278
+ - One Field per control. The submit button is `primary`, named with its verb, and shows `loading`.
2279
+ - On a server error, keep the dialog open and show the error on the field it belongs to. Close it only on success.
2280
+ - On phones the dialog becomes a sheet by itself. Don't build a separate mobile layout.
2281
+
2282
+ ### Settings that save at once
2283
+
2284
+ ```tsx
2285
+ <Fieldset.Root>
2286
+ <Fieldset.Legend>Notifications</Fieldset.Legend>
2287
+ <Field.Root>
2288
+ <Field.Label>
2289
+ <Switch checked={mentions} onCheckedChange={saveMentions} /> Email me when I'm mentioned
2290
+ </Field.Label>
2291
+ <Field.Description>Sent at most once an hour.</Field.Description>
2292
+ </Field.Root>
2293
+ </Fieldset.Root>
2294
+ ```
2295
+
2296
+ No Save button and no toast: the Switch shows the result. If saving fails, move the Switch back and show a danger Toast.
2297
+
2298
+ ### A toolbar
2299
+
2300
+ ```tsx
2301
+ <Tooltip.Provider>
2302
+ <ToggleGroup multiple size="sm" value={marks} onValueChange={setMarks} aria-label="Formatting">
2303
+ <Tooltip.Root>
2304
+ <Tooltip.Trigger render={<Toggle value="bold" icon={<Bold />} aria-label="Bold" />} />
2305
+ <Tooltip.Popup shortcut="⌘ B">Bold</Tooltip.Popup>
2306
+ </Tooltip.Root>
2307
+ …
2308
+ <Separator orientation="vertical" />
2309
+ …
2310
+ </ToggleGroup>
2311
+ </Tooltip.Provider>
2312
+ ```
2313
+
2314
+ One `Tooltip.Provider` around the toolbar (or the app) so moving along it opens the next tooltip at once.
2315
+
2316
+ ### Row and entry actions
2317
+
2318
+ - Put rare actions in a ghost "More actions" Menu trigger at the end of the row. Name it for the row: `aria-label={`Actions for ${token.name}`}`.
2319
+ - Show one or two frequent actions as xs or sm ghost Buttons beside it, each with a Tooltip.
2320
+ - On an entry the trigger appears on hover; on touch screens it is always visible (see [Entry](patterns.md#entry)).
2321
+
2322
+ ### Inside a shadow root or a host page
2323
+
2324
+ In an extension or an embed, pass the same `container` to every `Popup` and to `Toast.Viewport`, so popups mount inside the shadow root and pick up its styles. See [Scoping inside a host page](building.md#scoping-inside-a-host-page).
2325
+
2326
+ ```tsx
2327
+ <Menu.Popup container={shadowRoot}>…</Menu.Popup>
2328
+ <Toast.Viewport container={shadowRoot} />
2329
+ ```
2330
+
2331
+ ## Size
2332
+
2333
+ - **Set `size` once, on the outermost part that takes it.** `Menu.Root`, `Select.Root`, `Combobox.Root`, `Tabs.Root`, `Collapsible.Root`, `Table.Root`, `Field.Root`, `Fieldset.Root`, `RadioGroup` and `ToggleGroup` pass their size to every part and every Button, Toggle, Checkbox or Input inside them. Don't repeat it on the parts.
2334
+ - **Pick by place, not by importance.** `md` everywhere by default, including dialogs, forms, onboarding and marketing pages. `sm` for dense toolbars, table rows and filters inside panels. `xs` for secondary actions beside 13px text (entry footers, row actions). See [Control sizes](layout.md#control-sizes).
2335
+ - **Never make a control bigger to make it stronger.** Emphasis is the `primary` variant.
2336
+ - **Don't mix sizes in one row.** A Button beside an Input has the Input's size.
2337
+ - **Dialogs and Popovers start at md.** Their panels are md wherever they are declared, so a Dialog inside a `Table.Root size="sm"` still has md Buttons and fields. Set `size` inside the panel only for a part that should differ.
2338
+ - **Menus follow their surroundings.** A Menu, Select or Combobox without its own `size` takes the size of the Root around it, so a menu opened from a sm toolbar has sm rows.
2339
+ - Text entry, menus, tabs and tables have no `xs`; an inherited `xs` renders them at `sm`.
2340
+
2341
+ ## Emphasis and color
2342
+
2343
+ - **One `primary` Button per view.** A view is a page, a dialog or a popover. Everything else is `neutral`, or `ghost` in toolbars and rows.
2344
+ - **`danger` confirms; it never starts.** The first click on "Delete" is a Menu item with `danger` or a neutral Button; the `danger` Button lives in the AlertDialog that follows.
2345
+ - **Dialog footers** are a ghost Cancel, then the action, named with its verb ("Delete note", "Create"), never "OK" or "Yes".
2346
+ - **Tone is status only.** Badge and Toast tones say success, warning or danger. Don't use them to highlight, decorate or color-code categories.
2347
+ - **Links are the only blue.** Don't color text, icons or backgrounds with `accent`.
2348
+
2349
+ ## Accessibility checklist
2350
+
2351
+ Run through it for every screen.
2352
+
2353
+ - [ ] Every control has a name: a `Field.Label`, a visible label, or `aria-label`. Placeholders are never names.
2354
+ - [ ] Every icon-only Button and Toggle has an `aria-label` and a Tooltip with the same text.
2355
+ - [ ] Every group has a name: `aria-label` on a ToggleGroup and a `Tabs.List`; a `Fieldset.Legend`; a `Table.Caption` or `aria-label` on a Table; a `Popover.Title` or `aria-label`; a `Dialog.Title`.
2356
+ - [ ] Checkboxes, Switches and Radios sit inside their `Field.Label`, so the text is clickable.
2357
+ - [ ] Repeated triggers are named for their row ("Actions for Backup token"), not just "More actions".
2358
+ - [ ] No fact appears only in a Tooltip, only in color, or only in a placeholder.
2359
+ - [ ] Loading regions have `aria-busy`; loading Buttons have a `loadingLabel`.
2360
+ - [ ] Errors are in `Field.Error` or a danger Toast with `timeout: 0`, worded as how to fix them.
2361
+ - [ ] No `outline: none`, custom focus ring or `tabIndex` on a component. Focus, keyboard and ARIA come from Base UI; don't add key handlers that fight them.
2362
+ - [ ] Nothing pressable is built from a `<div>`. If the package has no component for it, build it on Base UI ([Building your own component](custom-components.md)).
2363
+
2364
+ ## Common mistakes
2365
+
2366
+ | Don't | Do |
2367
+ | --- | --- |
2368
+ | An Input or checkbox list inside a Menu | A Popover |
2369
+ | A Popover holding only a list of actions | A Menu |
2370
+ | A Menu to choose a form value | A Select in a Field |
2371
+ | A Dialog for one or two quick controls | A Popover |
2372
+ | A Dialog for "Are you sure?" | An AlertDialog |
2373
+ | A confirmation for an action that can be undone | Run it, then a Toast with Undo |
2374
+ | A Tooltip with a link, a button or a paragraph | A Popover |
2375
+ | A Tooltip on text that isn't a control | Visible text, or a Popover |
2376
+ | A Toast for a field's error | `Field.Error` under the field |
2377
+ | A success Toast after every Switch | Nothing; the Switch shows it |
2378
+ | A Button that navigates | A Link, or an anchor with `buttonClasses()` |
2379
+ | `<Button render={<a href="…" />}>` | `<a className={buttonClasses()} href="…">` |
2380
+ | A Button nested inside a `Trigger` | `render={<Button … />}` on the Trigger |
2381
+ | A clickable Badge | A Toggle (filters) or a Link with `badgeClasses()` (tag pages) |
2382
+ | Tabs to filter a list | A ToggleGroup without `multiple` |
2383
+ | A ToggleGroup to switch page sections | Tabs |
2384
+ | A Switch in a form with a Save button | A Checkbox |
2385
+ | A Checkbox that saves at once | A Switch |
2386
+ | A Select with 30 options | A Combobox |
2387
+ | A Select with two options and room to spare | A RadioGroup |
2388
+ | A boxed card around each item | Whitespace, a section title, or a Separator |
2389
+ | A Spinner where a list will appear | Skeletons in the shape of the list |
2390
+ | `size="md"` or `"lg"` on a Button to emphasize it | `variant="primary"` at the row's size |
2391
+ | `size` on every part of a Menu or Select | `size` on its Root |
2392
+ | Two `primary` Buttons in one view | One `primary`, the rest `neutral` |
2393
+ | `danger` Button as the first click | A `danger` Menu item, then an AlertDialog |
2394
+ | A placeholder as the only label | `Field.Label`, or `aria-label` |
2395
+ | Color as the only signal of status | A Badge or Toast with a word and an icon |
2396
+ | `className` that changes a component's color, height or radius | Use the component as it is, or change the package |
2397
+ | Copying a component's CSS to make a lookalike | Base UI with a class function or public classes |
2398
+ | A `<div onClick>` as a control | A component, or Base UI's part with a class function |
2399
+
2400
+ ## Migrating from another UI kit
2401
+
2402
+ Names and parts from other libraries and where they go.
2403
+
2404
+ | Other kits | Memos UI |
2405
+ | --- | --- |
2406
+ | Modal, Dialog | [Dialog](components/dialog.md); `sheet` covers phones |
2407
+ | ConfirmDialog, AlertDialog, `window.confirm` | [AlertDialog](components/dialog.md) |
2408
+ | Drawer, Sheet | Dialog (a bottom sheet below 640px). There is no side drawer; a narrow sidebar below `breakpoint-md` is the [page pattern](patterns.md#page) |
2409
+ | DropdownMenu, ActionMenu | [Menu](components/menu.md) |
2410
+ | ContextMenu | Not built. Put the same actions in a Menu on a visible trigger |
2411
+ | HoverCard | [Popover](components/popover.md) with `openOnHover` on the trigger |
2412
+ | Tooltip with a `title` or `content` prop | [Tooltip](components/tooltip.md) parts: Root, Trigger, Popup |
2413
+ | Snackbar, Toaster, sonner's `toast()` | [Toast](components/toast.md) and `Toast.useToastManager().add()` |
2414
+ | Toast `variant="destructive"` | `type: "danger"` |
2415
+ | Card, Paper, Panel | No component: spacing, a section title and [Separator](components/separator.md) |
2416
+ | Divider | [Separator](components/separator.md) |
2417
+ | Chip, Tag | [Badge](components/badge.md) to show, [Toggle](components/toggle.md) to filter |
2418
+ | SegmentedControl, RadioButtons in a row | [ToggleGroup](components/toggle-group.md) without `multiple` |
2419
+ | Accordion | [Collapsible](components/collapsible.md)s |
2420
+ | Slider, NumberInput, Stepper | Input `type="number"` or a Select |
2421
+ | Autocomplete, SearchSelect | [Combobox](components/combobox.md) |
2422
+ | NativeSelect, `<select>` | [Select](components/select.md) |
2423
+ | Label, FormLabel | `Field.Label` |
2424
+ | FormMessage, HelperText | `Field.Error`, `Field.Description` |
2425
+ | FormItem, FormControl | `Field.Root` |
2426
+ | Loader, CircularProgress | [Spinner](components/spinner.md), or a control's `loading` |
2427
+ | Progress bar | Not built. Use Skeletons for loading, or text ("3 of 10") |
2428
+ | Typography, Text, Heading | The type classes (`mu-body`, `mu-caption`, `mu-heading`) from [Typography](typography.md) |
2429
+ | Markdown or rich-text body | [Prose](components/prose.md) |
2430
+ | `variant="secondary"`, `"outline"` on a button | `neutral`; `ghost` in toolbars |
2431
+ | `variant="destructive"` on a button | `danger`, only inside a confirmation |
2432
+ | `size="lg"` | `md`; emphasis comes from `primary` |
2433
+ | `options={[…]}`, `items={[…]}` data props | Parts: `Select.Item`, `Menu.Item`, `Tabs.Tab`. Select and Combobox still take `items` on the Root for labels and filtering |
2434
+ | `asChild` | `render={<… />}` |
2435
+
2061
2436
  <!-- docs/patterns.md -->
2062
2437
 
2063
2438
  # Patterns
@@ -2173,7 +2548,7 @@ Inside another page (the web clipper, an embed), mount the UI under a `.mu-root`
2173
2548
 
2174
2549
  ## Choosing a theme
2175
2550
 
2176
- Set `data-theme="light" | "dark" | "contrast"` on the root element or on any `.mu-root`. Without the attribute the tokens are Light. The app, not the package, reads `prefers-color-scheme` and the user's saved choice. See [Color](color.md#themes). An app can add its own themes on top of these three; see [App themes](color.md#app-themes).
2551
+ Set `data-theme="light" | "dark"` on the root element or on any `.mu-root`. Without the attribute the tokens are Light. The app, not the package, reads `prefers-color-scheme` and the user's saved choice. See [Color](color.md#themes). An app can add its own themes on top of these two; see [App themes](color.md#app-themes).
2177
2552
 
2178
2553
  An app changes only the color, shadow and font tokens. Every other token and every `mu-*` class rule is internal. See [What an app can change](color.md#what-an-app-can-change).
2179
2554
 
@@ -2266,7 +2641,7 @@ toast.add({ title: "Note archived", type: "success" });
2266
2641
  1. A reason: a screen in a product needs it, and no existing component or pattern covers it.
2267
2642
  2. A generic name and API that would make sense in any of our products.
2268
2643
  3. Tokens only: no raw colors, sizes or shadows.
2269
- 4. Both sizes, all [states](states.md), all three themes, and reduced motion.
2644
+ 4. Both sizes, all [states](states.md), both themes, and reduced motion.
2270
2645
  5. Keyboard and screen reader behavior from Base UI.
2271
2646
  6. A page in `docs/components/` and an entry in the [inventory](components/README.md).
2272
2647
 
@@ -2284,7 +2659,7 @@ An app always has parts the package doesn't ship and shouldn't: product parts (a
2284
2659
  2. **Behavior from Base UI.** Build anything with focus, keyboard, an open state or a popup on [`@base-ui/react`](https://base-ui.com), as the package does. It is a peer dependency of the package at one exact version, so the app's components and the package's share one copy. Upgrade it only with the package.
2285
2660
  3. **Looks from a class function** when the part should look like a component: an anchor that looks like a Button, an editor that looks like a Textarea, a suggestion list that looks like a Menu. See [Class functions](#class-functions).
2286
2661
  4. **Otherwise, from the public classes and tokens.** Size the part with a size row class and read the [row variables](#row-variables); give it depth with a [depth class](depth.md); set text with a [type class](typography.md); color it with `var(--mu-<token>)` or the [Tailwind utilities](#tailwind-css).
2287
- 5. **Check it like a component.** It works in Light, Dark and High contrast and under reduced motion; text keeps 4.5:1 contrast; focus shows on `:focus-visible` (`mu-focus`); touch targets reach 44px (`mu-hit`); icon-only controls have an `aria-label` and a [Tooltip](components/tooltip.md).
2662
+ 5. **Check it like a component.** It works in Light and Dark and under reduced motion; text keeps 4.5:1 contrast; focus shows on `:focus-visible` (`mu-focus`); touch targets reach 44px (`mu-hit`); icon-only controls have an `aria-label` and a [Tooltip](components/tooltip.md).
2288
2663
 
2289
2664
  ## Class functions
2290
2665
 
@@ -2301,7 +2676,7 @@ A class function returns the classes that make any element look like a component
2301
2676
 
2302
2677
  State is set with attributes, never with extra classes:
2303
2678
 
2304
- - A field shows the focus ring when it or anything inside it has focus. `aria-invalid="true"` shows the error edge, and `aria-disabled="true"` dims it.
2679
+ - A field darkens its edge to `focus-edge` when it or anything inside it has focus. `aria-invalid="true"` shows the error edge, and `aria-disabled="true"` dims it.
2305
2680
  - A menu row is highlighted while it has `data-highlighted`, and dimmed with `data-disabled`. Base UI sets both; a list the app drives itself sets them on the active row.
2306
2681
  - A popup fades in with `data-starting-style` and out with `data-ending-style`, which Base UI's popups set.
2307
2682
 
@@ -2341,7 +2716,7 @@ Apply these classes to an app's own elements. Don't override their rules: the pr
2341
2716
  | `mu-popup` | `surface`, `shadow-pop` and `radius-xl` | A part that floats |
2342
2717
  | `mu-popup-motion` | The popup fade and rise, none under reduced motion | A popup Base UI opens |
2343
2718
  | `mu-positioner` | The popup layer | A popup's positioner |
2344
- | `mu-focus` | The focus ring on `:focus-visible` | Anything focusable |
2719
+ | `mu-focus` | The ink focus ring on `:focus-visible`, 1px outside the edge | Anything focusable |
2345
2720
  | `mu-hit` | An invisible 44px touch target on `pointer: coarse` | Anything pressable smaller than 44px |
2346
2721
  | `mu-icon` | Icon size and stroke | A Lucide icon outside a control |
2347
2722
  | `mu-visually-hidden` | Hidden on screen, read by screen readers | Text for screen readers only |
@@ -2393,7 +2768,7 @@ An app on Tailwind CSS v4 loads `tailwind.css` after the package's other stylesh
2393
2768
  @import "@usememos/ui/tailwind.css";
2394
2769
  ```
2395
2770
 
2396
- It maps the 26 color tokens, five shadow tokens, seven radius tokens and three font tokens to utilities with an `mu-` prefix, so they never clash with an app's own colors:
2771
+ It maps the 27 color tokens, five shadow tokens, seven radius tokens and three font tokens to utilities with an `mu-` prefix, so they never clash with an app's own colors:
2397
2772
 
2398
2773
  | Token | Utility |
2399
2774
  | --- | --- |
package/llms.txt CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  > Memos UI is one calm, dense and tactile system for every product we build: memos (the app), the website, the web clipper and whatever comes next. It reads like ink on paper: pure grays, black ink for the one thing that matters, and no brand color competing with what people write. Controls have a little physical depth, so you can tell at a glance what holds a value and what you can press.
4
4
 
5
- React components on Base UI, CSS tokens and foundation styles. Load `@usememos/ui/tokens.css`, then `@usememos/ui/styles.css`; set `data-theme` to `light`, `dark` or `contrast` on the root element. Components are compound parts named after Base UI's anatomy (`Menu.Root`, `Menu.Trigger`, `Menu.Popup`, `Menu.Item`); icons are Lucide elements. Every docs page is in llms-full.txt next to this file.
5
+ React components on Base UI, CSS tokens and foundation styles. Load `@usememos/ui/tokens.css`, then `@usememos/ui/styles.css`; set `data-theme` to `light` or `dark` on the root element. Components are compound parts named after Base UI's anatomy (`Menu.Root`, `Menu.Trigger`, `Menu.Popup`, `Menu.Item`); icons are Lucide elements. Every docs page is in llms-full.txt next to this file.
6
6
 
7
7
  ## Docs
8
8
 
9
9
  - [Principles and voice](https://github.com/usememos/ui/blob/main/docs/principles.md): The taste in six rules, and how interface text is written
10
- - [Color](https://github.com/usememos/ui/blob/main/docs/color.md): Color roles, every color token in Light, Dark and High contrast, and how themes are chosen
10
+ - [Color](https://github.com/usememos/ui/blob/main/docs/color.md): Color roles, every color token in Light and Dark, and how themes are chosen
11
11
  - [Depth](https://github.com/usememos/ui/blob/main/docs/depth.md): The tactile model: recessed, key, raised, popup and flat; shadow tokens
12
12
  - [Typography](https://github.com/usememos/ui/blob/main/docs/typography.md): The system font, the type scale and text rules
13
13
  - [Size, spacing and layout](https://github.com/usememos/ui/blob/main/docs/layout.md): Control sizes, the 4px scale, radius, layout widths, breakpoints and layers
@@ -15,6 +15,7 @@ React components on Base UI, CSS tokens and foundation styles. Load `@usememos/u
15
15
  - [States](https://github.com/usememos/ui/blob/main/docs/states.md): Hover, pressed, loading, disabled, invalid and focus
16
16
  - [Icons](https://github.com/usememos/ui/blob/main/docs/icons.md): Lucide, sizes, fixed stroke widths and accessibility
17
17
  - [Components](https://github.com/usememos/ui/blob/main/docs/components/README.md): The 28 components, what was left out, and one page per component
18
+ - [Using the components](https://github.com/usememos/ui/blob/main/docs/usage.md): Which component to pick (overlays, controls, feedback), recipes for combining them, size, emphasis, an accessibility checklist, common mistakes and a map from other UI kits
18
19
  - [Patterns](https://github.com/usememos/ui/blob/main/docs/patterns.md): Page, form, entry, confirmation, loading, empty state and mobile
19
20
  - [Building on it](https://github.com/usememos/ui/blob/main/docs/building.md): Base UI, loading the CSS, scoping inside a host page, theme selection and API conventions
20
21
  - [Building your own component](https://github.com/usememos/ui/blob/main/docs/custom-components.md): How an app builds a part the package doesn't ship: Base UI, class functions, public classes, row variables and Tailwind CSS
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@usememos/ui",
3
- "version": "26.10.5",
3
+ "version": "26.11.1",
4
4
  "description": "The Memos UI design system: tokens, foundation styles and React components for usememos products.",
5
5
  "keywords": [
6
6
  "react",