mirror of
https://github.com/langgenius/dify.git
synced 2026-09-08 02:43:49 +08:00
chore(dify-ui): enforce strict ESLint rules (#38793)
This commit is contained in:
parent
2a2193dabb
commit
4efab8d7a3
4
.github/workflows/style.yml
vendored
4
.github/workflows/style.yml
vendored
@ -176,9 +176,9 @@ jobs:
|
|||||||
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
uses: actions/cache/restore@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
|
||||||
with:
|
with:
|
||||||
path: .eslintcache
|
path: .eslintcache
|
||||||
key: ${{ runner.os }}-eslint-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'web/eslint.config.mjs', 'web/eslint.constants.mjs', 'web/plugins/eslint/**') }}-${{ github.sha }}
|
key: ${{ runner.os }}-eslint-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'packages/dify-ui/eslint.config.mjs', 'web/eslint.config.mjs', 'web/eslint.constants.mjs', 'web/plugins/eslint/**') }}-${{ github.sha }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-eslint-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'web/eslint.config.mjs', 'web/eslint.constants.mjs', 'web/plugins/eslint/**') }}-
|
${{ runner.os }}-eslint-${{ hashFiles('pnpm-lock.yaml', 'eslint.config.mjs', 'packages/dify-ui/eslint.config.mjs', 'web/eslint.config.mjs', 'web/eslint.constants.mjs', 'web/plugins/eslint/**') }}-
|
||||||
|
|
||||||
- name: Style check
|
- name: Style check
|
||||||
if: steps.changed-files.outputs.any_changed == 'true'
|
if: steps.changed-files.outputs.any_changed == 'true'
|
||||||
|
|||||||
@ -188,6 +188,7 @@ See `[web/docs/overlay.md](../../web/docs/overlay.md)` for the web app overlay b
|
|||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
|
- `vp run @langgenius/dify-ui#lint` (from the repository root) — strict ESLint checks for component source, stories, tests, and package configuration.
|
||||||
- `pnpm -C packages/dify-ui test` — Vitest unit tests for primitives.
|
- `pnpm -C packages/dify-ui test` — Vitest unit tests for primitives.
|
||||||
- `pnpm -C packages/dify-ui storybook` — Storybook on the default port. Each primitive has `index.stories.tsx`.
|
- `pnpm -C packages/dify-ui storybook` — Storybook on the default port. Each primitive has `index.stories.tsx`.
|
||||||
- `pnpm -C packages/dify-ui test:storybook` — Storybook component tests in Vitest browser mode. Stories without `play` are render and a11y smoke tests; stories with `play` should cover public UI contracts such as opening overlays, keyboard navigation, disabled/loading guards, form submission, and controlled state updates.
|
- `pnpm -C packages/dify-ui test:storybook` — Storybook component tests in Vitest browser mode. Stories without `play` are render and a11y smoke tests; stories with `play` should cover public UI contracts such as opening overlays, keyboard navigation, disabled/loading guards, form submission, and controlled state updates.
|
||||||
|
|||||||
109
packages/dify-ui/eslint.config.mjs
Normal file
109
packages/dify-ui/eslint.config.mjs
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// @ts-check
|
||||||
|
|
||||||
|
import path from 'node:path'
|
||||||
|
import antfu, { GLOB_MARKDOWN_CODE, GLOB_TS, GLOB_TSX } from '@antfu/eslint-config'
|
||||||
|
import tailwindcss from 'eslint-plugin-better-tailwindcss'
|
||||||
|
import jsxA11y from 'eslint-plugin-jsx-a11y'
|
||||||
|
import storybook from 'eslint-plugin-storybook'
|
||||||
|
|
||||||
|
const SOURCE_FILES = [GLOB_TS, GLOB_TSX]
|
||||||
|
const TEST_FILES = ['**/__tests__/**/*.{ts,tsx}', '**/*.spec.{ts,tsx}']
|
||||||
|
|
||||||
|
export default antfu(
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
'coverage/',
|
||||||
|
'dist/',
|
||||||
|
'storybook-static/',
|
||||||
|
],
|
||||||
|
react: {
|
||||||
|
overrides: {
|
||||||
|
'react/exhaustive-deps': ['error', { additionalHooks: 'useIsoLayoutEffect' }],
|
||||||
|
'react/no-context-provider': 'off',
|
||||||
|
'react/no-unnecessary-use-prefix': 'error',
|
||||||
|
'react/no-use-context': 'off',
|
||||||
|
'react/rules-of-hooks': 'error',
|
||||||
|
'react/set-state-in-effect': 'error',
|
||||||
|
'react/set-state-in-render': 'error',
|
||||||
|
'react/static-components': 'error',
|
||||||
|
'react-refresh/only-export-components': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
typescript: {
|
||||||
|
overrides: {
|
||||||
|
'ts/consistent-type-definitions': ['error', 'type'],
|
||||||
|
'ts/no-explicit-any': 'error',
|
||||||
|
'ts/no-redeclare': 'off',
|
||||||
|
},
|
||||||
|
erasableOnly: true,
|
||||||
|
},
|
||||||
|
test: {
|
||||||
|
overrides: {
|
||||||
|
'test/prefer-lowercase-title': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
stylistic: {
|
||||||
|
overrides: {
|
||||||
|
'antfu/top-level-function': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
e18e: false,
|
||||||
|
pnpm: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: [GLOB_TSX],
|
||||||
|
...jsxA11y.flatConfigs.recommended,
|
||||||
|
rules: {
|
||||||
|
...jsxA11y.flatConfigs.recommended.rules,
|
||||||
|
'jsx-a11y/anchor-has-content': 'off',
|
||||||
|
'jsx-a11y/label-has-associated-control': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...storybook.configs['flat/recommended'],
|
||||||
|
{
|
||||||
|
name: 'dify-ui/storybook',
|
||||||
|
files: ['**/.storybook/main.{js,cjs,mjs,ts}'],
|
||||||
|
rules: {
|
||||||
|
'storybook/no-uninstalled-addons': ['error', {
|
||||||
|
packageJsonLocation: path.resolve(import.meta.dirname, 'package.json'),
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'dify-ui/tailwind',
|
||||||
|
files: SOURCE_FILES,
|
||||||
|
ignores: [GLOB_MARKDOWN_CODE, ...TEST_FILES],
|
||||||
|
plugins: {
|
||||||
|
tailwindcss,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'tailwindcss/enforce-consistent-class-order': 'error',
|
||||||
|
'tailwindcss/no-duplicate-classes': 'error',
|
||||||
|
'tailwindcss/no-deprecated-classes': 'error',
|
||||||
|
'tailwindcss/no-unknown-classes': 'error',
|
||||||
|
'tailwindcss/no-unnecessary-whitespace': 'error',
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
'better-tailwindcss': {
|
||||||
|
cwd: import.meta.dirname,
|
||||||
|
entryPoint: path.resolve(import.meta.dirname, './.storybook/storybook.css'),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: TEST_FILES,
|
||||||
|
rules: {
|
||||||
|
'react/purity': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
rules: {
|
||||||
|
'node/prefer-global/process': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
linterOptions: {
|
||||||
|
reportUnusedDisableDirectives: 'error',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
@ -151,6 +151,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"lint": "eslint --cache --max-warnings=0 .",
|
||||||
"storybook": "storybook dev -p 6006",
|
"storybook": "storybook dev -p 6006",
|
||||||
"storybook:build": "storybook build",
|
"storybook:build": "storybook build",
|
||||||
"test": "vp test --project unit",
|
"test": "vp test --project unit",
|
||||||
@ -170,10 +171,12 @@
|
|||||||
"tailwind-merge": "catalog:"
|
"tailwind-merge": "catalog:"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@antfu/eslint-config": "catalog:",
|
||||||
"@base-ui/react": "catalog:",
|
"@base-ui/react": "catalog:",
|
||||||
"@chromatic-com/storybook": "catalog:",
|
"@chromatic-com/storybook": "catalog:",
|
||||||
"@dify/tsconfig": "workspace:*",
|
"@dify/tsconfig": "workspace:*",
|
||||||
"@egoist/tailwindcss-icons": "catalog:",
|
"@egoist/tailwindcss-icons": "catalog:",
|
||||||
|
"@eslint-react/eslint-plugin": "catalog:",
|
||||||
"@iconify-json/ri": "catalog:",
|
"@iconify-json/ri": "catalog:",
|
||||||
"@storybook/addon-a11y": "catalog:",
|
"@storybook/addon-a11y": "catalog:",
|
||||||
"@storybook/addon-docs": "catalog:",
|
"@storybook/addon-docs": "catalog:",
|
||||||
@ -192,6 +195,11 @@
|
|||||||
"@vitest/browser-playwright": "catalog:",
|
"@vitest/browser-playwright": "catalog:",
|
||||||
"@vitest/coverage-v8": "catalog:",
|
"@vitest/coverage-v8": "catalog:",
|
||||||
"class-variance-authority": "catalog:",
|
"class-variance-authority": "catalog:",
|
||||||
|
"eslint": "catalog:",
|
||||||
|
"eslint-plugin-better-tailwindcss": "catalog:",
|
||||||
|
"eslint-plugin-jsx-a11y": "catalog:",
|
||||||
|
"eslint-plugin-react-refresh": "catalog:",
|
||||||
|
"eslint-plugin-storybook": "catalog:",
|
||||||
"playwright": "catalog:",
|
"playwright": "catalog:",
|
||||||
"react": "catalog:",
|
"react": "catalog:",
|
||||||
"react-dom": "catalog:",
|
"react-dom": "catalog:",
|
||||||
|
|||||||
@ -254,7 +254,7 @@ const BasicTagAutocomplete = ({
|
|||||||
openOnInputClick
|
openOnInputClick
|
||||||
>
|
>
|
||||||
<AutocompleteInputGroup size={size}>
|
<AutocompleteInputGroup size={size}>
|
||||||
<span className="i-ri-search-line ml-2 size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
<span className="ml-2 i-ri-search-line size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
||||||
<AutocompleteInput size={size} placeholder="Search tags or type a new one…" aria-label="Search tags or type a new one" />
|
<AutocompleteInput size={size} placeholder="Search tags or type a new one…" aria-label="Search tags or type a new one" />
|
||||||
<AutocompleteClear size={size} />
|
<AutocompleteClear size={size} />
|
||||||
<AutocompleteTrigger size={size} />
|
<AutocompleteTrigger size={size} />
|
||||||
@ -396,7 +396,7 @@ const AsyncSearchDemo = () => {
|
|||||||
mode="list"
|
mode="list"
|
||||||
>
|
>
|
||||||
<AutocompleteInputGroup>
|
<AutocompleteInputGroup>
|
||||||
<span className="i-ri-cloud-line ml-2 size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
<span className="ml-2 i-ri-cloud-line size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
||||||
<AutocompleteInput placeholder="Search remote resources…" aria-label="Search remote resources" />
|
<AutocompleteInput placeholder="Search remote resources…" aria-label="Search remote resources" />
|
||||||
<AutocompleteClear />
|
<AutocompleteClear />
|
||||||
<AutocompleteTrigger />
|
<AutocompleteTrigger />
|
||||||
@ -441,7 +441,7 @@ const VirtualizedSuggestionList = ({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
className="max-h-[min(22rem,var(--available-height))] overflow-y-auto overflow-x-hidden overscroll-contain outline-hidden"
|
className="max-h-[min(22rem,var(--available-height))] overflow-x-hidden overflow-y-auto overscroll-contain outline-hidden"
|
||||||
>
|
>
|
||||||
<AutocompleteList
|
<AutocompleteList
|
||||||
className="relative max-h-none overflow-visible p-0"
|
className="relative max-h-none overflow-visible p-0"
|
||||||
@ -504,6 +504,7 @@ const FuzzyHighlight = ({
|
|||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
{parts.map((part, index) => (
|
{parts.map((part, index) => (
|
||||||
part.toLowerCase() === query.trim().toLowerCase()
|
part.toLowerCase() === query.trim().toLowerCase()
|
||||||
|
// eslint-disable-next-line react/no-array-index-key -- Repeated text fragments have no stable identity and never preserve state.
|
||||||
? <mark key={`${part}-${index}`} className="bg-transparent text-text-accent">{part}</mark>
|
? <mark key={`${part}-${index}`} className="bg-transparent text-text-accent">{part}</mark>
|
||||||
: part
|
: part
|
||||||
))}
|
))}
|
||||||
@ -527,7 +528,7 @@ const FuzzyMatchingDemo = () => {
|
|||||||
openOnInputClick
|
openOnInputClick
|
||||||
>
|
>
|
||||||
<AutocompleteInputGroup>
|
<AutocompleteInputGroup>
|
||||||
<span className="i-ri-sparkling-2-line ml-2 size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
<span className="ml-2 i-ri-sparkling-2-line size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
||||||
<AutocompleteInput placeholder="Fuzzy search workflow suggestions…" aria-label="Fuzzy search workflow suggestions" />
|
<AutocompleteInput placeholder="Fuzzy search workflow suggestions…" aria-label="Fuzzy search workflow suggestions" />
|
||||||
<AutocompleteClear />
|
<AutocompleteClear />
|
||||||
<AutocompleteTrigger />
|
<AutocompleteTrigger />
|
||||||
@ -600,7 +601,7 @@ export const InlineAutocomplete: Story = {
|
|||||||
openOnInputClick
|
openOnInputClick
|
||||||
>
|
>
|
||||||
<AutocompleteInputGroup>
|
<AutocompleteInputGroup>
|
||||||
<span className="i-ri-text-snippet ml-2 size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
<span className="ml-2 i-ri-text-snippet size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
||||||
<AutocompleteInput placeholder="Type a prompt starter…" aria-label="Type a prompt starter" />
|
<AutocompleteInput placeholder="Type a prompt starter…" aria-label="Type a prompt starter" />
|
||||||
<AutocompleteClear />
|
<AutocompleteClear />
|
||||||
<AutocompleteTrigger />
|
<AutocompleteTrigger />
|
||||||
@ -628,7 +629,7 @@ export const GroupedSuggestions: Story = {
|
|||||||
openOnInputClick
|
openOnInputClick
|
||||||
>
|
>
|
||||||
<AutocompleteInputGroup>
|
<AutocompleteInputGroup>
|
||||||
<span className="i-ri-command-line ml-2 size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
<span className="ml-2 i-ri-command-line size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
||||||
<AutocompleteInput placeholder="Search tags, nodes, or prompt starters…" aria-label="Search tags, nodes, or prompt starters" />
|
<AutocompleteInput placeholder="Search tags, nodes, or prompt starters…" aria-label="Search tags, nodes, or prompt starters" />
|
||||||
<AutocompleteClear />
|
<AutocompleteClear />
|
||||||
<AutocompleteTrigger />
|
<AutocompleteTrigger />
|
||||||
@ -657,7 +658,7 @@ export const LimitResults: Story = {
|
|||||||
openOnInputClick
|
openOnInputClick
|
||||||
>
|
>
|
||||||
<AutocompleteInputGroup>
|
<AutocompleteInputGroup>
|
||||||
<span className="i-ri-tools-line ml-2 size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
<span className="ml-2 i-ri-tools-line size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
||||||
<AutocompleteInput placeholder="Search workflow suggestions…" aria-label="Search workflow suggestions" />
|
<AutocompleteInput placeholder="Search workflow suggestions…" aria-label="Search workflow suggestions" />
|
||||||
<AutocompleteClear />
|
<AutocompleteClear />
|
||||||
<AutocompleteTrigger />
|
<AutocompleteTrigger />
|
||||||
@ -691,7 +692,7 @@ export const CommandPalette: Story = {
|
|||||||
keepHighlight
|
keepHighlight
|
||||||
>
|
>
|
||||||
<AutocompleteInputGroup className="mb-2">
|
<AutocompleteInputGroup className="mb-2">
|
||||||
<span className="i-ri-search-line ml-2 size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
<span className="ml-2 i-ri-search-line size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
||||||
<AutocompleteInput placeholder="Run a command…" aria-label="Run a command" aria-expanded="true" />
|
<AutocompleteInput placeholder="Run a command…" aria-label="Run a command" aria-expanded="true" />
|
||||||
<AutocompleteClear />
|
<AutocompleteClear />
|
||||||
</AutocompleteInputGroup>
|
</AutocompleteInputGroup>
|
||||||
@ -717,7 +718,7 @@ const VirtualizedLongSuggestionsDemo = () => {
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AutocompleteInputGroup>
|
<AutocompleteInputGroup>
|
||||||
<span className="i-ri-search-line ml-2 size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
<span className="ml-2 i-ri-search-line size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
||||||
<AutocompleteInput placeholder="Search 1,000 workspace suggestions…" aria-label="Search 1,000 workspace suggestions" />
|
<AutocompleteInput placeholder="Search 1,000 workspace suggestions…" aria-label="Search 1,000 workspace suggestions" />
|
||||||
<AutocompleteClear />
|
<AutocompleteClear />
|
||||||
<AutocompleteTrigger />
|
<AutocompleteTrigger />
|
||||||
@ -751,7 +752,7 @@ export const Empty: Story = {
|
|||||||
openOnInputClick
|
openOnInputClick
|
||||||
>
|
>
|
||||||
<AutocompleteInputGroup>
|
<AutocompleteInputGroup>
|
||||||
<span className="i-ri-search-line ml-2 size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
<span className="ml-2 i-ri-search-line size-4 shrink-0 text-text-tertiary" aria-hidden="true" />
|
||||||
<AutocompleteInput placeholder="Search tags or type a new one…" aria-label="Search tags or type a new one" />
|
<AutocompleteInput placeholder="Search tags or type a new one…" aria-label="Search tags or type a new one" />
|
||||||
<AutocompleteClear />
|
<AutocompleteClear />
|
||||||
<AutocompleteTrigger />
|
<AutocompleteTrigger />
|
||||||
|
|||||||
@ -12,7 +12,7 @@ const buttonVariants = cva(
|
|||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
'primary': [
|
'primary': [
|
||||||
'border-components-button-primary-border bg-components-button-primary-bg text-components-button-primary-text shadow',
|
'border-components-button-primary-border bg-components-button-primary-bg text-components-button-primary-text shadow-sm',
|
||||||
'hover:border-components-button-primary-border-hover hover:bg-components-button-primary-bg-hover',
|
'hover:border-components-button-primary-border-hover hover:bg-components-button-primary-bg-hover',
|
||||||
'data-[disabled]:border-components-button-primary-border-disabled data-[disabled]:bg-components-button-primary-bg-disabled data-[disabled]:text-components-button-primary-text-disabled data-[disabled]:shadow-none',
|
'data-[disabled]:border-components-button-primary-border-disabled data-[disabled]:bg-components-button-primary-bg-disabled data-[disabled]:text-components-button-primary-text-disabled data-[disabled]:shadow-none',
|
||||||
],
|
],
|
||||||
|
|||||||
@ -9,7 +9,7 @@ const checkboxRootClassName = cn(
|
|||||||
'inline-flex size-4 shrink-0 touch-manipulation items-center justify-center rounded-sm shadow-xs shadow-shadow-shadow-3 transition-colors motion-reduce:transition-none',
|
'inline-flex size-4 shrink-0 touch-manipulation items-center justify-center rounded-sm shadow-xs shadow-shadow-shadow-3 transition-colors motion-reduce:transition-none',
|
||||||
'border border-components-checkbox-border bg-components-checkbox-bg-unchecked text-components-checkbox-icon',
|
'border border-components-checkbox-border bg-components-checkbox-bg-unchecked text-components-checkbox-icon',
|
||||||
'hover:border-components-checkbox-border-hover hover:bg-components-checkbox-bg-unchecked-hover',
|
'hover:border-components-checkbox-border-hover hover:bg-components-checkbox-bg-unchecked-hover',
|
||||||
'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:ring-offset-0',
|
'focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:ring-offset-0 focus-visible:outline-hidden',
|
||||||
'data-checked:border-transparent data-checked:bg-components-checkbox-bg data-checked:hover:bg-components-checkbox-bg-hover',
|
'data-checked:border-transparent data-checked:bg-components-checkbox-bg data-checked:hover:bg-components-checkbox-bg-hover',
|
||||||
'data-indeterminate:border-transparent data-indeterminate:bg-components-checkbox-bg data-indeterminate:hover:bg-components-checkbox-bg-hover',
|
'data-indeterminate:border-transparent data-indeterminate:bg-components-checkbox-bg data-indeterminate:hover:bg-components-checkbox-bg-hover',
|
||||||
'data-disabled:cursor-not-allowed data-disabled:border-components-checkbox-border-disabled data-disabled:bg-components-checkbox-bg-disabled',
|
'data-disabled:cursor-not-allowed data-disabled:border-components-checkbox-border-disabled data-disabled:bg-components-checkbox-bg-disabled',
|
||||||
|
|||||||
@ -89,25 +89,27 @@ export const DefaultOpen: Story = {
|
|||||||
),
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Controlled: Story = {
|
function ControlledDemo() {
|
||||||
render: () => {
|
const [open, setOpen] = React.useState(true)
|
||||||
const [open, setOpen] = React.useState(true)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col items-start gap-3">
|
<div className="flex flex-col items-start gap-3">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="rounded-lg border border-divider-subtle bg-components-button-secondary-bg px-3 py-1.5 system-sm-medium text-components-button-secondary-text shadow-xs shadow-shadow-shadow-3 outline-hidden hover:bg-state-base-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid"
|
className="rounded-lg border border-divider-subtle bg-components-button-secondary-bg px-3 py-1.5 system-sm-medium text-components-button-secondary-text shadow-xs shadow-shadow-shadow-3 outline-hidden hover:bg-state-base-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid"
|
||||||
onClick={() => setOpen(value => !value)}
|
onClick={() => setOpen(value => !value)}
|
||||||
>
|
>
|
||||||
{open ? 'Close panel' : 'Open panel'}
|
{open ? 'Close panel' : 'Open panel'}
|
||||||
</button>
|
</button>
|
||||||
<Collapsible open={open} onOpenChange={setOpen} className={rootClassName}>
|
<Collapsible open={open} onOpenChange={setOpen} className={rootClassName}>
|
||||||
<RecoveryKeys />
|
<RecoveryKeys />
|
||||||
</Collapsible>
|
</Collapsible>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
},
|
}
|
||||||
|
|
||||||
|
export const Controlled: Story = {
|
||||||
|
render: () => <ControlledDemo />,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const Disabled: Story = {
|
export const Disabled: Story = {
|
||||||
@ -172,7 +174,7 @@ export const SettingsSections: Story = {
|
|||||||
<TriggerIcon />
|
<TriggerIcon />
|
||||||
</CollapsibleTrigger>
|
</CollapsibleTrigger>
|
||||||
<CollapsiblePanel className={sectionPanelClassName}>
|
<CollapsiblePanel className={sectionPanelClassName}>
|
||||||
<div className="px-3 pb-3 pt-1 system-sm-regular text-text-secondary">
|
<div className="px-3 pt-1 pb-3 system-sm-regular text-text-secondary">
|
||||||
{section.description}
|
{section.description}
|
||||||
</div>
|
</div>
|
||||||
</CollapsiblePanel>
|
</CollapsiblePanel>
|
||||||
|
|||||||
@ -212,8 +212,8 @@ const renderOptionItem = (option: Option) => (
|
|||||||
<ComboboxItemText className="flex items-center gap-2 px-0">
|
<ComboboxItemText className="flex items-center gap-2 px-0">
|
||||||
{option.icon && <span aria-hidden className={cn(option.icon, 'size-4 shrink-0 text-text-tertiary')} />}
|
{option.icon && <span aria-hidden className={cn(option.icon, 'size-4 shrink-0 text-text-tertiary')} />}
|
||||||
<span className="min-w-0 flex-1">
|
<span className="min-w-0 flex-1">
|
||||||
<span className="block truncate text-text-secondary system-sm-medium">{option.label}</span>
|
<span className="block truncate system-sm-medium text-text-secondary">{option.label}</span>
|
||||||
{option.meta && <span className="block truncate text-text-tertiary system-xs-regular">{option.meta}</span>}
|
{option.meta && <span className="block truncate system-xs-regular text-text-tertiary">{option.meta}</span>}
|
||||||
</span>
|
</span>
|
||||||
</ComboboxItemText>
|
</ComboboxItemText>
|
||||||
<ComboboxItemIndicator />
|
<ComboboxItemIndicator />
|
||||||
@ -233,8 +233,8 @@ const renderVirtualizedOptionItem = (option: Option, index: number) => (
|
|||||||
<ComboboxItemText className="flex items-center gap-2 px-0">
|
<ComboboxItemText className="flex items-center gap-2 px-0">
|
||||||
{option.icon && <span aria-hidden className={cn(option.icon, 'size-4 shrink-0 text-text-tertiary')} />}
|
{option.icon && <span aria-hidden className={cn(option.icon, 'size-4 shrink-0 text-text-tertiary')} />}
|
||||||
<span className="min-w-0 flex-1">
|
<span className="min-w-0 flex-1">
|
||||||
<span className="block truncate text-text-secondary system-sm-medium">{option.label}</span>
|
<span className="block truncate system-sm-medium text-text-secondary">{option.label}</span>
|
||||||
{option.meta && <span className="block truncate text-text-tertiary system-xs-regular">{option.meta}</span>}
|
{option.meta && <span className="block truncate system-xs-regular text-text-tertiary">{option.meta}</span>}
|
||||||
</span>
|
</span>
|
||||||
</ComboboxItemText>
|
</ComboboxItemText>
|
||||||
<ComboboxItemIndicator />
|
<ComboboxItemIndicator />
|
||||||
@ -300,7 +300,7 @@ const VirtualizedModelList = ({
|
|||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={scrollRef}
|
ref={scrollRef}
|
||||||
className="max-h-[min(22rem,var(--available-height))] overflow-y-auto overflow-x-hidden overscroll-contain outline-hidden"
|
className="max-h-[min(22rem,var(--available-height))] overflow-x-hidden overflow-y-auto overscroll-contain outline-hidden"
|
||||||
>
|
>
|
||||||
<ComboboxList
|
<ComboboxList
|
||||||
className="relative max-h-none overflow-visible p-0"
|
className="relative max-h-none overflow-visible p-0"
|
||||||
@ -854,7 +854,7 @@ const ControlledDemo = () => {
|
|||||||
</ComboboxContent>
|
</ComboboxContent>
|
||||||
</Combobox>
|
</Combobox>
|
||||||
</div>
|
</div>
|
||||||
<span className="rounded-md border border-divider-subtle bg-components-panel-bg px-2 py-1 text-text-tertiary system-xs-regular">
|
<span className="rounded-md border border-divider-subtle bg-components-panel-bg px-2 py-1 system-xs-regular text-text-tertiary">
|
||||||
Selected:
|
Selected:
|
||||||
{' '}
|
{' '}
|
||||||
{value?.label ?? 'None'}
|
{value?.label ?? 'None'}
|
||||||
|
|||||||
@ -478,7 +478,7 @@ export function ComboboxChip({
|
|||||||
}: BaseCombobox.Chip.Props) {
|
}: BaseCombobox.Chip.Props) {
|
||||||
return (
|
return (
|
||||||
<BaseCombobox.Chip
|
<BaseCombobox.Chip
|
||||||
className={cn('inline-flex max-w-full min-w-0 items-center gap-1 rounded-md bg-state-base-hover px-1.5 py-0.5 text-text-secondary system-xs-medium', className)}
|
className={cn('inline-flex max-w-full min-w-0 items-center gap-1 rounded-md bg-state-base-hover px-1.5 py-0.5 system-xs-medium text-text-secondary', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -324,7 +324,7 @@ const OutsideScrollingContentDemo = () => {
|
|||||||
<DialogPopup
|
<DialogPopup
|
||||||
ref={popupRef}
|
ref={popupRef}
|
||||||
initialFocus={popupRef}
|
initialFocus={popupRef}
|
||||||
className="relative mx-auto flex w-120 max-w-[calc(100vw-2rem)] flex-col overflow-hidden outline-hidden transition-[translate] duration-[700ms] ease-[cubic-bezier(0.45,1.005,0,1.005)] data-starting-style:translate-y-[100dvh] data-starting-style:scale-100 data-starting-style:opacity-100 data-ending-style:translate-y-[max(100dvh,100%)] data-ending-style:scale-100 data-ending-style:opacity-100 data-ending-style:duration-[350ms] data-ending-style:ease-[cubic-bezier(0.375,0.015,0.545,0.455)]"
|
className="relative mx-auto flex w-120 max-w-[calc(100vw-2rem)] flex-col overflow-hidden outline-hidden transition-[translate] duration-[700ms] ease-[cubic-bezier(0.45,1.005,0,1.005)] data-ending-style:translate-y-[max(100dvh,100%)] data-ending-style:scale-100 data-ending-style:opacity-100 data-ending-style:duration-[350ms] data-ending-style:ease-[cubic-bezier(0.375,0.015,0.545,0.455)] data-starting-style:translate-y-[100dvh] data-starting-style:scale-100 data-starting-style:opacity-100"
|
||||||
>
|
>
|
||||||
<DialogCloseButton />
|
<DialogCloseButton />
|
||||||
<ReleaseNoteHeader
|
<ReleaseNoteHeader
|
||||||
@ -361,10 +361,10 @@ export const OutsidePopupElements: Story = {
|
|||||||
<DialogPortal>
|
<DialogPortal>
|
||||||
<DialogBackdrop className="min-h-dvh" />
|
<DialogBackdrop className="min-h-dvh" />
|
||||||
<DialogViewport className="grid place-items-center px-4 py-12 xl:py-6">
|
<DialogViewport className="grid place-items-center px-4 py-12 xl:py-6">
|
||||||
<DialogPopup className="group/popup relative flex h-full w-full max-w-[70rem] justify-center border-0 bg-transparent shadow-none pointer-events-none transition-opacity data-starting-style:scale-100 data-starting-style:opacity-0 data-ending-style:scale-100 data-ending-style:opacity-0">
|
<DialogPopup className="group/popup pointer-events-none relative flex h-full w-full max-w-[70rem] justify-center border-0 bg-transparent shadow-none transition-opacity data-ending-style:scale-100 data-ending-style:opacity-0 data-starting-style:scale-100 data-starting-style:opacity-0">
|
||||||
<DialogCloseButton
|
<DialogCloseButton
|
||||||
aria-label="Close"
|
aria-label="Close"
|
||||||
className="pointer-events-auto absolute right-0 -top-10 z-10 flex size-8 items-center justify-center rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg text-text-tertiary shadow-xs outline-hidden hover:bg-components-button-secondary-bg-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid xl:top-0"
|
className="pointer-events-auto absolute -top-10 right-0 z-10 flex size-8 items-center justify-center rounded-lg border-[0.5px] border-components-button-secondary-border bg-components-button-secondary-bg text-text-tertiary shadow-xs outline-hidden hover:bg-components-button-secondary-bg-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid xl:top-0"
|
||||||
>
|
>
|
||||||
</DialogCloseButton>
|
</DialogCloseButton>
|
||||||
<div className="pointer-events-auto flex h-full w-full max-w-[70rem] flex-col overflow-hidden rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg p-6 shadow-xl transition-[scale] duration-500 ease-[cubic-bezier(0.22,1,0.36,1)] group-data-starting-style/popup:scale-105">
|
<div className="pointer-events-auto flex h-full w-full max-w-[70rem] flex-col overflow-hidden rounded-2xl border-[0.5px] border-components-panel-border bg-components-panel-bg p-6 shadow-xl transition-[scale] duration-500 ease-[cubic-bezier(0.22,1,0.36,1)] group-data-starting-style/popup:scale-105">
|
||||||
@ -401,7 +401,7 @@ const InsideScrollingContentDemo = () => {
|
|||||||
<DialogBackdrop />
|
<DialogBackdrop />
|
||||||
<DialogViewport className="flex items-center justify-center overflow-hidden p-4">
|
<DialogViewport className="flex items-center justify-center overflow-hidden p-4">
|
||||||
<DialogPopup
|
<DialogPopup
|
||||||
className="relative flex h-[min(44rem,calc(100dvh-2rem))] w-120 max-w-[calc(100vw-2rem)] min-h-0 flex-col overflow-hidden"
|
className="relative flex h-[min(44rem,calc(100dvh-2rem))] min-h-0 w-120 max-w-[calc(100vw-2rem)] flex-col overflow-hidden"
|
||||||
>
|
>
|
||||||
<DialogCloseButton />
|
<DialogCloseButton />
|
||||||
<ReleaseNoteHeader
|
<ReleaseNoteHeader
|
||||||
|
|||||||
@ -78,7 +78,7 @@ export function DialogCloseButton({
|
|||||||
aria-label={ariaLabel}
|
aria-label={ariaLabel}
|
||||||
{...props}
|
{...props}
|
||||||
className={cn(
|
className={cn(
|
||||||
'absolute top-6 end-6 z-10 flex h-5 w-5 cursor-pointer items-center justify-center rounded-2xl hover:bg-state-base-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
|
'absolute inset-e-6 top-6 z-10 flex h-5 w-5 cursor-pointer items-center justify-center rounded-2xl hover:bg-state-base-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden disabled:cursor-not-allowed disabled:opacity-50',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
|||||||
@ -232,7 +232,7 @@ export const Positions: Story = {
|
|||||||
<DrawerPortal>
|
<DrawerPortal>
|
||||||
<DrawerBackdrop className="fixed" />
|
<DrawerBackdrop className="fixed" />
|
||||||
<DrawerViewport className="flex items-end justify-center">
|
<DrawerViewport className="flex items-end justify-center">
|
||||||
<DrawerPopup className="-mb-12 touch-auto data-[swipe-direction=down]:max-h-[calc(80dvh_+_3rem)] data-[swipe-direction=down]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_3rem_+_2px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_3rem_+_2px))] data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]">
|
<DrawerPopup className="-mb-12 touch-auto data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)] data-[swipe-direction=down]:max-h-[calc(80dvh_+_3rem)] data-[swipe-direction=down]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_3rem_+_2px))] data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_3rem_+_2px))]">
|
||||||
<div className={handleClassName} />
|
<div className={handleClassName} />
|
||||||
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-12">
|
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-12">
|
||||||
<div className="mx-auto w-full max-w-lg px-6 pt-6 pb-4 text-center">
|
<div className="mx-auto w-full max-w-lg px-6 pt-6 pb-4 text-center">
|
||||||
@ -263,7 +263,7 @@ export const Positions: Story = {
|
|||||||
<DrawerPortal>
|
<DrawerPortal>
|
||||||
<DrawerBackdrop className="fixed" />
|
<DrawerBackdrop className="fixed" />
|
||||||
<DrawerViewport className="flex items-start justify-center">
|
<DrawerViewport className="flex items-start justify-center">
|
||||||
<DrawerPopup className="-mt-12 touch-auto data-[swipe-direction=up]:max-h-[calc(80dvh_+_3rem)] data-[swipe-direction=up]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-starting-style:data-[swipe-direction=up]:transform-[translateY(calc(-100%_+_3rem_-_2px))] data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(-100%_+_3rem_-_2px))] data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]">
|
<DrawerPopup className="-mt-12 touch-auto data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)] data-[swipe-direction=up]:max-h-[calc(80dvh_+_3rem)] data-[swipe-direction=up]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(-100%_+_3rem_-_2px))] data-starting-style:data-[swipe-direction=up]:transform-[translateY(calc(-100%_+_3rem_-_2px))]">
|
||||||
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pt-12">
|
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pt-12">
|
||||||
<div className="mx-auto w-full max-w-128 px-6 pt-6 pb-4 text-center">
|
<div className="mx-auto w-full max-w-128 px-6 pt-6 pb-4 text-center">
|
||||||
<DrawerTitle className="text-lg/6 font-semibold text-text-primary">
|
<DrawerTitle className="text-lg/6 font-semibold text-text-primary">
|
||||||
@ -314,12 +314,12 @@ function SnapPointsDemo() {
|
|||||||
<DrawerViewport className="flex touch-none items-end justify-center">
|
<DrawerViewport className="flex touch-none items-end justify-center">
|
||||||
<DrawerPopup
|
<DrawerPopup
|
||||||
className={cn(
|
className={cn(
|
||||||
'relative overflow-visible touch-none',
|
'relative touch-none overflow-visible',
|
||||||
'[--bleed:3rem] [--top-margin:1rem]',
|
'[--bleed:3rem] [--top-margin:1rem]',
|
||||||
'pb-[max(0px,calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))]',
|
'pb-[max(0px,calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))]',
|
||||||
'after:pointer-events-none after:absolute after:inset-x-0 after:top-full after:h-(--bleed) after:bg-inherit after:content-[""]',
|
'after:pointer-events-none after:absolute after:inset-x-0 after:top-full after:h-(--bleed) after:bg-inherit after:content-[""]',
|
||||||
'data-[swipe-direction=down]:max-h-[calc(100dvh_-_var(--top-margin))]',
|
'data-[swipe-direction=down]:max-h-[calc(100dvh_-_var(--top-margin))]',
|
||||||
'data-starting-style:pb-0 data-ending-style:pb-0',
|
'data-ending-style:pb-0 data-starting-style:pb-0',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<div className="shrink-0 touch-none border-b-[0.5px] border-divider-subtle px-6 pt-3.5 pb-4">
|
<div className="shrink-0 touch-none border-b-[0.5px] border-divider-subtle px-6 pt-3.5 pb-4">
|
||||||
@ -374,13 +374,13 @@ export const NestedDrawers: Story = {
|
|||||||
<DrawerViewport>
|
<DrawerViewport>
|
||||||
<DrawerPopup
|
<DrawerPopup
|
||||||
className={cn(
|
className={cn(
|
||||||
'[--bleed:3rem] [--stack-step:0.05] [--stack-scale:calc(1_-_(var(--nested-drawers,0)_*_var(--stack-step)))]',
|
'[--bleed:3rem] [--stack-scale:calc(1_-_(var(--nested-drawers,0)_*_var(--stack-step)))] [--stack-step:0.05]',
|
||||||
'[--stack-height:max(0px,calc(var(--drawer-frontmost-height,var(--drawer-height))_-_var(--bleed)))]',
|
'[--stack-height:max(0px,calc(var(--drawer-frontmost-height,var(--drawer-height))_-_var(--bleed)))]',
|
||||||
'-mb-12 touch-auto origin-bottom',
|
'-mb-12 origin-bottom touch-auto',
|
||||||
'after:pointer-events-none after:absolute after:inset-0 after:bg-transparent after:content-[""] after:transition-[background-color] after:duration-200',
|
'after:pointer-events-none after:absolute after:inset-0 after:bg-transparent after:transition-[background-color] after:duration-200 after:content-[""]',
|
||||||
'data-[swipe-direction=down]:h-(--drawer-height) data-[swipe-direction=down]:max-h-[calc(82dvh_+_3rem)]',
|
'data-[swipe-direction=down]:h-(--drawer-height) data-[swipe-direction=down]:max-h-[calc(82dvh_+_3rem)]',
|
||||||
'data-[swipe-direction=down]:transform-[translateY(calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))_scale(var(--stack-scale))]',
|
'data-[swipe-direction=down]:transform-[translateY(calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))_scale(var(--stack-scale))]',
|
||||||
'data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))]',
|
'data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))] data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))]',
|
||||||
'data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]',
|
'data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]',
|
||||||
'data-nested-drawer-open:data-[swipe-direction=down]:h-[calc(var(--stack-height)_+_var(--bleed))]',
|
'data-nested-drawer-open:data-[swipe-direction=down]:h-[calc(var(--stack-height)_+_var(--bleed))]',
|
||||||
'data-nested-drawer-open:overflow-hidden data-nested-drawer-open:shadow-lg',
|
'data-nested-drawer-open:overflow-hidden data-nested-drawer-open:shadow-lg',
|
||||||
@ -411,13 +411,13 @@ export const NestedDrawers: Story = {
|
|||||||
<DrawerViewport className="flex items-end justify-center">
|
<DrawerViewport className="flex items-end justify-center">
|
||||||
<DrawerPopup
|
<DrawerPopup
|
||||||
className={cn(
|
className={cn(
|
||||||
'[--bleed:3rem] [--stack-step:0.05] [--stack-scale:calc(1_-_(var(--nested-drawers,0)_*_var(--stack-step)))]',
|
'[--bleed:3rem] [--stack-scale:calc(1_-_(var(--nested-drawers,0)_*_var(--stack-step)))] [--stack-step:0.05]',
|
||||||
'[--stack-height:max(0px,calc(var(--drawer-frontmost-height,var(--drawer-height))_-_var(--bleed)))]',
|
'[--stack-height:max(0px,calc(var(--drawer-frontmost-height,var(--drawer-height))_-_var(--bleed)))]',
|
||||||
'-mb-12 touch-auto origin-bottom',
|
'-mb-12 origin-bottom touch-auto',
|
||||||
'after:pointer-events-none after:absolute after:inset-0 after:bg-transparent after:content-[""] after:transition-[background-color] after:duration-200',
|
'after:pointer-events-none after:absolute after:inset-0 after:bg-transparent after:transition-[background-color] after:duration-200 after:content-[""]',
|
||||||
'data-[swipe-direction=down]:h-(--drawer-height) data-[swipe-direction=down]:max-h-[calc(82dvh_+_3rem)]',
|
'data-[swipe-direction=down]:h-(--drawer-height) data-[swipe-direction=down]:max-h-[calc(82dvh_+_3rem)]',
|
||||||
'data-[swipe-direction=down]:transform-[translateY(calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))_scale(var(--stack-scale))]',
|
'data-[swipe-direction=down]:transform-[translateY(calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))_scale(var(--stack-scale))]',
|
||||||
'data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))]',
|
'data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))] data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))]',
|
||||||
'data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]',
|
'data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]',
|
||||||
'data-nested-drawer-open:data-[swipe-direction=down]:h-[calc(var(--stack-height)_+_var(--bleed))]',
|
'data-nested-drawer-open:data-[swipe-direction=down]:h-[calc(var(--stack-height)_+_var(--bleed))]',
|
||||||
'data-nested-drawer-open:overflow-hidden data-nested-drawer-open:shadow-lg',
|
'data-nested-drawer-open:overflow-hidden data-nested-drawer-open:shadow-lg',
|
||||||
@ -454,13 +454,13 @@ export const NestedDrawers: Story = {
|
|||||||
<DrawerViewport className="flex items-end justify-center">
|
<DrawerViewport className="flex items-end justify-center">
|
||||||
<DrawerPopup
|
<DrawerPopup
|
||||||
className={cn(
|
className={cn(
|
||||||
'[--bleed:3rem] [--stack-step:0.05] [--stack-scale:calc(1_-_(var(--nested-drawers,0)_*_var(--stack-step)))]',
|
'[--bleed:3rem] [--stack-scale:calc(1_-_(var(--nested-drawers,0)_*_var(--stack-step)))] [--stack-step:0.05]',
|
||||||
'[--stack-height:max(0px,calc(var(--drawer-frontmost-height,var(--drawer-height))_-_var(--bleed)))]',
|
'[--stack-height:max(0px,calc(var(--drawer-frontmost-height,var(--drawer-height))_-_var(--bleed)))]',
|
||||||
'-mb-12 touch-auto origin-bottom',
|
'-mb-12 origin-bottom touch-auto',
|
||||||
'after:pointer-events-none after:absolute after:inset-0 after:bg-transparent after:content-[""] after:transition-[background-color] after:duration-200',
|
'after:pointer-events-none after:absolute after:inset-0 after:bg-transparent after:transition-[background-color] after:duration-200 after:content-[""]',
|
||||||
'data-[swipe-direction=down]:h-(--drawer-height) data-[swipe-direction=down]:max-h-[calc(82dvh_+_3rem)]',
|
'data-[swipe-direction=down]:h-(--drawer-height) data-[swipe-direction=down]:max-h-[calc(82dvh_+_3rem)]',
|
||||||
'data-[swipe-direction=down]:transform-[translateY(calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))_scale(var(--stack-scale))]',
|
'data-[swipe-direction=down]:transform-[translateY(calc(var(--drawer-snap-point-offset,0px)_+_var(--drawer-swipe-movement-y,0px)))_scale(var(--stack-scale))]',
|
||||||
'data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))]',
|
'data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))] data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_var(--bleed)_+_2px))]',
|
||||||
'data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]',
|
'data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]',
|
||||||
'data-nested-drawer-open:data-[swipe-direction=down]:h-[calc(var(--stack-height)_+_var(--bleed))]',
|
'data-nested-drawer-open:data-[swipe-direction=down]:h-[calc(var(--stack-height)_+_var(--bleed))]',
|
||||||
'data-nested-drawer-open:overflow-hidden data-nested-drawer-open:shadow-lg',
|
'data-nested-drawer-open:overflow-hidden data-nested-drawer-open:shadow-lg',
|
||||||
@ -533,7 +533,7 @@ function IndentEffectDemo() {
|
|||||||
<DrawerPortal container={portalContainer}>
|
<DrawerPortal container={portalContainer}>
|
||||||
<DrawerBackdrop />
|
<DrawerBackdrop />
|
||||||
<DrawerViewport className="absolute flex items-end justify-center">
|
<DrawerViewport className="absolute flex items-end justify-center">
|
||||||
<DrawerPopup className="absolute -mb-12 touch-auto data-[swipe-direction=down]:max-h-[calc(80dvh_+_3rem)] data-[swipe-direction=down]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_3rem_+_2px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_3rem_+_2px))] data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]">
|
<DrawerPopup className="absolute -mb-12 touch-auto data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)] data-[swipe-direction=down]:max-h-[calc(80dvh_+_3rem)] data-[swipe-direction=down]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_3rem_+_2px))] data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_-_3rem_+_2px))]">
|
||||||
<div className={handleClassName} />
|
<div className={handleClassName} />
|
||||||
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-12">
|
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-12">
|
||||||
<div className="mx-auto w-full max-w-96 px-6 pt-6 pb-4 text-center">
|
<div className="mx-auto w-full max-w-96 px-6 pt-6 pb-4 text-center">
|
||||||
@ -590,7 +590,7 @@ function NonModalDemo() {
|
|||||||
</div>
|
</div>
|
||||||
<DrawerPortal>
|
<DrawerPortal>
|
||||||
<DrawerViewport className="pointer-events-none">
|
<DrawerViewport className="pointer-events-none">
|
||||||
<DrawerPopup className="pointer-events-auto touch-auto data-[swipe-direction=right]:right-3 data-[swipe-direction=right]:top-16 data-[swipe-direction=right]:bottom-3 data-[swipe-direction=right]:h-auto data-[swipe-direction=right]:max-w-[420px] data-[swipe-direction=right]:rounded-2xl data-[swipe-direction=right]:border-r-[0.5px]">
|
<DrawerPopup className="pointer-events-auto touch-auto data-[swipe-direction=right]:top-16 data-[swipe-direction=right]:right-3 data-[swipe-direction=right]:bottom-3 data-[swipe-direction=right]:h-auto data-[swipe-direction=right]:max-w-[420px] data-[swipe-direction=right]:rounded-2xl data-[swipe-direction=right]:border-r-[0.5px]">
|
||||||
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-0">
|
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-0">
|
||||||
<div className="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
|
<div className="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
@ -666,11 +666,11 @@ export const MobileNavigation: Story = {
|
|||||||
<DrawerViewport className="group">
|
<DrawerViewport className="group">
|
||||||
<ScrollAreaRoot
|
<ScrollAreaRoot
|
||||||
style={{ position: undefined }}
|
style={{ position: undefined }}
|
||||||
className="h-full overscroll-contain transition-transform duration-600 ease-[cubic-bezier(0.45,1.005,0,1.005)] motion-reduce:transition-none group-data-starting-style:translate-y-[100dvh] group-data-ending-style:pointer-events-none"
|
className="h-full overscroll-contain transition-transform duration-600 ease-[cubic-bezier(0.45,1.005,0,1.005)] group-data-ending-style:pointer-events-none group-data-starting-style:translate-y-[100dvh] motion-reduce:transition-none"
|
||||||
>
|
>
|
||||||
<ScrollAreaViewport className="size-full touch-auto overscroll-contain" role="region" aria-label="Mobile drawer viewport">
|
<ScrollAreaViewport className="size-full touch-auto overscroll-contain" role="region" aria-label="Mobile drawer viewport">
|
||||||
<ScrollAreaContent className="flex min-h-full min-w-0 items-end justify-center pt-8 min-[42rem]:px-16 min-[42rem]:py-16">
|
<ScrollAreaContent className="flex min-h-full min-w-0 items-end justify-center pt-8 min-[42rem]:px-16 min-[42rem]:py-16">
|
||||||
<DrawerPopup className="relative w-full max-w-[42rem] touch-auto overflow-visible transition-transform duration-600 ease-[cubic-bezier(0.45,1.005,0,1.005)] motion-reduce:transition-none data-[swipe-direction=down]:inset-auto data-[swipe-direction=down]:max-h-none data-[swipe-direction=down]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-swiping:select-none data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(max(100dvh,100%)_+_2px))] data-ending-style:duration-350 data-ending-style:ease-[cubic-bezier(0.375,0.015,0.545,0.455)] min-[42rem]:rounded-2xl min-[42rem]:border-[0.5px] min-[42rem]:border-b-[0.5px]">
|
<DrawerPopup className="relative w-full max-w-[42rem] touch-auto overflow-visible transition-transform duration-600 ease-[cubic-bezier(0.45,1.005,0,1.005)] data-ending-style:duration-350 data-ending-style:ease-[cubic-bezier(0.375,0.015,0.545,0.455)] data-swiping:select-none data-[swipe-direction=down]:inset-auto data-[swipe-direction=down]:max-h-none data-[swipe-direction=down]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(max(100dvh,100%)_+_2px))] motion-reduce:transition-none min-[42rem]:rounded-2xl min-[42rem]:border-[0.5px] min-[42rem]:border-b-[0.5px]">
|
||||||
<nav aria-label="Mobile navigation" className="relative flex flex-col bg-components-panel-bg">
|
<nav aria-label="Mobile navigation" className="relative flex flex-col bg-components-panel-bg">
|
||||||
<div className="grid grid-cols-[1fr_auto_1fr] items-start px-6 pt-4">
|
<div className="grid grid-cols-[1fr_auto_1fr] items-start px-6 pt-4">
|
||||||
<div aria-hidden className="h-9 w-9" />
|
<div aria-hidden className="h-9 w-9" />
|
||||||
@ -745,7 +745,7 @@ function SwipeToOpenDemo() {
|
|||||||
<DrawerPortal container={portalContainer}>
|
<DrawerPortal container={portalContainer}>
|
||||||
<DrawerBackdrop className="absolute" />
|
<DrawerBackdrop className="absolute" />
|
||||||
<DrawerViewport className="absolute">
|
<DrawerViewport className="absolute">
|
||||||
<DrawerPopup className="absolute touch-auto data-[swipe-direction=right]:-right-12 data-[swipe-direction=right]:h-full data-[swipe-direction=right]:w-[calc(22.5rem_+_3rem)] data-[swipe-direction=right]:max-w-[calc(100%_+_3rem)] data-[swipe-direction=right]:transform-[translateX(var(--drawer-swipe-movement-x,0px))] data-starting-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_-_3rem_+_2px))] data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_-_3rem_+_2px))] data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]">
|
<DrawerPopup className="absolute touch-auto data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)] data-[swipe-direction=right]:-right-12 data-[swipe-direction=right]:h-full data-[swipe-direction=right]:w-[calc(22.5rem_+_3rem)] data-[swipe-direction=right]:max-w-[calc(100%_+_3rem)] data-[swipe-direction=right]:transform-[translateX(var(--drawer-swipe-movement-x,0px))] data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_-_3rem_+_2px))] data-starting-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_-_3rem_+_2px))]">
|
||||||
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pr-12 pb-0">
|
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pr-12 pb-0">
|
||||||
<div className="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
|
<div className="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
@ -792,7 +792,7 @@ function ActionSheetDemo() {
|
|||||||
<DrawerPortal>
|
<DrawerPortal>
|
||||||
<DrawerBackdrop className="fixed" />
|
<DrawerBackdrop className="fixed" />
|
||||||
<DrawerViewport className="flex items-end justify-center">
|
<DrawerViewport className="flex items-end justify-center">
|
||||||
<DrawerPopup className="pointer-events-none relative flex w-full max-w-80 flex-col gap-3 overflow-visible border-none bg-transparent px-4 pb-[calc(1rem_+_env(safe-area-inset-bottom,0px))] shadow-none data-[swipe-direction=down]:inset-auto data-[swipe-direction=down]:max-h-none data-[swipe-direction=down]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_+_1rem_+_2px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_+_1rem_+_2px))] data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)]">
|
<DrawerPopup className="pointer-events-none relative flex w-full max-w-80 flex-col gap-3 overflow-visible border-none bg-transparent px-4 pb-[calc(1rem_+_env(safe-area-inset-bottom,0px))] shadow-none data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)] data-[swipe-direction=down]:inset-auto data-[swipe-direction=down]:max-h-none data-[swipe-direction=down]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_+_1rem_+_2px))] data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%_+_1rem_+_2px))]">
|
||||||
<DrawerContent className="pointer-events-auto flex-none overflow-hidden rounded-2xl border-[0.5px] border-divider-subtle bg-components-panel-bg p-0 pb-0 shadow-xl">
|
<DrawerContent className="pointer-events-auto flex-none overflow-hidden rounded-2xl border-[0.5px] border-divider-subtle bg-components-panel-bg p-0 pb-0 shadow-xl">
|
||||||
<DrawerTitle className="sr-only">App actions</DrawerTitle>
|
<DrawerTitle className="sr-only">App actions</DrawerTitle>
|
||||||
<DrawerDescription className="sr-only">
|
<DrawerDescription className="sr-only">
|
||||||
@ -942,7 +942,7 @@ export const StackingAndAnimations: Story = {
|
|||||||
<DrawerPortal>
|
<DrawerPortal>
|
||||||
<DrawerBackdrop className="fixed" />
|
<DrawerBackdrop className="fixed" />
|
||||||
<DrawerViewport>
|
<DrawerViewport>
|
||||||
<DrawerPopup className="duration-500 ease-[cubic-bezier(0.32,0.72,0,1)] data-[swipe-direction=right]:max-w-105 data-[swipe-direction=right]:transform-[translateX(var(--drawer-swipe-movement-x,0px))] data-starting-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_+_2px))] data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_+_2px))] data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)] data-swiping:shadow-none data-nested-drawer-open:brightness-95 data-nested-drawer-open:[&_[data-animation-content]]:opacity-0 data-nested-drawer-swiping:[&_[data-animation-content]]:opacity-100">
|
<DrawerPopup className="duration-500 ease-[cubic-bezier(0.32,0.72,0,1)] data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)] data-nested-drawer-open:brightness-95 data-swiping:shadow-none data-[swipe-direction=right]:max-w-105 data-[swipe-direction=right]:transform-[translateX(var(--drawer-swipe-movement-x,0px))] data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_+_2px))] data-starting-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_+_2px))] data-nested-drawer-open:[&_[data-animation-content]]:opacity-0 data-nested-drawer-swiping:[&_[data-animation-content]]:opacity-100">
|
||||||
<DrawerContent data-animation-content className="flex min-h-0 flex-1 flex-col p-0 pb-0 transition-opacity duration-300">
|
<DrawerContent data-animation-content className="flex min-h-0 flex-1 flex-col p-0 pb-0 transition-opacity duration-300">
|
||||||
<div className="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
|
<div className="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
@ -966,7 +966,7 @@ export const StackingAndAnimations: Story = {
|
|||||||
</DrawerTrigger>
|
</DrawerTrigger>
|
||||||
<DrawerPortal>
|
<DrawerPortal>
|
||||||
<DrawerViewport>
|
<DrawerViewport>
|
||||||
<DrawerPopup className="duration-500 ease-[cubic-bezier(0.32,0.72,0,1)] data-[swipe-direction=right]:max-w-105 data-[swipe-direction=right]:transform-[translateX(var(--drawer-swipe-movement-x,0px))] data-starting-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_+_2px))] data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_+_2px))] data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)] data-swiping:shadow-none">
|
<DrawerPopup className="duration-500 ease-[cubic-bezier(0.32,0.72,0,1)] data-ending-style:duration-[calc(var(--drawer-swipe-strength)_*_400ms)] data-swiping:shadow-none data-[swipe-direction=right]:max-w-105 data-[swipe-direction=right]:transform-[translateX(var(--drawer-swipe-movement-x,0px))] data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_+_2px))] data-starting-style:data-[swipe-direction=right]:transform-[translateX(calc(100%_+_2px))]">
|
||||||
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-0">
|
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-0">
|
||||||
<div className="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
|
<div className="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
@ -1027,7 +1027,7 @@ export const InstantRightPanel: Story = {
|
|||||||
</DrawerTrigger>
|
</DrawerTrigger>
|
||||||
<DrawerPortal>
|
<DrawerPortal>
|
||||||
<DrawerViewport className="pointer-events-none">
|
<DrawerViewport className="pointer-events-none">
|
||||||
<DrawerPopup className="pointer-events-auto transition-none duration-0 data-[swipe-direction=right]:max-w-105 data-[swipe-direction=right]:transform-[translateX(var(--drawer-swipe-movement-x,0px))] data-starting-style:data-[swipe-direction=right]:transform-[translateX(0)] data-ending-style:data-[swipe-direction=right]:transform-[translateX(0)] data-swiping:shadow-none">
|
<DrawerPopup className="pointer-events-auto transition-none duration-0 data-swiping:shadow-none data-[swipe-direction=right]:max-w-105 data-[swipe-direction=right]:transform-[translateX(var(--drawer-swipe-movement-x,0px))] data-ending-style:data-[swipe-direction=right]:transform-[translateX(0)] data-starting-style:data-[swipe-direction=right]:transform-[translateX(0)]">
|
||||||
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-0">
|
<DrawerContent className="flex min-h-0 flex-1 flex-col p-0 pb-0">
|
||||||
<div className="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
|
<div className="flex shrink-0 items-start justify-between gap-4 px-6 pt-6 pb-4">
|
||||||
<div className="min-w-0">
|
<div className="min-w-0">
|
||||||
|
|||||||
@ -60,16 +60,16 @@ export function DrawerPopup({
|
|||||||
return (
|
return (
|
||||||
<BaseDrawer.Popup
|
<BaseDrawer.Popup
|
||||||
className={cn(
|
className={cn(
|
||||||
'fixed z-50 flex min-h-0 flex-col overflow-hidden border-[0.5px] border-components-panel-border bg-components-panel-bg text-text-primary shadow-xl outline-hidden touch-none',
|
'fixed z-50 flex min-h-0 touch-none flex-col overflow-hidden border-[0.5px] border-components-panel-border bg-components-panel-bg text-text-primary shadow-xl outline-hidden',
|
||||||
'transition-[transform,opacity,box-shadow] duration-200 data-swiping:select-none data-swiping:duration-0 motion-reduce:transition-none',
|
'transition-[transform,opacity,box-shadow] duration-200 data-swiping:duration-0 data-swiping:select-none motion-reduce:transition-none',
|
||||||
'data-[swipe-direction=right]:inset-y-0 data-[swipe-direction=right]:right-0 data-[swipe-direction=right]:h-dvh data-[swipe-direction=right]:w-120 data-[swipe-direction=right]:max-w-[calc(100vw-2rem)] data-[swipe-direction=right]:rounded-l-2xl data-[swipe-direction=right]:border-r-0 data-[swipe-direction=right]:transform-[translateX(var(--drawer-swipe-movement-x,0px))]',
|
'data-[swipe-direction=right]:inset-y-0 data-[swipe-direction=right]:right-0 data-[swipe-direction=right]:h-dvh data-[swipe-direction=right]:w-120 data-[swipe-direction=right]:max-w-[calc(100vw-2rem)] data-[swipe-direction=right]:transform-[translateX(var(--drawer-swipe-movement-x,0px))] data-[swipe-direction=right]:rounded-l-2xl data-[swipe-direction=right]:border-r-0',
|
||||||
'data-starting-style:data-[swipe-direction=right]:transform-[translateX(calc(100%+2px))] data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(100%+2px))]',
|
'data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(100%+2px))] data-starting-style:data-[swipe-direction=right]:transform-[translateX(calc(100%+2px))]',
|
||||||
'data-[swipe-direction=left]:inset-y-0 data-[swipe-direction=left]:left-0 data-[swipe-direction=left]:h-dvh data-[swipe-direction=left]:w-120 data-[swipe-direction=left]:max-w-[calc(100vw-2rem)] data-[swipe-direction=left]:rounded-r-2xl data-[swipe-direction=left]:border-l-0 data-[swipe-direction=left]:transform-[translateX(var(--drawer-swipe-movement-x,0px))]',
|
'data-[swipe-direction=left]:inset-y-0 data-[swipe-direction=left]:left-0 data-[swipe-direction=left]:h-dvh data-[swipe-direction=left]:w-120 data-[swipe-direction=left]:max-w-[calc(100vw-2rem)] data-[swipe-direction=left]:transform-[translateX(var(--drawer-swipe-movement-x,0px))] data-[swipe-direction=left]:rounded-r-2xl data-[swipe-direction=left]:border-l-0',
|
||||||
'data-starting-style:data-[swipe-direction=left]:transform-[translateX(calc(-100%-2px))] data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(-100%-2px))]',
|
'data-ending-style:data-[swipe-direction=left]:transform-[translateX(calc(-100%-2px))] data-starting-style:data-[swipe-direction=left]:transform-[translateX(calc(-100%-2px))]',
|
||||||
'data-[swipe-direction=down]:inset-x-0 data-[swipe-direction=down]:bottom-0 data-[swipe-direction=down]:max-h-[calc(100dvh-2rem)] data-[swipe-direction=down]:w-full data-[swipe-direction=down]:rounded-t-2xl data-[swipe-direction=down]:border-b-0 data-[swipe-direction=down]:transform-[translateY(calc(var(--drawer-snap-point-offset,0px)+var(--drawer-swipe-movement-y,0px)))]',
|
'data-[swipe-direction=down]:inset-x-0 data-[swipe-direction=down]:bottom-0 data-[swipe-direction=down]:max-h-[calc(100dvh-2rem)] data-[swipe-direction=down]:w-full data-[swipe-direction=down]:transform-[translateY(calc(var(--drawer-snap-point-offset,0px)+var(--drawer-swipe-movement-y,0px)))] data-[swipe-direction=down]:rounded-t-2xl data-[swipe-direction=down]:border-b-0',
|
||||||
'data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%+2px))] data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%+2px))]',
|
'data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(100%+2px))] data-starting-style:data-[swipe-direction=down]:transform-[translateY(calc(100%+2px))]',
|
||||||
'data-[swipe-direction=up]:inset-x-0 data-[swipe-direction=up]:top-0 data-[swipe-direction=up]:max-h-[calc(100dvh-2rem)] data-[swipe-direction=up]:w-full data-[swipe-direction=up]:rounded-b-2xl data-[swipe-direction=up]:border-t-0 data-[swipe-direction=up]:transform-[translateY(var(--drawer-swipe-movement-y,0px))]',
|
'data-[swipe-direction=up]:inset-x-0 data-[swipe-direction=up]:top-0 data-[swipe-direction=up]:max-h-[calc(100dvh-2rem)] data-[swipe-direction=up]:w-full data-[swipe-direction=up]:transform-[translateY(var(--drawer-swipe-movement-y,0px))] data-[swipe-direction=up]:rounded-b-2xl data-[swipe-direction=up]:border-t-0',
|
||||||
'data-starting-style:data-[swipe-direction=up]:transform-[translateY(calc(-100%-2px))] data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(-100%-2px))]',
|
'data-ending-style:data-[swipe-direction=up]:transform-[translateY(calc(-100%-2px))] data-starting-style:data-[swipe-direction=up]:transform-[translateY(calc(-100%-2px))]',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@ -98,7 +98,7 @@ export function FieldDescription({
|
|||||||
}: FieldDescriptionProps) {
|
}: FieldDescriptionProps) {
|
||||||
return (
|
return (
|
||||||
<BaseField.Description
|
<BaseField.Description
|
||||||
className={cn('py-0.5 text-text-tertiary body-xs-regular', className)}
|
className={cn('py-0.5 body-xs-regular text-text-tertiary', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
@ -116,7 +116,7 @@ export function FieldError({
|
|||||||
}: FieldErrorProps) {
|
}: FieldErrorProps) {
|
||||||
return (
|
return (
|
||||||
<BaseField.Error
|
<BaseField.Error
|
||||||
className={cn('py-0.5 text-text-destructive body-xs-regular', className)}
|
className={cn('py-0.5 body-xs-regular text-text-destructive', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -34,7 +34,7 @@ export function FieldsetLegend({
|
|||||||
}: FieldsetLegendProps) {
|
}: FieldsetLegendProps) {
|
||||||
return (
|
return (
|
||||||
<BaseFieldset.Legend
|
<BaseFieldset.Legend
|
||||||
className={cn('mb-1 py-1 text-text-secondary system-sm-medium', className)}
|
className={cn('mb-1 py-1 system-sm-medium text-text-secondary', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -226,7 +226,7 @@ export function FileTreeGuide({
|
|||||||
const defaultProps: useRender.ElementProps<'span'> = {
|
const defaultProps: useRender.ElementProps<'span'> = {
|
||||||
'aria-hidden': true,
|
'aria-hidden': true,
|
||||||
'className': cn(
|
'className': cn(
|
||||||
'relative h-6 w-5 shrink-0 before:absolute before:bottom-[-1px] before:left-1/2 before:top-0 before:w-px before:-translate-x-1/2 before:bg-divider-subtle',
|
'relative h-6 w-5 shrink-0 before:absolute before:top-0 before:bottom-[-1px] before:left-1/2 before:w-px before:-translate-x-1/2 before:bg-divider-subtle',
|
||||||
className,
|
className,
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -287,8 +287,8 @@ export function FileTreeIcon({
|
|||||||
type === 'folder'
|
type === 'folder'
|
||||||
? (
|
? (
|
||||||
<React.Fragment>
|
<React.Fragment>
|
||||||
<span className="size-4 i-ri-folder-line group-data-panel-open/file-tree-row:hidden" />
|
<span className="i-ri-folder-line size-4 group-data-panel-open/file-tree-row:hidden" />
|
||||||
<span className="hidden size-4 text-text-secondary i-ri-folder-open-line group-data-panel-open/file-tree-row:block" />
|
<span className="i-ri-folder-open-line hidden size-4 text-text-secondary group-data-panel-open/file-tree-row:block" />
|
||||||
</React.Fragment>
|
</React.Fragment>
|
||||||
)
|
)
|
||||||
: <span className={cn('size-4', fileTreeIconClassNames[type])} />
|
: <span className={cn('size-4', fileTreeIconClassNames[type])} />
|
||||||
|
|||||||
@ -30,7 +30,7 @@ type Story = StoryObj<typeof meta>
|
|||||||
export const Basic: Story = {
|
export const Basic: Story = {
|
||||||
render: () => (
|
render: () => (
|
||||||
<div className="w-80">
|
<div className="w-80">
|
||||||
<label htmlFor="workspace-name" className="mb-1 block w-fit py-1 text-text-secondary system-sm-medium">
|
<label htmlFor="workspace-name" className="mb-1 block w-fit py-1 system-sm-medium text-text-secondary">
|
||||||
Workspace name
|
Workspace name
|
||||||
</label>
|
</label>
|
||||||
<Input
|
<Input
|
||||||
@ -46,15 +46,15 @@ export const Basic: Story = {
|
|||||||
export const Sizes: Story = {
|
export const Sizes: Story = {
|
||||||
render: () => (
|
render: () => (
|
||||||
<div className="grid w-80 gap-3">
|
<div className="grid w-80 gap-3">
|
||||||
<label className="grid gap-1 text-text-secondary system-sm-medium" htmlFor="small-input">
|
<label className="grid gap-1 system-sm-medium text-text-secondary" htmlFor="small-input">
|
||||||
Small
|
Small
|
||||||
<Input id="small-input" size="small" name="smallInput" placeholder="e.g. tag…" autoComplete="off" />
|
<Input id="small-input" size="small" name="smallInput" placeholder="e.g. tag…" autoComplete="off" />
|
||||||
</label>
|
</label>
|
||||||
<label className="grid gap-1 text-text-secondary system-sm-medium" htmlFor="medium-input">
|
<label className="grid gap-1 system-sm-medium text-text-secondary" htmlFor="medium-input">
|
||||||
Medium
|
Medium
|
||||||
<Input id="medium-input" name="mediumInput" placeholder="e.g. Production API…" autoComplete="off" />
|
<Input id="medium-input" name="mediumInput" placeholder="e.g. Production API…" autoComplete="off" />
|
||||||
</label>
|
</label>
|
||||||
<label className="grid gap-1 text-text-secondary system-sm-medium" htmlFor="large-input">
|
<label className="grid gap-1 system-sm-medium text-text-secondary" htmlFor="large-input">
|
||||||
Large
|
Large
|
||||||
<Input id="large-input" size="large" name="largeInput" placeholder="e.g. Customer portal…" autoComplete="off" />
|
<Input id="large-input" size="large" name="largeInput" placeholder="e.g. Customer portal…" autoComplete="off" />
|
||||||
</label>
|
</label>
|
||||||
@ -66,11 +66,11 @@ export const States: Story = {
|
|||||||
render: () => (
|
render: () => (
|
||||||
<div className="grid w-80 gap-3">
|
<div className="grid w-80 gap-3">
|
||||||
<div className="grid gap-1">
|
<div className="grid gap-1">
|
||||||
<label className="text-text-secondary system-sm-medium" htmlFor="placeholder-state">Placeholder</label>
|
<label className="system-sm-medium text-text-secondary" htmlFor="placeholder-state">Placeholder</label>
|
||||||
<Input id="placeholder-state" name="placeholderState" placeholder="e.g. Search datasets…" autoComplete="off" />
|
<Input id="placeholder-state" name="placeholderState" placeholder="e.g. Search datasets…" autoComplete="off" />
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-1">
|
<div className="grid gap-1">
|
||||||
<label className="text-text-secondary system-sm-medium" htmlFor="filled-state">Filled</label>
|
<label className="system-sm-medium text-text-secondary" htmlFor="filled-state">Filled</label>
|
||||||
<Input id="filled-state" name="filledState" defaultValue="Customer knowledge base" autoComplete="off" />
|
<Input id="filled-state" name="filledState" defaultValue="Customer knowledge base" autoComplete="off" />
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-1">
|
<div className="grid gap-1">
|
||||||
@ -88,11 +88,11 @@ export const States: Story = {
|
|||||||
</Field>
|
</Field>
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-1">
|
<div className="grid gap-1">
|
||||||
<label className="text-text-secondary system-sm-medium" htmlFor="disabled-state">Disabled</label>
|
<label className="system-sm-medium text-text-secondary" htmlFor="disabled-state">Disabled</label>
|
||||||
<Input id="disabled-state" disabled name="disabledEmail" type="email" inputMode="email" placeholder="name@example.com…" autoComplete="email" spellCheck={false} />
|
<Input id="disabled-state" disabled name="disabledEmail" type="email" inputMode="email" placeholder="name@example.com…" autoComplete="email" spellCheck={false} />
|
||||||
</div>
|
</div>
|
||||||
<div className="grid gap-1">
|
<div className="grid gap-1">
|
||||||
<label className="text-text-secondary system-sm-medium" htmlFor="readonly-state">Read-only</label>
|
<label className="system-sm-medium text-text-secondary" htmlFor="readonly-state">Read-only</label>
|
||||||
<Input id="readonly-state" readOnly name="endpoint" type="url" inputMode="url" defaultValue="https://api.example.com" autoComplete="url" spellCheck={false} />
|
<Input id="readonly-state" readOnly name="endpoint" type="url" inputMode="url" defaultValue="https://api.example.com" autoComplete="url" spellCheck={false} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -71,6 +71,7 @@ const HotkeyKbdGroup = ({
|
|||||||
}) => (
|
}) => (
|
||||||
<KbdGroup>
|
<KbdGroup>
|
||||||
{displayKeys(hotkey, platform).map((key, index) => (
|
{displayKeys(hotkey, platform).map((key, index) => (
|
||||||
|
// eslint-disable-next-line react/no-array-index-key -- Repeated display keys are static, ordered tokens with no component state.
|
||||||
<Kbd key={`${key}-${index}`} color={color}>
|
<Kbd key={`${key}-${index}`} color={color}>
|
||||||
{key}
|
{key}
|
||||||
</Kbd>
|
</Kbd>
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import { cva } from 'class-variance-authority'
|
|||||||
import { cn } from '../cn'
|
import { cn } from '../cn'
|
||||||
|
|
||||||
const kbdVariants = cva(
|
const kbdVariants = cva(
|
||||||
'pointer-events-none inline-flex h-4 min-w-4 select-none items-center justify-center rounded-sm px-px font-sans system-kbd capitalize not-italic',
|
'pointer-events-none inline-flex h-4 min-w-4 items-center justify-center rounded-sm px-px font-sans system-kbd capitalize not-italic select-none',
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
color: {
|
color: {
|
||||||
|
|||||||
@ -67,7 +67,7 @@ function NumberFieldExample({
|
|||||||
}: NumberFieldExampleProps) {
|
}: NumberFieldExampleProps) {
|
||||||
return (
|
return (
|
||||||
<div className="grid w-80 gap-1">
|
<div className="grid w-80 gap-1">
|
||||||
<label htmlFor={id} className="text-text-secondary system-sm-medium">
|
<label htmlFor={id} className="system-sm-medium text-text-secondary">
|
||||||
{label}
|
{label}
|
||||||
</label>
|
</label>
|
||||||
<NumberField
|
<NumberField
|
||||||
@ -281,7 +281,7 @@ function FormDemo() {
|
|||||||
<Button type="submit" variant="primary">Save Settings</Button>
|
<Button type="submit" variant="primary">Save Settings</Button>
|
||||||
</div>
|
</div>
|
||||||
{savedValue && (
|
{savedValue && (
|
||||||
<div className="rounded-lg bg-background-section px-3 py-2 text-text-secondary system-xs-regular">
|
<div className="rounded-lg bg-background-section px-3 py-2 system-xs-regular text-text-secondary">
|
||||||
Saved:
|
Saved:
|
||||||
{' '}
|
{' '}
|
||||||
{savedValue}
|
{savedValue}
|
||||||
|
|||||||
@ -255,6 +255,18 @@ describe('Pagination primitive', () => {
|
|||||||
expect(screen.container.querySelector('ol')).not.toBeInTheDocument()
|
expect(screen.container.querySelector('ol')).not.toBeInTheDocument()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('does not invoke a custom page list renderer when there are no pages', async () => {
|
||||||
|
const renderPageList = vi.fn(() => <ol />)
|
||||||
|
|
||||||
|
await render(
|
||||||
|
<PaginationRoot page={1} totalPages={0} onPageChange={vi.fn()}>
|
||||||
|
<PaginationPageList render={renderPageList} />
|
||||||
|
</PaginationRoot>,
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(renderPageList).not.toHaveBeenCalled()
|
||||||
|
})
|
||||||
|
|
||||||
it('allows custom page rendering while keeping the shared context', async () => {
|
it('allows custom page rendering while keeping the shared context', async () => {
|
||||||
const onPageChange = vi.fn()
|
const onPageChange = vi.fn()
|
||||||
const screen = await render(
|
const screen = await render(
|
||||||
|
|||||||
@ -228,7 +228,7 @@ export function PaginationNavigation({
|
|||||||
...props
|
...props
|
||||||
}: PaginationNavigationProps) {
|
}: PaginationNavigationProps) {
|
||||||
const defaultProps: useRender.ElementProps<'div'> = {
|
const defaultProps: useRender.ElementProps<'div'> = {
|
||||||
className: cn('flex shrink-0 items-center justify-self-start gap-0.5 rounded-[10px] bg-background-section-burn p-0.5', className),
|
className: cn('flex shrink-0 items-center gap-0.5 justify-self-start rounded-[10px] bg-background-section-burn p-0.5', className),
|
||||||
}
|
}
|
||||||
|
|
||||||
return useRender({
|
return useRender({
|
||||||
@ -355,7 +355,7 @@ export function PaginationPageJump({
|
|||||||
return (
|
return (
|
||||||
<span
|
<span
|
||||||
data-page-summary={`${pagination.page}/${pagination.totalPages}`}
|
data-page-summary={`${pagination.page}/${pagination.totalPages}`}
|
||||||
className="inline-grid h-7 system-xs-medium tabular-nums after:invisible after:col-start-1 after:row-start-1 after:py-1.5 after:pe-3 after:ps-2 after:content-[attr(data-page-summary)]"
|
className="inline-grid h-7 system-xs-medium tabular-nums after:invisible after:col-start-1 after:row-start-1 after:py-1.5 after:ps-2 after:pe-3 after:content-[attr(data-page-summary)]"
|
||||||
>
|
>
|
||||||
<NumberField
|
<NumberField
|
||||||
key={pagination.page}
|
key={pagination.page}
|
||||||
@ -375,6 +375,7 @@ export function PaginationPageJump({
|
|||||||
>
|
>
|
||||||
<NumberFieldInput
|
<NumberFieldInput
|
||||||
aria-label={inputLabel}
|
aria-label={inputLabel}
|
||||||
|
// eslint-disable-next-line jsx-a11y/no-autofocus -- Editing starts after an explicit user action and focus must move to the replacement input.
|
||||||
autoFocus
|
autoFocus
|
||||||
className="px-2 py-1.5 text-center system-xs-medium tabular-nums"
|
className="px-2 py-1.5 text-center system-xs-medium tabular-nums"
|
||||||
onBlur={() => requestAnimationFrame(() => setEditing(false))}
|
onBlur={() => requestAnimationFrame(() => setEditing(false))}
|
||||||
@ -410,7 +411,7 @@ export function PaginationPageJump({
|
|||||||
type="button"
|
type="button"
|
||||||
aria-label={ariaLabel ?? `Edit page number, current page ${pagination.page} of ${pagination.totalPages}`}
|
aria-label={ariaLabel ?? `Edit page number, current page ${pagination.page} of ${pagination.totalPages}`}
|
||||||
className={cn(
|
className={cn(
|
||||||
'inline-flex h-7 touch-manipulation items-center justify-center gap-0.5 rounded-lg px-2 py-1.5 system-xs-medium tabular-nums text-text-secondary outline-hidden transition-colors hover:cursor-text hover:bg-state-base-hover-alt focus-visible:ring-2 focus-visible:ring-state-accent-solid motion-reduce:transition-none',
|
'inline-flex h-7 touch-manipulation items-center justify-center gap-0.5 rounded-lg px-2 py-1.5 system-xs-medium text-text-secondary tabular-nums outline-hidden transition-colors hover:cursor-text hover:bg-state-base-hover-alt focus-visible:ring-2 focus-visible:ring-state-accent-solid motion-reduce:transition-none',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
onClick={(event) => {
|
onClick={(event) => {
|
||||||
@ -440,11 +441,8 @@ export function PaginationPageList({
|
|||||||
}: PaginationPageListProps) {
|
}: PaginationPageListProps) {
|
||||||
const pagination = usePaginationContext('PaginationPageList')
|
const pagination = usePaginationContext('PaginationPageList')
|
||||||
|
|
||||||
if (!pagination.hasPages)
|
|
||||||
return null
|
|
||||||
|
|
||||||
const defaultProps: useRender.ElementProps<'ol'> = {
|
const defaultProps: useRender.ElementProps<'ol'> = {
|
||||||
className: cn('col-start-2 flex min-w-0 list-none items-center justify-self-center gap-0.5', className),
|
className: cn('col-start-2 flex min-w-0 list-none items-center gap-0.5 justify-self-center', className),
|
||||||
children: pagination.items.map(item => (
|
children: pagination.items.map(item => (
|
||||||
<li key={item}>
|
<li key={item}>
|
||||||
{typeof item === 'number'
|
{typeof item === 'number'
|
||||||
@ -458,6 +456,7 @@ export function PaginationPageList({
|
|||||||
defaultTagName: 'ol',
|
defaultTagName: 'ol',
|
||||||
render,
|
render,
|
||||||
props: mergeProps<'ol'>(defaultProps, props),
|
props: mergeProps<'ol'>(defaultProps, props),
|
||||||
|
enabled: pagination.hasPages,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -483,7 +482,7 @@ export function PaginationPage({
|
|||||||
aria-current={current ? 'page' : undefined}
|
aria-current={current ? 'page' : undefined}
|
||||||
aria-label={ariaLabel ?? (current ? `Page ${page}, current page` : `Go to page ${page}`)}
|
aria-label={ariaLabel ?? (current ? `Page ${page}, current page` : `Go to page ${page}`)}
|
||||||
className={cn(
|
className={cn(
|
||||||
'inline-flex h-8 min-w-8 touch-manipulation items-center justify-center rounded-lg px-1 py-2 system-sm-medium tabular-nums text-text-tertiary outline-hidden hover:bg-components-button-ghost-bg-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid',
|
'inline-flex h-8 min-w-8 touch-manipulation items-center justify-center rounded-lg px-1 py-2 system-sm-medium text-text-tertiary tabular-nums outline-hidden hover:bg-components-button-ghost-bg-hover hover:text-text-secondary focus-visible:ring-2 focus-visible:ring-state-accent-solid',
|
||||||
current && 'bg-components-button-tertiary-bg text-components-button-tertiary-text hover:bg-components-button-ghost-bg-hover',
|
current && 'bg-components-button-tertiary-bg text-components-button-tertiary-text hover:bg-components-button-ghost-bg-hover',
|
||||||
className,
|
className,
|
||||||
)}
|
)}
|
||||||
@ -537,8 +536,8 @@ export function PaginationPageSize<Value extends number = number>({
|
|||||||
className,
|
className,
|
||||||
}: PaginationPageSizeProps<Value>) {
|
}: PaginationPageSizeProps<Value>) {
|
||||||
return (
|
return (
|
||||||
<div className={cn('group/page-size col-start-3 flex shrink-0 items-center justify-end justify-self-end gap-2', className)}>
|
<div className={cn('group/page-size col-start-3 flex shrink-0 items-center justify-end gap-2 justify-self-end', className)}>
|
||||||
<div className="w-13 shrink-0 text-end system-2xs-regular-uppercase text-text-tertiary opacity-0 transition-opacity group-hover/page-size:opacity-100 group-focus-within/page-size:opacity-100 motion-reduce:transition-none">
|
<div className="w-13 shrink-0 text-end system-2xs-regular-uppercase text-text-tertiary opacity-0 transition-opacity group-focus-within/page-size:opacity-100 group-hover/page-size:opacity-100 motion-reduce:transition-none">
|
||||||
{label}
|
{label}
|
||||||
</div>
|
</div>
|
||||||
<SegmentedControl
|
<SegmentedControl
|
||||||
@ -648,12 +647,12 @@ export function PaginationSkeleton({
|
|||||||
'className': cn('flex w-full min-w-0 items-center justify-between px-6 py-3 select-none', className),
|
'className': cn('flex w-full min-w-0 items-center justify-between px-6 py-3 select-none', className),
|
||||||
'children': (
|
'children': (
|
||||||
<div className="grid w-full min-w-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-2">
|
<div className="grid w-full min-w-0 grid-cols-[minmax(0,1fr)_auto_minmax(0,1fr)] items-center gap-2">
|
||||||
<div className="flex shrink-0 items-center justify-self-start gap-0.5 rounded-[10px] bg-background-section-burn p-0.5">
|
<div className="flex shrink-0 items-center gap-0.5 justify-self-start rounded-[10px] bg-background-section-burn p-0.5">
|
||||||
<div className="size-7 animate-pulse rounded-lg bg-state-base-hover motion-reduce:animate-none" />
|
<div className="size-7 animate-pulse rounded-lg bg-state-base-hover motion-reduce:animate-none" />
|
||||||
<div className="h-7 min-w-14 animate-pulse rounded-lg bg-state-base-hover motion-reduce:animate-none" />
|
<div className="h-7 min-w-14 animate-pulse rounded-lg bg-state-base-hover motion-reduce:animate-none" />
|
||||||
<div className="size-7 animate-pulse rounded-lg bg-state-base-hover motion-reduce:animate-none" />
|
<div className="size-7 animate-pulse rounded-lg bg-state-base-hover motion-reduce:animate-none" />
|
||||||
</div>
|
</div>
|
||||||
<div className="col-start-2 flex items-center justify-self-center gap-0.5">
|
<div className="col-start-2 flex items-center gap-0.5 justify-self-center">
|
||||||
{range(1, 8).map(item => (
|
{range(1, 8).map(item => (
|
||||||
<div key={item} className="h-8 min-w-8 animate-pulse rounded-lg bg-state-base-hover motion-reduce:animate-none" />
|
<div key={item} className="h-8 min-w-8 animate-pulse rounded-lg bg-state-base-hover motion-reduce:animate-none" />
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -1,6 +1,5 @@
|
|||||||
import type { Meta, StoryObj } from '@storybook/react-vite'
|
import type { Meta, StoryObj } from '@storybook/react-vite'
|
||||||
import type { Placement } from '.'
|
import type { Placement } from '.'
|
||||||
import { Button } from '@langgenius/dify-ui/button'
|
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import {
|
import {
|
||||||
Popover,
|
Popover,
|
||||||
@ -10,6 +9,7 @@ import {
|
|||||||
PopoverTitle,
|
PopoverTitle,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from '.'
|
} from '.'
|
||||||
|
import { Button } from '../button'
|
||||||
import { Kbd, KbdGroup } from '../kbd'
|
import { Kbd, KbdGroup } from '../kbd'
|
||||||
|
|
||||||
const triggerButtonClassName = 'rounded-lg border border-divider-subtle bg-components-button-secondary-bg px-3 py-1.5 text-sm text-text-secondary shadow-xs outline-hidden hover:bg-state-base-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid'
|
const triggerButtonClassName = 'rounded-lg border border-divider-subtle bg-components-button-secondary-bg px-3 py-1.5 text-sm text-text-secondary shadow-xs outline-hidden hover:bg-state-base-hover focus-visible:ring-2 focus-visible:ring-state-accent-solid'
|
||||||
|
|||||||
@ -61,7 +61,7 @@ export function RadioControl({
|
|||||||
'inline-flex size-4 shrink-0 touch-manipulation items-center justify-center rounded-full p-0 transition-colors motion-reduce:transition-none',
|
'inline-flex size-4 shrink-0 touch-manipulation items-center justify-center rounded-full p-0 transition-colors motion-reduce:transition-none',
|
||||||
'border border-components-radio-border bg-components-radio-bg shadow-xs shadow-shadow-shadow-3',
|
'border border-components-radio-border bg-components-radio-bg shadow-xs shadow-shadow-shadow-3',
|
||||||
'hover:border-components-radio-border-hover hover:bg-components-radio-bg-hover',
|
'hover:border-components-radio-border-hover hover:bg-components-radio-bg-hover',
|
||||||
'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:ring-offset-0',
|
'focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:ring-offset-0 focus-visible:outline-hidden',
|
||||||
'data-checked:border-[5px] data-checked:border-components-radio-border-checked data-checked:hover:border-components-radio-border-checked-hover',
|
'data-checked:border-[5px] data-checked:border-components-radio-border-checked data-checked:hover:border-components-radio-border-checked-hover',
|
||||||
'data-disabled:cursor-not-allowed data-disabled:border-components-radio-border-disabled data-disabled:bg-components-radio-bg-disabled',
|
'data-disabled:cursor-not-allowed data-disabled:border-components-radio-border-disabled data-disabled:bg-components-radio-bg-disabled',
|
||||||
'data-disabled:hover:border-components-radio-border-disabled data-disabled:hover:bg-components-radio-bg-disabled',
|
'data-disabled:hover:border-components-radio-border-disabled data-disabled:hover:bg-components-radio-bg-disabled',
|
||||||
@ -86,7 +86,7 @@ export function Radio<Value = string>({
|
|||||||
'inline-flex size-4 shrink-0 touch-manipulation items-center justify-center rounded-full p-0 transition-colors motion-reduce:transition-none',
|
'inline-flex size-4 shrink-0 touch-manipulation items-center justify-center rounded-full p-0 transition-colors motion-reduce:transition-none',
|
||||||
'border border-components-radio-border bg-components-radio-bg shadow-xs shadow-shadow-shadow-3',
|
'border border-components-radio-border bg-components-radio-bg shadow-xs shadow-shadow-shadow-3',
|
||||||
'hover:border-components-radio-border-hover hover:bg-components-radio-bg-hover',
|
'hover:border-components-radio-border-hover hover:bg-components-radio-bg-hover',
|
||||||
'focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:ring-offset-0',
|
'focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:ring-offset-0 focus-visible:outline-hidden',
|
||||||
'data-checked:border-[5px] data-checked:border-components-radio-border-checked data-checked:hover:border-components-radio-border-checked-hover',
|
'data-checked:border-[5px] data-checked:border-components-radio-border-checked data-checked:hover:border-components-radio-border-checked-hover',
|
||||||
'data-disabled:cursor-not-allowed data-disabled:border-components-radio-border-disabled data-disabled:bg-components-radio-bg-disabled',
|
'data-disabled:cursor-not-allowed data-disabled:border-components-radio-border-disabled data-disabled:bg-components-radio-bg-disabled',
|
||||||
'data-disabled:hover:border-components-radio-border-disabled data-disabled:hover:bg-components-radio-bg-disabled',
|
'data-disabled:hover:border-components-radio-border-disabled data-disabled:hover:bg-components-radio-bg-disabled',
|
||||||
|
|||||||
@ -68,7 +68,7 @@ function StorySection({
|
|||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<div className="system-xs-medium-uppercase text-text-tertiary">{eyebrow}</div>
|
<div className="system-xs-medium-uppercase text-text-tertiary">{eyebrow}</div>
|
||||||
<h3 className="system-md-semibold text-text-primary">{title}</h3>
|
<h3 className="system-md-semibold text-text-primary">{title}</h3>
|
||||||
<p className="max-w-[72ch] text-pretty system-sm-regular text-text-secondary">{description}</p>
|
<p className="max-w-[72ch] system-sm-regular text-pretty text-text-secondary">{description}</p>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-5 flex justify-center">
|
<div className="mt-5 flex justify-center">
|
||||||
{children}
|
{children}
|
||||||
@ -103,7 +103,7 @@ export const Anatomy: Story = {
|
|||||||
>
|
>
|
||||||
<ScrollAreaRoot className="relative h-75 w-full max-w-105 min-w-0">
|
<ScrollAreaRoot className="relative h-75 w-full max-w-105 min-w-0">
|
||||||
<ScrollAreaViewport aria-label="Scrollable anatomy example" role="region" className="h-full max-h-full max-w-full rounded-xl border-[0.5px] border-divider-subtle bg-components-panel-bg">
|
<ScrollAreaViewport aria-label="Scrollable anatomy example" role="region" className="h-full max-h-full max-w-full rounded-xl border-[0.5px] border-divider-subtle bg-components-panel-bg">
|
||||||
<VerticalContent className="flex flex-col gap-4 py-2 pl-3 pr-5 text-text-secondary system-sm-regular leading-6">
|
<VerticalContent className="flex flex-col gap-4 py-2 pr-5 pl-3 system-sm-regular leading-6 text-text-secondary">
|
||||||
{articleParagraphs.map(paragraph => (
|
{articleParagraphs.map(paragraph => (
|
||||||
<p key={paragraph}>
|
<p key={paragraph}>
|
||||||
{paragraph}
|
{paragraph}
|
||||||
@ -128,7 +128,7 @@ export const Vertical: Story = {
|
|||||||
>
|
>
|
||||||
<ScrollAreaRoot className="relative h-90 w-full max-w-130 min-w-0">
|
<ScrollAreaRoot className="relative h-90 w-full max-w-130 min-w-0">
|
||||||
<ScrollAreaViewport aria-label="Long form content" role="region" className="h-full max-h-full max-w-full rounded-xl border-[0.5px] border-divider-subtle bg-components-panel-bg">
|
<ScrollAreaViewport aria-label="Long form content" role="region" className="h-full max-h-full max-w-full rounded-xl border-[0.5px] border-divider-subtle bg-components-panel-bg">
|
||||||
<VerticalContent className="flex flex-col gap-4 p-4 pr-6 text-text-secondary system-sm-regular leading-6">
|
<VerticalContent className="flex flex-col gap-4 p-4 pr-6 system-sm-regular leading-6 text-text-secondary">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<div className="system-xs-medium-uppercase text-text-tertiary">Article</div>
|
<div className="system-xs-medium-uppercase text-text-tertiary">Article</div>
|
||||||
<div className="system-md-semibold text-text-primary">Scrollable text region</div>
|
<div className="system-md-semibold text-text-primary">Scrollable text region</div>
|
||||||
@ -201,7 +201,7 @@ export const ScrollFade: Story = {
|
|||||||
'mask-linear-[to_bottom,transparent_0,black_min(40px,var(--scroll-area-overflow-y-start)),black_calc(100%_-_min(40px,var(--scroll-area-overflow-y-end,40px))),transparent_100%] mask-no-repeat',
|
'mask-linear-[to_bottom,transparent_0,black_min(40px,var(--scroll-area-overflow-y-start)),black_calc(100%_-_min(40px,var(--scroll-area-overflow-y-end,40px))),transparent_100%] mask-no-repeat',
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<VerticalContent className="flex flex-col gap-4 px-4 py-3 pr-6 text-text-secondary system-sm-regular leading-6">
|
<VerticalContent className="flex flex-col gap-4 px-4 py-3 pr-6 system-sm-regular leading-6 text-text-secondary">
|
||||||
{Array.from({ length: 5 }, (_, groupIndex) => (
|
{Array.from({ length: 5 }, (_, groupIndex) => (
|
||||||
articleParagraphs.map(paragraph => (
|
articleParagraphs.map(paragraph => (
|
||||||
<p key={`${groupIndex}-${paragraph}`}>
|
<p key={`${groupIndex}-${paragraph}`}>
|
||||||
@ -232,7 +232,7 @@ export const Horizontal: Story = {
|
|||||||
<ScrollAreaContent className="min-h-full min-w-max p-4 pb-6">
|
<ScrollAreaContent className="min-h-full min-w-max p-4 pb-6">
|
||||||
<div className="grid grid-cols-[repeat(18,6.25rem)] gap-3">
|
<div className="grid grid-cols-[repeat(18,6.25rem)] gap-3">
|
||||||
{gridCells.slice(0, 18).map(cell => (
|
{gridCells.slice(0, 18).map(cell => (
|
||||||
<div key={cell} className="flex h-24 items-center justify-center rounded-xl border border-divider-subtle bg-components-panel-bg-alt tabular-nums system-md-semibold text-text-secondary">
|
<div key={cell} className="flex h-24 items-center justify-center rounded-xl border border-divider-subtle bg-components-panel-bg-alt system-md-semibold text-text-secondary tabular-nums">
|
||||||
{cell}
|
{cell}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@ -259,7 +259,7 @@ export const BothAxes: Story = {
|
|||||||
<ScrollAreaContent className="pt-3 pr-6 pb-6 pl-3">
|
<ScrollAreaContent className="pt-3 pr-6 pb-6 pl-3">
|
||||||
<div className="grid grid-cols-[repeat(10,6.25rem)] grid-rows-[repeat(10,6.25rem)] gap-3">
|
<div className="grid grid-cols-[repeat(10,6.25rem)] grid-rows-[repeat(10,6.25rem)] gap-3">
|
||||||
{gridCells.map(cell => (
|
{gridCells.map(cell => (
|
||||||
<div key={cell} className="flex items-center justify-center rounded-lg border border-divider-subtle bg-components-panel-bg-alt tabular-nums system-md-semibold text-text-secondary">
|
<div key={cell} className="flex items-center justify-center rounded-lg border border-divider-subtle bg-components-panel-bg-alt system-md-semibold text-text-secondary tabular-nums">
|
||||||
{cell}
|
{cell}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|||||||
@ -42,7 +42,7 @@ const scrollAreaThumbClassName = cn(
|
|||||||
|
|
||||||
const scrollAreaViewportClassName = cn(
|
const scrollAreaViewportClassName = cn(
|
||||||
'size-full min-h-0 min-w-0',
|
'size-full min-h-0 min-w-0',
|
||||||
'focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-solid focus-visible:outline-state-accent-solid',
|
'focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-state-accent-solid focus-visible:outline-solid',
|
||||||
)
|
)
|
||||||
|
|
||||||
const scrollAreaCornerClassName = 'bg-transparent'
|
const scrollAreaCornerClassName = 'bg-transparent'
|
||||||
|
|||||||
@ -33,7 +33,7 @@ export function SegmentedControlItem<Value extends string = string>({
|
|||||||
}: SegmentedControlItemProps<Value>) {
|
}: SegmentedControlItemProps<Value>) {
|
||||||
return (
|
return (
|
||||||
<BaseToggle
|
<BaseToggle
|
||||||
className={cn('relative flex h-7 min-w-0 touch-manipulation items-center justify-center gap-0.5 overflow-hidden whitespace-nowrap rounded-lg border-[0.5px] border-transparent px-2 py-1 system-sm-medium text-text-secondary transition-colors duration-150 hover:bg-state-base-hover hover:text-text-secondary focus-visible:outline-hidden focus-visible:inset-ring-2 focus-visible:inset-ring-state-accent-solid data-pressed:border-components-segmented-control-item-active-border data-pressed:bg-components-segmented-control-item-active-bg data-pressed:text-text-accent-light-mode-only data-pressed:shadow-xs data-pressed:shadow-shadow-shadow-3 data-disabled:cursor-not-allowed data-disabled:bg-transparent data-disabled:text-text-disabled data-disabled:shadow-none data-disabled:hover:bg-transparent data-disabled:hover:text-text-disabled motion-reduce:transition-none', className)}
|
className={cn('relative flex h-7 min-w-0 touch-manipulation items-center justify-center gap-0.5 overflow-hidden rounded-lg border-[0.5px] border-transparent px-2 py-1 system-sm-medium whitespace-nowrap text-text-secondary transition-colors duration-150 hover:bg-state-base-hover hover:text-text-secondary focus-visible:inset-ring-2 focus-visible:inset-ring-state-accent-solid focus-visible:outline-hidden data-disabled:cursor-not-allowed data-disabled:bg-transparent data-disabled:text-text-disabled data-disabled:shadow-none data-disabled:hover:bg-transparent data-disabled:hover:text-text-disabled data-pressed:border-components-segmented-control-item-active-border data-pressed:bg-components-segmented-control-item-active-bg data-pressed:text-text-accent-light-mode-only data-pressed:shadow-xs data-pressed:shadow-shadow-shadow-3 motion-reduce:transition-none', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -50,8 +50,8 @@ const switchSpinnerVariants = cva(
|
|||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
size: {
|
size: {
|
||||||
md: 'size-2 left-[calc(50%+6px)] group-data-checked:left-[calc(50%-6px)]',
|
md: 'left-[calc(50%+6px)] size-2 group-data-checked:left-[calc(50%-6px)]',
|
||||||
lg: 'size-2.5 left-[calc(50%+8px)] group-data-checked:left-[calc(50%-8px)]',
|
lg: 'left-[calc(50%+8px)] size-2.5 group-data-checked:left-[calc(50%-8px)]',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -34,7 +34,7 @@ export function TabsTab({
|
|||||||
}: TabsTabProps) {
|
}: TabsTabProps) {
|
||||||
return (
|
return (
|
||||||
<BaseTabs.Tab
|
<BaseTabs.Tab
|
||||||
className={cn('touch-manipulation focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-state-accent-solid relative flex cursor-pointer items-center border-b-2 border-transparent pt-2.5 pb-2 system-md-semibold text-text-tertiary data-active:border-components-tab-active data-active:text-text-primary data-disabled:cursor-not-allowed data-disabled:text-text-tertiary data-disabled:opacity-30 data-active:data-disabled:text-text-primary', className)}
|
className={cn('relative flex cursor-pointer touch-manipulation items-center border-b-2 border-transparent pt-2.5 pb-2 system-md-semibold text-text-tertiary focus-visible:ring-2 focus-visible:ring-state-accent-solid focus-visible:outline-hidden data-active:border-components-tab-active data-active:text-text-primary data-disabled:cursor-not-allowed data-disabled:text-text-tertiary data-disabled:opacity-30 data-active:data-disabled:text-text-primary', className)}
|
||||||
{...props}
|
{...props}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -31,7 +31,7 @@ type Story = StoryObj<typeof meta>
|
|||||||
export const Basic: Story = {
|
export const Basic: Story = {
|
||||||
render: () => (
|
render: () => (
|
||||||
<div className="w-80">
|
<div className="w-80">
|
||||||
<label htmlFor="workspace-description" className="mb-1 block w-fit py-1 text-text-secondary system-sm-medium">
|
<label htmlFor="workspace-description" className="mb-1 block w-fit py-1 system-sm-medium text-text-secondary">
|
||||||
Workspace description
|
Workspace description
|
||||||
</label>
|
</label>
|
||||||
<Textarea
|
<Textarea
|
||||||
@ -46,15 +46,15 @@ export const Basic: Story = {
|
|||||||
export const Sizes: Story = {
|
export const Sizes: Story = {
|
||||||
render: () => (
|
render: () => (
|
||||||
<div className="grid w-80 gap-3">
|
<div className="grid w-80 gap-3">
|
||||||
<label className="grid gap-1 text-text-secondary system-sm-medium" htmlFor="small-textarea">
|
<label className="grid gap-1 system-sm-medium text-text-secondary" htmlFor="small-textarea">
|
||||||
Small
|
Small
|
||||||
<Textarea id="small-textarea" size="small" name="smallTextarea" placeholder="Short note..." rows={3} />
|
<Textarea id="small-textarea" size="small" name="smallTextarea" placeholder="Short note..." rows={3} />
|
||||||
</label>
|
</label>
|
||||||
<label className="grid gap-1 text-text-secondary system-sm-medium" htmlFor="medium-textarea">
|
<label className="grid gap-1 system-sm-medium text-text-secondary" htmlFor="medium-textarea">
|
||||||
Medium
|
Medium
|
||||||
<Textarea id="medium-textarea" name="mediumTextarea" placeholder="Add context..." rows={3} />
|
<Textarea id="medium-textarea" name="mediumTextarea" placeholder="Add context..." rows={3} />
|
||||||
</label>
|
</label>
|
||||||
<label className="grid gap-1 text-text-secondary system-sm-medium" htmlFor="large-textarea">
|
<label className="grid gap-1 system-sm-medium text-text-secondary" htmlFor="large-textarea">
|
||||||
Large
|
Large
|
||||||
<Textarea id="large-textarea" size="large" name="largeTextarea" placeholder="Write a longer instruction..." rows={3} />
|
<Textarea id="large-textarea" size="large" name="largeTextarea" placeholder="Write a longer instruction..." rows={3} />
|
||||||
</label>
|
</label>
|
||||||
@ -119,7 +119,7 @@ const FormDemo = () => {
|
|||||||
<Button type="submit" variant="primary">Save Settings</Button>
|
<Button type="submit" variant="primary">Save Settings</Button>
|
||||||
</div>
|
</div>
|
||||||
{savedDescription && (
|
{savedDescription && (
|
||||||
<div className="rounded-lg bg-background-section px-3 py-2 text-text-secondary system-xs-regular">
|
<div className="rounded-lg bg-background-section px-3 py-2 system-xs-regular text-text-secondary">
|
||||||
Saved:
|
Saved:
|
||||||
{' '}
|
{' '}
|
||||||
{savedDescription}
|
{savedDescription}
|
||||||
@ -173,7 +173,7 @@ const CharacterCounterDemo = () => {
|
|||||||
rows={4}
|
rows={4}
|
||||||
className="resize-y pb-8"
|
className="resize-y pb-8"
|
||||||
/>
|
/>
|
||||||
<div className="pointer-events-none absolute right-2 bottom-2 flex h-5 items-center rounded-md bg-background-section px-1 text-text-quaternary system-xs-medium">
|
<div className="pointer-events-none absolute right-2 bottom-2 flex h-5 items-center rounded-md bg-background-section px-1 system-xs-medium text-text-quaternary">
|
||||||
<span>{value.length}</span>
|
<span>{value.length}</span>
|
||||||
/
|
/
|
||||||
<span className="text-text-tertiary">{maxLength}</span>
|
<span className="text-text-tertiary">{maxLength}</span>
|
||||||
|
|||||||
@ -159,7 +159,7 @@ function ToastCard({
|
|||||||
'[transition:transform_500ms_cubic-bezier(0.22,1,0.36,1),opacity_500ms,height_150ms] motion-reduce:transition-none',
|
'[transition:transform_500ms_cubic-bezier(0.22,1,0.36,1),opacity_500ms,height_150ms] motion-reduce:transition-none',
|
||||||
'transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+(var(--toast-index)*var(--toast-peek))+(var(--toast-shrink)*var(--toast-current-height))))_scale(var(--toast-scale))]',
|
'transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-swipe-movement-y)+(var(--toast-index)*var(--toast-peek))+(var(--toast-shrink)*var(--toast-current-height))))_scale(var(--toast-scale))]',
|
||||||
'data-expanded:h-(--toast-height) data-expanded:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-offset-y)+var(--toast-swipe-movement-y)+(var(--toast-index)*8px)))_scale(1)]',
|
'data-expanded:h-(--toast-height) data-expanded:transform-[translateX(var(--toast-swipe-movement-x))_translateY(calc(var(--toast-offset-y)+var(--toast-swipe-movement-y)+(var(--toast-index)*8px)))_scale(1)]',
|
||||||
'data-ending-style:pointer-events-none data-ending-style:after:pointer-events-none data-ending-style:transform-[translateY(-150%)] data-ending-style:opacity-0',
|
'data-ending-style:pointer-events-none data-ending-style:transform-[translateY(-150%)] data-ending-style:opacity-0 data-ending-style:after:pointer-events-none',
|
||||||
'data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+150%))]',
|
'data-ending-style:data-[swipe-direction=down]:transform-[translateY(calc(var(--toast-swipe-movement-y)+150%))]',
|
||||||
'data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+150%))]',
|
'data-ending-style:data-[swipe-direction=right]:transform-[translateX(calc(var(--toast-swipe-movement-x)+150%))]',
|
||||||
'data-limited:pointer-events-none data-limited:opacity-0 data-starting-style:transform-[translateY(-150%)] data-starting-style:opacity-0',
|
'data-limited:pointer-events-none data-limited:opacity-0 data-starting-style:transform-[translateY(-150%)] data-starting-style:opacity-0',
|
||||||
|
|||||||
948
pnpm-lock.yaml
generated
948
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user