diff --git a/ui/src/views/indexed-nfa/fragments/aside.fragment.tsx b/ui/src/views/indexed-nfa/fragments/aside.fragment.tsx deleted file mode 100644 index 9802000..0000000 --- a/ui/src/views/indexed-nfa/fragments/aside.fragment.tsx +++ /dev/null @@ -1,320 +0,0 @@ -import { useEffect, useMemo, useRef, useState } from 'react'; -import { Link } from 'react-router-dom'; - -import { App } from '@/app.context'; -import { - Button, - Flex, - Icon, - IconName, - Menu, - NFAIcon, - NFAPreview, - ResolvedAddress, - Text, -} from '@/components'; -import { env } from '@/constants'; -import { FleekERC721 } from '@/integrations/ethereum/contracts'; -import { forwardStyledRef } from '@/theme'; -import { AppLog, getDate, getRepositoryFromURL } from '@/utils'; -import { parseNumberToHexColor } from '@/utils/color'; - -import { IndexedNFA } from '../indexed-nfa.context'; -import { IndexedNFAStyles as S } from '../indexed-nfa.styles'; -import { Tab, TabContainer } from './tabs'; - -const Preview: React.FC = () => { - const { nfa } = IndexedNFA.useContext(); - - const color = useMemo( - () => `#${parseNumberToHexColor(nfa.color ?? '')}`, - [nfa] - ); - - return ( - - ); -}; - -type BadgeProps = { - verified: boolean; -}; - -const Badge: React.FC = ({ verified }: BadgeProps) => { - const text = useMemo( - () => (verified ? 'Verified' : 'Unverified'), - [verified] - ); - - const icon = useMemo(() => (verified ? 'verified' : 'error'), [verified]); - const color = useMemo(() => (verified ? '$green10' : '$red10'), [verified]); - return ( - - - {text} - - ); -}; - -const Header: React.FC = () => { - const { nfa } = IndexedNFA.useContext(); - - return ( - - - {nfa.name} - - - - - - {nfa.owner.id} - - - ); -}; - -type HeaderDataProps = { - label: string; - children: React.ReactNode; -}; - -const HeaderData: React.FC = ({ - label, - children, -}: HeaderDataProps) => ( - - {label} - {children} - -); - -const NFAInfo: React.FC = () => { - const { nfa } = IndexedNFA.useContext(); - return ( - - - {nfa.accessPoints?.length ?? 0} - - - - - {getDate(nfa.createdAt)} - - ); -}; - -type CustomButtonProps = { - icon: IconName; -}; - -const CustomButon = forwardStyledRef( - ({ icon, ...props }, ref) => ( - - ) -); - -type MenuItemProps = { - label: string; - iconName: IconName; - onClick: () => void; -}; - -const MenuItem: React.FC = ({ - label, - iconName, - onClick, -}: MenuItemProps) => { - return ( - - - {label} - - ); -}; - -const ButtonsFragment: React.FC = () => { - const { nfa } = IndexedNFA.useContext(); - - const handleShareOnClick = (): void => { - const location = window.location.href; - navigator.clipboard.writeText(location); - AppLog.successToast('Link copied to clipboard'); - }; - - const handleShareOpenSeaOnClick = (): void => { - window.open( - `https://${ - env.environment === 'development' ? 'testnets' : '' - }.opensea.io/assets/${ - env.environment === 'development' ? 'goerli' : 'ethereum' - }/${FleekERC721.address}/${nfa.tokenId}`, - '_blank' - ); - }; - - const handleShareOnTwitterOnClick = (): void => { - window.open(env.twitter.url, '_blank'); //TODO replace with twitter share - }; - - return ( - - - - - - - - - - - - - - {/* TODO add tooltip to copy link */} - - - ); -}; - -const PropertiesFragment: React.FC = () => { - const { nfa } = IndexedNFA.useContext(); - - const traitsToShow = useMemo(() => { - return [ - [nfa.ENS, 'ENS'], - [getRepositoryFromURL(nfa.gitRepository.id), 'Repository'], - [10, 'Version'], - [nfa.externalURL, 'Domain'], - ]; - }, [nfa]); - - return ( - - {traitsToShow.map(([value, label], index) => ( - - - {value || '-'} - - {label} - - ))} - - ); -}; - -const OverviewFragment: React.FC = () => { - const { nfa } = IndexedNFA.useContext(); - - return ( - - - Token ID - {nfa.tokenId} - - - - Network - Mainnet - - - - Standard - ERC_721 - - - - Description - - - {nfa.description} - - - ); -}; - -const TabFragment: React.FC = () => { - const [tabSelected, setTabSelected] = useState(0); - const handleClick = (index: number): void => { - setTabSelected(index); - }; - return ( - <> - - {['Overview', 'Properties'].map((label, index) => ( - - ))} - - {tabSelected === 0 ? : } - - ); -}; - -export const IndexedNFAAsideFragment: React.FC = () => { - const ref = useRef(null); - const [top, setTop] = useState(); - const { nfa } = IndexedNFA.useContext(); - - const { backgroundColor } = App.useContext(); - const background = `radial-gradient(closest-corner circle at 90% 45%, #${backgroundColor}8c 1% ,#${backgroundColor}57 20%, transparent 40%), radial-gradient(closest-corner circle at 60% 25%, #${backgroundColor} 3%, #${backgroundColor}73 30%, #181818 70%)`; - - useEffect(() => { - setTop(ref.current?.getBoundingClientRect().top); - }, [ref]); - - return ( - - -
- - - - - - ); -}; diff --git a/ui/src/views/indexed-nfa/fragments/aside/aside-buttons.fragment.tsx b/ui/src/views/indexed-nfa/fragments/aside/aside-buttons.fragment.tsx new file mode 100644 index 0000000..77520b5 --- /dev/null +++ b/ui/src/views/indexed-nfa/fragments/aside/aside-buttons.fragment.tsx @@ -0,0 +1,96 @@ +import { Button, Flex, Icon, IconName, Menu } from '@/components'; +import { env } from '@/constants'; +import { FleekERC721 } from '@/integrations/ethereum/contracts'; +import { forwardStyledRef } from '@/theme'; +import { AppLog } from '@/utils'; + +import { IndexedNFA } from '../../indexed-nfa.context'; +import { IndexedNFAStyles as S } from '../../indexed-nfa.styles'; + +type CustomButtonProps = { + icon: IconName; +}; + +const CustomButon = forwardStyledRef( + ({ icon, ...props }, ref) => ( + + ) +); + +type MenuItemProps = { + label: string; + iconName: IconName; + onClick: () => void; +}; + +const MenuItem: React.FC = ({ + label, + iconName, + onClick, +}: MenuItemProps) => { + return ( + + + {label} + + ); +}; + +export const ButtonsFragment: React.FC = () => { + const { nfa } = IndexedNFA.useContext(); + + const handleShareOnClick = (): void => { + const location = window.location.href; + navigator.clipboard.writeText(location); + AppLog.successToast('Link copied to clipboard'); + }; + + const handleShareOpenSeaOnClick = (): void => { + window.open( + `https://${ + env.environment === 'development' ? 'testnets' : '' + }.opensea.io/assets/${ + env.environment === 'development' ? 'goerli' : 'ethereum' + }/${FleekERC721.address}/${nfa.tokenId}`, + '_blank' + ); + }; + + const handleShareOnTwitterOnClick = (): void => { + window.open(env.twitter.url, '_blank'); //TODO replace with twitter share + }; + + return ( + + + + + {/* TODO remove span and render as fragment */} + + + + + + + + + + {/* TODO add tooltip to copy link */} + + + ); +}; diff --git a/ui/src/views/indexed-nfa/fragments/aside/aside-header.fragment.tsx b/ui/src/views/indexed-nfa/fragments/aside/aside-header.fragment.tsx new file mode 100644 index 0000000..85ece31 --- /dev/null +++ b/ui/src/views/indexed-nfa/fragments/aside/aside-header.fragment.tsx @@ -0,0 +1,44 @@ +import { useMemo } from 'react'; + +import { Flex, Icon, NFAIcon, ResolvedAddress } from '@/components'; + +import { IndexedNFA } from '../../indexed-nfa.context'; +import { IndexedNFAStyles as S } from '../../indexed-nfa.styles'; + +type BadgeProps = { + verified: boolean; +}; + +const Badge: React.FC = ({ verified }: BadgeProps) => { + const text = useMemo( + () => (verified ? 'Verified' : 'Unverified'), + [verified] + ); + + const icon = useMemo(() => (verified ? 'verified' : 'error'), [verified]); + const color = useMemo(() => (verified ? '$green10' : '$red10'), [verified]); + return ( + + + {text} + + ); +}; + +export const Header: React.FC = () => { + const { nfa } = IndexedNFA.useContext(); + + return ( + + + {nfa.name} + + + + + + {nfa.owner.id} + + + ); +}; diff --git a/ui/src/views/indexed-nfa/fragments/aside/aside-nfa-info.fragment.tsx b/ui/src/views/indexed-nfa/fragments/aside/aside-nfa-info.fragment.tsx new file mode 100644 index 0000000..0759cc6 --- /dev/null +++ b/ui/src/views/indexed-nfa/fragments/aside/aside-nfa-info.fragment.tsx @@ -0,0 +1,35 @@ +import { Flex, Text } from '@/components'; +import { getDate } from '@/utils'; + +import { IndexedNFA } from '../../indexed-nfa.context'; +import { IndexedNFAStyles as S } from '../../indexed-nfa.styles'; + +type HeaderDataProps = { + label: string; + children: React.ReactNode; +}; + +const HeaderData: React.FC = ({ + label, + children, +}: HeaderDataProps) => ( + + {label} + {children} + +); + +export const NFAInfo: React.FC = () => { + const { nfa } = IndexedNFA.useContext(); + return ( + + + {nfa.accessPoints?.length ?? 0} + + + + + {getDate(nfa.createdAt)} + + ); +}; diff --git a/ui/src/views/indexed-nfa/fragments/aside/aside-preview.fragment.tsx b/ui/src/views/indexed-nfa/fragments/aside/aside-preview.fragment.tsx new file mode 100644 index 0000000..8facad7 --- /dev/null +++ b/ui/src/views/indexed-nfa/fragments/aside/aside-preview.fragment.tsx @@ -0,0 +1,29 @@ +import { useMemo } from 'react'; + +import { NFAPreview } from '@/components'; +import { parseNumberToHexColor } from '@/utils/color'; + +import { IndexedNFA } from '../../indexed-nfa.context'; + +export const Preview: React.FC = () => { + const { nfa } = IndexedNFA.useContext(); + + const color = useMemo( + () => `#${parseNumberToHexColor(nfa.color ?? '')}`, + [nfa] + ); + + return ( + + ); +}; diff --git a/ui/src/views/indexed-nfa/fragments/aside/aside-tabs.fragment.tsx b/ui/src/views/indexed-nfa/fragments/aside/aside-tabs.fragment.tsx new file mode 100644 index 0000000..9e3de9a --- /dev/null +++ b/ui/src/views/indexed-nfa/fragments/aside/aside-tabs.fragment.tsx @@ -0,0 +1,92 @@ +import { useMemo, useState } from 'react'; + +import { Flex } from '@/components'; +import { getRepositoryFromURL } from '@/utils'; + +import { IndexedNFA } from '../../indexed-nfa.context'; +import { IndexedNFAStyles as S } from '../../indexed-nfa.styles'; +import { Tab, TabContainer } from '../../tabs'; + +const OverviewFragment: React.FC = () => { + const { nfa } = IndexedNFA.useContext(); + + return ( + + + Token ID + {nfa.tokenId} + + + + Network + Mainnet + + + + Standard + ERC_721 + + + + Description + + + {nfa.description} + + + ); +}; + +const PropertiesFragment: React.FC = () => { + const { nfa } = IndexedNFA.useContext(); + + const traitsToShow = useMemo(() => { + return [ + [nfa.ENS, 'ENS'], + [getRepositoryFromURL(nfa.gitRepository.id), 'Repository'], + [nfa.externalURL, 'Domain'], + ]; + }, [nfa]); + + return ( + + {traitsToShow.map(([value, label], index) => ( + + + {value || '-'} + + {label} + + ))} + + ); +}; + +export const TabFragment: React.FC = () => { + const [tabSelected, setTabSelected] = useState(0); + const handleClick = (index: number): void => { + setTabSelected(index); + }; + + return ( + <> + + {['Overview', 'Properties'].map((label, index) => ( + + ))} + + {tabSelected === 0 ? : } + + ); +}; diff --git a/ui/src/views/indexed-nfa/fragments/aside/aside.fragment.tsx b/ui/src/views/indexed-nfa/fragments/aside/aside.fragment.tsx new file mode 100644 index 0000000..ae4f766 --- /dev/null +++ b/ui/src/views/indexed-nfa/fragments/aside/aside.fragment.tsx @@ -0,0 +1,48 @@ +import { useEffect, useRef, useState } from 'react'; +import { Link } from 'react-router-dom'; + +import { App } from '@/app.context'; +import { Button } from '@/components'; +import { parseNumberToHexColor } from '@/utils/color'; + +import { IndexedNFA } from '../../indexed-nfa.context'; +import { IndexedNFAStyles as S } from '../../indexed-nfa.styles'; +import { ButtonsFragment } from './aside-buttons.fragment'; +import { Header } from './aside-header.fragment'; +import { NFAInfo } from './aside-nfa-info.fragment'; +import { Preview } from './aside-preview.fragment'; +import { TabFragment } from './aside-tabs.fragment'; + +export const IndexedNFAAsideFragment: React.FC = () => { + const ref = useRef(null); + const [top, setTop] = useState(); + const { nfa } = IndexedNFA.useContext(); + + const { backgroundColor } = App.useContext(); + const background = `radial-gradient(closest-corner circle at 90% 45%, #${backgroundColor}8c 1% ,#${backgroundColor}57 20%, transparent 40%), radial-gradient(closest-corner circle at 60% 25%, #${backgroundColor} 3%, #${backgroundColor}73 30%, #181818 70%)`; + + useEffect(() => { + setTop(ref.current?.getBoundingClientRect().top); + }, [ref]); + + return ( + + +
+ + + + + + ); +}; diff --git a/ui/src/views/indexed-nfa/fragments/index.ts b/ui/src/views/indexed-nfa/fragments/index.ts index d90e1fb..e31d087 100644 --- a/ui/src/views/indexed-nfa/fragments/index.ts +++ b/ui/src/views/indexed-nfa/fragments/index.ts @@ -1,3 +1,3 @@ -export * from './aside.fragment'; -export * from './main.fragment'; +export * from './aside/aside.fragment'; +export * from './main/main.fragment'; export * from './skeleton.fragment'; diff --git a/ui/src/views/indexed-nfa/fragments/main.fragment.tsx b/ui/src/views/indexed-nfa/fragments/main.fragment.tsx deleted file mode 100644 index 698169e..0000000 --- a/ui/src/views/indexed-nfa/fragments/main.fragment.tsx +++ /dev/null @@ -1,121 +0,0 @@ -import React, { useState } from 'react'; - -import Rectangle1 from '@/assets/Rectangle-199.png'; -import Rectangle2 from '@/assets/Rectangle-200.png'; -import Rectangle3 from '@/assets/Rectangle-201.png'; -import { Combobox, Flex, ResolvedAddress, Text } from '@/components'; -import { getTimeSince } from '@/utils'; - -import { IndexedNFA } from '../indexed-nfa.context'; -import { IndexedNFAStyles as S } from '../indexed-nfa.styles'; - -type SortItem = { - value: string; - label: string; -}; - -const orderResults: SortItem[] = [ - { value: 'newest', label: 'Newest' }, - { value: 'oldest', label: 'Oldest' }, -]; - -const Header: React.FC = () => { - const [selectedValue, setSelectedValue] = useState(orderResults[0]); - - const handleSortChange = (item: SortItem | undefined): void => { - //TODO integrate with context and sort - if (item) { - setSelectedValue(item); - } - }; - return ( - <> - - Hosted NFAs - - {({ Field, Options }) => ( - <> - - {(selected) => selected?.label || 'Select'} - - - {(item) => item.label} - - - )} - - - - ); -}; - -//TODO remove -const thumbnailMocks = [Rectangle1, Rectangle2, Rectangle3]; - -const AccessPointsListFragment: React.FC = () => { - const { - nfa: { accessPoints }, - } = IndexedNFA.useContext(); - - return ( - - {accessPoints && accessPoints?.length > 0 ? ( - accessPoints.map((item, index) => ( - - - - - - {item.id} - - - {item.owner.id} - - - {/* TODO get from bunny CDN */} - 220 views - - - {getTimeSince(item.createdAt)} - - - - - )) - ) : ( -
No access points found
- )} -
- ); -}; - -export const IndexedNFAMainFragment: React.FC = () => { - return ( - -
- - - ); -}; diff --git a/ui/src/views/indexed-nfa/fragments/main/main-ap-list.fragment.tsx b/ui/src/views/indexed-nfa/fragments/main/main-ap-list.fragment.tsx new file mode 100644 index 0000000..00b1453 --- /dev/null +++ b/ui/src/views/indexed-nfa/fragments/main/main-ap-list.fragment.tsx @@ -0,0 +1,61 @@ +import Rectangle1 from '@/assets/Rectangle-199.png'; +import Rectangle2 from '@/assets/Rectangle-200.png'; +import Rectangle3 from '@/assets/Rectangle-201.png'; +import { Flex, ResolvedAddress, Text } from '@/components'; +import { getTimeSince } from '@/utils'; + +import { IndexedNFA } from '../../indexed-nfa.context'; +import { IndexedNFAStyles as S } from '../../indexed-nfa.styles'; + +//TODO remove +const thumbnailMocks = [Rectangle1, Rectangle2, Rectangle3]; + +export const AccessPointsListFragment: React.FC = () => { + const { + nfa: { accessPoints }, + } = IndexedNFA.useContext(); + + return ( + + {accessPoints && accessPoints?.length > 0 ? ( + accessPoints.map((item, index) => ( + + + + + + {item.id} + + + {item.owner.id} + + + {/* TODO get from bunny CDN */} + 220 views + + + {getTimeSince(item.createdAt)} + + + + + )) + ) : ( + +

No hosted NFAs

+
+ )} +
+ ); +}; diff --git a/ui/src/views/indexed-nfa/fragments/main/main-header.fragment.tsx b/ui/src/views/indexed-nfa/fragments/main/main-header.fragment.tsx new file mode 100644 index 0000000..c866d75 --- /dev/null +++ b/ui/src/views/indexed-nfa/fragments/main/main-header.fragment.tsx @@ -0,0 +1,56 @@ +import { useState } from 'react'; + +import { Combobox, Flex } from '@/components'; + +import { IndexedNFAStyles as S } from '../../indexed-nfa.styles'; + +type SortItem = { + value: string; + label: string; +}; + +const orderResults: SortItem[] = [ + { value: 'newest', label: 'Newest' }, + { value: 'oldest', label: 'Oldest' }, +]; + +export const Header: React.FC = () => { + const [selectedValue, setSelectedValue] = useState(orderResults[0]); + + const handleSortChange = (item: SortItem | undefined): void => { + //TODO integrate with context and sort + if (item) { + setSelectedValue(item); + } + }; + return ( + <> + + Hosted NFAs + + {({ Field, Options }) => ( + <> + + {(selected) => selected?.label || 'Select'} + + + {(item) => item.label} + + + )} + + + + ); +}; diff --git a/ui/src/views/indexed-nfa/fragments/main/main.fragment.tsx b/ui/src/views/indexed-nfa/fragments/main/main.fragment.tsx new file mode 100644 index 0000000..2cdb4bc --- /dev/null +++ b/ui/src/views/indexed-nfa/fragments/main/main.fragment.tsx @@ -0,0 +1,12 @@ +import { IndexedNFAStyles as S } from '../../indexed-nfa.styles'; +import { AccessPointsListFragment } from './main-ap-list.fragment'; +import { Header } from './main-header.fragment'; + +export const IndexedNFAMainFragment: React.FC = () => { + return ( + +
+ + + ); +}; diff --git a/ui/src/views/indexed-nfa/indexed-nfa.styles.ts b/ui/src/views/indexed-nfa/indexed-nfa.styles.ts index b7e9aef..e67d924 100644 --- a/ui/src/views/indexed-nfa/indexed-nfa.styles.ts +++ b/ui/src/views/indexed-nfa/indexed-nfa.styles.ts @@ -56,7 +56,6 @@ export const IndexedNFAStyles = { lineHeight: 1.35, fontWeight: 700, - // maxWidth: '10rem', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', @@ -151,12 +150,6 @@ export const IndexedNFAStyles = { lineHeight: 1.35, fontWeight: 700, }), - SectionHeading: styled('h2', { - fontSize: '$xl', - lineHeight: 1.2, - fontWeight: 700, - marginTop: Spacing, - }), AccessPoint: { List: styled('div', { display: 'flex', @@ -186,6 +179,12 @@ export const IndexedNFAStyles = { color: '$slate12', fontSize: '$lg', }), + NoResults: styled('div', { + display: 'flex', + justifyContent: 'center', + + fontSize: '$lg', + }), }, Divider: { Line: styled('span', { @@ -199,144 +198,6 @@ export const IndexedNFAStyles = { borderRadius: '100%', }), }, - Paragraph: styled('p', { - color: '$slate11', - lineHeight: 1.43, - }), - DataContainer: styled('div', { - display: 'flex', - flexDirection: 'column', - border: '1px solid $slate6', - borderRadius: '$lg', - padding: Spacing, - gap: `$1`, - }), - DataList: styled('div', { - display: 'flex', - flexWrap: 'wrap', - gap: '$5', - }), - VerificationBanner: styled('div', { - position: 'relative', - display: 'flex', - alignItems: 'center', - border: '1px solid $slate6', - borderRadius: '$lg', - padding: '$8 $5', - fontWeight: 700, - overflow: 'hidden', - - '&:after': { - content: '""', - position: 'absolute', - right: '-$5', - top: '-$10', - bottom: '-$10', - left: '84%', - borderRadius: '80% 0 0 80%', - }, - - variants: { - verified: { - true: { - borderColor: '$green11', - color: '$green11', - '&:after': { - backgroundColor: '$green11', - }, - }, - false: { - borderColor: '$red11', - color: '$red11', - '&:after': { - backgroundColor: '$red11', - }, - }, - }, - }, - }), - Table: { - Container: styled('div', { - border: '1px solid $slate6', - borderRadius: '10px', - padding: '0 $5', - - maxHeight: '15.125rem', - overflow: 'auto', - }), - Root: styled('table', { - width: 'calc(100% + 2 * $space$5)', - margin: '0 -$5', - }), - Head: styled('thead', { - position: 'sticky', - top: 0, - backgroundColor: '$black', - - '&:after': { - position: 'absolute', - content: '""', - bottom: 0, - left: 0, - right: 0, - borderBottom: '1px solid $slate6', - }, - }), - Row: styled('tr'), - Data: styled('td', { - padding: '$3', - maxWidth: '10rem', - overflow: 'hidden', - textOverflow: 'ellipsis', - whiteSpace: 'nowrap', - }), - Body: styled('tbody', { - tr: { - '&:hover': { - backgroundColor: '$slate6', - cursor: 'pointer', - }, - }, - }), - Marker: styled('span', { - display: 'block', - margin: 'auto', - width: '0.5625rem', - height: '0.5625rem', - borderRadius: '$full', - backgroundColor: '$slate6', - - variants: { - variant: { - active: { - backgroundColor: '$green11', - }, - inactive: { - backgroundColor: '$slate8', - }, - }, - text: { - true: { - fontSize: '$xs', - padding: '0 $2', - width: 'fit-content', - height: 'fit-content', - }, - }, - }, - - compoundVariants: [ - { - variant: 'active', - text: true, - css: { - color: '$green11', - backgroundColor: '$green3', - }, - }, - ], - }), - }, }, Skeleton: styled(Skeleton, { diff --git a/ui/src/views/indexed-nfa/indexed-nfa.tsx b/ui/src/views/indexed-nfa/indexed-nfa.tsx index 773af84..51fdd49 100644 --- a/ui/src/views/indexed-nfa/indexed-nfa.tsx +++ b/ui/src/views/indexed-nfa/indexed-nfa.tsx @@ -54,11 +54,6 @@ export const IndexedNFAView: React.FC = () => { return ; } - if (!data.token) { - //TODO add 404 page - return
Token not found
; - } - return ( diff --git a/ui/src/views/indexed-nfa/fragments/tabs/index.ts b/ui/src/views/indexed-nfa/tabs/index.ts similarity index 100% rename from ui/src/views/indexed-nfa/fragments/tabs/index.ts rename to ui/src/views/indexed-nfa/tabs/index.ts diff --git a/ui/src/views/indexed-nfa/fragments/tabs/tabs.styles.ts b/ui/src/views/indexed-nfa/tabs/tabs.styles.ts similarity index 100% rename from ui/src/views/indexed-nfa/fragments/tabs/tabs.styles.ts rename to ui/src/views/indexed-nfa/tabs/tabs.styles.ts diff --git a/ui/src/views/indexed-nfa/fragments/tabs/tabs.tsx b/ui/src/views/indexed-nfa/tabs/tabs.tsx similarity index 100% rename from ui/src/views/indexed-nfa/fragments/tabs/tabs.tsx rename to ui/src/views/indexed-nfa/tabs/tabs.tsx