{"id":18613049,"url":"https://github.com/eduzz/ui-layout","last_synced_at":"2026-03-03T15:01:40.356Z","repository":{"id":177675095,"uuid":"654231991","full_name":"eduzz/ui-layout","owner":"eduzz","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-08T13:13:25.000Z","size":690,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":15,"default_branch":"master","last_synced_at":"2025-01-08T14:35:16.474Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/eduzz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":".github/CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-06-15T17:03:32.000Z","updated_at":"2025-01-08T13:12:06.000Z","dependencies_parsed_at":null,"dependency_job_id":"6dfbd901-37ef-4b2f-abb2-5fd84dbf6679","html_url":"https://github.com/eduzz/ui-layout","commit_stats":{"total_commits":112,"total_committers":7,"mean_commits":16.0,"dds":0.5178571428571428,"last_synced_commit":"4dc98742a9398773c306d703fedb8f58a4bdc79d"},"previous_names":["eduzz/ui-layout"],"tags_count":47,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduzz%2Fui-layout","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduzz%2Fui-layout/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduzz%2Fui-layout/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/eduzz%2Fui-layout/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/eduzz","download_url":"https://codeload.github.com/eduzz/ui-layout/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239406441,"owners_count":19633024,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-07T03:19:41.467Z","updated_at":"2026-03-03T15:01:40.344Z","avatar_url":"https://github.com/eduzz.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Eduzz UI\n\nUI padrão das aplicações, aqui você vai encontrar:\n\n* [Layout](#layout)\n* [App Loader](#app-loader)\n\n# Layout\n\nEstrutura padrão das aplicações.\n\n## Importação\n\n```ts\nimport Layout from '@eduzz/ui-layout';\n\n// ou\nimport Layout from '@eduzz/ui-layout';\nimport Sidebar from '@eduzz/ui-layout/Sidebar';\nimport Topbar from '@eduzz/ui-layout/Topbar';\nimport Content from '@eduzz/ui-layout/Content';\n```\n\n## Estrutura base\n\n```jsx\n\u003cLayout\u003e\n  \u003cLayout.Topbar /\u003e\n  \u003cLayout.Sidebar /\u003e\n  \u003cLayout.Content /\u003e\n\u003c/Layout\u003e\n```\n\n## Desestruturando\n\nPara simplificar a escrita do código, você pode desestruturar os componentes.\n\n```jsx\nimport Layout from '@eduzz/ui-layout';\n\nconst { Sidebar, Topbar, Content } = Layout;\nconst { Item, Group, GroupWithGroupSwitcher } = Sidebar;\n\nfunction CustomLayout() {\n  return (\n    \u003cLayout\u003e\n      \u003cTopbar {...topbarProps}\u003e\n        {...}\n      \u003c/Topbar\u003e\n\n      \u003cSidebar {...sidebarProps}\u003e\n        {...}\n      \u003c/Sidebar\u003e\n\n      \u003cContent\u003e\n        {...}\n      \u003c/Content\u003e\n    \u003c/Layout\u003e\n  );\n}\n\nexport default CustomLayout;\n```\n\n## Exemplo\n\n```jsx\nimport { NavLink, useLocation } from 'react-router-dom';\n\nconst { Sidebar, Topbar, Content } = Layout;\nconst { Item, Group, GroupWithGroupSwitcher } = Sidebar;\n\nfunction MyComponent() {\n  const location = useLocation();\n\n  return (\n    \u003cLayout\u003e\n      \u003cTopbar\n        currentApplication='orbita'\n        user={{\n          name: 'Houston User',\n          belt: 'Black Belt',\n          avatar: 'https://picsum.photos/200',\n          tag: 'unity'\n        }}\n      \u003e\n        \u003cTopbar.UnitySupportChat token='...token gerado pelo servidor' /\u003e\n\n        \u003cTopbar.Action icon={\u003cNotificationOutline size={25} /\u003e} label='Notificações' /\u003e\n        \u003cTopbar.Action icon={\u003cInfoChatOutline size={25} /\u003e} /\u003e\n\n        \u003cTopbar.UserMenu\u003e\n          \u003cTopbar.UserMenuItem\u003eMeus Dados\u003c/Topbar.UserMenuItem\u003e\n          \u003cTopbar.UserMenuItem\u003eMinhas Compras\u003c/Topbar.UserMenuItem\u003e\n\n          \u003cTopbar.UserMenuGroup label='Contas:'\u003e\n            \u003cTopbar.UserMenuItem href='http://google.com' target='_blank'\u003e\n              John Doe\n            \u003c/Topbar.UserMenuItem\u003e\n            \u003cTopbar.UserMenuItem disabled\u003eJohn Doe 2\u003c/Topbar.UserMenuItem\u003e\n          \u003c/Topbar.UserMenuGroup\u003e\n\n          \u003cTopbar.UserMenuDivider /\u003e\n\n          \u003cTopbar.UserMenuItem\u003eSair\u003c/Topbar.UserMenuItem\u003e\n        \u003c/Topbar.UserMenu\u003e\n      \u003c/Topbar\u003e\n\n      \u003cSidebar currentLocation={location.pathname}\u003e\n        \u003cItem href='/agendamento'\u003eResumo\u003c/Item\u003e\n\n        \u003cGroupWithGroupSwitcher\n            label='Integrações'\n            options={[\n              {\n                id: 'whatsapp',\n                label: 'Whatsapp',\n                icon: \u003cWhatsAppOutlined /\u003e,\n                items: [\n                  \u003cItem key={'option-1-item-1'} id='sidebar-option-1-item-1'\u003e\n                    Templates\n                  \u003c/Item\u003e,\n                  \u003cItem key={'option-1-item-2'} id='sidebar-option-1-item-2'\u003e\n                    Configurações\n                  \u003c/Item\u003e\n                ]\n              },\n              {\n                id: 'email',\n                label: 'Email',\n                icon: \u003cMailOutlined /\u003e,\n                items: [\n                  \u003cItem key={'option-2-item-1'} id='sidebar-option-2-item-1'\u003e\n                    Layout\n                  \u003c/Item\u003e,\n                  \u003cItem key={'option-2-item-2'} id='sidebar-option-2-item-2'\u003e\n                    Templates\n                  \u003c/Item\u003e,\n                  \u003cItem key={'option-2-item-3'} id='sidebar-option-2-item-3'\u003e\n                    Configurações\n                  \u003c/Item\u003e\n                ]\n              }\n            ]}\n          /\u003e\n\n        \u003cGroup label='Agendamento'\u003e\n          \u003cItem as={NavLink} to='/agendamento'\u003e\n            Evento\n          \u003c/Item\u003e\n          \u003cItem as={NavLink} to='/agendamento'\u003e\n            MasterMind\n          \u003c/Item\u003e\n          \u003cItem as={NavLink} to='/agendamento'\u003e\n            Lançamento\n          \u003c/Item\u003e\n        \u003c/Group\u003e\n\n        \u003cItem disabled\u003eMarketplace\u003c/Item\u003e\n      \u003c/Sidebar\u003e\n\n      \u003cContent\u003e{/*Your content here*/}\u003c/Content\u003e\n    \u003c/Layout\u003e\n  );\n}\n```\n\n## Props\n\n### Layout props\n\n| prop                    | tipo                                   | obrigatório | padrão    | descrição                                                                        |\n|-------------------------|----------------------------------------|-------------|-----------|----------------------------------------------------------------------------------|\n| mode                    | `'light' \\| 'dark'`                    | `false`     | `'light'` | Modo (Dark ou Light mode)                                                        |\n| persistMode             | `boolean`                              | `false`     | `false`   | Faz o modo (Dark ou Light mode) persistirem no localStorage como `eduzz-ui-mode` |\n| acceptModeBySearchParam | `boolean`                              | `false`     | `false`   | Aceita receber `?eduzzMode=dark` na URL por exemplo, para definir o `mode`       |\n| onModeChange            | `(newMode: 'light' \\| 'dark') =\u003e void` | `false`     | -         | Função a ser executada toda vez que houver uma mudança de modo.                  |\n\n### Topbar props\n\n| prop               | tipo     | obrigatório | padrão | descrição                                                   |\n|--------------------|----------|-------------|--------|-------------------------------------------------------------|\n| logo               | `url`    | `false`     | -      | Url para o logo padrao.                                     |\n| logoMobile         | `url`    | `false`     | -      | Url para o logo na versão mobile.                           |\n| currentApplication | `string` | `false`     | -      | Aplicação que está sendo usada, para marcar no menu de apps |\n| user               | `object` | `false`     | -      | Se existe um usuário logado, sem ele não terá o menu User   |\n\n### Topbar.Action props\n\n| prop     | tipo        | obrigatório | padrão  | descrição                                            |\n|----------|-------------|-------------|---------|------------------------------------------------------|\n| icon     | `ReactNode` | `true`      | -       | Icone, tamanho ideal 25                              |\n| label    | `string`    | `false`     | -       |                                                      |\n| isActive | `boolean`   | `false`     | `false` | Se o icone deve manter o estado de pressionado/ativo |\n| onClick  | `function`  | `false`     | -       |                                                      |\n\n### Topbar.UserMenuItem props\n\n| prop     | tipo        | obrigatório | padrão | descrição               |\n|----------|-------------|-------------|--------|-------------------------|\n| icon     | `ReactNode` | `true`      | -      | Icone, tamanho ideal 25 |\n| children | `string`    | `false`     | -      | Deve ser uma string     |\n| disabled | `boolean`   | `false`     | -      |                         |\n| onClick  | `function`  | `false`     | -      |                         |\n\n### Topbar.UserMenuGroup props\n\n| prop     | tipo        | obrigatório | padrão | descrição |\n|----------|-------------|-------------|--------|-----------|\n| label    | `string`    | `true`      | -      |           |\n| children | `ReactNode` | `true`      | -      |           |\n\n### Topbar.UnitySupportChat props\n\n| prop  | tipo     | obrigatório | padrão | descrição                                         |\n|-------|----------|-------------|--------|---------------------------------------------------|\n| token | `string` | `false`     | -      | Token gerado pelo servidor para uso do LiveHelper |\n\n### Topbar.HyperflowSupportChat props\n\n| prop            | tipo                    | obrigatório | padrão | descrição                                            |\n|-----------------|-------------------------|-------------|--------|------------------------------------------------------|\n| accountsJwt     | `() =\u003e Promise\u003cstring\u003e` | `true`      | -      | JWT gerado a partir do accounts                      |\n| hyperflowConfig | `HyperflowConfig`       | `true`      | -      | Tokens dos canais do Hyperflow                       |\n| currentUser     | `CurrentUser`           | `true`      | -      | Dados do usuário que serão enviados para o Hyperflow |\n| hyperflowJwt    | `string`                | `true`      | -      | JWT gerado a partir do secret da Hyperflow           |\n\n```ts\nexport type CurrentUser = {\n  tag: string;\n  belt: string;\n  isClubeBlack: boolean;\n  id: number;\n  name: string;\n  email: string;\n  isAccessPolicy: boolean;\n} \u0026 (\n  | {\n      isAccessPolicy: true;\n      originalUserId: number;\n      originalUserName: string;\n      originalUserEmail: string;\n    }\n  | { isAccessPolicy: false }\n);\n\ntype HyperflowConfig = {\n  chatUnityID: string;\n  chatBlackID: string;\n  chatEliteID: string;\n  flowId: string;\n  origin: 'blinket' | 'checkout' | 'myeduzz' | 'nutror' | 'orbitpages' | 'safevideo';\n};\n```\n\nDocumentação de apoio: [Hyperflow](https://www.notion.so/eduzz/Doc-Implementa-o-do-Chat-Hyperflow-982b8fc935ee4f59974401df8668bda7)\n\n### Topbar.ModeSwitcher props\n\n| prop               | tipo     | obrigatório | padrão | descrição                                                   |\n|--------------------|----------|-------------|--------|-------------------------------------------------------------|\n| tooltip| `string`| `false`| `'Tema'`|  Texto para o tooltip do botão. mode |\n| badgeDot| `boolean`| `false`| `false`| Se um badgeDot deve ser adicionado ao botão .|\n\n### Sidebar props\n\n| prop            | tipo     | obrigatório | padrão | descrição                                |\n|-----------------|----------|-------------|--------|------------------------------------------|\n| currentLocation | `string` | `false`     | -      | Caminho de localização atual (pathname). |\n\n### Sidebar.Item props\n\n| prop     | tipo                | obrigatório | padrão  | descrição                                                                   |\n|----------|---------------------|-------------|---------|-----------------------------------------------------------------------------|\n| as       | `React.ElementType` | `false`     | -       | Componente que envolve o item.                                              |\n| `any`    | `any`               | `false`     | -       | Qualquer prop que o `as` receba                                             |\n| isActive | `boolean`           | `false`     | `false` | Irá usar o `currentLocation` fornecido para tentar ver se está ativo ou não |\n| tabIndex | `number`            | `false`     | -       |                                                                             |\n| disabled | `boolean`           | `false`     | -       |                                                                             |\n| onClick  | `function`          | `false`     | -       |                                                                             |\n\n### Sidebar.Group props\n\n| prop     | tipo              | obrigatório | padrão | descrição |\n|----------|-------------------|-------------|--------|-----------|\n| label    | `React.ReactNode` | `false`     | -      | -         |\n| tabIndex | `number`          | `false`     | -      |           |\n\n### Sidebar.GroupWithGroupSwitcher props\n\n| prop      | tipo                                        | obrigatório | padrão | descrição                                                                                             |\n|-----------|---------------------------------------------|-------------|--------|-------------------------------------------------------------------------------------------------------|\n| id        | `string`                                    | `false`     | -      | Identificador único para o elemento raiz (HTML `\u003cli\u003e`).                                             |\n| label     | `ReactNode`                                 | `false`     | -      | Label ou título do grupo, exibido acima das opções do seletor.                                        |\n| options   | `SidebarGroupWithGroupSwitcherOption[]`     | `true`      | -      | Array de opções que serão renderizadas no grupo. Cada opção define um conjunto de itens e atributos.   |\n| className | `string`                                    | `false`     | -      | Classe CSS adicional para customização do componente.                                               |\n| defaultOptionId | `string `                             | `false`     | -      | Valor padrão selecionado, caso não seja informado, será utilizada a primeira opção como padrão |\n| onChangeOption | `(option: SidebarGroupWithGroupSwitcherOption) =\u003e void` | `false` | -      | Função que será chamada como callback ao alterar a opção |\n\n### SidebarGroupWithGroupSwitcherOption\n\n| prop  | tipo           | obrigatório | padrão | descrição                                                                              |\n|-------|----------------|-------------|--------|----------------------------------------------------------------------------------------|\n| id    | `string`       | `true`      | -      | Identificador único da opção.                                                          |\n| label | `string`       | `true`      | -      | Texto que representa o rótulo da opção. Pode ser um nome ou título descritivo.         |\n| icon  | `ReactNode`    | `false`     | -      | Elemento opcional que pode conter um ícone ou qualquer outro elemento visual.          |\n| items | `ReactNode[]`  | `true`      | -      | Conjunto de itens (children) que serão renderizados quando a opção estiver selecionada. |\n\n\n### Content props\n\n| prop           | tipo      | obrigatório | padrão | descrição        |\n|----------------|-----------|-------------|--------|------------------|\n| disablePadding | `boolean` | `false`     | -      | Remove o padding |\n\n# App Loader\n\nLoader de aplicação padrão.\n\n## Importação\n\n```js\nimport AppLoader, { useAppLoader } from '@eduzz/ui-layout';\n```\n\n## Exemplo\n\nColoque no momento de `createRoot` e use o lazy para aparecer o loader antes da aplicação. Coloque o minimo de imports nesse arquivo para carregar o mais rapido possível.\n\n```jsx\nimport { lazy } from 'react';\nimport { createRoot } from 'react-dom/client';\nimport AppLoader from '@eduzz/ui-layout'; \n\nconst App = lazy(() =\u003e import('./App'));\n\ncreateRoot(document.getElementById('app') as HTMLElement).render(\n  \u003cAppLoader\u003e\n    \u003cApp /\u003e\n  \u003c/AppLoader\u003e\n);\n\n// App.tsx\nimport { useEffect } from 'react';\nimport { useAppLoader } from '@eduzz/ui-layout';\n\nfunction App() {\n  const appLoader = useAppLoader();\n\n  useEffect(() =\u003e {\n    // Faça o que precisar ser feito e entao chame o `hide`\n    appLoader.hide();\n    // Caso queira aparecer novamente\n    appLoader.show();\n    // Se algo acontecer pode mostrar uma mensagem de erro\n    appLoader.error(new Error(), () =\u003e console.log('Tente novamente'));\n  }, []);\n\n  return \u003cdiv /\u003e\n}\n```\n\n## Props\n\n### AppLoader props\n\n| prop         | tipo             | obrigatório | padrão       |\n|--------------|------------------|-------------|--------------|\n| logo         | `url\\|ReactNode` | `false`     | `Eduzz Logo` |\n| logoDarkMode | `url\\|ReactNode` | `false`     | `Eduzz Logo` |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feduzz%2Fui-layout","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Feduzz%2Fui-layout","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Feduzz%2Fui-layout/lists"}