@exsto/ds 0.0.1-rc.22 → 0.0.1-rc.23

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
@@ -190,6 +190,10 @@ import { cn, POPUP_FRAME_CLASS, POPUP_LIST_HEIGHT_CLASS, POPUP_LIST_WIDTH_CLASS,
190
190
  - `POPUP_GROUP_LABEL_CLASS` is a group's heading. `ComboboxGroup`, `ComboboxLabel`, `ComboboxCollection` and `ComboboxSeparator` give a Combobox its groups, drawn the same way Select draws its own.
191
191
  - `POPUP_FRAME_CLASS` is the frame (a 10px radius and a 1px ring, no border). `POPUP_LIST_WIDTH_CLASS` is its width: at least the control and 8rem, as wide as the longest row, 28rem at most. `POPUP_LIST_HEIGHT_CLASS` caps the scrolling part: eight rows, or as many whole rows as the room allows, so a list never ends on half a row. Put it on a `ScrollArea` inside a popup that is a flex column with `max-h-(--available-height)`; the class carries the 4px of air above and below the rows as a margin, so the list inside takes `px-1` and no vertical padding (padding there scrolls with the rows and leaves a strip of the next row at the foot). `POPUP_LAYER_CLASS` (`z-60`) goes on the popup's positioner, so it is drawn above the Sheet, Dialog or Drawer (`z-50`) it is opened from.
192
192
 
193
+ ## Changes in 0.0.1-rc.23
194
+
195
+ - **A TabsList keeps the chosen tab clear of its edge fade when the row changes size after load** (a font swapping in, data arriving). The scroll that reveals the chosen tab now repeats on a change of size until the reader scrolls, presses a key or touches; before, a chosen last tab could end 2px inside the edge with the fade covering most of it.
196
+
193
197
  ## Changes in 0.0.1-rc.22
194
198
 
195
199
  - **Muted text on highlighted rows meets 4.5:1 (new token); apps import components.css and drop local workarounds.** The new `--muted-foreground-highlighted` (`oklch(0.52 0 0)` light; dark unchanged at `0.708`) is what `--muted-foreground` becomes inside a `[data-highlighted]` row or a selected Command item, by one rule in `components.css` (it ships in `@exsto/ds/styles.css`). A detail, a shortcut or an icon in a Select, Combobox, Command or menu row was 4.34:1 on the light row; any local `text-foreground/70` for it can go.
@@ -1 +1 @@
1
- c03808127789c94fe2d8be09626e7ef3bbc23d071e6410ea8f1a2aa4afefe320
1
+ 237f9a6de1d109e6a11bc94cd65028316f93bb0be9dac50c29fd7b50604c39e5
@@ -56,7 +56,21 @@ var TabsList = ({ className, variant = "default", children, ref, ...props }) =>
56
56
  if (!horizontal || !viewport || !list) return;
57
57
  const revealSelected = () => reveal(viewport, list.querySelector("[aria-selected=\"true\"]"));
58
58
  const revealFocused = (event) => reveal(viewport, event.target.closest("[role=\"tab\"]"));
59
+ let reader = false;
60
+ const take = () => {
61
+ reader = true;
62
+ };
63
+ const sizes = new ResizeObserver(() => reader || revealSelected());
64
+ const events = [
65
+ "wheel",
66
+ "pointerdown",
67
+ "keydown",
68
+ "touchstart"
69
+ ];
59
70
  revealSelected();
71
+ sizes.observe(list);
72
+ sizes.observe(viewport);
73
+ for (const name of events) viewport.addEventListener(name, take, { passive: true });
60
74
  const observer = new MutationObserver(revealSelected);
61
75
  observer.observe(list, {
62
76
  subtree: true,
@@ -66,6 +80,8 @@ var TabsList = ({ className, variant = "default", children, ref, ...props }) =>
66
80
  list.addEventListener("focusin", revealFocused);
67
81
  return () => {
68
82
  observer.disconnect();
83
+ sizes.disconnect();
84
+ for (const name of events) viewport.removeEventListener(name, take);
69
85
  list.removeEventListener("focusin", revealFocused);
70
86
  };
71
87
  }, [horizontal]);
@@ -1 +1 @@
1
- {"version":3,"file":"tabs.js","names":[],"sources":["../../../../../../../ui/src/components/ui/tabs/tabs.tsx"],"sourcesContent":["import { Tabs as BaseTabs } from '@base-ui/react/tabs';\nimport { ScrollArea } from '@edyn/ui/components/ui/scroll-area';\nimport { useHoldsFocusable } from '@edyn/ui/hooks/use-holds-focusable';\nimport { useMergedRefs } from '@edyn/ui/hooks/use-merged-refs';\nimport { cn } from '@edyn/ui/lib/utils';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type * as React from 'react';\nimport { createContext, useContext, useEffect, useRef } from 'react';\n\nexport interface ITabsProps extends Omit<BaseTabs.Root.Props, 'value' | 'defaultValue' | 'onValueChange' | 'className' | 'orientation' | 'children'> {\n /** Controlled selected tab. Provide with `onValueChange`. */\n value?: string;\n /** Uncontrolled initial tab. Use this when the component should own its state. */\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n className?: string;\n orientation?: 'horizontal' | 'vertical';\n children: React.ReactNode;\n}\n\nconst OrientationContext = createContext<'horizontal' | 'vertical'>('horizontal');\n\nexport const Tabs = ({ value, defaultValue, onValueChange, className, orientation = 'horizontal', children, ...props }: ITabsProps) => (\n <BaseTabs.Root\n data-slot=\"tabs\"\n {...props}\n data-orientation={orientation}\n value={value}\n defaultValue={defaultValue}\n orientation={orientation}\n onValueChange={(next) => {\n onValueChange?.(String(next));\n }}\n className={cn('group/tabs flex w-full gap-2 data-[orientation=horizontal]:flex-col', className)}\n >\n <OrientationContext value={orientation}>{children}</OrientationContext>\n </BaseTabs.Root>\n);\n\nexport const tabsListVariants = cva(\n 'group/tabs-list flex w-fit items-center group-data-[orientation=horizontal]/tabs:min-w-max justify-center rounded-lg p-[3px] text-muted-foreground group-data-[orientation=horizontal]/tabs:h-8 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none',\n {\n variants: {\n variant: {\n default: 'bg-muted',\n line: 'gap-1 bg-transparent',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n);\n\nexport interface ITabsListProps extends VariantProps<typeof tabsListVariants>, Omit<BaseTabs.List.Props, 'className' | 'children'> {\n className?: string;\n children: React.ReactNode;\n}\n\n/** Room kept between a tab and the edge it is scrolled to: the 24px edge fade and a little more. */\nconst REVEAL_MARGIN = 32;\n\n/** Scrolls a list sideways, inside its viewport only, until a tab stands clear of both edge fades. */\nconst reveal = (viewport: HTMLElement, tab: Element | null) => {\n if (!tab) {\n return;\n }\n const edge = viewport.getBoundingClientRect();\n const box = tab.getBoundingClientRect();\n if (box.left < edge.left + REVEAL_MARGIN) {\n viewport.scrollBy({ left: box.left - edge.left - REVEAL_MARGIN });\n } else if (box.right > edge.right - REVEAL_MARGIN) {\n viewport.scrollBy({ left: box.right - edge.right + REVEAL_MARGIN });\n }\n};\n\n/**\n * A row of tabs wider than its box scrolls sideways inside it, with a fade at each edge that hides tabs, and the selected tab\n * (and the one holding focus) is scrolled into view. A vertical list is not wrapped.\n */\nexport const TabsList = ({ className, variant = 'default', children, ref, ...props }: ITabsListProps) => {\n const horizontal = useContext(OrientationContext) === 'horizontal';\n const refViewport = useRef<HTMLDivElement | null>(null);\n const refList = useRef<HTMLDivElement | null>(null);\n const refs = useMergedRefs(refList, ref);\n\n useEffect(() => {\n const viewport = refViewport.current;\n const list = refList.current;\n if (!horizontal || !viewport || !list) {\n return;\n }\n const revealSelected = () => reveal(viewport, list.querySelector('[aria-selected=\"true\"]'));\n const revealFocused = (event: FocusEvent) => reveal(viewport, (event.target as Element).closest('[role=\"tab\"]'));\n revealSelected();\n const observer = new MutationObserver(revealSelected);\n observer.observe(list, { subtree: true, attributes: true, attributeFilter: ['aria-selected'] });\n list.addEventListener('focusin', revealFocused);\n return () => {\n observer.disconnect();\n list.removeEventListener('focusin', revealFocused);\n };\n }, [horizontal]);\n\n const list = (\n <BaseTabs.List data-slot=\"tabs-list\" {...props} data-variant={variant} ref={refs} className={cn(tabsListVariants({ variant }), className)}>\n {children}\n </BaseTabs.List>\n );\n return horizontal ? (\n <ScrollArea orientation=\"horizontal\" fade viewportRef={refViewport}>\n {list}\n </ScrollArea>\n ) : (\n list\n );\n};\n\nexport interface ITabsTriggerProps extends Omit<BaseTabs.Tab.Props, 'value' | 'disabled' | 'className' | 'children'> {\n value: string;\n disabled?: boolean;\n className?: string;\n children: React.ReactNode;\n}\n\nexport const TabsTrigger = ({ value, disabled, className, children, ...props }: ITabsTriggerProps) => (\n <BaseTabs.Tab\n {...props}\n value={value}\n disabled={disabled}\n className={cn(\n 'relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start hover:text-foreground focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\"size-\"])]:size-4',\n 'group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent',\n 'data-active:bg-background data-active:text-foreground dark:data-active:border-control dark:data-active:bg-input/30 dark:data-active:text-foreground',\n 'after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100',\n className,\n )}\n >\n {children}\n </BaseTabs.Tab>\n);\n\nexport interface ITabsContentProps extends Omit<BaseTabs.Panel.Props, 'value' | 'keepMounted' | 'className' | 'children'> {\n value: string;\n keepMounted?: boolean;\n className?: string;\n children: React.ReactNode;\n}\n\n/** Base UI makes every open panel a tab stop; undefined takes that away. */\nconst NO_TAB_STOP = { tabIndex: undefined } as const;\n\n/** A panel takes Tab only when nothing inside it can, and then shows a 1px line inside its edge (focus.css). */\nexport const TabsContent = ({ value, keepMounted = false, className, children, ref, ...props }: ITabsContentProps) => {\n const refPanel = useRef<HTMLDivElement | null>(null);\n const refs = useMergedRefs(refPanel, ref);\n const holdsFocusable = useHoldsFocusable(refPanel);\n return (\n <BaseTabs.Panel\n data-slot=\"tabs-content\"\n {...(holdsFocusable ? NO_TAB_STOP : null)}\n {...props}\n ref={refs}\n value={value}\n keepMounted={keepMounted}\n className={cn('flex-1 text-sm outline-none', className)}\n >\n {children}\n </BaseTabs.Panel>\n );\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"tabs.js","names":[],"sources":["../../../../../../../ui/src/components/ui/tabs/tabs.tsx"],"sourcesContent":["import { Tabs as BaseTabs } from '@base-ui/react/tabs';\nimport { ScrollArea } from '@edyn/ui/components/ui/scroll-area';\nimport { useHoldsFocusable } from '@edyn/ui/hooks/use-holds-focusable';\nimport { useMergedRefs } from '@edyn/ui/hooks/use-merged-refs';\nimport { cn } from '@edyn/ui/lib/utils';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport type * as React from 'react';\nimport { createContext, useContext, useEffect, useRef } from 'react';\n\nexport interface ITabsProps extends Omit<BaseTabs.Root.Props, 'value' | 'defaultValue' | 'onValueChange' | 'className' | 'orientation' | 'children'> {\n /** Controlled selected tab. Provide with `onValueChange`. */\n value?: string;\n /** Uncontrolled initial tab. Use this when the component should own its state. */\n defaultValue?: string;\n onValueChange?: (value: string) => void;\n className?: string;\n orientation?: 'horizontal' | 'vertical';\n children: React.ReactNode;\n}\n\nconst OrientationContext = createContext<'horizontal' | 'vertical'>('horizontal');\n\nexport const Tabs = ({ value, defaultValue, onValueChange, className, orientation = 'horizontal', children, ...props }: ITabsProps) => (\n <BaseTabs.Root\n data-slot=\"tabs\"\n {...props}\n data-orientation={orientation}\n value={value}\n defaultValue={defaultValue}\n orientation={orientation}\n onValueChange={(next) => {\n onValueChange?.(String(next));\n }}\n className={cn('group/tabs flex w-full gap-2 data-[orientation=horizontal]:flex-col', className)}\n >\n <OrientationContext value={orientation}>{children}</OrientationContext>\n </BaseTabs.Root>\n);\n\nexport const tabsListVariants = cva(\n 'group/tabs-list flex w-fit items-center group-data-[orientation=horizontal]/tabs:min-w-max justify-center rounded-lg p-[3px] text-muted-foreground group-data-[orientation=horizontal]/tabs:h-8 group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col data-[variant=line]:rounded-none',\n {\n variants: {\n variant: {\n default: 'bg-muted',\n line: 'gap-1 bg-transparent',\n },\n },\n defaultVariants: {\n variant: 'default',\n },\n },\n);\n\nexport interface ITabsListProps extends VariantProps<typeof tabsListVariants>, Omit<BaseTabs.List.Props, 'className' | 'children'> {\n className?: string;\n children: React.ReactNode;\n}\n\n/** Room kept between a tab and the edge it is scrolled to: the 24px edge fade and a little more. */\nconst REVEAL_MARGIN = 32;\n\n/** Scrolls a list sideways, inside its viewport only, until a tab stands clear of both edge fades. */\nconst reveal = (viewport: HTMLElement, tab: Element | null) => {\n if (!tab) {\n return;\n }\n const edge = viewport.getBoundingClientRect();\n const box = tab.getBoundingClientRect();\n if (box.left < edge.left + REVEAL_MARGIN) {\n viewport.scrollBy({ left: box.left - edge.left - REVEAL_MARGIN });\n } else if (box.right > edge.right - REVEAL_MARGIN) {\n viewport.scrollBy({ left: box.right - edge.right + REVEAL_MARGIN });\n }\n};\n\n/**\n * A row of tabs wider than its box scrolls sideways inside it, with a fade at each edge that hides tabs, and the selected tab\n * (and the one holding focus) is scrolled into view. A vertical list is not wrapped.\n */\nexport const TabsList = ({ className, variant = 'default', children, ref, ...props }: ITabsListProps) => {\n const horizontal = useContext(OrientationContext) === 'horizontal';\n const refViewport = useRef<HTMLDivElement | null>(null);\n const refList = useRef<HTMLDivElement | null>(null);\n const refs = useMergedRefs(refList, ref);\n\n useEffect(() => {\n const viewport = refViewport.current;\n const list = refList.current;\n if (!horizontal || !viewport || !list) {\n return;\n }\n const revealSelected = () => reveal(viewport, list.querySelector('[aria-selected=\"true\"]'));\n const revealFocused = (event: FocusEvent) => reveal(viewport, (event.target as Element).closest('[role=\"tab\"]'));\n // Until the reader scrolls, a change of size (a font, a data load) keeps the chosen tab clear of the fades.\n let reader = false;\n const take = () => {\n reader = true;\n };\n const sizes = new ResizeObserver(() => reader || revealSelected());\n const events = ['wheel', 'pointerdown', 'keydown', 'touchstart'] as const;\n revealSelected();\n sizes.observe(list);\n sizes.observe(viewport);\n for (const name of events) {\n viewport.addEventListener(name, take, { passive: true });\n }\n const observer = new MutationObserver(revealSelected);\n observer.observe(list, { subtree: true, attributes: true, attributeFilter: ['aria-selected'] });\n list.addEventListener('focusin', revealFocused);\n return () => {\n observer.disconnect();\n sizes.disconnect();\n for (const name of events) {\n viewport.removeEventListener(name, take);\n }\n list.removeEventListener('focusin', revealFocused);\n };\n }, [horizontal]);\n\n const list = (\n <BaseTabs.List data-slot=\"tabs-list\" {...props} data-variant={variant} ref={refs} className={cn(tabsListVariants({ variant }), className)}>\n {children}\n </BaseTabs.List>\n );\n return horizontal ? (\n <ScrollArea orientation=\"horizontal\" fade viewportRef={refViewport}>\n {list}\n </ScrollArea>\n ) : (\n list\n );\n};\n\nexport interface ITabsTriggerProps extends Omit<BaseTabs.Tab.Props, 'value' | 'disabled' | 'className' | 'children'> {\n value: string;\n disabled?: boolean;\n className?: string;\n children: React.ReactNode;\n}\n\nexport const TabsTrigger = ({ value, disabled, className, children, ...props }: ITabsTriggerProps) => (\n <BaseTabs.Tab\n {...props}\n value={value}\n disabled={disabled}\n className={cn(\n 'relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start hover:text-foreground focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*=\"size-\"])]:size-4',\n 'group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent',\n 'data-active:bg-background data-active:text-foreground dark:data-active:border-control dark:data-active:bg-input/30 dark:data-active:text-foreground',\n 'after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100',\n className,\n )}\n >\n {children}\n </BaseTabs.Tab>\n);\n\nexport interface ITabsContentProps extends Omit<BaseTabs.Panel.Props, 'value' | 'keepMounted' | 'className' | 'children'> {\n value: string;\n keepMounted?: boolean;\n className?: string;\n children: React.ReactNode;\n}\n\n/** Base UI makes every open panel a tab stop; undefined takes that away. */\nconst NO_TAB_STOP = { tabIndex: undefined } as const;\n\n/** A panel takes Tab only when nothing inside it can, and then shows a 1px line inside its edge (focus.css). */\nexport const TabsContent = ({ value, keepMounted = false, className, children, ref, ...props }: ITabsContentProps) => {\n const refPanel = useRef<HTMLDivElement | null>(null);\n const refs = useMergedRefs(refPanel, ref);\n const holdsFocusable = useHoldsFocusable(refPanel);\n return (\n <BaseTabs.Panel\n data-slot=\"tabs-content\"\n {...(holdsFocusable ? NO_TAB_STOP : null)}\n {...props}\n ref={refs}\n value={value}\n keepMounted={keepMounted}\n className={cn('flex-1 text-sm outline-none', className)}\n >\n {children}\n </BaseTabs.Panel>\n );\n};\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exsto/ds",
3
- "version": "0.0.1-rc.22",
3
+ "version": "0.0.1-rc.23",
4
4
  "description": "The eDynamix design system: React components and design tokens.",
5
5
  "license": "Apache-2.0",
6
6
  "keywords": [