fake.modules transposition for aspect-oriented Dendritic Nix. with cross-aspect dependencies. Discussions: https://oeiuwq.zulipchat.com/join/nqp26cd4kngon6mo3ncgnuap/ dendrix.oeiuwq.com/Dendritic.html
dendritic nix aspect oriented
at main 154 lines 5.1 kB view raw
1--- 2import MobileMenuFooter from '@astrojs/starlight/components/MobileMenuFooter.astro'; 3import SidebarPersister from '@astrojs/starlight/components/SidebarPersister.astro'; 4import SidebarSublist from '@astrojs/starlight/components/SidebarSublist.astro'; 5 6const { sidebar, id } = Astro.locals.starlightRoute; 7 8import { Icon } from '@astrojs/starlight/components'; 9 10import TabbedContent from './tabs/TabbedContent.astro'; 11import TabListItem from './tabs/TabListItem.astro'; 12import TabPanel from './tabs/TabPanel.astro'; 13 14/** Get the icon for a group. Update the icon names in the array to change the icons associated with a group. */ 15const getIcon = (index: number) => 16 (['nix', 'open-book', 'rocket', 'puzzle', 'information', 'setting'] as const)[index]; 17 18/** Convert a group label to an `id` we can use to identify tab panels. */ 19// The id is prefixed to avoid clashing with existing heading IDs on the page. 20const makeId = (label: string) => '__tab-' + label.toLowerCase().replaceAll(/\s+/g, '-'); 21 22/** Determine if an array of sidebar items contains the current page. */ 23const isCurrent = (sidebar: SidebarEntry[]): boolean => 24 sidebar 25 .map((entry) => (entry.type === 'link' ? entry.isCurrent : isCurrent(entry.entries))) 26 .some((entry) => entry === true); 27 28--- 29<SidebarPersister> 30 <TabbedContent class="tabbed-sidebar"> 31 <Fragment slot="tab-list"> 32 { 33 sidebar.map(({ label, entries }, index) => ( 34 <TabListItem id={makeId(label)} initial={isCurrent(entries)} class="tab-item"> 35 <Icon class="icon" name={getIcon(index)} /> {label} 36 </TabListItem> 37 )) 38 } 39 </Fragment> 40 { 41 sidebar.map(({ label, entries }) => ( 42 <TabPanel id={makeId(label)} initial={isCurrent(entries)}> 43 <SidebarSublist sublist={entries} /> 44 </TabPanel> 45 )) 46 } 47 </TabbedContent> 48</SidebarPersister> 49 50<div class="md:sl-hidden"> 51 <MobileMenuFooter /> 52</div> 53 54<style> 55 /** Add "EN" to the end of sidebar items with the `fallback` class. */ 56 :global(.fallback)::after { 57 content: 'EN'; 58 vertical-align: super; 59 font-size: 0.75em; 60 font-weight: 700; 61 } 62 63 /** Align sponsors at sidebar bottom when there is room. */ 64 .desktop-footer { 65 margin-top: auto; 66 } 67 68 /** Always show the scrollbar gutter. */ 69 :global(.sidebar-pane) { 70 overflow-y: scroll; 71 } 72 73 /* Styles for the custom tab switcher. */ 74 .tabbed-sidebar { 75 /* Layout variables */ 76 --tab-switcher-border-width: 1px; 77 --tab-switcher-padding: calc(0.25rem - var(--tab-switcher-border-width)); 78 --tab-item-border-radius: 0.5rem; 79 --tab-switcher-border-radius: calc( 80 var(--tab-item-border-radius) + var(--tab-switcher-padding) + var(--tab-switcher-border-width) 81 ); 82 83 /* Color variables */ 84 --tab-switcher-border-color: var(--sl-color-hairline-light); 85 --tab-switcher-background-color: var(--sl-color-gray-7, var(--sl-color-gray-6)); 86 --tab-switcher-text-color: var(--sl-color-gray-3); 87 --tab-switcher-text-color--active: var(--sl-color-white); 88 --tab-switcher-icon-color: var(--sl-color-gray-4); 89 --tab-switcher-icon-color--active: var(--sl-color-text-accent); 90 --tab-item-background-color--hover: var(--sl-color-gray-6); 91 --tab-item-background-color--active: var(--sl-color-black); 92 } 93 /* Dark theme variations */ 94 :global([data-theme='dark']) .tabbed-sidebar { 95 --tab-switcher-text-color: var(--sl-color-gray-2); 96 --tab-switcher-icon-color: var(--sl-color-gray-3); 97 --tab-item-background-color--hover: var(--sl-color-gray-5); 98 } 99 100 @media (min-width: 50rem) { 101 /* Dark theme variations with the desktop sidebar visible */ 102 :global([data-theme='dark']) .tabbed-sidebar { 103 --tab-switcher-background-color: var(--sl-color-black); 104 --tab-item-background-color--hover: var(--sl-color-gray-6); 105 --tab-item-background-color--active: var(--sl-color-gray-6); 106 } 107 } 108 109 .tabbed-sidebar.tab-list { 110 border: var(--tab-switcher-border-width) solid var(--tab-switcher-border-color); 111 border-radius: var(--tab-switcher-border-radius); 112 display: flex; 113 flex-direction: column; 114 gap: 0.25rem; 115 padding: var(--tab-switcher-padding); 116 background-color: var(--tab-switcher-background-color); 117 margin-bottom: 1.5rem; 118 } 119 120 .tab-item :global(a) { 121 border: var(--tab-switcher-border-width) solid transparent; 122 border-radius: var(--tab-item-border-radius); 123 display: flex; 124 align-items: center; 125 gap: 0.5rem; 126 padding: calc(0.5rem - var(--tab-switcher-border-width)); 127 background-clip: padding-box; 128 line-height: var(--sl-line-height-headings); 129 text-decoration: none; 130 color: var(--tab-switcher-text-color); 131 font-weight: 600; 132 } 133 134 .tab-item :global(a:hover) { 135 color: var(--tab-switcher-text-color--active); 136 background-color: var(--tab-item-background-color--hover); 137 } 138 .tab-item :global(a[aria-selected='true']) { 139 border-color: var(--tab-switcher-border-color); 140 color: var(--tab-switcher-text-color--active); 141 background-color: var(--tab-item-background-color--active); 142 } 143 144 .icon { 145 margin: 0.25rem; 146 color: var(--tab-switcher-icon-color); 147 } 148 .tab-item :global(a:hover) .icon { 149 color: inherit; 150 } 151 .tab-item :global(a[aria-selected='true']) .icon { 152 color: var(--tab-switcher-icon-color--active); 153 } 154</style>