Auto-expand URL bar height

This commit is contained in:
Gregory Schier
2023-10-27 10:57:07 -07:00
parent 4bf82ec3e9
commit 439af5e8f2
6 changed files with 284 additions and 267 deletions

View File

@@ -47,11 +47,11 @@ export const UrlBar = memo(function UrlBar({ id: requestId, url, method, classNa
<form onSubmit={handleSubmit} className={classNames('url-bar', className)}> <form onSubmit={handleSubmit} className={classNames('url-bar', className)}>
<Input <Input
ref={inputRef} ref={inputRef}
size="sm" size="auto"
hideLabel hideLabel
useTemplating useTemplating
contentType="url" contentType="url"
className="px-0" className="px-0 py-0.5"
name="url" name="url"
label="Enter URL" label="Enter URL"
forceUpdateKey={updateKey} forceUpdateKey={updateKey}
@@ -63,7 +63,7 @@ export const UrlBar = memo(function UrlBar({ id: requestId, url, method, classNa
<RequestMethodDropdown <RequestMethodDropdown
method={method} method={method}
onChange={handleMethodChange} onChange={handleMethodChange}
className="mx-0.5 h-full my-1" className="!h-auto mx-0.5 my-0.5"
/> />
} }
rightSlot={ rightSlot={
@@ -72,7 +72,7 @@ export const UrlBar = memo(function UrlBar({ id: requestId, url, method, classNa
iconSize="sm" iconSize="sm"
title="Send Request" title="Send Request"
type="submit" type="submit"
className="w-8 mr-0.5" className="!h-auto w-8 mr-0.5 my-0.5"
icon={loading ? 'update' : 'paperPlane'} icon={loading ? 'update' : 'paperPlane'}
spin={loading} spin={loading}
/> />

View File

@@ -1,203 +1,210 @@
.cm-wrapper { .cm-wrapper {
@apply h-full overflow-hidden; @apply h-full overflow-hidden;
.cm-editor {
@apply w-full block text-base;
* {
@apply cursor-text;
}
&.cm-focused {
outline: none !important;
}
.cm-content {
@apply py-0;
}
.cm-line {
@apply text-gray-800 pl-1 pr-1.5;
}
.cm-placeholder {
@apply text-placeholder;
}
.cm-scroller {
/* Inherit line-height from outside */
line-height: inherit;
}
/* Don't show selection on blurred input */
.cm-selectionBackground {
@apply bg-transparent;
}
&.cm-focused .cm-selectionBackground {
@apply bg-selection;
}
/* Style gutters */
.cm-gutters {
@apply border-0 text-gray-500/50;
.cm-gutterElement {
@apply cursor-default;
}
}
.placeholder-widget {
@apply text-xs text-gray-800 dark:text-gray-900 px-1 rounded cursor-default dark:shadow;
/* NOTE: Background and border are translucent so we can see text selection through it */
@apply bg-gray-300/40 border border-gray-300 border-opacity-40 hover:border-opacity-80;
/* Bring above on hover */
@apply hover:z-10 relative;
}
}
&.cm-singleline {
.cm-editor {
@apply w-full h-auto;
}
.cm-scroller {
@apply font-mono text-[0.8rem] overflow-hidden;
}
.cm-line {
@apply px-2 overflow-hidden;
}
}
&.cm-multiline {
&.cm-full-height {
@apply relative;
.cm-editor {
@apply inset-0 absolute;
position: absolute !important;
}
}
.cm-editor { .cm-editor {
@apply w-full block text-base; @apply h-full;
* {
@apply cursor-text;
}
&.cm-focused {
outline: none !important;
}
.cm-content {
@apply py-0;
}
.cm-line {
@apply text-gray-800 pl-1 pr-1.5;
}
.cm-placeholder {
@apply text-placeholder;
}
.cm-scroller {
/* Inherit line-height from outside */
line-height: inherit;
}
/* Don't show selection on blurred input */
.cm-selectionBackground {
@apply bg-transparent;
}
&.cm-focused .cm-selectionBackground {
@apply bg-selection;
}
/* Style gutters */
.cm-gutters {
@apply border-0 text-gray-500/50;
.cm-gutterElement {
@apply cursor-default;
}
}
.placeholder-widget {
@apply text-xs text-gray-800 dark:text-gray-900 px-1 rounded cursor-default dark:shadow;
/* NOTE: Background and border are translucent so we can see text selection through it */
@apply bg-gray-300/40 border border-gray-300 border-opacity-40 hover:border-opacity-80;
/* Bring above on hover */
@apply hover:z-10 relative;
}
} }
&.cm-singleline { .cm-scroller {
.cm-editor { @apply font-mono text-[0.75rem];
@apply w-full h-auto;
}
.cm-scroller { /*
@apply font-mono text-[0.8rem] overflow-hidden;
}
.cm-line {
@apply px-2 overflow-hidden;
}
}
&.cm-multiline {
&.cm-full-height {
@apply relative;
.cm-editor {
@apply inset-0 absolute;
position: absolute !important;
}
}
.cm-editor {
@apply h-full;
}
.cm-scroller {
@apply font-mono text-[0.75rem];
/*
* Round corners or they'll stick out of the editor bounds of editor is rounded. * Round corners or they'll stick out of the editor bounds of editor is rounded.
* Could potentially be pushed up from the editor like we do with bg color but this * Could potentially be pushed up from the editor like we do with bg color but this
* is probably fine. * is probably fine.
*/ */
@apply rounded-lg; @apply rounded-lg;
}
} }
}
} }
/* Obscure text for password fields */ /* Obscure text for password fields */
.cm-wrapper.cm-obscure-text .cm-line { .cm-wrapper.cm-obscure-text .cm-line {
-webkit-text-security: disc; -webkit-text-security: disc;
} }
.cm-editor .cm-gutterElement { .cm-editor .cm-gutterElement {
@apply flex items-center; @apply flex items-center;
transition: color var(--transition-duration); transition: color var(--transition-duration);
} }
.cm-editor .fold-gutter-icon { .cm-editor .fold-gutter-icon {
@apply pt-[0.25em] pl-[0.4em] px-[0.4em] h-4 cursor-pointer rounded; @apply pt-[0.25em] pl-[0.4em] px-[0.4em] h-4 cursor-pointer rounded;
} }
.cm-editor .fold-gutter-icon::after { .cm-editor .fold-gutter-icon::after {
@apply block w-1.5 h-1.5 border-transparent -rotate-45 @apply block w-1.5 h-1.5 border-transparent -rotate-45
border-l border-b border-l-[currentColor] border-b-[currentColor] content-['']; border-l border-b border-l-[currentColor] border-b-[currentColor] content-[''];
} }
.cm-editor .fold-gutter-icon[data-open] { .cm-editor .fold-gutter-icon[data-open] {
@apply pt-[0.38em] pl-[0.3em]; @apply pt-[0.38em] pl-[0.3em];
} }
.cm-editor .fold-gutter-icon[data-open]::after { .cm-editor .fold-gutter-icon[data-open]::after {
@apply rotate-[-135deg]; @apply rotate-[-135deg];
} }
.cm-editor .fold-gutter-icon:hover { .cm-editor .fold-gutter-icon:hover {
@apply text-gray-900 bg-gray-300/50; @apply text-gray-900 bg-gray-300/50;
} }
.cm-editor .cm-foldPlaceholder { .cm-editor .cm-foldPlaceholder {
@apply px-2 border border-gray-400/50 bg-gray-300/50 cursor-default; @apply px-2 border border-gray-400/50 bg-gray-300/50 cursor-default;
@apply hover:text-gray-800 hover:border-gray-400; @apply hover:text-gray-800 hover:border-gray-400;
} }
.cm-editor .cm-activeLineGutter { .cm-editor .cm-activeLineGutter {
@apply bg-transparent; @apply bg-transparent;
} }
.cm-wrapper:not(.cm-readonly) .cm-editor { .cm-wrapper:not(.cm-readonly) .cm-editor {
&.cm-focused .cm-activeLineGutter { &.cm-focused .cm-activeLineGutter {
@apply text-gray-600; @apply text-gray-600;
} }
.cm-cursor { .cm-cursor {
@apply border-l-2 border-gray-800; @apply border-l-2 border-gray-800;
} }
} }
.cm-singleline .cm-editor { .cm-singleline .cm-editor {
.cm-content { .cm-content {
@apply h-full flex items-center; @apply h-full flex items-center;
/* Break characters on line wrapping mode, useful for URL field.
* We can make this dynamic if we need it to be configurable later
*/
&.cm-lineWrapping {
@apply break-all;
} }
}
} }
/* NOTE: Extra selector required to override default styles */ /* NOTE: Extra selector required to override default styles */
.cm-tooltip.cm-tooltip { .cm-tooltip.cm-tooltip {
@apply shadow-lg bg-gray-50 rounded text-gray-700 border border-gray-200 z-50 pointer-events-auto text-[0.75rem]; @apply shadow-lg bg-gray-50 rounded text-gray-700 border border-gray-200 z-50 pointer-events-auto text-[0.75rem];
&.cm-completionInfo-right { &.cm-completionInfo-right {
@apply ml-1 -mt-0.5 text-sm; @apply ml-1 -mt-0.5 text-sm;
}
&.cm-completionInfo-right-narrow {
@apply ml-1;
}
* {
@apply transition-none;
}
&.cm-tooltip-autocomplete {
& > ul {
@apply p-1 max-h-[40vh];
} }
&.cm-completionInfo-right-narrow { & > ul > li {
@apply ml-1; @apply cursor-default px-2 rounded-sm text-gray-600 h-7 flex items-center;
} }
* { & > ul > li[aria-selected] {
@apply transition-none; @apply bg-highlight text-gray-900;
} }
&.cm-tooltip-autocomplete { .cm-completionIcon {
& > ul { @apply text-sm flex items-center pb-0.5 flex-shrink-0;
@apply p-1 max-h-[40vh];
}
& > ul > li {
@apply cursor-default px-2 rounded-sm text-gray-600 h-7 flex items-center;
}
& > ul > li[aria-selected] {
@apply bg-highlight text-gray-900;
}
.cm-completionIcon {
@apply text-sm flex items-center pb-0.5 flex-shrink-0;
}
.cm-completionLabel {
@apply text-gray-700;
}
.cm-completionDetail {
@apply ml-auto pl-6;
}
} }
.cm-completionLabel {
@apply text-gray-700;
}
.cm-completionDetail {
@apply ml-auto pl-6;
}
}
} }
/* Add default icon. Needs low priority so it can be overwritten */ /* Add default icon. Needs low priority so it can be overwritten */
.cm-completionIcon::after { .cm-completionIcon::after {
content: '𝑥'; content: '𝑥';
} }

View File

@@ -36,7 +36,7 @@ export interface EditorProps {
onChange?: (value: string) => void; onChange?: (value: string) => void;
onFocus?: () => void; onFocus?: () => void;
onBlur?: () => void; onBlur?: () => void;
onSubmit?: () => void; onEnter?: () => void;
singleLine?: boolean; singleLine?: boolean;
wrapLines?: boolean; wrapLines?: boolean;
format?: (v: string) => string; format?: (v: string) => string;
@@ -58,7 +58,7 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
onChange, onChange,
onFocus, onFocus,
onBlur, onBlur,
onSubmit, onEnter,
className, className,
singleLine, singleLine,
format, format,
@@ -80,10 +80,10 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
}, [onChange]); }, [onChange]);
// Use ref so we can update the onChange handler without re-initializing the editor // Use ref so we can update the onChange handler without re-initializing the editor
const handleSubmit = useRef<EditorProps['onSubmit']>(onSubmit); const handleEnter = useRef<EditorProps['onEnter']>(onEnter);
useEffect(() => { useEffect(() => {
handleSubmit.current = onSubmit; handleEnter.current = onEnter;
}, [onSubmit]); }, [onEnter]);
// Use ref so we can update the onChange handler without re-initializing the editor // Use ref so we can update the onChange handler without re-initializing the editor
const handleFocus = useRef<EditorProps['onFocus']>(onFocus); const handleFocus = useRef<EditorProps['onFocus']>(onFocus);
@@ -143,7 +143,12 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
let view: EditorView; let view: EditorView;
try { try {
const languageCompartment = new Compartment(); const languageCompartment = new Compartment();
const langExt = getLanguageExtension({ contentType, useTemplating, autocomplete, environment }); const langExt = getLanguageExtension({
contentType,
useTemplating,
autocomplete,
environment,
});
const state = EditorState.create({ const state = EditorState.create({
doc: `${defaultValue ?? ''}`, doc: `${defaultValue ?? ''}`,
@@ -155,7 +160,7 @@ const _Editor = forwardRef<EditorView | undefined, EditorProps>(function Editor(
container, container,
readOnly, readOnly,
singleLine, singleLine,
onSubmit: handleSubmit, onEnter: handleEnter,
onChange: handleChange, onChange: handleChange,
onFocus: handleFocus, onFocus: handleFocus,
onBlur: handleBlur, onBlur: handleBlur,
@@ -228,13 +233,13 @@ function getExtensions({
onChange, onChange,
onFocus, onFocus,
onBlur, onBlur,
onSubmit, onEnter,
}: Pick<EditorProps, 'singleLine' | 'readOnly'> & { }: Pick<EditorProps, 'singleLine' | 'readOnly'> & {
container: HTMLDivElement | null; container: HTMLDivElement | null;
onChange: MutableRefObject<EditorProps['onChange']>; onChange: MutableRefObject<EditorProps['onChange']>;
onFocus: MutableRefObject<EditorProps['onFocus']>; onFocus: MutableRefObject<EditorProps['onFocus']>;
onBlur: MutableRefObject<EditorProps['onBlur']>; onBlur: MutableRefObject<EditorProps['onBlur']>;
onSubmit: MutableRefObject<EditorProps['onSubmit']>; onEnter: MutableRefObject<EditorProps['onEnter']>;
}) { }) {
// TODO: Ensure tooltips render inside the dialog if we are in one. // TODO: Ensure tooltips render inside the dialog if we are in one.
const parent = const parent =
@@ -253,19 +258,19 @@ function getExtensions({
: []), : []),
...(singleLine ...(singleLine
? [ ? [
EditorView.domEventHandlers({ EditorView.domEventHandlers({
focus: (_, view) => { focus: (_, view) => {
// select all text on focus, like a regular input does // select all text on focus, like a regular input does
view.dispatch({ selection: { anchor: 0, head: view.state.doc.length } }); view.dispatch({ selection: { anchor: 0, head: view.state.doc.length } });
}, },
keydown: (e) => { keydown: (e) => {
// Submit nearest form on enter if there is one // Submit nearest form on enter if there is one
if (onSubmit != null && e.key === 'Enter') { if (onEnter != null && e.key === 'Enter') {
onSubmit.current?.(); onEnter.current?.();
} }
}, },
}), }),
] ]
: []), : []),
// Handle onFocus // Handle onFocus

View File

@@ -21,7 +21,7 @@ export type InputProps = Omit<HTMLAttributes<HTMLInputElement>, 'onChange' | 'on
defaultValue?: string; defaultValue?: string;
leftSlot?: ReactNode; leftSlot?: ReactNode;
rightSlot?: ReactNode; rightSlot?: ReactNode;
size?: 'sm' | 'md'; size?: 'sm' | 'md' | 'auto';
className?: string; className?: string;
placeholder?: string; placeholder?: string;
autoFocus?: boolean; autoFocus?: boolean;
@@ -31,24 +31,24 @@ export type InputProps = Omit<HTMLAttributes<HTMLInputElement>, 'onChange' | 'on
export const Input = forwardRef<EditorView | undefined, InputProps>(function Input( export const Input = forwardRef<EditorView | undefined, InputProps>(function Input(
{ {
label,
type = 'text',
hideLabel,
className, className,
containerClassName, containerClassName,
labelClassName,
onChange,
placeholder,
size = 'md',
name,
leftSlot,
rightSlot,
defaultValue, defaultValue,
validate,
require,
onFocus,
onBlur,
forceUpdateKey, forceUpdateKey,
hideLabel,
label,
labelClassName,
leftSlot,
name,
onBlur,
onChange,
onFocus,
placeholder,
require,
rightSlot,
size = 'md',
type = 'text',
validate,
...props ...props
}: InputProps, }: InputProps,
ref, ref,
@@ -70,10 +70,7 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
const id = `input-${name}`; const id = `input-${name}`;
const inputClassName = classNames( const inputClassName = classNames(
className, className,
'!bg-transparent min-w-0 h-full w-full focus:outline-none placeholder:text-placeholder', '!bg-transparent min-w-0 h-auto w-full focus:outline-none placeholder:text-placeholder',
// Bump things over if the slots are occupied
leftSlot && 'pl-0.5 -ml-2',
rightSlot && 'pr-0.5 -mr-2',
); );
const isValid = useMemo(() => { const isValid = useMemo(() => {
@@ -92,7 +89,7 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
const wrapperRef = useRef<HTMLDivElement>(null); const wrapperRef = useRef<HTMLDivElement>(null);
const handleSubmit = useCallback(() => { const handleEnter = useCallback(() => {
const form = wrapperRef.current?.closest('form'); const form = wrapperRef.current?.closest('form');
if (!isValid || form == null) return; if (!isValid || form == null) return;
@@ -112,7 +109,7 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
{label} {label}
</label> </label>
<HStack <HStack
alignItems="center" alignItems="stretch"
className={classNames( className={classNames(
containerClassName, containerClassName,
'relative w-full rounded-md text-gray-900', 'relative w-full rounded-md text-gray-900',
@@ -121,24 +118,31 @@ export const Input = forwardRef<EditorView | undefined, InputProps>(function Inp
!isValid && '!border-invalid', !isValid && '!border-invalid',
size === 'md' && 'h-md leading-md', size === 'md' && 'h-md leading-md',
size === 'sm' && 'h-sm leading-sm', size === 'sm' && 'h-sm leading-sm',
size === 'auto' && '!min-h-sm',
)} )}
> >
{leftSlot} {leftSlot}
<Editor <HStack
ref={ref} alignItems="center"
id={id} className={classNames('w-full', leftSlot && 'pl-0.5 -ml-2', rightSlot && 'pr-0.5 -mr-2')}
singleLine >
onSubmit={handleSubmit} <Editor
type={type === 'password' && !obscured ? 'text' : type} ref={ref}
defaultValue={defaultValue} id={id}
forceUpdateKey={forceUpdateKey} singleLine
placeholder={placeholder} wrapLines={size === 'auto'}
onChange={handleChange} onEnter={handleEnter}
className={inputClassName} type={type === 'password' && !obscured ? 'text' : type}
onFocus={handleFocus} defaultValue={defaultValue}
onBlur={handleBlur} forceUpdateKey={forceUpdateKey}
{...props} placeholder={placeholder}
/> onChange={handleChange}
className={inputClassName}
onFocus={handleFocus}
onBlur={handleBlur}
{...props}
/>
</HStack>
{type === 'password' && ( {type === 'password' && (
<IconButton <IconButton
title={obscured ? `Show ${label}` : `Obscure ${label}`} title={obscured ? `Show ${label}` : `Obscure ${label}`}

View File

@@ -56,7 +56,7 @@ export const VStack = forwardRef(function VStack(
type BaseStackProps = HTMLAttributes<HTMLElement> & { type BaseStackProps = HTMLAttributes<HTMLElement> & {
as?: ComponentType | 'ul' | 'form'; as?: ComponentType | 'ul' | 'form';
space?: keyof typeof gapClasses; space?: keyof typeof gapClasses;
alignItems?: 'start' | 'center'; alignItems?: 'start' | 'center' | 'stretch';
justifyContent?: 'start' | 'center' | 'end' | 'between'; justifyContent?: 'start' | 'center' | 'end' | 'between';
}; };
@@ -74,6 +74,7 @@ const BaseStack = forwardRef(function BaseStack(
'flex', 'flex',
alignItems === 'center' && 'items-center', alignItems === 'center' && 'items-center',
alignItems === 'start' && 'items-start', alignItems === 'start' && 'items-start',
alignItems === 'stretch' && 'items-stretch',
justifyContent === 'start' && 'justify-start', justifyContent === 'start' && 'justify-start',
justifyContent === 'center' && 'justify-center', justifyContent === 'center' && 'justify-center',
justifyContent === 'end' && 'justify-end', justifyContent === 'end' && 'justify-end',

View File

@@ -1,89 +1,89 @@
const plugin = require('tailwindcss/plugin') const plugin = require('tailwindcss/plugin');
const height = {
xs: '1.75rem',
sm: '2.0rem',
md: '2.5rem',
};
/** @type {import("tailwindcss").Config} */ /** @type {import("tailwindcss").Config} */
module.exports = { module.exports = {
darkMode: ["class", "[data-appearance=\"dark\"]"], darkMode: ['class', '[data-appearance="dark"]'],
content: [ content: ['./index.html', './src-web/**/*.{html,js,jsx,ts,tsx}'],
"./index.html",
"./src-web/**/*.{html,js,jsx,ts,tsx}"
],
theme: { theme: {
extend: { extend: {
opacity: { opacity: {
"disabled": "0.3" disabled: '0.3',
}, },
fontSize: { fontSize: {
"xs": "0.8rem" xs: '0.8rem',
},
height: {
"xs": "1.75rem",
"sm": "2.0rem",
"md": "2.5rem"
}, },
height,
minHeight: height,
lineHeight: { lineHeight: {
// HACK: Minus 2 to account for borders inside inputs // HACK: Minus 2 to account for borders inside inputs
"xs": "calc(1.75rem - 2px)", xs: 'calc(1.75rem - 2px)',
"sm": "calc(2.0rem - 2px)", sm: 'calc(2.0rem - 2px)',
"md": "calc(2.5rem - 2px)" md: 'calc(2.5rem - 2px)',
}, },
}, },
fontFamily: { fontFamily: {
"mono": ["JetBrains Mono", "Menlo", "monospace"], mono: ['JetBrains Mono', 'Menlo', 'monospace'],
"sans": [ sans: [
"Inter", 'Inter',
"-apple-system", '-apple-system',
"BlinkMacSystemFont", 'BlinkMacSystemFont',
"Segoe UI", 'Segoe UI',
"Roboto", 'Roboto',
"Oxygen-Sans", 'Oxygen-Sans',
"Ubuntu", 'Ubuntu',
"Cantarell", 'Cantarell',
"Helvetica Neue", 'Helvetica Neue',
"sans-serif", 'sans-serif',
"Apple Color Emoji", 'Apple Color Emoji',
"Segoe UI Emoji", 'Segoe UI Emoji',
"Segoe UI Symbol", 'Segoe UI Symbol',
], ],
}, },
fontSize: { fontSize: {
'3xs': "0.6rem", '3xs': '0.6rem',
'2xs': "0.7rem", '2xs': '0.7rem',
xs: "0.8rem", xs: '0.8rem',
sm: "0.9rem", sm: '0.9rem',
base: "1rem", base: '1rem',
xl: "1.25rem", xl: '1.25rem',
"2xl": "1.563rem", '2xl': '1.563rem',
"3xl": "1.953rem", '3xl': '1.953rem',
"4xl": "2.441rem", '4xl': '2.441rem',
"5xl": "3.052rem" '5xl': '3.052rem',
}, },
colors: { colors: {
selection: "hsl(var(--color-violet-500) / 0.4)", selection: 'hsl(var(--color-violet-500) / 0.4)',
focus: "hsl(var(--color-blue-500) / 0.6)", focus: 'hsl(var(--color-blue-500) / 0.6)',
invalid: "hsl(var(--color-red-500))", invalid: 'hsl(var(--color-red-500))',
highlight: "hsl(var(--color-gray-300) / 0.35)", highlight: 'hsl(var(--color-gray-300) / 0.35)',
highlightSecondary: "hsl(var(--color-gray-300) / 0.2)", highlightSecondary: 'hsl(var(--color-gray-300) / 0.2)',
transparent: "transparent", transparent: 'transparent',
white: "hsl(0 100% 100% / <alpha-value>)", white: 'hsl(0 100% 100% / <alpha-value>)',
black: "hsl(0 100% 0% / <alpha-value>)", black: 'hsl(0 100% 0% / <alpha-value>)',
placeholder: "hsl(var(--color-gray-400) / <alpha-value>)", placeholder: 'hsl(var(--color-gray-400) / <alpha-value>)',
red: color("red"), red: color('red'),
orange: color("orange"), orange: color('orange'),
yellow: color("yellow"), yellow: color('yellow'),
gray: color("gray"), gray: color('gray'),
blue: color("blue"), blue: color('blue'),
green: color("green"), green: color('green'),
pink: color("pink"), pink: color('pink'),
violet: color("violet") violet: color('violet'),
} },
}, },
plugins: [ plugins: [
require("@tailwindcss/container-queries"), require('@tailwindcss/container-queries'),
plugin(function({ addVariant }) { plugin(function ({ addVariant }) {
addVariant('hocus', ['&:hover', '&:focus-visible', '&.focus:focus']) addVariant('hocus', ['&:hover', '&:focus-visible', '&.focus:focus']);
addVariant('focus-visible-or-class', ['&:focus-visible', '&.focus:focus']) addVariant('focus-visible-or-class', ['&:focus-visible', '&.focus:focus']);
}) }),
] ],
}; };
function color(name) { function color(name) {
@@ -100,6 +100,6 @@ function color(name) {
800: `hsl(var(--color-${name}-800) / <alpha-value>)`, 800: `hsl(var(--color-${name}-800) / <alpha-value>)`,
900: `hsl(var(--color-${name}-900) / <alpha-value>)`, 900: `hsl(var(--color-${name}-900) / <alpha-value>)`,
950: `hsl(var(--color-${name}-950) / <alpha-value>)`, 950: `hsl(var(--color-${name}-950) / <alpha-value>)`,
1000: `hsl(var(--color-${name}-1000) / <alpha-value>)` 1000: `hsl(var(--color-${name}-1000) / <alpha-value>)`,
}; };
} }