diff --git a/packages/code-connect/components/DatePicker/BaseComponentsCalendarDay.figma.tsx b/packages/code-connect/components/DatePicker/BaseComponentsCalendarDay.figma.tsx new file mode 100644 index 00000000000..8fde324c68f --- /dev/null +++ b/packages/code-connect/components/DatePicker/BaseComponentsCalendarDay.figma.tsx @@ -0,0 +1,15 @@ +import figma from '@figma/code-connect'; +import { CalendarMonth } from '@patternfly/react-core'; + +// Documentation for CalendarMonth can be found at https://www.patternfly.org/components/calendar-month + +figma.connect( + CalendarMonth, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7741-2677', + { + props: { + date: '2025-06-16' + }, + example: (props) => <CalendarMonth date={new Date(props.date)} onChange={() => {}} onMonthChange={() => {}} /> + } +); diff --git a/packages/code-connect/components/DatePicker/CalendarMonth.figma.tsx b/packages/code-connect/components/DatePicker/CalendarMonth.figma.tsx new file mode 100644 index 00000000000..bb1a7c9dc2a --- /dev/null +++ b/packages/code-connect/components/DatePicker/CalendarMonth.figma.tsx @@ -0,0 +1,48 @@ +import figma from '@figma/code-connect'; +import { CalendarMonth, Title } from '@patternfly/react-core'; + +// Documentation for CalendarMonth can be found at https://www.patternfly.org/components/calendar-month + +figma.connect( + CalendarMonth, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7958-136846', + { + props: { + date: '2025-06-16' + }, + example: (props) => ( + <CalendarMonth + date={props.date} + inlineProps={{ component: 'article', ariaLabelledby: 'favorite-date' }} + onChange={() => {}} + onMonthChange={() => {}} + /> + ) + } +); + +figma.connect( + CalendarMonth, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7958-136846', + { + variant: { Type: 'With date range' }, + props: { + rangeStart: new Date(2020, 10, 11), + date: new Date(2020, 10, 24) + }, + example: (props) => ( + <> + <Title headingLevel="h4" id="favorite-date"> + Select your favorite date + </Title> + <CalendarMonth + date={props.date} + inlineProps={{ component: 'article', ariaLabelledby: 'favorite-date' }} + onChange={() => {}} + onMonthChange={() => {}} + rangeStart={props.rangeStart} + /> + </> + ) + } +); diff --git a/packages/code-connect/components/DatePicker/DateAndTimePicker.figma.tsx b/packages/code-connect/components/DatePicker/DateAndTimePicker.figma.tsx new file mode 100644 index 00000000000..7cca6f3bed5 --- /dev/null +++ b/packages/code-connect/components/DatePicker/DateAndTimePicker.figma.tsx @@ -0,0 +1,80 @@ +import figma from '@figma/code-connect'; +import { + Button, + CalendarMonth, + Dropdown, + DropdownItem, + DropdownList, + InputGroup, + InputGroupItem, + MenuToggle, + Popover, + TextInput, + TimePicker +} from '@patternfly/react-core'; +import OutlinedCalendarAltIcon from '@patternfly/react-icons/dist/esm/icons/outlined-calendar-alt-icon'; +import OutlinedClockIcon from '@patternfly/react-icons/dist/esm/icons/outlined-clock-icon'; + +// Documentation for TimePicker can be found at https://www.patternfly.org/components/time-picker + +const time = ( + <Dropdown + onSelect={() => {}} + isOpen={false} + onOpenChange={() => {}} + toggle={() => ( + <MenuToggle + ref={null} + onClick={() => {}} + isExpanded={false} + aria-label="Time picker" + icon={<OutlinedClockIcon />} + /> + )} + > + <DropdownList> + <DropdownItem value={0} key="action"> + Action + </DropdownItem> + <DropdownItem value={1} key="operation"> + Operation + </DropdownItem> + </DropdownList> + </Dropdown> +); + +const calendarButton = ( + <Button variant="control" aria-label="Toggle the calendar" onClick={() => {}} icon={<OutlinedCalendarAltIcon />} /> +); + +const calendar = <CalendarMonth date={new Date('2025-06-16')} onChange={() => {}} onMonthChange={() => {}} />; + +figma.connect( + TimePicker, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7958-136824', + { + props: { + valueDate: 'MM-DD-YYYY', + valueTime: 'HH:MM' + }, + example: (props) => ( + <div style={{ width: '300px' }}> + <Popover position="bottom" bodyContent={calendar} showClose={false} isVisible={false} hasNoPadding hasAutoWidth> + <InputGroup> + <InputGroupItem> + <TextInput + type="text" + id="date-time" + aria-label="date and time picker demo" + value={props.valueDate + ' ' + props.valueTime} + readOnlyVariant="default" + /> + </InputGroupItem> + <InputGroupItem>{calendarButton}</InputGroupItem> + <InputGroupItem>{time}</InputGroupItem> + </InputGroup> + </Popover> + </div> + ) + } +); diff --git a/packages/code-connect/components/DatePicker/DatePicker.figma.tsx b/packages/code-connect/components/DatePicker/DatePicker.figma.tsx new file mode 100644 index 00000000000..a95c1a45606 --- /dev/null +++ b/packages/code-connect/components/DatePicker/DatePicker.figma.tsx @@ -0,0 +1,28 @@ +import figma from '@figma/code-connect'; +import { DatePicker } from '@patternfly/react-core'; + +// Documentation for DatePicker can be found at https://www.patternfly.org/components/date-picker + +figma.connect( + DatePicker, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7958:136841', + { + example: () => ( + <DatePicker + // eslint-disable-next-line no-console + onBlur={(_event, str, date) => console.log('onBlur', str, date)} + // eslint-disable-next-line no-console + onChange={(_event, str, date) => console.log('onChange', str, date)} + /> + ) + } +); + +figma.connect( + DatePicker, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7958:136841', + { + variant: { State: 'Invalid' }, + example: () => <DatePicker requiredDateOptions={{ isRequired: true, emptyDateText: 'Date is required' }} /> + } +); diff --git a/packages/code-connect/components/DatePicker/TimePicker.figma.tsx b/packages/code-connect/components/DatePicker/TimePicker.figma.tsx new file mode 100644 index 00000000000..9b1068df3f0 --- /dev/null +++ b/packages/code-connect/components/DatePicker/TimePicker.figma.tsx @@ -0,0 +1,24 @@ +import figma from '@figma/code-connect'; +import { TimePicker } from '@patternfly/react-core'; + +// Documentation for TimePicker can be found at https://www.patternfly.org/components/time-picker + +figma.connect( + TimePicker, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7958-136830', + { + props: { + isDisabled: figma.enum('State', { Disabled: true }) + }, + example: (props) => <TimePicker isDisabled={props.isDisabled} onChange={() => {}} time="3:35 AM" /> + } +); + +figma.connect( + TimePicker, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7958-136830', + { + variant: { State: 'Invalid' }, + example: () => <TimePicker is24Hour minTime="9:30" maxTime="17:15" time="18:00" /> + } +); diff --git a/packages/code-connect/components/DatePicker/TimePickerMenu.figma.tsx b/packages/code-connect/components/DatePicker/TimePickerMenu.figma.tsx new file mode 100644 index 00000000000..303d8899783 --- /dev/null +++ b/packages/code-connect/components/DatePicker/TimePickerMenu.figma.tsx @@ -0,0 +1,12 @@ +import figma from '@figma/code-connect'; +import { TimePicker } from '@patternfly/react-core'; + +// Documentation for TimePicker can be found at https://www.patternfly.org/components/time-picker + +figma.connect( + TimePicker, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7958-136828', + { + example: () => <TimePicker time="3:35 AM" onChange={() => {}} /> + } +); diff --git a/packages/code-connect/components/EmptyState/EmptyState.figma.tsx b/packages/code-connect/components/EmptyState/EmptyState.figma.tsx new file mode 100644 index 00000000000..461da3215b3 --- /dev/null +++ b/packages/code-connect/components/EmptyState/EmptyState.figma.tsx @@ -0,0 +1,70 @@ +import figma from '@figma/code-connect'; +import { EmptyState, EmptyStateBody, EmptyStateFooter, EmptyStateActions, Button } from '@patternfly/react-core'; +import PlusCircleIcon from '@patternfly/react-icons/dist/esm/icons/plus-circle-icon'; + +// TODO: DESIGN: Add Empty state footer +// TODO: DESIGN: Consolodate empty state examples +// TODO: DESIGN: Add empty state footer +// TODO: DESIGN: Add empty state actions +// TODO: DESIGN: Add empty state icon +// TODO: DESIGN: Add empty state title +// TODO: DESIGN: Add empty state body +// TODO: DESIGN: Add empty state variant +// TODO: DESIGN: Add empty state status +// Based on Code Connect's limitations, this component needs to be overhauled. Using the base component approach present in +// other components would significantly reduce complexity. + +figma.connect( + EmptyState, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=7896-37441', + { + props: { + // string + body: figma.string('Body text'), + title: figma.string('Header text'), + + // enum + status: figma.enum('Type', { + Custom: 'custom', + Warning: 'warning', + Success: 'success', + Danger: 'danger', + Info: 'info' + }), + variant: figma.enum('Size', { + Basic: 'full', + 'Extra small': 'xs', + Small: 'sm', + Large: 'lg', + 'Extra large': 'xl' + }), + + actions: figma.children('Empty state footer') + }, + example: (props) => ( + <EmptyState + // this may need to be updated for accessibility + headingLevel="h4" + icon={<PlusCircleIcon />} + variant={props.variant} + status={props.status} + titleText={props.title} + > + <EmptyStateBody>{props.body}</EmptyStateBody> + <EmptyStateFooter> + <EmptyStateActions> + <Button variant="primary">Primary action</Button> + </EmptyStateActions> + <EmptyStateActions> + <Button variant="link">Multiple</Button> + <Button variant="link">Action Buttons</Button> + <Button variant="link">Can</Button> + <Button variant="link">Go here</Button> + <Button variant="link">In the secondary</Button> + <Button variant="link">Action area</Button> + </EmptyStateActions> + </EmptyStateFooter> + </EmptyState> + ) + } +); diff --git a/packages/code-connect/components/FileUpload/MultipleFileUpload.figma.tsx b/packages/code-connect/components/FileUpload/MultipleFileUpload.figma.tsx new file mode 100644 index 00000000000..d57533f9693 --- /dev/null +++ b/packages/code-connect/components/FileUpload/MultipleFileUpload.figma.tsx @@ -0,0 +1,70 @@ +import figma from '@figma/code-connect'; +import { + FileUpload, + MultipleFileUpload, + MultipleFileUploadMain, + MultipleFileUploadStatus, + MultipleFileUploadStatusItem +} from '@patternfly/react-core'; +import UploadIcon from '@patternfly/react-icons/dist/esm/icons/upload-icon'; + +// TODO: DESIGN: Add status toggle text +// TODO: DESIGN: Add status toggle icon +// TODO: DESIGN: Add text separator +// TODO: DESIGN: Add info text +// TODO: DESIGN: Add status toggle text +// TODO: DESIGN: Add status toggle icon + +figma.connect( + FileUpload, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=8949-96128', + { + props: { + // static + titleText: 'Drag and drop files here', + titleTextSeparator: 'or', + infoText: 'Accepted file types: JPEG, Doc, PDF, PNG', + + // enum + isHorizontal: figma.enum('Layout', { Horizontal: true }), + + children: figma.children('*') + }, + example: (props) => ( + // Documentation for FileUpload can be found at https://www.patternfly.org/components/file-upload + <MultipleFileUpload + dropzoneProps={{ + accept: { + 'image/jpeg': ['.jpg', '.jpeg'], + 'application/msword': ['.doc'], + 'application/pdf': ['.pdf'], + 'image/png': ['.png'] + } + }} + isHorizontal={props.isHorizontal} + onFileDrop={() => {}} + > + <MultipleFileUploadMain + infoText={props.infoText} + titleIcon={<UploadIcon />} + titleText={props.titleText} + titleTextSeparator={props.titleTextSeparator} + /> + + <MultipleFileUploadStatus + aria-label="Current uploads" + statusToggleIcon="StatusToggleIcon" + statusToggleText="Status toggle text" + > + <MultipleFileUploadStatusItem + file="file-upload-file" + key="file-upload-key" + onClearClick={() => {}} + onReadSuccess={() => {}} + onReadFail={() => {}} + /> + </MultipleFileUploadStatus> + </MultipleFileUpload> + ) + } +); diff --git a/packages/code-connect/components/FileUpload/SimpleFileUpload.figma.tsx b/packages/code-connect/components/FileUpload/SimpleFileUpload.figma.tsx new file mode 100644 index 00000000000..2ce61e3078a --- /dev/null +++ b/packages/code-connect/components/FileUpload/SimpleFileUpload.figma.tsx @@ -0,0 +1,66 @@ +import figma from '@figma/code-connect'; +import { FileUpload, FileUploadHelperText, HelperText, HelperTextItem } from '@patternfly/react-core'; + +// TODO: DESIGN: Add filename placeholder +// TODO: DESIGN: Add browse button text +// TODO: DESIGN: Add FileUploadHelperText + +figma.connect( + FileUpload, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=8949-96043', + { + props: { + // boolean + showHelperText: figma.boolean('Show helper text'), + hideDefaultPreview: figma.boolean('Show text preview box', { + true: false, + false: true + }), + helperText: figma.boolean('Show helper text', { + true: ( + <FileUploadHelperText> + <HelperText> + <HelperTextItem id="helper-text-example-helpText">Upload a CSV file</HelperTextItem> + </HelperText> + </FileUploadHelperText> + ), + false: undefined + }), + + // enum + allowEditingUploadedText: figma.enum('State', { 'Uploaded + Editable': true }), + isDragActive: figma.enum('State', { + 'Drag state': true, + false: undefined + }), + isLoading: figma.enum('State', { 'In progress upload': true }), + isValidated: figma.enum('State', { + 'Invalid upload': 'error', + 'Uploaded + Editable': 'success', + 'Uploaded + Not Editable': 'success' + }) + }, + example: (props) => ( + // Documentation for FileUpload can be found at https://www.patternfly.org/components/file-upload + <FileUpload + id="file-upload-id" + type="text" + aria-label="File upload example" + browseButtonText="Upload" + isLoading={props.isLoading} + validated={props.isValidated} + isDragActive={props.isDragActive} + hideDefaultPreview={props.hideDefaultPreview} + allowEditingUploadedText={props.allowEditingUploadedText} + onFileInputChange={() => {}} + onDataChange={() => {}} + onTextChange={() => {}} + onReadStarted={() => {}} + onReadFinished={() => {}} + onClearClick={() => {}} + > + {props.helperText} + </FileUpload> + ) + } +); diff --git a/packages/code-connect/components/Hint/Hint.figma.tsx b/packages/code-connect/components/Hint/Hint.figma.tsx new file mode 100644 index 00000000000..e678389d130 --- /dev/null +++ b/packages/code-connect/components/Hint/Hint.figma.tsx @@ -0,0 +1,94 @@ +import figma from '@figma/code-connect'; +import { + Hint, + HintBody, + HintFooter, + HintTitle, + DropdownList, + Dropdown, + DropdownItem, + Divider +} from '@patternfly/react-core'; +import EllipsisVIcon from '@patternfly/react-icons/dist/esm/icons/ellipsis-v-icon'; +import MenuToggle from '@patternfly/react-core/dist/js/components/MenuToggle/MenuToggle'; + +// TODO: DESIGN: Use dropdown from figma for actions +// TODO: DESIGN: Create hint title +// TODO: DESIGN: Create hint body +// TODO: DESIGN: Create hint footer + +// Note: Figma will not render conditional props within React components. +// This means that the <HintTitle>, <HintBody>, and <HintFooter> tags will not be properly render figma.string() +// Documentation for Hint can be found at https://www.patternfly.org/components/hint + +figma.connect( + Hint, + 'https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1118-3329', + { + props: { + // Pre-defined title options (enum works, boolean with JSX doesn't) + hintTitle: figma.enum('Show Title', { + false: undefined, + true: <HintTitle>Hint title</HintTitle> + }), + + // Pre-defined body options + hintBody: figma.enum('Show Body', { + false: undefined, + true: <HintBody>This is hint body text that provides helpful information.</HintBody> + }), + + // Pre-defined footer options + hintFooter: figma.enum('Show Footer', { + false: undefined, + true: <HintFooter>Footer content or link</HintFooter> + }) + }, + example: (props) => ( + <Hint + actions={ + <Dropdown + isOpen={false} + onSelect={() => {}} + onOpenChange={() => {}} + toggle={() => ( + <MenuToggle + aria-label="With title example kebab toggle" + variant="plain" + onClick={() => {}} + isExpanded={false} + icon={<EllipsisVIcon />} + /> + )} + > + <DropdownList> + <DropdownItem value={0} key="action"> + Action + </DropdownItem> + <DropdownItem value={1} key="link" to="#default-link2" onClick={() => {}}> + Link + </DropdownItem> + <DropdownItem value={2} isDisabled key="disabled action"> + Disabled Action + </DropdownItem> + <DropdownItem value={3} isDisabled key="disabled link" to="#default-link4"> + Disabled Link + </DropdownItem> + <Divider component="li" key="separator" /> + <DropdownItem value={4} key="separated action"> + Separated Action + </DropdownItem> + <DropdownItem value={5} key="separated link" to="#default-link6" onClick={() => {}}> + Separated Link + </DropdownItem> + </DropdownList> + </Dropdown> + } + > + {props.hintTitle} + {props.hintBody} + {props.hintFooter} + </Hint> + ) + } +); diff --git a/packages/code-connect/components/InlineEdit/FieldSpecificInlineEdit.figma.tsx b/packages/code-connect/components/InlineEdit/FieldSpecificInlineEdit.figma.tsx new file mode 100644 index 00000000000..38ec11644d0 --- /dev/null +++ b/packages/code-connect/components/InlineEdit/FieldSpecificInlineEdit.figma.tsx @@ -0,0 +1,53 @@ +import figma from '@figma/code-connect'; + +// Inline edit is NOT a React component +// Documentation for InlineEdit can be found at https://www.patternfly.org/components/inline-edit + +figma.connect('https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1664-8856', { + props: {}, + example: () => ( + <form className="pf-v6-c-inline-edit" id="single-inline-edit-example"> + <div className="pf-v6-c-inline-edit__group"> + <div className="pf-v6-c-inline-edit__value" id="single-inline-edit-example-label"> + Static value + </div> + <div className="pf-v6-c-inline-edit__action pf-m-enable-editable"> + <button + className="pf-v6-c-button pf-m-plain" + type="button" + id="single-inline-edit-example-edit-button" + aria-label="Edit" + aria-labelledby="single-inline-edit-example-edit-button single-inline-edit-example-label" + > + <span className="pf-v6-c-button__icon"> + <i className="fas fa-pencil-alt" aria-hidden="true"></i> + </span> + </button> + </div> + </div> + <div className="pf-v6-c-inline-edit__group"> + <div className="pf-v6-c-inline-edit__input"> + <span className="pf-v6-c-form-control"> + <input type="text" value="Static value" aria-label="Editable text input" /> + </span> + </div> + <div className="pf-v6-c-inline-edit__group pf-m-action-group pf-m-icon-group"> + <div className="pf-v6-c-inline-edit__action pf-m-valid"> + <button className="pf-v6-c-button pf-m-plain" type="button" aria-label="Save edits"> + <span className="pf-v6-c-button__icon"> + <i className="fas fa-check" aria-hidden="true"></i> + </span> + </button> + </div> + <div className="pf-v6-c-inline-edit__action"> + <button className="pf-v6-c-button pf-m-plain" type="button" aria-label="Cancel edits"> + <span className="pf-v6-c-button__icon"> + <i className="fas fa-times" aria-hidden="true"></i> + </span> + </button> + </div> + </div> + </div> + </form> + ) +}); diff --git a/packages/code-connect/components/InlineEdit/InlineEditActionGroup.figma.tsx b/packages/code-connect/components/InlineEdit/InlineEditActionGroup.figma.tsx new file mode 100644 index 00000000000..0837009b006 --- /dev/null +++ b/packages/code-connect/components/InlineEdit/InlineEditActionGroup.figma.tsx @@ -0,0 +1,24 @@ +import figma from '@figma/code-connect'; + +// Inline edit is NOT a React component +// Documentation for InlineEdit can be found at https://www.patternfly.org/components/inline-edit + +figma.connect('https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1664-5805', { + props: {}, + example: () => ( + <div className="pf-v6-c-inline-edit pf-m-inline-editable" id="inline-edit-action-group-example"> + <div className="pf-v6-c-inline-edit__group pf-m-action-group"> + <div className="pf-v6-c-inline-edit__action"> + <button className="pf-v6-c-button pf-m-primary" type="button"> + <span className="pf-v6-c-button__text">Save</span> + </button> + </div> + <div className="pf-v6-c-inline-edit__action"> + <button className="pf-v6-c-button pf-m-secondary" type="button"> + <span className="pf-v6-c-button__text">Cancel</span> + </button> + </div> + </div> + </div> + ) +}); diff --git a/packages/code-connect/components/InlineEdit/InlineEditToggle.figma.tsx b/packages/code-connect/components/InlineEdit/InlineEditToggle.figma.tsx new file mode 100644 index 00000000000..d20bca9228b --- /dev/null +++ b/packages/code-connect/components/InlineEdit/InlineEditToggle.figma.tsx @@ -0,0 +1,25 @@ +import figma from '@figma/code-connect'; + +// Inline edit is NOT a React component +// Documentation for InlineEdit can be found at https://www.patternfly.org/components/inline-edit + +figma.connect('https://www.figma.com/design/aEBBvq0J3EPXxHvv6WgDx9/PatternFly-6--Components-Test?node-id=1664-8905', { + props: {}, + example: () => ( + <div className="pf-v6-c-inline-edit" id="inline-edit-toggle-example"> + <div className="pf-v6-c-inline-edit__action pf-m-enable-editable"> + <button + className="pf-v6-c-button pf-m-plain" + type="button" + id="inline-edit-toggle-example-edit-button" + aria-label="Edit" + aria-labelledby="inline-edit-toggle-example-edit-button inline-edit-toggle-example-label" + > + <span className="pf-v6-c-button__icon"> + <i className="fas fa-pencil-alt" aria-hidden="true"></i> + </span> + </button> + </div> + </div> + ) +});