UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

503 lines 670 kB
{ "schemaVersion": 2, "components": { "actionbar": { "source": "https://github.com/primer/react/tree/main/packages/react/src/ActionBar", "id": "actionbar", "name": "ActionBar", "status": "alpha", "a11yReviewed": true, "stories": [ { "id": "experimental-components-actionbar--default", "code": "() => (\n <ActionBar aria-label=\"Toolbar\">\n <ActionBar.IconButton\n icon={BoldIcon}\n aria-label=\"Bold\"\n ></ActionBar.IconButton>\n <ActionBar.IconButton\n icon={ItalicIcon}\n aria-label=\"Italic\"\n ></ActionBar.IconButton>\n <ActionBar.IconButton\n icon={CodeIcon}\n aria-label=\"Code\"\n ></ActionBar.IconButton>\n <ActionBar.IconButton\n icon={LinkIcon}\n aria-label=\"Link\"\n ></ActionBar.IconButton>\n <ActionBar.Divider />\n <ActionBar.IconButton\n icon={FileAddedIcon}\n aria-label=\"File Added\"\n ></ActionBar.IconButton>\n <ActionBar.IconButton\n icon={SearchIcon}\n aria-label=\"Search\"\n ></ActionBar.IconButton>\n <ActionBar.IconButton\n icon={QuoteIcon}\n aria-label=\"Insert Quote\"\n ></ActionBar.IconButton>\n <ActionBar.IconButton\n icon={ListUnorderedIcon}\n aria-label=\"Unordered List\"\n ></ActionBar.IconButton>\n <ActionBar.IconButton\n icon={ListOrderedIcon}\n aria-label=\"Ordered List\"\n ></ActionBar.IconButton>\n <ActionBar.IconButton\n icon={TasklistIcon}\n aria-label=\"Task List\"\n ></ActionBar.IconButton>\n </ActionBar>\n)" } ], "importPath": "@primer/react", "props": [ { "name": "aria-label", "type": "string", "required": false, "description": "When provided, a label is added to the action bar", "defaultValue": "" }, { "name": "aria-labelledby", "type": "string", "required": false, "description": "When provided, uses the element with that ID as the accessible name for the ActionBar", "defaultValue": "" }, { "name": "children", "type": "ReactNode", "required": false, "description": "Buttons in the action bar", "defaultValue": "" }, { "name": "size", "type": "'small' | 'large' | 'medium'", "required": false, "description": "Size of the action bar", "defaultValue": "" }, { "name": "flush", "type": "boolean", "required": false, "description": "Allows ActionBar to be flush with the container", "defaultValue": "false" }, { "name": "className", "type": "string", "required": false, "description": "Custom className", "defaultValue": "" } ], "subcomponents": [ { "name": "ActionBar.IconButton", "props": [ { "name": "children", "type": "React.ReactNode", "defaultValue": "", "required": true, "description": "This will be the Button description." }, { "name": "icon", "type": "Component", "defaultValue": "", "description": "Provide an octicon. It will be placed in the center of the button" }, { "name": "aria-label", "type": "string", "defaultValue": "", "description": "Use an aria label to describe the functionality of the button. Please refer to [our guidance on alt text](https://primer.style/guides/accessibility/alternative-text-for-images) for tips on writing good alternative text." }, { "name": "disabled", "type": "boolean", "defaultValue": "", "description": "Provides a disabled state for the button. The button will remain focusable, and have `aria-disabled` applied." } ], "passthrough": { "element": "IconButton", "url": "/react/IconButton" } }, { "name": "ActionBar.Divider", "props": [] } ] }, "action_list": { "source": "https://github.com/primer/react/tree/main/packages/react/src/ActionList", "id": "action_list", "name": "ActionList", "status": "beta", "a11yReviewed": false, "stories": [ { "id": "components-actionlist--default", "code": "() => (\n <ActionList>\n <ActionList.Item>Copy link</ActionList.Item>\n <ActionList.Item>Quote reply</ActionList.Item>\n <ActionList.Item>Edit comment</ActionList.Item>\n </ActionList>\n)" }, { "id": "components-actionlist-features--simple-list", "code": "() => (\n <ActionList>\n <ActionList.Item>Copy link</ActionList.Item>\n <ActionList.Item>Quote reply</ActionList.Item>\n <ActionList.Item>Edit comment</ActionList.Item>\n <ActionList.Divider />\n <ActionList.Item variant=\"danger\">Delete file</ActionList.Item>\n </ActionList>\n)" }, { "id": "components-actionlist-features--with-visual-list-heading", "code": "() => (\n <ActionList>\n <ActionList.Heading as=\"h2\" size=\"small\">\n Filter by\n </ActionList.Heading>\n <ActionList.Group>\n <ActionList.GroupHeading as=\"h3\">Repositories</ActionList.GroupHeading>\n <ActionList.Item onSelect={() => {}}>\n <ActionList.LeadingVisual>\n <FileDirectoryIcon />\n </ActionList.LeadingVisual>\n app/assets/modules\n </ActionList.Item>\n <ActionList.Item onSelect={() => {}}>\n <ActionList.LeadingVisual>\n <FileDirectoryIcon />\n </ActionList.LeadingVisual>\n src/react/components\n </ActionList.Item>\n <ActionList.Item onSelect={() => {}}>\n <ActionList.LeadingVisual>\n <FileDirectoryIcon />\n </ActionList.LeadingVisual>\n memex/shared-ui/components\n </ActionList.Item>\n <ActionList.Item onSelect={() => {}}>\n <ActionList.LeadingVisual>\n <FileDirectoryIcon />\n </ActionList.LeadingVisual>\n views/assets/modules\n </ActionList.Item>\n </ActionList.Group>\n\n <ActionList.Group>\n <ActionList.GroupHeading as=\"h3\">Advanced</ActionList.GroupHeading>\n <ActionList.Item onSelect={() => {}}>\n <ActionList.LeadingVisual>\n <PlusCircleIcon />\n </ActionList.LeadingVisual>\n Owner\n </ActionList.Item>\n <ActionList.Item onSelect={() => {}}>\n <ActionList.LeadingVisual>\n <PlusCircleIcon />\n </ActionList.LeadingVisual>\n Symbol\n </ActionList.Item>\n <ActionList.Item onSelect={() => {}}>\n <ActionList.LeadingVisual>\n <PlusCircleIcon />\n </ActionList.LeadingVisual>\n Exclude archived\n </ActionList.Item>\n </ActionList.Group>\n </ActionList>\n)" }, { "id": "components-actionlist-features--with-custom-heading", "code": "() => (\n <>\n <Heading\n as=\"h1\"\n id=\"list-heading\"\n sx={{\n fontSize: 3,\n marginX: 3,\n }}\n >\n Details\n </Heading>\n <ActionList aria-labelledby=\"list-heading\">\n <ActionList.LinkItem href=\"https://github.com/primer/react#readme\">\n <ActionList.LeadingVisual>\n <BookIcon />\n </ActionList.LeadingVisual>\n Readme\n </ActionList.LinkItem>\n <ActionList.LinkItem href=\"https://github.com/primer/react/blob/main/LICENSE\">\n <ActionList.LeadingVisual>\n <LawIcon />\n </ActionList.LeadingVisual>\n MIT License\n </ActionList.LinkItem>\n <ActionList.LinkItem href=\"https://github.com/primer/react/stargazers\">\n <ActionList.LeadingVisual>\n <StarIcon />\n </ActionList.LeadingVisual>\n <strong>1.5k</strong> stars\n </ActionList.LinkItem>\n <ActionList.LinkItem href=\"https://github.com/primer/react/watchers\">\n <ActionList.LeadingVisual>\n <EyeIcon />\n </ActionList.LeadingVisual>\n <strong>21</strong> watching\n </ActionList.LinkItem>\n <ActionList.LinkItem href=\"https://github.com/primer/react/network/members\">\n <ActionList.LeadingVisual>\n <RepoForkedIcon />\n </ActionList.LeadingVisual>\n <strong>225</strong> forks\n </ActionList.LinkItem>\n </ActionList>\n </>\n)" }, { "id": "components-actionlist-features--with-icons", "code": "() => (\n <ActionList>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <LinkIcon />\n </ActionList.LeadingVisual>\n github.com/primer\n </ActionList.Item>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <LawIcon />\n </ActionList.LeadingVisual>\n MIT License\n </ActionList.Item>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <StarIcon />\n </ActionList.LeadingVisual>\n 256 stars\n </ActionList.Item>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <RepoForkedIcon />\n </ActionList.LeadingVisual>\n 3 forks\n </ActionList.Item>\n <ActionList.Item variant=\"danger\">\n <ActionList.LeadingVisual>\n <AlertIcon />\n </ActionList.LeadingVisual>\n 4 vulnerabilities\n </ActionList.Item>\n </ActionList>\n)" }, { "id": "components-actionlist-features--with-avatars", "code": "() => (\n <ActionList>\n {users.map((user) => (\n <ActionList.Item key={user.login}>\n <ActionList.LeadingVisual>\n <Avatar src={`https://github.com/${user.login}.png`} />\n </ActionList.LeadingVisual>\n {user.login}\n </ActionList.Item>\n ))}\n </ActionList>\n)" }, { "id": "components-actionlist-features--item-dividers", "code": "() => (\n <ActionList showDividers>\n <ActionList.Item>Copy link</ActionList.Item>\n <ActionList.Item>Quote reply</ActionList.Item>\n <ActionList.Item>Edit comment</ActionList.Item>\n </ActionList>\n)" }, { "id": "components-actionlist-features--single-divider", "code": "() => (\n <ActionList>\n <ActionList.Item>Copy link</ActionList.Item>\n <ActionList.Item>Quote reply</ActionList.Item>\n <ActionList.Item>Edit comment</ActionList.Item>\n <ActionList.Divider />\n <ActionList.Item variant=\"danger\">Delete file</ActionList.Item>\n </ActionList>\n)" }, { "id": "components-actionlist-features--inline-description", "code": "() => (\n <ActionList>\n {users.map((user) => (\n <ActionList.Item key={user.login}>\n <ActionList.LeadingVisual>\n <Avatar src={`https://github.com/${user.login}.png`} />\n </ActionList.LeadingVisual>\n {user.login}\n <ActionList.Description>{user.name}</ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList>\n)" }, { "id": "components-actionlist-features--block-description", "code": "() => (\n <ActionList>\n {users.map((user) => (\n <ActionList.Item key={user.login}>\n <ActionList.LeadingVisual>\n <Avatar src={`https://github.com/${user.login}.png`} />\n </ActionList.LeadingVisual>\n {user.login}\n <ActionList.Description variant=\"block\">\n {user.name}\n </ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList>\n)" }, { "id": "components-actionlist-features--single-select", "code": "() => {\n const [selectedIndex, setSelectedIndex] = React.useState(0)\n return (\n <ActionList\n selectionVariant=\"single\"\n showDividers\n role=\"menu\"\n aria-label=\"Project\"\n >\n {projects.map((project, index) => (\n <ActionList.Item\n key={index}\n role=\"menuitemradio\"\n selected={index === selectedIndex}\n aria-checked={index === selectedIndex}\n onSelect={() => setSelectedIndex(index)}\n >\n <ActionList.LeadingVisual>\n <TableIcon />\n </ActionList.LeadingVisual>\n {project.name}\n <ActionList.Description variant=\"block\">\n {project.scope}\n </ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--inactive-single-select", "code": "() => {\n const [selectedIndex, setSelectedIndex] = React.useState(1)\n return (\n <ActionList\n selectionVariant=\"single\"\n showDividers\n role=\"menu\"\n aria-label=\"Project\"\n >\n {/* menuitem because state is inactive */}\n <ActionList.Item\n role=\"menuitem\"\n selected={false}\n inactiveText=\"Unavailable due to an outage\"\n >\n Inactive item\n </ActionList.Item>\n <ActionList.Item\n role=\"menuitemradio\"\n selected={selectedIndex === 1}\n aria-checked={selectedIndex === 1}\n onSelect={() => setSelectedIndex(1)}\n >\n Item 2\n </ActionList.Item>\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--multi-select", "code": "() => {\n const [selectedIndices, setSelectedIndices] = React.useState<number[]>([0])\n const handleSelect = (index: number) => {\n if (selectedIndices.includes(index)) {\n setSelectedIndices(selectedIndices.filter((i) => i !== index))\n } else {\n setSelectedIndices([...selectedIndices, index])\n }\n }\n return (\n <ActionList\n selectionVariant=\"multiple\"\n showDividers\n role=\"menu\"\n aria-label=\"Project\"\n >\n {projects.map((project, index) => (\n <ActionList.Item\n key={index}\n role=\"menuitemcheckbox\"\n selected={selectedIndices.includes(index)}\n aria-checked={selectedIndices.includes(index)}\n onSelect={() => handleSelect(index)}\n disabled={index === 3 ? true : undefined}\n >\n <ActionList.LeadingVisual>\n <TableIcon />\n </ActionList.LeadingVisual>\n {project.name}\n <ActionList.Description variant=\"block\">\n {project.scope}\n </ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--listbox-single-select", "code": "() => {\n const [selectedIndice, setSelectedIndice] = React.useState<number>(0)\n const handleSelect = (index: number) => {\n setSelectedIndice(index)\n }\n return (\n <ActionList selectionVariant=\"single\" role=\"listbox\" aria-label=\"Projects\">\n {projects.map((project, index) => (\n <ActionList.Item\n key={index}\n selected={selectedIndice === index}\n aria-checked={selectedIndice === index}\n onSelect={() => handleSelect(index)}\n disabled={index === 3 ? true : undefined}\n role=\"option\"\n >\n <ActionList.LeadingVisual>\n <TableIcon />\n </ActionList.LeadingVisual>\n {project.name}\n <ActionList.Description variant=\"block\">\n {project.scope}\n </ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--listbox-multi-select", "code": "() => {\n const [selectedIndices, setSelectedIndices] = React.useState<number[]>([0])\n const handleSelect = (index: number) => {\n if (selectedIndices.includes(index)) {\n setSelectedIndices(selectedIndices.filter((i) => i !== index))\n } else {\n setSelectedIndices([...selectedIndices, index])\n }\n }\n return (\n <ActionList role=\"menu\" selectionVariant=\"multiple\" aria-label=\"Projects\">\n {projects.map((project, index) => (\n <ActionList.Item\n key={index}\n role=\"menuitemcheckbox\"\n selected={selectedIndices.includes(index)}\n aria-checked={selectedIndices.includes(index)}\n onSelect={() => handleSelect(index)}\n disabled={index === 3 ? true : undefined}\n >\n <ActionList.LeadingVisual>\n <TableIcon />\n </ActionList.LeadingVisual>\n {project.name}\n <ActionList.Description variant=\"block\">\n {project.scope}\n </ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--with-dynamic-content", "code": "() => {\n const [isTrue, setIsTrue] = React.useState(false)\n return (\n <FeatureFlags\n flags={{\n primer_react_action_list_item_as_button: true,\n }}\n >\n <ActionList>\n <ActionList.Item\n onSelect={() => {\n setIsTrue(!isTrue)\n }}\n >\n Activated? {isTrue ? 'Yes' : 'No'}\n </ActionList.Item>\n </ActionList>\n </FeatureFlags>\n )\n}" }, { "id": "components-actionlist-features--disabled-selected-multiselect", "code": "() => (\n <ActionList selectionVariant=\"multiple\" role=\"menu\" aria-label=\"Project\">\n <ActionList.Item role=\"menuitemcheckbox\" selected aria-checked disabled>\n Selected disabled item\n </ActionList.Item>\n <ActionList.Item\n role=\"menuitemcheckbox\"\n selected={false}\n aria-checked={false}\n >\n Item 2\n </ActionList.Item>\n </ActionList>\n)" }, { "id": "components-actionlist-features--disabled-multiselect", "code": "() => (\n <ActionList selectionVariant=\"multiple\" role=\"menu\" aria-label=\"Project\">\n <ActionList.Item\n role=\"menuitemcheckbox\"\n selected={false}\n aria-checked={false}\n disabled\n >\n Disabled item\n </ActionList.Item>\n <ActionList.Item\n role=\"menuitemcheckbox\"\n selected={false}\n aria-checked={false}\n >\n Item 2\n </ActionList.Item>\n </ActionList>\n)" }, { "id": "components-actionlist-features--inactive-multiselect", "code": "() => {\n const [selectedIndices, setSelectedIndices] = React.useState<number[]>([0])\n const handleSelect = (index: number) => {\n if (selectedIndices.includes(index)) {\n setSelectedIndices(selectedIndices.filter((i) => i !== index))\n } else {\n setSelectedIndices([...selectedIndices, index])\n }\n }\n return (\n <ActionList selectionVariant=\"multiple\" role=\"menu\" aria-label=\"Project\">\n {/* menuitem because state is inactive */}\n <ActionList.Item\n role=\"menuitem\"\n selected={false}\n inactiveText=\"Unavailable due to an outage\"\n >\n Inactive item\n </ActionList.Item>\n <ActionList.Item\n role=\"menuitemcheckbox\"\n selected={selectedIndices.includes(1)}\n aria-checked={selectedIndices.includes(1)}\n onSelect={() => handleSelect(1)}\n >\n Item 2\n </ActionList.Item>\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--disabled-item", "code": "() => {\n const [selectedIndex, setSelectedIndex] = React.useState(0)\n return (\n <ActionList\n selectionVariant=\"single\"\n showDividers\n role=\"menu\"\n aria-label=\"Project\"\n >\n {projects.map((project, index) => (\n <ActionList.Item\n key={index}\n role=\"menuitemradio\"\n selected={index === selectedIndex}\n aria-checked={index === selectedIndex}\n onSelect={() => setSelectedIndex(index)}\n disabled={index === 1}\n >\n <ActionList.LeadingVisual>\n <TableIcon />\n </ActionList.LeadingVisual>\n {project.name}\n <ActionList.Description variant=\"block\">\n {project.scope}\n </ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--inactive-item", "code": "() => {\n return (\n <ActionList aria-label=\"Project\">\n {projects.map((project, index) => (\n <ActionList.Item\n key={index}\n inactiveText={\n index === 1 ? 'Unavailable due to an outage' : undefined\n }\n >\n <ActionList.LeadingVisual>\n <TableIcon />\n </ActionList.LeadingVisual>\n {project.name}\n <ActionList.Description variant=\"block\">\n {project.scope}\n </ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--loading-item", "code": "() => {\n return (\n <ActionList aria-label=\"Project\">\n {projects.map((project, index) => (\n <ActionList.Item key={index} loading={index === 1}>\n {project.name}\n <ActionList.Description variant=\"block\">\n {project.scope}\n </ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--links", "code": "() => (\n <ActionList>\n <ActionList.Heading\n as=\"h1\"\n sx={{\n fontSize: 1,\n }}\n >\n Details\n </ActionList.Heading>\n <ActionList.LinkItem href=\"https://github.com/primer/react#readme\">\n <ActionList.LeadingVisual>\n <BookIcon />\n </ActionList.LeadingVisual>\n Readme\n </ActionList.LinkItem>\n <ActionList.LinkItem href=\"https://github.com/primer/react/blob/main/LICENSE\">\n <ActionList.LeadingVisual>\n <LawIcon />\n </ActionList.LeadingVisual>\n MIT License\n </ActionList.LinkItem>\n <ActionList.LinkItem href=\"https://github.com/primer/react/stargazers\">\n <ActionList.LeadingVisual>\n <StarIcon />\n </ActionList.LeadingVisual>\n <strong>1.5k</strong> stars\n </ActionList.LinkItem>\n <ActionList.LinkItem href=\"https://github.com/primer/react/watchers\">\n <ActionList.LeadingVisual>\n <EyeIcon />\n </ActionList.LeadingVisual>\n <strong>21</strong> watching\n </ActionList.LinkItem>\n <ActionList.LinkItem href=\"https://github.com/primer/react/network/members\">\n <ActionList.LeadingVisual>\n <RepoForkedIcon />\n </ActionList.LeadingVisual>\n <strong>225</strong> forks\n </ActionList.LinkItem>\n </ActionList>\n)" }, { "id": "components-actionlist-features--custom-item-children", "code": "() => (\n <ActionList>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <ArrowRightIcon />\n </ActionList.LeadingVisual>\n <Label>Choose this one</Label>\n <ActionList.TrailingVisual>\n <ArrowLeftIcon />\n </ActionList.TrailingVisual>\n </ActionList.Item>\n </ActionList>\n)" }, { "id": "components-actionlist-features--text-wrap-and-truncation", "code": "() => (\n <Box maxWidth=\"300px\">\n <ActionList showDividers>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <ArrowRightIcon />\n </ActionList.LeadingVisual>\n Block Description. Long text should wrap\n <ActionList.Description variant=\"block\">\n This description is long, but it is block so it wraps\n </ActionList.Description>\n <ActionList.TrailingVisual>\n <ArrowLeftIcon />\n </ActionList.TrailingVisual>\n </ActionList.Item>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <ArrowRightIcon />\n </ActionList.LeadingVisual>\n Inline Description\n <ActionList.Description truncate>\n This description gets truncated because it is inline with truncation\n </ActionList.Description>\n <ActionList.TrailingVisual>\n <ArrowLeftIcon />\n </ActionList.TrailingVisual>\n </ActionList.Item>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <ArrowRightIcon />\n </ActionList.LeadingVisual>\n Description with truncation and complex children\n <ActionList.Description truncate>\n With <strong>bold</strong> and <em>italic</em> text, and it should\n truncate if it is too long\n </ActionList.Description>\n <ActionList.TrailingVisual>\n <ArrowLeftIcon />\n </ActionList.TrailingVisual>\n </ActionList.Item>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <ArrowRightIcon />\n </ActionList.LeadingVisual>\n Inline Description\n <ActionList.Description>\n This description wraps because it is inline without truncation\n </ActionList.Description>\n <ActionList.TrailingVisual>\n <ArrowLeftIcon />\n </ActionList.TrailingVisual>\n </ActionList.Item>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <ArrowRightIcon />\n </ActionList.LeadingVisual>\n Really long text without a description should wrap so it wraps\n <ActionList.TrailingVisual>\n <ArrowLeftIcon />\n </ActionList.TrailingVisual>\n </ActionList.Item>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <ArrowRightIcon />\n </ActionList.LeadingVisual>\n SomethingSomething/SomethingElse.Some.Thing.Lalala.la\n <ActionList.TrailingVisual>\n <ArrowLeftIcon />\n </ActionList.TrailingVisual>\n </ActionList.Item>\n </ActionList>\n </Box>\n)" }, { "id": "components-actionlist-features--conditional-children", "code": "() => {\n type reviewerType = {\n name: string\n id?: string\n type?: string\n login?: string\n slug?: string\n members?: number\n }\n const potentialReviewers: reviewerType[] = [...teams, ...users]\n return (\n <ActionList showDividers>\n {potentialReviewers.map((reviewer, index) => (\n <ActionList.Item key={index}>\n <ActionList.LeadingVisual>\n {reviewer.type === 'team' ? (\n <Avatar\n src={`https://avatars.githubusercontent.com/t/${reviewer.id}`}\n />\n ) : (\n <Avatar\n src={`https://avatars.githubusercontent.com/${reviewer.login}`}\n />\n )}\n </ActionList.LeadingVisual>\n {reviewer.login || reviewer.slug}\n {reviewer.type === 'team' ? (\n <ActionList.Description variant=\"block\">\n {reviewer.name}\n </ActionList.Description>\n ) : (\n <ActionList.Description>{reviewer.name}</ActionList.Description>\n )}\n {reviewer.type === 'team' && (\n <ActionList.TrailingVisual>\n <PeopleIcon />\n {reviewer.members}\n </ActionList.TrailingVisual>\n )}\n </ActionList.Item>\n ))}\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--child-with-side-effects", "code": "() => {\n const user = users[0]\n const [selected, setSelected] = React.useState(true)\n const SideEffectDescription = () => {\n // eslint-disable-next-line react-compiler/react-compiler\n const [seconds, setSeconds] = React.useState(0)\n\n // eslint-disable-next-line react-compiler/react-compiler\n React.useEffect(() => {\n const fn = () => setSeconds((s) => s + 1)\n const interval = window.setInterval(fn, 1000)\n return () => window.clearInterval(interval)\n }, [])\n return <>{seconds} seconds passed</>\n }\n return (\n <ActionList\n selectionVariant=\"multiple\"\n role=\"listbox\"\n aria-label=\"Assignees\"\n >\n <ActionList.Item\n selected={selected}\n onSelect={() => setSelected(!selected)}\n role=\"option\"\n >\n <ActionList.LeadingVisual>\n <Avatar src={`https://avatars.githubusercontent.com/${user.login}`} />\n </ActionList.LeadingVisual>\n {user.login}\n <ActionList.Description>\n <SideEffectDescription />\n </ActionList.Description>\n </ActionList.Item>\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--inside-overlay", "code": "() => {\n const [open, setOpen] = React.useState(false)\n const toggle = () => setOpen(!open)\n return (\n <AnchoredOverlay\n open={open}\n onOpen={toggle}\n onClose={toggle}\n renderAnchor={(props) => (\n <button type=\"button\" {...props}>\n toggle overlay\n </button>\n )}\n >\n <ActionList role=\"menu\">\n <ActionList.Item role=\"menuitem\">\n Use your arrow keys\n <ActionList.TrailingVisual>↓</ActionList.TrailingVisual>\n </ActionList.Item>\n <ActionList.Item role=\"menuitem\">\n keep going\n <ActionList.TrailingVisual>↓</ActionList.TrailingVisual>\n </ActionList.Item>\n <ActionList.Item role=\"menuitem\">\n more more\n <ActionList.TrailingVisual>↓</ActionList.TrailingVisual>\n </ActionList.Item>\n <ActionList.Divider />\n <ActionList.Item variant=\"danger\" role=\"menuitem\">\n now go up!\n <ActionList.TrailingVisual>↑</ActionList.TrailingVisual>\n </ActionList.Item>\n </ActionList>\n </AnchoredOverlay>\n )\n}" }, { "id": "components-actionlist-features--group-with-subtle-title", "code": "() => {\n const [assignees, setAssignees] = React.useState(users.slice(0, 1))\n const toggleAssignee = (assignee: (typeof users)[number]) => {\n const assigneeIndex = assignees.findIndex((a) => a.login === assignee.login)\n if (assigneeIndex === -1) setAssignees([...assignees, assignee])\n else setAssignees(assignees.filter((_, index) => index !== assigneeIndex))\n }\n return (\n <ActionList\n selectionVariant=\"multiple\"\n role=\"menu\"\n showDividers\n aria-label=\"Reviewers\"\n >\n <ActionList.Group>\n <ActionList.GroupHeading>Everyone</ActionList.GroupHeading>\n {users.slice(2).map((user) => (\n <ActionList.Item\n role=\"menuitemcheckbox\"\n key={user.login}\n selected={Boolean(\n assignees.find((assignee) => assignee.login === user.login),\n )}\n aria-checked={Boolean(\n assignees.find((assignee) => assignee.login === user.login),\n )}\n onSelect={() => toggleAssignee(user)}\n >\n <ActionList.LeadingVisual>\n <Avatar src={`https://github.com/${user.login}.png`} />\n </ActionList.LeadingVisual>\n {user.login}\n <ActionList.Description>{user.name}</ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList.Group>\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--group-with-filled-title", "code": "() => {\n const [assignees, setAssignees] = React.useState(users.slice(0, 1))\n const toggleAssignee = (assignee: (typeof users)[number]) => {\n const assigneeIndex = assignees.findIndex((a) => a.login === assignee.login)\n if (assigneeIndex === -1) setAssignees([...assignees, assignee])\n else setAssignees(assignees.filter((_, index) => index !== assigneeIndex))\n }\n return (\n <ActionList\n selectionVariant=\"multiple\"\n role=\"menu\"\n showDividers\n aria-label=\"Reviewers\"\n >\n <ActionList.Group>\n <ActionList.GroupHeading variant=\"filled\">\n Everyone\n </ActionList.GroupHeading>\n {users.slice(2).map((user) => (\n <ActionList.Item\n role=\"menuitemcheckbox\"\n key={user.login}\n selected={Boolean(\n assignees.find((assignee) => assignee.login === user.login),\n )}\n aria-checked={Boolean(\n assignees.find((assignee) => assignee.login === user.login),\n )}\n onSelect={() => toggleAssignee(user)}\n >\n <ActionList.LeadingVisual>\n <Avatar src={`https://github.com/${user.login}.png`} />\n </ActionList.LeadingVisual>\n {user.login}\n <ActionList.Description>{user.name}</ActionList.Description>\n </ActionList.Item>\n ))}\n </ActionList.Group>\n </ActionList>\n )\n}" }, { "id": "components-actionlist-features--with-custom-trailing-visuals", "code": "() => (\n <ActionList>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <IssueOpenedIcon />\n </ActionList.LeadingVisual>\n Issues\n <ActionList.TrailingVisual>\n <CounterLabel>20</CounterLabel>\n </ActionList.TrailingVisual>\n </ActionList.Item>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <GitPullRequestIcon />\n </ActionList.LeadingVisual>\n PRs\n <ActionList.TrailingVisual>\n <CounterLabel>12</CounterLabel>\n </ActionList.TrailingVisual>\n </ActionList.Item>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <ProjectIcon />\n </ActionList.LeadingVisual>\n Projects\n <ActionList.TrailingVisual>\n <CounterLabel>2</CounterLabel>\n </ActionList.TrailingVisual>\n </ActionList.Item>\n </ActionList>\n)" }, { "id": "components-actionlist-features--with-trailing-action", "code": "() => {\n const [loadingState, setLoadingState] = React.useState(false)\n\n // Auto-toggle every 2.5 seconds to continuously show transitions\n React.useEffect(() => {\n const interval = setInterval(() => {\n setLoadingState((prev) => !prev)\n }, 2500)\n return () => clearInterval(interval)\n }, [])\n return (\n <FeatureFlags\n flags={{\n primer_react_action_list_item_as_button: true,\n }}\n >\n <ActionList>\n <ActionList.Item>\n <ActionList.LeadingVisual>\n <FileDirectoryIcon />\n </ActionList.LeadingVisual>\n Item 1 (with default TrailingAction)\n <ActionList.TrailingAction\n label=\"Expand sidebar\"\n icon={ArrowLeftIcon}\n />\n </ActionList.Item>\n <ActionList.Item>\n Item 2 (with link TrailingAction)\n <ActionList.TrailingAction\n as=\"a\"\n href=\"#\"\n label=\"Some action 1\"\n icon={ArrowRightIcon}\n />\n </ActionList.Item>\n <ActionList.Item>\n Item 3\n <ActionList.Description>\n This is an inline description.\n </ActionList.Description>\n <ActionList.TrailingAction label=\"Some action 2\" icon={BookIcon} />\n </ActionList.Item>\n <ActionList.Item>\n Item 4\n <ActionList.Description variant=\"block\">\n This is a block description.\n </ActionList.Description>\n <ActionList.TrailingAction label=\"Some action 3\" icon={BookIcon} />\n </ActionList.Item>\n <ActionList.Item>\n Item 5\n <ActionList.Description variant=\"block\">\n This is a block description.\n </ActionList.Description>\n <ActionList.TrailingAction label=\"Some action 4\" />\n </ActionList.Item>\n <ActionList.Item>\n Item 6\n <ActionList.TrailingAction href=\"#\" as=\"a\" label=\"Some action 5\" />\n </ActionList.Item>\n <ActionList.Item>\n Icon button loading state\n <ActionList.Description>\n Shows how IconButton maintains width and centers spinner when\n loading\n </ActionList.Description>\n <ActionList.TrailingAction\n label=\"Process item\"\n icon={ArrowRightIcon}\n loading\n />\n </ActionList.Item>\n <ActionList.Item>\n Icon button with transitions\n <ActionList.Description>\n Automatically toggles loading state every 2.5 seconds to show\n transitions\n </ActionList.Description>\n <ActionList.TrailingAction\n label=\"Toggle loading\"\n icon={ArrowRightIcon}\n loading={loadingState}\n />\n </ActionList.Item>\n <ActionList.Item>\n Text button loading state\n <ActionList.Description>\n Shows how text button aligns spinner to the right and preserves\n width\n </ActionList.Description>\n <ActionList.TrailingAction label=\"Save changes\" loading />\n </ActionList.Item>\n <ActionList.Item>\n Text button with transitions\n <ActionList.Description>\n Automatically toggles loading state every 2.5 seconds to show\n transitions\n </ActionList.Description>\n <ActionList.TrailingAction\n label=\"Apply settings\"\n loading={loadingState}\n />\n </ActionList.Item>\n <ActionList.LinkItem href=\"#\">\n LinkItem 1\n <ActionList.Description>\n with TrailingAction this is a long description and should not cause\n horizontal scroll on smaller screen sizes\n </ActionList.Description>\n <ActionList.TrailingAction label=\"Another action\" />\n </ActionList.LinkItem>\n <ActionList.LinkItem href=\"#\">\n LinkItem 2\n <ActionList.Description>\n with TrailingVisual this is a long description and should not cause\n horizontal scroll on smaller screen sizes\n </ActionList.Description>\n <ActionList.TrailingVisual>\n <TableIcon />\n </ActionList.TrailingVisual>\n </ActionList.LinkItem>\n <ActionList.Item inactiveText=\"Unavailable due to an outage\">\n Inactive Item\n <ActionList.Description>With TrailingAction</ActionList.Description>\n <ActionList.TrailingAction\n as=\"a\"\n href=\"#\"\n label=\"Some action 8\"\n icon={ArrowRightIcon}\n />\n </ActionList.Item>\n </ActionList>\n </FeatureFlags>\n )\n}" }, { "id": "components-actionlist-features--full-variant", "code": "() => (\n <ActionList variant=\"full\">\n <ActionList.Item>Copy link</ActionList.Item>\n <ActionList.Item>Quote reply</ActionList.Item>\n <ActionList.Item>Edit comment</ActionList.Item>\n <ActionList.Divider />\n <ActionList.Item variant=\"danger\">Delete file</ActionList.Item>\n </ActionList>\n)" }, { "id": "components-actionlist-features--large-item", "code": "() => (\n <ActionList>\n <ActionList.Item size=\"large\">Large item</ActionList.Item>\n <ActionList.Item size=\"large\">\n Large item\n <ActionList.Description>With inline description</ActionList.Description>\n </ActionList.Item>\n <ActionList.Item size=\"large\">\n Large item\n <ActionList.Description variant=\"block\">\n With block description\n </ActionList.Description>\n </ActionList.Item>\n </ActionList>\n)" } ], "importPath": "@primer/react", "props": [ { "name": "children", "type": "ActionList.Item[] | ActionList.LinkItem[] | ActionList.Group[]", "defaultValue": "", "required": true, "description": "" }, { "name": "variant", "type": "'inset' | 'horizontal-inset' | 'full'", "defaultValue": "'inset'", "description": "`inset` children are offset (vertically and/or horizontally) from list edges. `full` children are flush (vertically and horizontally) with list edges" }, { "name": "selectionVariant", "type": "'single' | 'multiple'", "defaultValue": "", "description": "Whether multiple items or a single item can be selected." }, { "name": "showDividers", "type": "boolean", "description": "Display a divider above each `Item` in this `List` when it does not follow a `Header` or `Divider`.", "defaultValue": "" }, { "name": "role", "type": "AriaRole", "defaultValue": "", "description": "ARIA role describing the function of the list. `listbox` and `menu` are a common values." }, { "name": "sx", "type": "SystemStyleObject", "deprecated": true } ], "subcomponents": [ { "name": "ActionList.Item", "props": [ { "name": "children", "type": "React.ReactNode | ActionList.LeadingVisual | ActionList.Description | ActionList.TrailingVisual", "defaultValue": "", "required": true, "description": "Primary content for an Item" }, { "name": "variant", "type": "'default' | 'danger'", "defaultValue": "'default'", "description": "`danger` indicates that the item is destructive." }, { "name": "size", "type": "'medium' | 'large'", "defaultValue": "'medium'", "description": "The block size of the ActionList items." }, { "name": "onSelect", "type": "(event: React.MouseEvent<HTMLLIElement> | React.KeyboardEvent<HTMLLIElement>) => void", "defaultValue": "", "description": "Callback that is called when the item is selected using either the mouse or keyboard. `event.preventDefault()` will prevent a menu from closing when within an `<ActionMenu />`. This is not called for disabled or inactive items." }, { "name": "selected", "type": "boolean", "defaultValue": "false", "description": "Indicate whether the item is selected. Only applies to items that can be selected." }, { "name": "active", "type": "boolean", "defaultValue": "false", "description": "Indicate whether the item is active. There should never be more than one active item." }, { "name": "disabled", "type": "boolean", "defaultValue": "false", "description": "Items that are disabled can not be clicked, selected, or navigated to." }, { "name": "inactiveText", "type": "string", "defaultValue": "", "description": "Text describing why the item is inactive. This may be used when an item's usual functionality is unavailable due to a system error such as a database outage.\nIf there is a leading visual, the alert icon will replace the leading visual.\nIf there is a trailing visual, it will replace the trailing visual.\nIf there is no visual passed, it will be shown in the trailing visual slot to preserve left alignment of item content.\nText will appear in a tooltip triggered by the alert icon in ActionList items, but text will appear below the description or title on ActionMenu items." }, { "name": "loading", "type": "boolean", "description": "Whether the item is loading." }, { "name": "role", "type": "AriaRole", "defaultValue": "", "description": "ARIA role describing the function of the item. `option` is a common value." }, { "name": "id", "type": "string", "required": false, "description": "id to attach to the root element of the Item", "defaultValue": "" }, { "name": "sx", "type": "SystemStyleObject", "deprecated": true } ] }, { "name": "ActionList.Heading", "props": [ { "name": "children", "type": "React.ReactNode", "defaultValue": "", "required": true, "description": "Use to give a heading to list" }, { "name": "as", "type": "h1 | h2 | h3 | h4 | h5 | h6", "defaultValue": "h3", "required": false, "description": "The level of the heading" }, { "name": "visuallyHidden", "type": "boolean", "required": false, "description": "", "defaultValue": "" }, { "name": "sx", "type": "SystemStyleObject", "deprecated": true } ] }, { "name": "ActionList.LinkItem", "props": [ { "name": "children", "type": "React.ReactNode | ActionList.LeadingVisual | ActionList.Description | ActionList.TrailingVisual", "defaultValue": "", "required": true, "description": "" }, { "name": "active", "type": "boolean", "defaultValue": "false", "description": "Indicate whether the item is active. There should never be more than one active item." }, { "name": "ref", "type": "React.RefObject<HTMLAnchorElement>" }, { "name": "as", "type": "React.ElementType", "defaultValue": "\"a\"" }, { "name": "inactiveText", "type": "string", "required": false, "description": "Text describing why the item is inactive. This may be used when an item's usual functionality\nis unavailable due to a system error such as a database outage.", "defaultValue": "" }, { "name": "sx", "type": "SystemStyleObject", "deprecated": true } ], "passthrough": { "element": "a", "url": "https://developer.mozilla.org/en-US/docs/Web/HTML/Element/a#Attributes" } }, { "name": "ActionList.LeadingVisual", "props": [ { "name": "children", "type": "React.ReactNode", "defaultValue": "", "required": true, "description": "Icon (or similar) positioned before item text." }, { "name": "sx", "type": "SystemStyleObject", "deprecated": true } ] }, { "name": "ActionList.TrailingVisual", "props": [ { "name": "children", "type": "React.ReactNode", "defaultValue": "", "required": true, "description": "Visual positioned after item text." }, { "name": "sx", "type": "SystemStyleObject", "deprecated": true } ] }, { "name": "ActionList.TrailingAction", "props": [ { "name": "as", "type": "a | button", "defaultValue": "button", "required": false, "description": "HTML element to render as." }, { "name": "label", "type": "string", "defaultValue": "", "required": true, "description": "Accessible name for the control." }, { "name": "icon", "type": "string", "defaultValue": "", "required": true, "description": "Octicon to pass into IconButton. When this is not set, TrailingAction renders as a `Button` instead of an `IconButton`." }, { "name": "href", "type": "string", "description": "href when the TrailingAction is rendered as a link." }, { "name": "loading", "type": "boolean", "defaultValue":