diff --git a/apps/solid/src/routes/components/input/button.route.tsx b/apps/solid/src/routes/components/control/button.route.tsx similarity index 100% rename from apps/solid/src/routes/components/input/button.route.tsx rename to apps/solid/src/routes/components/control/button.route.tsx diff --git a/apps/solid/src/routes/components/control/input.route.tsx b/apps/solid/src/routes/components/control/input.route.tsx new file mode 100644 index 00000000..8b959bcf --- /dev/null +++ b/apps/solid/src/routes/components/control/input.route.tsx @@ -0,0 +1,132 @@ +import { Component, For } from 'solid-js'; +import { Container, Heading, Divider, Input } from '@spuxx/solid'; + +export const InputRoute: Component = () => { + function validate(_value: string, event: Event) { + const input = event.currentTarget as HTMLInputElement; + input.reportValidity(); + } + + const variants = ['contained', 'outlined']; + + return ( + <> + + Input + + + Variants + + + + + + + + Validation + + + {(variant) => ( + <> + + + + )} + + + + Sizes + + + {(variant) => ( + <> + + + + + + + )} + + + + With Icon + + + {(variant) => ( + <> + + + + )} + + + + Input Types + + + {(variant) => ( + <> + + + + )} + + + + + ); +}; diff --git a/apps/solid/src/routes/routes.tsx b/apps/solid/src/routes/routes.tsx index 59e4a1f2..8786428a 100644 --- a/apps/solid/src/routes/routes.tsx +++ b/apps/solid/src/routes/routes.tsx @@ -1,9 +1,10 @@ import { RouteProps } from '@solidjs/router'; import { IndexRoute } from './index.route'; -import { ButtonRoute } from './components/input/button.route'; +import { ButtonRoute } from './components/control/button.route'; import { ContainerRoute } from './components/layout/container.route'; import { DividerRoute } from './components/layout/divider.route'; import { DialogRoute } from './dialog.route'; +import { InputRoute } from './components/control/input.route'; export const routes: RouteProps[] = [ { @@ -11,9 +12,13 @@ export const routes: RouteProps[] = [ component: IndexRoute, }, { - path: '/components/input/button', + path: '/components/control/button', component: () => ButtonRoute, }, + { + path: '/components/control/input', + component: () => InputRoute, + }, { path: '/components/layout/container', component: () => ContainerRoute, diff --git a/apps/starlight/src/assets/sidebar.ts b/apps/starlight/src/assets/sidebar.ts index 7277ec5e..83e7a53e 100644 --- a/apps/starlight/src/assets/sidebar.ts +++ b/apps/starlight/src/assets/sidebar.ts @@ -51,8 +51,8 @@ export const sidebar: StarlightUserConfigWithPlugins['sidebar'] = [ label: 'Components', items: [ { - label: 'Input', - autogenerate: { directory: 'solid/components/input' }, + label: 'Control', + autogenerate: { directory: 'solid/components/control' }, }, { label: 'Layout', diff --git a/apps/starlight/src/content/docs/solid/components/input/button.mdx b/apps/starlight/src/content/docs/solid/components/control/button.mdx similarity index 100% rename from apps/starlight/src/content/docs/solid/components/input/button.mdx rename to apps/starlight/src/content/docs/solid/components/control/button.mdx diff --git a/packages/browser-utils/src/styles/colors.css b/packages/browser-utils/src/styles/colors.css index 8264c9a6..aea9662a 100644 --- a/packages/browser-utils/src/styles/colors.css +++ b/packages/browser-utils/src/styles/colors.css @@ -8,6 +8,10 @@ color: var(--spx-color-surface); } +.spx[spx-variant='colored'].spx[spx-color='accent'] { + color: var(--spx-color-accent); +} + .spx[spx-variant='colored'].spx[spx-color='primary'] { color: var(--spx-color-primary); } @@ -50,6 +54,11 @@ color: var(--spx-color-on-surface); } +.spx[spx-variant='contained'].spx[spx-color='accent'] { + background: var(--spx-color-accent); + color: var(--spx-color-on-accent); +} + .spx[spx-variant='contained'].spx[spx-color='primary'] { background: var(--spx-color-primary); color: var(--spx-color-on-primary); @@ -96,6 +105,11 @@ color: var(--spx-color-surface); } +.spx[spx-variant='outlined'].spx[spx-color='accent'] { + border-color: var(--spx-color-accent); + color: var(--spx-color-accent); +} + .spx[spx-variant='outlined'].spx[spx-color='primary'] { border-color: var(--spx-color-primary); color: var(--spx-color-primary); diff --git a/packages/browser-utils/src/styles/components.css b/packages/browser-utils/src/styles/components.css index 6a669ea2..8432b590 100644 --- a/packages/browser-utils/src/styles/components.css +++ b/packages/browser-utils/src/styles/components.css @@ -1,4 +1,5 @@ -@import './components/input/button.css'; +@import './components/control/button.css'; +@import './components/control/input.css'; @import './components/layout/divider.css'; @import './components/layout/container.css'; @import './components/typography/heading.css'; diff --git a/packages/browser-utils/src/styles/components/input/button.css b/packages/browser-utils/src/styles/components/control/button.css similarity index 71% rename from packages/browser-utils/src/styles/components/input/button.css rename to packages/browser-utils/src/styles/components/control/button.css index 6554701e..0b151ecc 100644 --- a/packages/browser-utils/src/styles/components/input/button.css +++ b/packages/browser-utils/src/styles/components/control/button.css @@ -47,3 +47,18 @@ .spx-button[spx-rounded] { border-radius: calc(var(--spx-control-height-default) / 2) !important; } + +.spx-button[spx-size='small'] { + min-width: var(--spx-control-width-small); + max-width: min(var(--spx-control-width-small), 100%); +} + +.spx-button[spx-size='medium'] { + min-width: var(--spx-control-width-medium); + max-width: min(var(--spx-control-width-medium), 100%); +} + +.spx-button[spx-size='large'] { + min-width: var(--spx-control-width-large); + max-width: min(var(--spx-control-width-large), 100%); +} diff --git a/packages/browser-utils/src/styles/components/control/input.css b/packages/browser-utils/src/styles/components/control/input.css new file mode 100644 index 00000000..45923453 --- /dev/null +++ b/packages/browser-utils/src/styles/components/control/input.css @@ -0,0 +1,160 @@ +.spx-input { + --spx-input-pd-x: 0.75rem; + + position: relative; + height: fit-content; + display: inline-flex; + border-radius: var(--spx-border-radius); + background: inherit; + pointer-events: none; + + input { + height: var(--spx-input-height-default); + line-height: var(--spx-input-height-default); + width: 100%; + box-sizing: border-box; + font-size: medium; + background: inherit; + border: none; + border-radius: var(--spx-border-radius); + padding: 0px var(--spx-input-pd-x); + pointer-events: all; + } + + input:focus-visible { + outline: none; + } + + label { + position: absolute; + font-size: medium; + top: 50%; + transform: translateY(-50%); + transition: + padding 200ms, + font-size 200ms, + transform 200ms; + pointer-events: none; + display: flex; + gap: 2px; + align-items: center; + } + + input::-webkit-calendar-picker-indicator, + [list]::-webkit-calendar-picker-indicator { + display: none !important; + } + + &:has(input:disabled) { + filter: var(--spx-filter-control-disabled); + } +} + +.spx-input[spx-size='small'] { + width: var(--spx-control-width-small); + max-width: 100%; +} + +.spx-input[spx-size='medium'] { + width: var(--spx-control-width-medium); + max-width: 100%; +} + +.spx-input[spx-size='large'] { + width: var(--spx-control-width-large); + max-width: 100%; +} + +/* Common */ +.spx-input[spx-variant='contained'], +.spx-input[spx-variant='outlined'] { + label { + left: var(--spx-input-pd-x); + } +} + +/* Contained */ +.spx-input[spx-variant='contained'] { + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + background: var(--spx-color-input-contained-bg); + + input { + color: inherit; + box-sizing: border-box; + border-bottom-left-radius: 0px; + border-bottom-right-radius: 0px; + padding-top: 1.25rem; + } + + label { + color: var(--spx-color-text-subtle); + } + + input:focus { + box-shadow: 0 var(--spx-border-width) 0 var(--spx-color-input-focus); + } + + input:focus + label { + transform: translateY(-2.15rem); + color: var(--spx-color-input-focus); + } + + input:focus + label, + input:not(:placeholder-shown) + label { + transform: translateY(-1.15rem); + font-size: smaller; + } +} + +.spx-input[spx-variant='contained']:has(input:invalid) { + border-color: var(--spx-color-error); + + label { + color: var(--spx-color-input-error); + } + + input { + box-shadow: 0 var(--spx-border-width) 0 var(--spx-color-input-error); + } +} + +/* Outlined */ +.spx-input[spx-variant='outlined'] { + background: inherit; + color: var(--spx-color-input-outlined-fg); + border-color: var(--spx-color-input-outlined-fg); + + input { + color: var(--spx-color-text-default); + } + + label { + padding: 0px 4px; + left: calc(var(--spx-input-pd-x) - 4px); + background: inherit; + } + + input:focus + label { + transform: translateY(-2.15rem); + color: var(--spx-color-input-focus); + } + + input:focus + label, + input:not(:placeholder-shown) + label { + transform: translateY(-2.15rem); + font-size: smaller; + } +} + +.spx-input[spx-variant='outlined']:has(input:focus) { + border-color: var(--spx-color-input-focus); +} + +.spx-input[spx-variant='outlined']:has(input:invalid) { + border-color: var(--spx-color-input-error); + + label { + color: var(--spx-color-input-error); + } +} diff --git a/packages/browser-utils/src/styles/layout.css b/packages/browser-utils/src/styles/layout.css index 05edfedf..3c4688ab 100644 --- a/packages/browser-utils/src/styles/layout.css +++ b/packages/browser-utils/src/styles/layout.css @@ -2,3 +2,13 @@ --spx-z-modal: 85; --spx-z-modal-overlay: 81; } + +.spx[spx-size='auto'] { + min-width: auto; + max-width: 100%; +} + +.spx[spx-size='full'] { + min-width: 100%; + max-width: 100%; +} diff --git a/packages/browser-utils/src/styles/variables.css b/packages/browser-utils/src/styles/variables.css index 4423936b..f090c7f3 100644 --- a/packages/browser-utils/src/styles/variables.css +++ b/packages/browser-utils/src/styles/variables.css @@ -1,10 +1,12 @@ :root { - --spx-control-height-default: 40px; --spx-main-content-width: 1440px; - --spx-control-width-small: 10rem; - --spx-control-width-medium: 20rem; - --spx-control-width-large: 30rem; - --spx-control-width-auto: auto; - --spx-control-width-full: 100%; + --spx-control-height-default: 40px; + --spx-input-height-default: 48px; + + --spx-control-width-small: 8rem; + --spx-control-width-medium: 16rem; + --spx-control-width-large: 24rem; + + --spx-border-width: 1px; } diff --git a/packages/browser-utils/src/styles/variants.css b/packages/browser-utils/src/styles/variants.css index 1f914617..5bbfe0bc 100644 --- a/packages/browser-utils/src/styles/variants.css +++ b/packages/browser-utils/src/styles/variants.css @@ -5,7 +5,7 @@ .spx[spx-variant='outlined'] { background: none; - border-width: 1px; + border-width: var(--spx-border-width); border-style: solid; border-radius: var(--spx-border-radius); } @@ -16,7 +16,7 @@ } .spx[spx-variant='underlined'] { - border-width: 0px 0px 1px 0px; + border-width: 0px 0px var(--spx-border-width) 0px; border-style: none none solid none; border-top-left-radius: var(--spx-border-radius); border-top-right-radius: var(--spx-border-radius); diff --git a/packages/browser-utils/src/themes/default.theme.css b/packages/browser-utils/src/themes/default.theme.css index 221825ca..414d076e 100644 --- a/packages/browser-utils/src/themes/default.theme.css +++ b/packages/browser-utils/src/themes/default.theme.css @@ -16,23 +16,34 @@ html *, --spx-color-on-background: var(--spx-color-text-default); --spx-color-surface: #3f3f46; --spx-color-on-surface: var(--spx-color-text-default); + --spx-color-accent: #2dd4bf; + --spx-color-on-accent: var(--spx-color-text-highlighted); --spx-color-primary: #0d9488; --spx-color-on-primary: var(--spx-color-text-highlighted); --spx-color-secondary: #3f3f46; --spx-color-on-secondary: var(--spx-color-text-default); --spx-color-gradient: linear-gradient(45deg, var(--spx-color-primary), #a21caf); --spx-color-on-gradient: var(--spx-color-text-highlighted); - /* Status Colors */ --spx-color-info: var(--spx-color-surface); --spx-color-on-info: var(--spx-color-text-default); - --spx-color-success: #166534; + --spx-color-success: #15803d; --spx-color-on-success: var(--spx-color-text-default); --spx-color-warning: #ca8a04; --spx-color-on-warning: var(--spx-color-text-default); --spx-color-error: #b91c1c; --spx-color-on-error: var(--spx-color-text-default); + /* Input Fields, Selects and similar controls */ + --spx-color-input-contained-bg: var(--spx-color-secondary); + --spx-color-input-outlined-fg: var(--spx-color-text-subtle); + --spx-color-input-focus: var(--spx-color-accent); + --spx-color-input-error: color-mix( + in srgb, + var(--spx-color-on-background), + var(--spx-color-error) 66% + ); + /* Modal Dialog */ --spx-color-modal: var(--spx-color-surface); --spx-color-on-modal: var(--spx-color-on-surface); diff --git a/packages/browser-utils/src/types/styles/index.ts b/packages/browser-utils/src/types/styles/index.ts index 18a004ba..2b046a86 100644 --- a/packages/browser-utils/src/types/styles/index.ts +++ b/packages/browser-utils/src/types/styles/index.ts @@ -46,3 +46,18 @@ export const ModalSize = { * The size of a modal dialog. */ export type ModalSize = (typeof ModalSize)[keyof typeof ModalSize]; + +/** + * The size of a control element. + */ +export const ControlSize = { + small: 'small', + medium: 'medium', + large: 'large', + auto: 'auto', + max: 'max', +}; +/** + * The size of a control element. + */ +export type ControlSize = (typeof ControlSize)[keyof typeof ControlSize]; diff --git a/packages/solid/src/components/input/button/button.component.test.tsx b/packages/solid/src/components/control/button/button.component.test.tsx similarity index 100% rename from packages/solid/src/components/input/button/button.component.test.tsx rename to packages/solid/src/components/control/button/button.component.test.tsx diff --git a/packages/solid/src/components/input/button/button.component.tsx b/packages/solid/src/components/control/button/button.component.tsx similarity index 91% rename from packages/solid/src/components/input/button/button.component.tsx rename to packages/solid/src/components/control/button/button.component.tsx index b41b6d56..b211cb84 100644 --- a/packages/solid/src/components/input/button/button.component.tsx +++ b/packages/solid/src/components/control/button/button.component.tsx @@ -9,7 +9,7 @@ import { attributes, classNames } from '@src/main'; * @returns The button component. */ export const Button: Component = (props) => { - const { variant = 'contained', color = 'primary', rounded, loading } = props; + const { variant = 'contained', color = 'primary', size, rounded, loading } = props; const disabled = loading ? true : props.disabled; return ( @@ -19,6 +19,7 @@ export const Button: Component = (props) => { title={props.title} spx-variant={variant} spx-color={color} + spx-size={size || undefined} spx-rounded={rounded || undefined} disabled={disabled || undefined} onClick={props.onClick} diff --git a/packages/solid/src/components/input/button/button.types.ts b/packages/solid/src/components/control/button/button.types.ts similarity index 82% rename from packages/solid/src/components/input/button/button.types.ts rename to packages/solid/src/components/control/button/button.types.ts index e9486898..bf89c9a8 100644 --- a/packages/solid/src/components/input/button/button.types.ts +++ b/packages/solid/src/components/control/button/button.types.ts @@ -1,12 +1,19 @@ import { IconifyIcon } from '@iconify-icon/solid'; import { JSX, ParentProps } from 'solid-js'; -import { BaseColor, ContentColor } from '@spuxx/browser-utils'; +import { BaseColor, ContentColor, ControlSize } from '@spuxx/browser-utils'; import { ComponentProps } from '@src/main'; /** * The Button component properties. */ -export interface ButtonProps extends ComponentProps, ParentProps { +export interface ButtonProps + extends ComponentProps>, + ParentProps { + /** + * The size of the button. + * @default undefined + */ + size?: ControlSize; /** * The variant of the button. * @default "contained" diff --git a/packages/solid/src/components/input/button/index.ts b/packages/solid/src/components/control/button/index.ts similarity index 100% rename from packages/solid/src/components/input/button/index.ts rename to packages/solid/src/components/control/button/index.ts diff --git a/packages/solid/src/components/control/input/index.ts b/packages/solid/src/components/control/input/index.ts new file mode 100644 index 00000000..d162b967 --- /dev/null +++ b/packages/solid/src/components/control/input/index.ts @@ -0,0 +1,2 @@ +export * from './input.component'; +export * from './input.types'; diff --git a/packages/solid/src/components/control/input/input.component.test.tsx b/packages/solid/src/components/control/input/input.component.test.tsx new file mode 100644 index 00000000..99612ada --- /dev/null +++ b/packages/solid/src/components/control/input/input.component.test.tsx @@ -0,0 +1,109 @@ +import { describe, expect, it, vi } from 'vitest'; +import { Input } from './input.component'; +import { fireEvent, render } from '@solidjs/testing-library'; + +describe('Input', () => { + it('should render with default values', () => { + const { container } = render(() => ); + const inputContainer = container.querySelector('.spx-input'); + expect(inputContainer).toBeInTheDocument(); + expect(inputContainer).toHaveAttribute('spx-variant', 'contained'); + expect(inputContainer).not.toHaveAttribute('spx-size'); + expect(inputContainer).toHaveClass('spx', 'spx-input'); + const input = inputContainer?.querySelector('input'); + expect(input).toBeInTheDocument(); + expect(input).toHaveAttribute('type', 'text'); + expect(input).toHaveAttribute('placeholder', ' '); + expect(input).not.toHaveAttribute('aria-placeholder'); + expect(input).not.toHaveAttribute('required'); + expect(input).not.toHaveAttribute('list'); + expect(input).not.toHaveAttribute('pattern'); + expect(input).not.toHaveAttribute('disabled'); + const label = inputContainer?.querySelector('label'); + expect(label).toBeInTheDocument(); + expect(label!.querySelector('iconify-icon')).not.toBeInTheDocument(); + expect(label).toHaveTextContent('Username'); + expect(label).toHaveAttribute('for', input!.id); + }); + + it('should render with custom values', () => { + const { container } = render(() => ( + + )); + const inputContainer = container.querySelector('.spx-input'); + expect(inputContainer).toBeInTheDocument(); + expect(inputContainer).toHaveAttribute('spx-variant', 'outlined'); + expect(inputContainer).toHaveAttribute('spx-size', 'small'); + expect(inputContainer).toHaveClass('spx', 'spx-input', 'my-class'); + expect(inputContainer).toHaveStyle({ color: 'rgb(255, 0, 0)' }); + const input = inputContainer?.querySelector('input'); + expect(input).toBeInTheDocument(); + expect(input).toHaveAttribute('type', 'email'); + expect(input).toHaveAttribute('required'); + expect(input).toHaveAttribute('disabled'); + }); + + it('should render with an icon', () => { + const { container } = render(() => ); + const inputContainer = container.querySelector('.spx-input'); + expect(inputContainer).toBeInTheDocument(); + const label = inputContainer?.querySelector('label'); + expect(label).toBeInTheDocument(); + expect(label!.querySelector('iconify-icon')).toBeInTheDocument(); + expect(label!.querySelector('iconify-icon')).toHaveAttribute('icon', 'mdi:account'); + }); + + it('should apply additional attributes to the input', () => { + const { container } = render(() => ); + const input = container.querySelector('input'); + expect(input).toHaveAttribute('min', '5'); + }); + + it('should render with a list of options', () => { + const options = [ + { value: 'one', label: 'One' }, + { value: 'two', label: 'Two' }, + ]; + const { container } = render(() => ); + const input = container.querySelector('input'); + expect(input).toHaveAttribute('list'); + const datalist = container.querySelector('datalist'); + expect(datalist).toBeInTheDocument(); + expect(datalist?.querySelectorAll('option')).toHaveLength(2); + }); + + it("should add a pattern containing all options if 'forceOption' is true", () => { + const options = [ + { value: 'one', label: 'One' }, + { value: 'two', label: 'Two' }, + ]; + const { container } = render(() => ); + const input = container.querySelector('input'); + expect(input).toHaveAttribute('pattern', 'one|two'); + }); + + it("should call the 'onChange' callback", () => { + const onChange = vi.fn(); + const { container } = render(() => ); + const input = container.querySelector('input'); + fireEvent.change(input!, { target: { value: 'spuxx' } }); + expect(onChange).toHaveBeenCalledTimes(1); + }); + + it("should call the 'onInput' callback", () => { + const onInput = vi.fn(); + const { container } = render(() => ); + const input = container.querySelector('input'); + fireEvent.input(input!, { key: 's' }); + expect(onInput).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/solid/src/components/control/input/input.component.tsx b/packages/solid/src/components/control/input/input.component.tsx new file mode 100644 index 00000000..2c8850b0 --- /dev/null +++ b/packages/solid/src/components/control/input/input.component.tsx @@ -0,0 +1,65 @@ +import { Component, For, JSX } from 'solid-js'; +import { InputProps } from './input.types'; +import { attributes, classNames } from '@src/main'; +import { Icon } from '@iconify-icon/solid'; +import { InputType } from '@spuxx/browser-utils'; + +export const Input: Component = (props) => { + const { + type = InputType.text, + variant = 'contained', + size, + required, + options, + forceOption, + } = props; + const id = props.attrs?.id ?? crypto.randomUUID(); + const listId = `${id}-options`; + const pattern = + options && forceOption ? options.map((o) => o.value).join('|') : props.attrs?.pattern; + + const handleChange: JSX.EventHandler = (event) => { + const input = event.currentTarget as HTMLInputElement; + if (props.onChange) props.onChange(input.value, event); + }; + + const handleInput: JSX.EventHandler = (event) => { + const input = event.currentTarget as HTMLInputElement; + if (props.onInput) props.onInput(input.value, event); + }; + + return ( +
+ + + {options && ( + + + {(option) => + + )} +
+ ); +}; diff --git a/packages/solid/src/components/control/input/input.types.ts b/packages/solid/src/components/control/input/input.types.ts new file mode 100644 index 00000000..b32a9c26 --- /dev/null +++ b/packages/solid/src/components/control/input/input.types.ts @@ -0,0 +1,80 @@ +import { ComponentProps } from '@src/main'; +import { ControlSize, InputType, SelectOption } from '@spuxx/browser-utils'; +import { DOMElement, JSX } from 'solid-js/jsx-runtime'; + +/** + * The Input component properties. + */ +export interface InputProps extends ComponentProps> { + /** + * The input label. + */ + label: string; + /** + * An optional icon to render as part of the label. + */ + icon?: string; + /** + * The type of the input. + * @default 'text' + */ + type?: InputType; + /** + * An optional list of options for the input. Will be rendered into a element that + * is linked to the input and will be used to provide suggestions as the user types. + */ + options?: SelectOption[]; + /** + * If true, validation will fail if the input value is not in the list of options. + * @default false + */ + forceOption?: boolean; + /** + * The size of the input. + * @default undefined + */ + size?: ControlSize; + /** + * The type of the input. + */ + // type?: JSX.HTMLAttributes['min']; + /** + * The input variant. + * @default 'contained' + */ + variant?: string; + /** + * Whether the input is required. + * @default false + */ + required?: boolean; + /** + * Whether the input is disabled. + * @default false + */ + disabled?: boolean; + /** + * Called when the input value changes. + * @param value The input value. + * @param event The input event. + */ + onChange?: ( + value: string, + event: Event & { + currentTarget: HTMLInputElement; + target: DOMElement; + }, + ) => void; + /** + * Called when a character is being inserted or removed. + * @param value The input value. + * @param event The input event. + */ + onInput?: ( + value: string, + event: Event & { + currentTarget: HTMLInputElement; + target: DOMElement; + }, + ) => void; +} diff --git a/packages/solid/src/components/layout/container/container.types.ts b/packages/solid/src/components/layout/container/container.types.ts index 50d0bf9b..4599984c 100644 --- a/packages/solid/src/components/layout/container/container.types.ts +++ b/packages/solid/src/components/layout/container/container.types.ts @@ -1,11 +1,13 @@ import { BaseColor } from '@spuxx/browser-utils'; import { ComponentProps } from '@src/main'; -import { ParentProps } from 'solid-js'; +import { JSX, ParentProps } from 'solid-js'; /** * The Container component's properties. */ -export interface ContainerProps extends ComponentProps, ParentProps { +export interface ContainerProps + extends ComponentProps>, + ParentProps { /** * The tag to use for the container. * @default 'div' diff --git a/packages/solid/src/components/layout/divider/divider.types.ts b/packages/solid/src/components/layout/divider/divider.types.ts index 19ebba24..6a8cc659 100644 --- a/packages/solid/src/components/layout/divider/divider.types.ts +++ b/packages/solid/src/components/layout/divider/divider.types.ts @@ -1,10 +1,11 @@ import { BaseColor, ContentColor } from '@spuxx/browser-utils'; import { ComponentProps } from '@src/main'; +import { JSX } from 'solid-js/jsx-runtime'; /** * The Divider component's properties. */ -export interface DividerProps extends ComponentProps { +export interface DividerProps extends ComponentProps> { /** * The color of the divider. * @default 'text-subtle' diff --git a/packages/solid/src/components/typography/heading/heading.types.ts b/packages/solid/src/components/typography/heading/heading.types.ts index a21adaf8..da47407b 100644 --- a/packages/solid/src/components/typography/heading/heading.types.ts +++ b/packages/solid/src/components/typography/heading/heading.types.ts @@ -1,10 +1,12 @@ import { ComponentProps } from '@src/main'; -import { ParentProps } from 'solid-js'; +import { JSX, ParentProps } from 'solid-js'; /** * The Heading component properties. */ -export interface HeadingProps extends ComponentProps, ParentProps { +export interface HeadingProps + extends ComponentProps>, + ParentProps { /** * The level of the heading. */ diff --git a/packages/solid/src/main.ts b/packages/solid/src/main.ts index 88ee4136..79e2c166 100644 --- a/packages/solid/src/main.ts +++ b/packages/solid/src/main.ts @@ -4,7 +4,8 @@ // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ export * from './types/public'; -export * from './components/input/button'; +export * from './components/control/button'; +export * from './components/control/input'; export * from './components/layout/container'; export * from './components/layout/divider'; export * from './components/typography/heading'; diff --git a/packages/solid/src/modal/built-in/confirm.modal.tsx b/packages/solid/src/modal/built-in/confirm.modal.tsx index 50979791..1a465d2c 100644 --- a/packages/solid/src/modal/built-in/confirm.modal.tsx +++ b/packages/solid/src/modal/built-in/confirm.modal.tsx @@ -3,7 +3,7 @@ import { ModalHeader } from '../template/modal-header.component'; import { ModalTemplate } from '../template/modal-template.component'; import { ModalBody } from '../template/modal-body.component'; import { ModalFooter } from '../template/modal-footer.component'; -import { Button } from '../../components/input/button'; +import { Button } from '../../components/control/button'; import { BaseColor, ContentColor } from '@spuxx/browser-utils'; import { Modal } from '../modal.service'; diff --git a/packages/solid/src/types/public/index.ts b/packages/solid/src/types/public/index.ts index e84a80f5..3edf6262 100644 --- a/packages/solid/src/types/public/index.ts +++ b/packages/solid/src/types/public/index.ts @@ -5,7 +5,7 @@ import type * as CSS from 'csstype'; * A property interface for components to extend from. Includes some basic properties used * by almost all components. */ -export interface ComponentProps { +export interface ComponentProps> { /** * The component's class names. */ @@ -19,5 +19,5 @@ export interface ComponentProps { /** * The component's attributes. */ - attrs?: Omit, 'style'>; + attrs?: Omit; }