diff --git a/packages/next/src/views/API/RenderJSON/index.css b/packages/next/src/views/API/RenderJSON/index.css new file mode 100644 index 00000000000..f212c8d6a63 --- /dev/null +++ b/packages/next/src/views/API/RenderJSON/index.css @@ -0,0 +1,122 @@ +@layer payload-default { + .query-inspector { + --tab-width: var(--spacer-4); + } + + .query-inspector__json-children { + position: relative; + + &::before { + content: ''; + position: absolute; + top: 0; + width: var(--stroke-width-small); + height: 100%; + border-left: var(--stroke-width-small) dashed var(--color-border); + } + } + + .query-inspector__json-children--nested { + li { + padding-left: var(--spacer-2); + } + } + + .query-inspector__row-line--nested { + .query-inspector__json-children { + padding-left: var(--tab-width); + } + } + + .query-inspector__list-wrap { + position: relative; + } + + .query-inspector__list-toggle { + all: unset; + text-align: left; + cursor: pointer; + border-radius: 0; + position: relative; + display: flex; + column-gap: var(--spacer-2-5); + row-gap: var(--spacer-2); + align-items: center; + background-color: var(--color-bg-secondary); + width: calc(100% + var(--spacer-2)); + margin-left: calc(-1 * var(--spacer-2)); + padding-left: var(--spacer-2); + + &:not(.query-inspector__list-toggle--empty) { + margin-left: calc(var(--tab-width) * -1 - var(--spacer-2)); + padding-left: calc(var(--tab-width) + var(--spacer-2)); + width: calc(100% + var(--tab-width) + var(--spacer-2)); + } + + svg .stroke { + stroke: var(--color-icon-tertiary); + } + + &:hover { + background-color: var(--color-bg-secondary-hover); + } + } + + .query-inspector__list-toggle--empty { + cursor: default; + pointer-events: none; + } + + .query-inspector__toggle-row-icon--open { + transform: rotate(0deg); + } + + .query-inspector__toggle-row-icon--closed { + transform: rotate(-90deg); + } + + .query-inspector__value-type--number { + .query-inspector__value { + color: var(--number-color); + } + } + + .query-inspector__value-type--string { + .query-inspector__value { + color: var(--string-color); + } + } + + .query-inspector__bracket { + position: relative; + } + + .query-inspector__bracket--position-end { + left: var(--stroke-width-medium); + width: calc(100% - var(--spacer-1)); + } + + /* Top-level JSON structure specific rules */ + .query-inspector__results { + & > .query-inspector__row-line--nested { + & > .query-inspector__list-toggle { + margin-left: calc(-1 * var(--spacer-2)); + padding-left: var(--spacer-2); + width: calc(100% + var(--spacer-2)); + column-gap: var(--spacer-1); + + .query-inspector__toggle-row-icon { + margin-left: calc(var(--spacer-1) * -1); + } + } + + & > .query-inspector__json-children { + padding-left: var(--spacer-3); + } + + & > .query-inspector__bracket--nested > .query-inspector__bracket--position-end { + padding-left: var(--spacer-3); + } + } + } +} diff --git a/packages/next/src/views/API/RenderJSON/index.scss b/packages/next/src/views/API/RenderJSON/index.scss deleted file mode 100644 index 29fd5ef2557..00000000000 --- a/packages/next/src/views/API/RenderJSON/index.scss +++ /dev/null @@ -1,129 +0,0 @@ -@import '~@payloadcms/ui/scss'; - -$tab-width: 24px; - -@layer payload-default { - .query-inspector { - --tab-width: 24px; - - &__json-children { - position: relative; - - &--nested { - & li { - padding-left: 8px; - } - } - - &:before { - content: ''; - position: absolute; - top: 0; - width: 1px; - height: 100%; - border-left: 1px dashed var(--theme-elevation-200); - } - } - - &__row-line { - &--nested { - .query-inspector__json-children { - padding-left: var(--tab-width); - } - } - } - - &__list-wrap { - position: relative; - } - - &__list-toggle { - all: unset; - width: 100%; - text-align: left; - cursor: pointer; - border-radius: 3px; - border-top-right-radius: 0; - border-bottom-right-radius: 0; - position: relative; - display: flex; - column-gap: 14px; - row-gap: 10px; - align-items: center; - left: 0; - width: calc(100% + 3px); - background-color: var(--theme-elevation-50); - - &:not(.query-inspector__list-toggle--empty) { - margin-left: calc(var(--tab-width) * -1 - 10px); - } - - svg .stroke { - stroke: var(--theme-elevation-400); - } - - &:hover { - background-color: var(--theme-elevation-100); - } - - &--empty { - cursor: default; - pointer-events: none; - } - } - - &__toggle-row-icon { - &--open { - transform: rotate(0deg); - } - &--closed { - transform: rotate(-90deg); - } - } - - &__value-type { - &--number { - .query-inspector__value { - color: var(--number-color); - } - } - - &--string { - .query-inspector__value { - color: var(--string-color); - } - } - } - - &__bracket { - position: relative; - - &--position-end { - left: 2px; - width: calc(100% - 5px); - } - } - - // Some specific rules targetting the very top of the nested JSON structure or very first items since they need slightly different styling - &__results { - & > .query-inspector__row-line--nested { - & > .query-inspector__list-toggle { - margin-left: 0; - column-gap: 6px; - - .query-inspector__toggle-row-icon { - margin-left: -4px; - } - } - - & > .query-inspector__json-children { - padding-left: calc(var(--base) * 1); - } - - & > .query-inspector__bracket--nested > .query-inspector__bracket--position-end { - padding-left: 16px; - } - } - } - } -} diff --git a/packages/next/src/views/API/RenderJSON/index.tsx b/packages/next/src/views/API/RenderJSON/index.tsx index 4ef9d68ad58..ea405b5cf60 100644 --- a/packages/next/src/views/API/RenderJSON/index.tsx +++ b/packages/next/src/views/API/RenderJSON/index.tsx @@ -2,7 +2,7 @@ import { ChevronIcon } from '@payloadcms/ui' import * as React from 'react' -import './index.scss' +import './index.css' const chars = { leftCurlyBracket: '\u007B', diff --git a/packages/next/src/views/API/index.client.tsx b/packages/next/src/views/API/index.client.tsx index c51f583c523..45428ee27c8 100644 --- a/packages/next/src/views/API/index.client.tsx +++ b/packages/next/src/views/API/index.client.tsx @@ -1,13 +1,14 @@ 'use client' import { + Button, CheckboxField, - CopyToClipboard, + ExternalLinkIcon, Form, - Gutter, MinimizeMaximizeIcon, NumberField, SetDocumentStepNav, + TextInput, toast, useConfig, useDocumentInfo, @@ -16,7 +17,7 @@ import { } from '@payloadcms/ui' import { useSearchParams } from 'next/navigation.js' -import './index.scss' +import './index.css' import { formatAdminURL, hasDraftsEnabled } from 'payload/shared' import * as React from 'react' @@ -123,9 +124,8 @@ export const APIViewClient: React.FC = () => { }, [i18n.language, fetchURL, authenticated]) return ( - { useAsTitle={collectionConfig ? collectionConfig?.admin?.useAsTitle : undefined} view="API" /> -
-
- - API URL - - - {fetchURL} - -
-
-
-
- {draftsEnabled && ( +
+
+
+ API URL +
+
+ +
+ +
+
+ {draftsEnabled && ( + setDraft(!draft)} + path="draft" + /> + )} setDraft(!draft)} - path="draft" + onChange={() => setAuthenticated(!authenticated)} + path="authenticated" /> +
+ {localeOptions && ( + )} - setAuthenticated(!authenticated)} - path="authenticated" + onChange={(value) => setDepth(value?.toString())} + path="depth" />
- {localeOptions && } - setDepth(value?.toString())} - path="depth" - /> -
- -
-
-
- +
-
- +
+
+ +
+
+ +
- +
) } diff --git a/packages/next/src/views/API/index.css b/packages/next/src/views/API/index.css new file mode 100644 index 00000000000..6ae5518fb29 --- /dev/null +++ b/packages/next/src/views/API/index.css @@ -0,0 +1,182 @@ +@layer payload-default { + .template-default__wrap:has(.query-inspector) { + overflow: hidden; + } + + .query-inspector { + --header-offset: 110px; + --string-color: var(--color-text-success); + --number-color: var(--color-text-warning); + flex: 1; + min-height: 0; + display: flex; + flex-direction: column; + + ul { + padding-left: var(--spacer-3); + } + } + + .query-inspector--fullscreen { + padding: 0; + + .query-inspector__configuration { + display: none; + } + + .query-inspector__content { + grid-template-columns: 1fr; + } + + .query-inspector__results-wrapper { + border: 0; + } + } + + .query-inspector__content { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); + flex: 1; + min-height: 0; + } + + .query-inspector__configuration { + padding: var(--spacer-3) var(--gutter-h); + overflow-y: auto; + } + + .query-inspector__api-url { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: var(--spacer-2); + + .query-inspector__api-url-open-button { + color: var(--color-icon-secondary); + + &:hover { + color: var(--color-icon); + } + } + } + + .query-inspector__api-url-field { + margin-bottom: var(--spacer-3); + } + + .query-inspector__api-url-input { + gap: 0; + + .field-type__wrap { + gap: 0; + } + + .form-input { + user-select: text; + -webkit-user-select: text; + cursor: text; + } + } + + .query-inspector__label { + font-weight: var(--text-body-large-strong-font-weight); + } + + .query-inspector__form-fields { + display: flex; + flex-direction: column; + gap: var(--spacing-field); + } + + .query-inspector__filter-query-checkboxes { + display: flex; + gap: var(--spacer-3); + + .checkbox-input label.field-label:not(.unstyled) { + color: var(--color-text); + font-family: var(--text-body-medium-font-family); + font-size: var(--text-body-medium-font-size); + font-weight: var(--text-body-medium-font-weight); + line-height: var(--text-body-medium-line-height); + } + } + + .query-inspector__results-wrapper { + font-family: var(--font-family-mono); + min-width: 0; + max-height: calc(100dvh - var(--header-offset)); + overflow-x: hidden; + overflow-y: auto; + background-color: var(--color-bg-secondary); + border-inline-start: var(--stroke-width-small) solid var(--color-border); + + ul { + margin: 0; + } + + li { + list-style: none; + } + } + + .query-inspector__toggle-fullscreen-button-container { + position: sticky; + top: 0; + z-index: 1; + } + + .query-inspector__toggle-fullscreen-button { + position: absolute; + right: var(--spacer-2); + top: var(--spacer-2); + background-color: var(--color-bg); + cursor: pointer; + margin: 0; + border: var(--stroke-width-small) solid var(--color-border); + border-radius: var(--radius-medium); + color: var(--color-icon); + display: flex; + align-items: center; + justify-content: center; + + &:hover { + background-color: var(--color-bg-hover); + color: var(--color-icon); + } + + &:active { + background-color: var(--color-bg-pressed); + color: var(--color-icon); + } + } + + .query-inspector__results { + padding: var(--spacer-2); + overflow: hidden; + } + + @media (max-width: 1024px) { + .query-inspector__content { + display: flex; + flex-direction: column; + min-height: 0; + gap: var(--spacer-3); + } + + .query-inspector__configuration { + padding-inline-end: var(--gutter-h); + } + + .query-inspector__results-wrapper { + border-inline-start: 0; + border-top: var(--stroke-width-small) solid var(--color-border); + flex: 1; + max-height: none; + min-height: 0; + } + + .query-inspector--fullscreen .query-inspector__results-wrapper { + border-top: 0; + } + } +} diff --git a/packages/next/src/views/API/index.scss b/packages/next/src/views/API/index.scss deleted file mode 100644 index c666a4923d8..00000000000 --- a/packages/next/src/views/API/index.scss +++ /dev/null @@ -1,119 +0,0 @@ -@import '~@payloadcms/ui/scss'; - -@layer payload-default { - .query-inspector { - --string-color: var(--color-success-450); - --number-color: var(--color-warning-450); - display: flex; - gap: calc(var(--base) * 2); - align-items: flex-start; - - ul { - padding-left: calc(var(--base) * 1); - } - - &--fullscreen { - padding-left: 0; - .query-inspector__configuration { - display: none; - } - } - - &__configuration { - margin-top: calc(var(--base) * 2); - width: 60%; - position: sticky; - top: var(--base); - } - - &__api-url { - margin-bottom: calc(var(--base) * 1.5); - - a { - display: block; - overflow: hidden; - text-overflow: ellipsis; - text-decoration: none; - - &:hover, - &:focus-visible { - text-decoration: underline; - } - } - } - - &__form-fields { - display: flex; - flex-direction: column; - gap: var(--base); - } - - &__label { - color: var(--theme-elevation-400); - } - - &__filter-query-checkboxes { - display: flex; - gap: var(--base); - } - - &__results-wrapper { - font-family: var(--font-mono); - width: 100%; - ul { - margin: 0; - } - li { - list-style: none; - } - } - - &__toggle-fullscreen-button-container { - position: sticky; - top: 0; - z-index: 1; - - @include mid-break { - display: none; - } - } - - &__toggle-fullscreen-button { - position: absolute; - right: calc(var(--base) * 0.5); - top: calc(var(--base) * 0.5); - padding: calc(var(--base) * 0.25); - background-color: var(--theme-elevation-0); - cursor: pointer; - z-index: 1; - margin: 0; - border: 0; - border-radius: 3px; - color: var(--theme-elevation-300); - &:hover { - color: var(--theme-elevation-700); - } - } - - &__results { - padding-top: calc(var(--base) * 0.5); - padding-left: calc(var(--base) * 0.5); - padding-bottom: calc(var(--base) * 0.5); - background-color: var(--theme-elevation-50); - overflow: auto; - min-height: 100vh; - } - - @include mid-break { - flex-direction: column; - padding-left: 0; - - .query-inspector__configuration { - position: relative; - width: 100%; - top: 0; - padding-inline-end: var(--gutter-h); - } - } - } -} diff --git a/packages/ui/src/css/spacing.css b/packages/ui/src/css/spacing.css index a1355668a66..f11a147d238 100644 --- a/packages/ui/src/css/spacing.css +++ b/packages/ui/src/css/spacing.css @@ -11,6 +11,7 @@ /* Layout spacing */ --gutter-h: var(--spacer-5); + --spacing-field: var(--spacer-3); --spacing-view-bottom: var(--gutter-h); /* Breakpoints */ @@ -27,6 +28,7 @@ @media (max-width: 768px) { :root { --gutter-h: var(--spacer-3); + --spacing-field: var(--spacer-2-5); --spacing-view-bottom: var(--spacer-6); } } diff --git a/packages/ui/src/elements/DocumentHeader/Tabs/index.css b/packages/ui/src/elements/DocumentHeader/Tabs/index.css index cecb144ed73..3eba8b61025 100644 --- a/packages/ui/src/elements/DocumentHeader/Tabs/index.css +++ b/packages/ui/src/elements/DocumentHeader/Tabs/index.css @@ -39,9 +39,5 @@ .doc-tabs__tabs-container { margin-right: auto; } - - .doc-tabs::after { - content: none; - } } } diff --git a/packages/ui/src/fields/Text/types.ts b/packages/ui/src/fields/Text/types.ts index d5e60c58ce7..8b7db3060a0 100644 --- a/packages/ui/src/fields/Text/types.ts +++ b/packages/ui/src/fields/Text/types.ts @@ -22,7 +22,9 @@ export type TextInputProps = { readonly description?: StaticDescription readonly Error?: React.ReactNode readonly htmlAttributes?: { + 'aria-label'?: JSX.IntrinsicElements['input']['aria-label'] autoComplete?: JSX.IntrinsicElements['input']['autoComplete'] + readOnly?: JSX.IntrinsicElements['input']['readOnly'] } readonly inputRef?: React.RefObject readonly Label?: React.ReactNode diff --git a/packages/ui/src/forms/RenderFields/index.css b/packages/ui/src/forms/RenderFields/index.css index 0f47c53a5c6..858b72100f6 100644 --- a/packages/ui/src/forms/RenderFields/index.css +++ b/packages/ui/src/forms/RenderFields/index.css @@ -11,8 +11,6 @@ } .render-fields { - --spacing-field: var(--spacer-3); - & > .field-type { margin-bottom: var(--spacing-field); position: relative; @@ -58,9 +56,5 @@ } } } - - @media (max-width: 768px) { - --spacing-field: var(--spacer-2-5); - } } } diff --git a/packages/ui/src/icons/MinimizeMaximize/index.tsx b/packages/ui/src/icons/MinimizeMaximize/index.tsx index f1ee5753981..9e2257ffd1a 100644 --- a/packages/ui/src/icons/MinimizeMaximize/index.tsx +++ b/packages/ui/src/icons/MinimizeMaximize/index.tsx @@ -5,13 +5,13 @@ import './index.css' // Minimized state paths - corners pointing outward (expand) const minimizedPaths = { 16: 'M4 3.5a.5.5 0 0 1 .5-.5H6a.5.5 0 0 1 0 1H4.5V5.5a.5.5 0 0 1-1 0V3.5zM12 3.5a.5.5 0 0 1 .5-.5h1.5a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0V4h-1a.5.5 0 0 1-.5-.5zM4 10.5a.5.5 0 0 1 1 0V12h1.5a.5.5 0 0 1 0 1H4.5a.5.5 0 0 1-.5-.5v-2zm9.5 0a.5.5 0 0 1 1 0v2a.5.5 0 0 1-.5.5H12a.5.5 0 0 1 0-1h1V10.5z', - 24: 'M6 5a.5.5 0 0 1 .5-.5H8a.5.5 0 0 1 0 1H6.5V7a.5.5 0 0 1-1 0V5.5A.5.5 0 0 1 6 5zm10 0a.5.5 0 0 1 .5-.5H18a.5.5 0 0 1 .5.5v1.5a.5.5 0 0 1-1 0V5.5H16a.5.5 0 0 1-.5-.5zM6 16.5a.5.5 0 0 1 1 0V18h1.5a.5.5 0 0 1 0 1H6.5a.5.5 0 0 1-.5-.5v-2zm11.5 0a.5.5 0 0 1 1 0v2a.5.5 0 0 1-.5.5H16a.5.5 0 0 1 0-1h1.5v-1.5z', + 24: 'M10.1465 13.1465C10.3417 12.9512 10.6583 12.9512 10.8535 13.1465C11.0488 13.3417 11.0488 13.6583 10.8535 13.8535L7.70703 17H10.5C10.7761 17 11 17.2239 11 17.5C11 17.7761 10.7761 18 10.5 18H6.5C6.22386 18 6 17.7761 6 17.5V13.5C6 13.2239 6.22386 13 6.5 13C6.77614 13 7 13.2239 7 13.5V16.293L10.1465 13.1465ZM17.5 6C17.7761 6 18 6.22386 18 6.5V10.5C18 10.7761 17.7761 11 17.5 11C17.2239 11 17 10.7761 17 10.5V7.70703L13.8535 10.8535C13.6583 11.0488 13.3417 11.0488 13.1465 10.8535C12.9512 10.6583 12.9512 10.3417 13.1465 10.1465L16.293 7H13.5C13.2239 7 13 6.77614 13 6.5C13 6.22386 13.2239 6 13.5 6H17.5Z', } // Maximized state paths - corners pointing inward (collapse) const maximizedPaths = { 16: 'M6 3a.5.5 0 0 1 .5.5V5a.5.5 0 0 1-.5.5H4.5a.5.5 0 0 1 0-1H5V3.5A.5.5 0 0 1 5.5 3H6zm4.5 0a.5.5 0 0 1 .5.5V4h1a.5.5 0 0 1 .5.5v.5a.5.5 0 0 1-.5.5H10a.5.5 0 0 1-.5-.5V3.5a.5.5 0 0 1 .5-.5zM6 10a.5.5 0 0 1 .5.5V11H5v-.5a.5.5 0 0 1 .5-.5h.5a.5.5 0 0 0-.5.5V12a.5.5 0 0 1-.5.5H4.5a.5.5 0 0 1 0-1H5v-.5a.5.5 0 0 1 .5-.5H6zm4.5.5a.5.5 0 0 1 .5-.5h1.5a.5.5 0 0 1 0 1H12v1a.5.5 0 0 1-1 0v-1.5z', - 24: 'M8 5a.5.5 0 0 1 .5.5V7a.5.5 0 0 1-.5.5H6.5a.5.5 0 0 1 0-1H7V5.5A.5.5 0 0 1 7.5 5H8zm8.5 0a.5.5 0 0 1 .5.5V6.5h1a.5.5 0 0 1 .5.5v.5a.5.5 0 0 1-.5.5H16a.5.5 0 0 1-.5-.5V5.5a.5.5 0 0 1 .5-.5zM8 16a.5.5 0 0 1 .5.5V18a.5.5 0 0 1-.5.5H6.5a.5.5 0 0 1 0-1H7v-1a.5.5 0 0 1 .5-.5H8zm8.5.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5V18a.5.5 0 0 1-.5.5H16a.5.5 0 0 1 0-1h1.5v-1z', + 24: 'M10.5 13C10.7761 13 11 13.2239 11 13.5V17.5C11 17.7761 10.7761 18 10.5 18C10.2239 18 10 17.7761 10 17.5V14.707L6.85352 17.8535C6.65825 18.0488 6.34175 18.0488 6.14648 17.8535C5.95122 17.6583 5.95122 17.3417 6.14648 17.1465L9.29297 14H6.5C6.22386 14 6 13.7761 6 13.5C6 13.2239 6.22386 13 6.5 13H10.5ZM17.1465 6.14648C17.3417 5.95122 17.6583 5.95122 17.8535 6.14648C18.0488 6.34175 18.0488 6.65825 17.8535 6.85352L14.707 10H17.5C17.7761 10 18 10.2239 18 10.5C18 10.7761 17.7761 11 17.5 11H13.5C13.2239 11 13 10.7761 13 10.5V6.5C13 6.22386 13.2239 6 13.5 6C13.7761 6 14 6.22386 14 6.5V9.29297L17.1465 6.14648Z', } export const MinimizeMaximizeIcon: React.FC<{