Skip to content

Commit 98dfdda

Browse files
authored
Merge pull request #8 from Xoshbin:feature/scoped-docs-layout
feat: redesign documentation layout with scoped navigation and fluid grid
2 parents 3a876db + e71de17 commit 98dfdda

File tree

6 files changed

+161
-109
lines changed

6 files changed

+161
-109
lines changed

dist/pertuk.css

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/views/components/header.blade.php

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,42 @@ class="absolute top-full mt-2 hidden max-h-96 w-full overflow-auto rounded-lg bo
4545

4646
<!-- Navigation -->
4747
<div class="flex items-center gap-4">
48+
<!-- Context Switcher (Desktop) -->
49+
<div class="hidden lg:flex items-center gap-1 mr-4 border-r border-gray-200 dark:border-gray-800 pr-4">
50+
@php
51+
// Identify top-level contexts for navigation
52+
$navContexts = collect($items ?? [])->map(function($item) {
53+
$parts = explode('/', $item['slug']);
54+
return count($parts) > 1 ? $parts[0] : 'General';
55+
})->unique();
56+
57+
// Current context
58+
$currentContext = 'General';
59+
if(isset($slug)) {
60+
$parts = explode('/', $slug);
61+
$currentContext = count($parts) > 1 ? $parts[0] : 'General';
62+
}
63+
@endphp
64+
65+
@foreach($navContexts as $context)
66+
@if($context !== 'General')
67+
@php
68+
// Find the index page or first page of this context to link to
69+
$firstDoc = collect($items ?? [])->first(function($item) use ($context) {
70+
return str_starts_with($item['slug'], $context . '/');
71+
});
72+
$linkUrl = $firstDoc
73+
? route('pertuk.docs.show', ['locale' => app()->getLocale(), 'slug' => $firstDoc['slug']])
74+
: '#';
75+
@endphp
76+
<a href="{{ $linkUrl }}"
77+
class="px-3 py-1.5 text-sm font-medium rounded-md transition-colors {{ $currentContext === $context ? 'text-orange-600 bg-orange-50 dark:text-orange-400 dark:bg-orange-900/20' : 'text-gray-600 hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-white dark:hover:bg-gray-800' }}">
78+
{{ ucfirst(str_replace('-', ' ', $context)) }}
79+
</a>
80+
@endif
81+
@endforeach
82+
</div>
83+
4884
<!-- Global Language Selector -->
4985
<div class="hidden md:block">
5086
<label for="global-lang-select" class="sr-only">{{ __('Language') }}</label>
@@ -68,7 +104,7 @@ class="rounded-md border border-gray-300 bg-white px-3 py-1.5 text-sm font-mediu
68104
$versions = \Xoshbin\Pertuk\Services\DocumentationService::getAvailableVersions();
69105
$currentVersion = $current_version ?? config('pertuk.default_version');
70106
$currentLocale = app()->getLocale();
71-
$currentSlug = $slug ?? 'index';
107+
$currentSlug = $currentSlug ?? $slug ?? 'index';
72108
$routePrefix = config('pertuk.route_prefix', 'docs');
73109
@endphp
74110
@if(count($versions) > 0)

resources/views/components/pertuk-layout.blade.php

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1-
@props(['title' => null, 'currentLocale' => null, 'currentVersion' => null, 'slug' => null])
1+
@props(['title' => null, 'currentLocale' => null, 'currentVersion' => null, 'slug' => null, 'items' => []])
22

33
@php
44
$locale = $currentLocale ?? app()->getLocale();
55
$isRtl = in_array($locale, config('pertuk.rtl_locales', ['ar', 'ckb']));
66
$current_version = $currentVersion; // Pass through to included header
77
@endphp
88
<!DOCTYPE html>
9-
<html lang="{{ str_replace('_', '-', $locale) }}" dir="{{ $isRtl ? 'rtl' : 'ltr' }}" class="h-full">
9+
<html lang="{{ str_replace('_', '-', $locale) }}" dir="{{ $isRtl ? 'rtl' : 'ltr' }}" class="h-full antialiased">
1010

1111
<head>
1212
<meta charset="utf-8">
@@ -22,29 +22,26 @@
2222
class="skip-link bg-orange-600 text-white px-4 py-2 rounded focus:outline-none focus:ring-2 focus:ring-orange-500">Skip
2323
to content</a>
2424

25-
@include('pertuk::components.header', ['current_version' => $current_version])
25+
@include('pertuk::components.header', ['current_version' => $current_version, 'slug' => $slug, 'items' => $items])
2626

27-
<div class="mx-auto max-w-8xl px-4 sm:px-6 lg:px-8">
28-
<div class="grid grid-cols-1 gap-8 lg:grid-cols-12 lg:gap-12 py-8">
27+
<!-- Fluid container for ERP-scale documentation -->
28+
<div class="mx-auto max-w-[1920px] px-4 sm:px-6 lg:px-8">
29+
<div class="grid grid-cols-1 lg:grid-cols-[18rem_1fr] xl:grid-cols-[18rem_1fr_18rem] gap-8 py-8 items-start">
2930
<!-- Sidebar -->
30-
<aside class="hidden lg:block lg:col-span-3 lg:order-1" aria-label="Navigation">
31-
<div class="sticky top-24 max-h-[calc(100vh-6rem)] overflow-y-auto">
32-
{{ $sidebar ?? '' }}
33-
</div>
31+
<aside class="hidden lg:block lg:sticky top-24 max-h-[calc(100vh-6rem)] overflow-y-auto pr-4 z-40 bg-white dark:bg-gray-950 lg:bg-transparent" aria-label="Navigation">
32+
{{ $sidebar ?? '' }}
3433
</aside>
3534

3635
<!-- Main Content -->
37-
<main id="main" class="col-span-1 lg:col-span-6 xl:col-span-6 lg:order-2 min-w-0">
36+
<main id="main" class="min-w-0">
3837
<div class="min-w-0">
3938
{{ $slot }}
4039
</div>
4140
</main>
4241

43-
<!-- Table of Contents -->
44-
<aside class="hidden xl:block xl:col-span-3 lg:order-3" aria-label="On this page">
45-
<div class="sticky top-24 max-h-[calc(100vh-6rem)] overflow-y-auto">
46-
{{ $toc ?? '' }}
47-
</div>
42+
<!-- Table of Contents (Right Sidebar) -->
43+
<aside class="hidden xl:block sticky top-24 max-h-[calc(100vh-6rem)] overflow-y-auto pl-4" aria-label="On this page">
44+
{{ $toc ?? '' }}
4845
</aside>
4946
</div>
5047
</div>
Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,94 @@
11
@php
22
/** @var array<int,array{slug:string,title:string}> $items */
3+
/** @var string $active */
34
4-
// Group items by category for better organization
5-
$groupedItems = collect($items)->groupBy(function ($item) {
5+
// 1. Determine Current Context
6+
$activeParts = explode('/', $active ?? '');
7+
$currentContext = count($activeParts) > 1 ? $activeParts[0] : 'General';
8+
9+
// 2. Filter Items for Context
10+
$contextItems = collect($items)->filter(function ($item) use ($currentContext) {
611
$parts = explode('/', $item['slug']);
7-
return count($parts) > 1 ? $parts[0] : 'Getting Started';
12+
$itemContext = count($parts) > 1 ? $parts[0] : 'General';
13+
return $itemContext === $currentContext;
14+
});
15+
16+
// 3. Group by Sub-category (if exists) or fallback to 'Main'
17+
$groupedItems = $contextItems->groupBy(function ($item) use ($currentContext) {
18+
// Remove context from slug to find sub-category
19+
$relSlug = $currentContext === 'General' ? $item['slug'] : substr($item['slug'], strlen($currentContext) + 1);
20+
21+
if (empty($relSlug)) {
22+
return 'Main';
23+
}
24+
25+
$parts = explode('/', $relSlug);
26+
27+
return (count($parts) > 1 && !empty($parts[0])) ? $parts[0] : 'Main';
28+
});
29+
30+
// Sort groups: 'Main' first, then alphabetical or bespoke order
31+
$groupedItems = $groupedItems->sortBy(function ($items, $key) {
32+
return $key === 'Main' ? '000' : $key;
833
});
934
1035
$locale = app()->getLocale();
1136
$isRtl = in_array($locale, config('pertuk.rtl_locales', ['ar', 'ckb']));
37+
$routePrefix = config('pertuk.route_prefix', 'docs');
1238
@endphp
1339

14-
<nav class="space-y-6">
40+
<nav class="space-y-6" x-data="{ search: '' }">
41+
<!-- Sidebar Search -->
42+
<div class="mb-4">
43+
<div class="relative">
44+
<div class="absolute inset-y-0 start-0 ps-3 flex items-center pointer-events-none">
45+
<svg class="h-4 w-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
46+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
47+
</svg>
48+
</div>
49+
<input type="text"
50+
x-model="search"
51+
placeholder="{{ __('Filter navigation...') }}"
52+
class="w-full rounded-md border border-gray-300 bg-white px-3 py-1.5 ps-9 text-sm text-gray-900 focus:border-orange-500 focus:outline-none focus:ring-1 focus:ring-orange-500 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100 dark:focus:ring-orange-500/50"
53+
>
54+
</div>
55+
</div>
56+
1557
@foreach ($groupedItems as $category => $categoryItems)
16-
<div class="space-y-3">
17-
@if ($category !== 'Getting Started' || $groupedItems->count() > 1)
18-
<h3 class="text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400 px-3">
58+
<div class="space-y-2" x-show="!search || $el.textContent.toLowerCase().includes(search.toLowerCase())">
59+
@if ($category !== 'Main' || $groupedItems->count() > 1)
60+
<h3 class="text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400 px-3 truncate" title="{{ str_replace('-', ' ', ucfirst($category)) }}">
1961
{{ str_replace('-', ' ', ucfirst($category)) }}
2062
</h3>
2163
@endif
2264

23-
<ul class="space-y-1">
65+
<ul class="space-y-0.5">
2466
@foreach ($categoryItems as $item)
2567
@php
2668
$isActive = ($active ?? '') === $item['slug'];
2769
$displayTitle = $item['title'];
2870
29-
// Clean up title if it contains category prefix
71+
// Cleanup title: remove context/category prefixes for cleaner sidebar
3072
if (str_contains($item['title'], ':')) {
31-
$displayTitle = trim(explode(':', $item['title'], 2)[1] ?? $item['title']);
73+
$parts = explode(':', $item['title']);
74+
$displayTitle = trim(end($parts));
3275
}
3376
@endphp
3477

35-
<li>
36-
<a href="{{ url('/' . config('pertuk.route_prefix', 'docs') . '/' . $locale . '/' . $item['slug']) }}"
37-
class="group flex items-center rounded-md px-3 py-2 text-sm font-medium transition-colors duration-200 @if ($isActive) bg-orange-50 text-orange-700 dark:bg-orange-900/20 dark:text-orange-400 @else text-gray-700 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-gray-800 dark:hover:text-white @endif"
78+
<li x-show="!search || '{{ strtolower($displayTitle) }}'.includes(search.toLowerCase())">
79+
<a href="{{ url('/' . $routePrefix . '/' . $locale . '/' . $item['slug']) }}"
80+
class="group flex items-center rounded-md px-3 py-1.5 text-sm font-medium transition-colors duration-200 border-l-2 {{ $isActive ? 'border-orange-500 bg-orange-50 text-orange-700 dark:bg-orange-900/20 dark:text-orange-400' : 'border-transparent text-gray-600 hover:text-gray-900 hover:bg-gray-50 dark:text-gray-400 dark:hover:bg-gray-800 dark:hover:text-gray-200' }}"
3881
@if ($isActive) aria-current="page" @endif>
39-
@if ($isActive)
40-
<svg class=" h-2 w-2 flex-shrink-0 text-orange-500" fill="currentColor" viewBox="0 0 8 8">
41-
<circle cx="4" cy="4" r="3" />
42-
</svg>
43-
@endif
44-
82+
4583
<span class="truncate">{{ $displayTitle }}</span>
46-
47-
@if ($isActive)
48-
<svg class="{{ $isRtl ? 'mr-auto rotate-180' : 'ml-auto' }} h-4 w-4 flex-shrink-0 text-orange-500"
49-
fill="none" stroke="currentColor" viewBox="0 0 24 24">
50-
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
51-
d="M9 5l7 7-7 7" />
52-
</svg>
53-
@endif
5484
</a>
5585
</li>
5686
@endforeach
5787
</ul>
5888
</div>
5989
@endforeach
60-
61-
<!-- Quick Links Section -->
62-
<div class="border-t border-gray-200 dark:border-gray-700 pt-6 space-y-3">
63-
<h3 class="text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400 px-3">
64-
Quick Links
65-
</h3>
66-
67-
<ul class="space-y-1">
68-
<li>
69-
<a href="https://github.com/your-repo" target="_blank" rel="noopener noreferrer"
70-
class="group flex items-center rounded-md px-3 py-2 text-sm font-medium text-gray-700 transition-colors duration-200 hover:bg-gray-100 hover:text-gray-900 dark:text-gray-300 dark:hover:bg-gray-800 dark:hover:text-white">
71-
<svg class=" h-4 w-4 flex-shrink-0 text-gray-400 group-hover:text-gray-500" fill="currentColor"
72-
viewBox="0 0 24 24">
73-
<path
74-
d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.30.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
75-
</svg>
76-
<span>GitHub</span>
77-
</a>
78-
</li>
79-
</ul>
90+
91+
<div x-show="search && $el.previousElementSibling.children.length === 0" class="px-3 text-sm text-gray-500 dark:text-gray-400 text-center py-4">
92+
{{ __('No results found') }}
8093
</div>
8194
</nav>

0 commit comments

Comments
 (0)