diff --git a/packages/assets/src/scss/_inputs-list.scss b/packages/assets/src/scss/_inputs-list.scss new file mode 100644 index 00000000..28522ea7 --- /dev/null +++ b/packages/assets/src/scss/_inputs-list.scss @@ -0,0 +1,36 @@ +@use 'functions' as *; + +.ids-choice-inputs-list { + $self: &; + + .ids-form-control { + &__label-wrapper { + margin-bottom: calculateRem(4px); + } + + &__helper-text-wrapper { + margin-top: calculateRem(4px); + } + } + + &__items { + display: flex; + flex-direction: column; + + & > * { + padding: calculateRem(4px) calculateRem(8px); + } + } + + &--horizontal { + #{$self}__items { + flex-direction: row; + flex-wrap: wrap; + gap: calculateRem(12px); + + & > * { + padding: calculateRem(4px) 0; + } + } + } +} diff --git a/packages/assets/src/scss/styles.scss b/packages/assets/src/scss/styles.scss index 8039cd06..627f8906 100644 --- a/packages/assets/src/scss/styles.scss +++ b/packages/assets/src/scss/styles.scss @@ -10,6 +10,7 @@ @use 'helper-text'; @use 'icons'; @use 'input'; +@use 'inputs-list'; @use 'label'; @use 'inputs/checkbox'; diff --git a/packages/components/src/internal/partials/BaseInputsList/BaseInputsList.stories.tsx b/packages/components/src/internal/partials/BaseInputsList/BaseInputsList.stories.tsx new file mode 100644 index 00000000..1e69ffeb --- /dev/null +++ b/packages/components/src/internal/partials/BaseInputsList/BaseInputsList.stories.tsx @@ -0,0 +1,82 @@ +import React from 'react'; + +import type { Meta, StoryObj } from '@storybook/react'; + +import BaseInputsList from './BaseInputsList'; +import { DIRECTION } from './BaseInputsList.types'; + +interface ItemType { + id: string; + label: string; +} + +const meta: Meta> = { + title: 'components/src/base/BaseInputsList', + component: BaseInputsList, + parameters: { + layout: 'centered', + docs: { + controls: { exclude: ['items', 'renderItem', 'labelProps', 'helperTextProps'] }, + }, + }, + tags: ['autodocs', 'foundation', 'base'], + argTypes: { + className: { control: 'text' }, + direction: { + control: 'select', + options: Object.values(DIRECTION), + }, + }, + args: { + items: [ + { id: '1', label: 'Item 1' }, + { id: '2', label: 'Item 2' }, + { id: '3', label: 'Item 3' }, + ], + renderItem: (item: ItemType) => ( +
+ {item.id}: {item.label} +
+ ), + }, +}; + +export default meta; + +type Story = StoryObj>; + +export const Default: Story = { + name: 'Default', + args: { + labelProps: { children: 'Choice Inputs List Label' }, + helperTextProps: { children: 'This is a helper text' }, + }, +}; + +export const Horizontal: Story = { + name: 'Horizontal', + args: { + labelProps: { children: 'Choice Inputs List Label' }, + helperTextProps: { children: 'This is a helper text' }, + direction: DIRECTION.HORIZONTAL, + }, +}; + +export const NoHelper: Story = { + name: 'No Helper', + args: { + labelProps: { children: 'Choice Inputs List Label' }, + }, +}; + +export const NoLabel: Story = { + name: 'No Label', + args: { + helperTextProps: { children: 'This is a helper text' }, + }, +}; + +export const OnlyItems: Story = { + name: 'Only Items', + args: {}, +}; diff --git a/packages/components/src/internal/partials/BaseInputsList/BaseInputsList.tsx b/packages/components/src/internal/partials/BaseInputsList/BaseInputsList.tsx new file mode 100644 index 00000000..1a03d08f --- /dev/null +++ b/packages/components/src/internal/partials/BaseInputsList/BaseInputsList.tsx @@ -0,0 +1,28 @@ +import React from 'react'; + +import BaseFormControl from '@ids-internal/partials/BaseFormControl'; +import { createCssClassNames } from '@ibexa/ids-core/helpers/cssClassNames'; + +import { BaseInputsListProps, DIRECTION } from './BaseInputsList.types'; + +const BaseInputsList = ({ + items, + renderItem, + className = '', + direction = DIRECTION.VERTICAL, + helperTextProps, + labelProps, +}: BaseInputsListProps) => { + const listClassName = createCssClassNames({ + 'ids-choice-inputs-list': true, + [`ids-choice-inputs-list--${direction}`]: true, + [className]: true, + }); + return ( + +
{items.map((item) => renderItem(item))}
+
+ ); +}; + +export default BaseInputsList; diff --git a/packages/components/src/internal/partials/BaseInputsList/BaseInputsList.types.ts b/packages/components/src/internal/partials/BaseInputsList/BaseInputsList.types.ts new file mode 100644 index 00000000..055b0a84 --- /dev/null +++ b/packages/components/src/internal/partials/BaseInputsList/BaseInputsList.types.ts @@ -0,0 +1,16 @@ +import { BaseComponentAriaAttributes } from '@ids-types/general'; +import { HelperTextProps } from '../../../HelperText/HelperText.types'; +import { LabelProps } from '../../../Label/Label.types'; + +export enum DIRECTION { + HORIZONTAL = 'horizontal', + VERTICAL = 'vertical', +} + +export interface BaseInputsListProps extends BaseComponentAriaAttributes { + items: T[]; + renderItem: (item: T) => React.ReactNode; + direction?: DIRECTION; + helperTextProps?: HelperTextProps; + labelProps?: LabelProps; +} diff --git a/packages/components/src/internal/partials/BaseInputsList/index.ts b/packages/components/src/internal/partials/BaseInputsList/index.ts new file mode 100644 index 00000000..b862b1d0 --- /dev/null +++ b/packages/components/src/internal/partials/BaseInputsList/index.ts @@ -0,0 +1,5 @@ +import { BaseInputsListProps, DIRECTION } from './BaseInputsList.types'; +import BaseInputsList from './BaseInputsList'; + +export default BaseInputsList; +export type { BaseInputsListProps, DIRECTION };