Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 111 additions & 37 deletions demo/components.html

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions resources/views/components-preview.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,33 @@
</div>
</div>

<div class="grid grid-cols-1 gap-5 items-start lg:grid-cols-3">
<div>
<h3 class="text-xl font-bold">Read more / Read less inline variant</h3>
<div class="text-sm text-muted">
If you want to have the inline variant you can use the variant like the example shown here
</div>
</div>
<div class="flex flex-col gap-3">
<h3 class="text-md font-bold">Inline read more / read less</h3>
<x-rapidez::readmore>
<x-slot:wrapper class="flex items-baseline">
<x-slot:slot class="line-clamp-1 mb-0 break-all">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque, repellat incidunt placeat. Quo accusantium laudantium, adipisci culpa ad enim dolores molestiae alias ducimus officiis labore facilis modi provident cupiditate? Voluptates. Lorem ipsum dolor sit amet consectetur adipisicing elit. Doloremque, repellat incidunt placeat. Quo accusantium laudantium, adipisci culpa ad enim dolores molestiae alias ducimus officiis labore facilis modi provident cupiditate? Voluptates.
<span
class="hidden invisible cursor-pointer items-center gap-1 whitespace-nowrap text-primary hover:underline"
data-read-less
data-text-less="@lang('Read less')"
>
<x-heroicon-o-chevron-up class="size-3.5 mt-px" stroke-width="2" />
</span>
</x-slot:slot>
<x-slot:less><span></span></x-slot:less>
</x-slot:wrapper>
</x-rapidez::readmore>
</div>
</div>

<h2 class="font-bold text-2xl mt-5">Prose component</h2>
<x-rapidez::prose>
<h1>Wayne Enterprises</h1>
Expand Down
109 changes: 81 additions & 28 deletions resources/views/components/readmore/readmore.blade.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
{{--
Read more/less component using the Tailwind CSS `peer` utility. Only used JS for checking if content overflows line-clamp container.
Read more/less component, JS used for checking if content overflows line-clamp container and to show or
hide the more/less buttons.

## Notes
- **Clamping** The default of line-clamp-5 is used.
- **Buttons** You can't use <button tags inside the slots because it's wrapped by a <label. Simply use a <span tag.
- **Buttons** You can't use <button> tags inside the slots because it's wrapped by a <label>. Simply use a <span> tag.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't true anymore, in this PR you have removed the label btw

- **Invisible** The read more/less buttons are shown/hidden with visible/invisible property. This prevents layout shifting

## Slots
- `more` Change the clickable element that reveals the content.
- `less` Change the clickable element that collapses the content.
- `wrapper` If you want to show it "inline" use the slot.

## Example
```
Expand All @@ -18,8 +20,9 @@
```

## Changing the line-clamp quantity and using custom read more/less buttons
Keep in mind that you add the data-read-more data-read-less on the overwritten button
```
<x-rapidez::readmore>
<x-rapidez::readmore>
<x-slot:slot class="line-clamp-3">
Content
</x-slot:slot>
Expand All @@ -31,40 +34,90 @@
</x-slot:less>
</x-rapidez::readmore>
```

## Inline variant
In some cases you may want to show the more/less buttons behind the text instead of below the text.
Add the classes `flex items-baseline` on the slot `wrapper`. Override the slot `less` by adding an empty <span></span> in it.
Move the read less button inside the default slot.
```
<x-rapidez::readmore>
<x-slot:wrapper class="flex items-baseline">
<x-slot:slot class="line-clamp-1 break-all">
Content
<span data-read-less class="hidden invisible cursor-pointer items-center gap-1 whitespace-nowrap text-primary hover:underline">
@lang('Read less')
<x-heroicon-o-chevron-up class="size-3.5 mt-px" stroke-width="2" />
</span>
</x-slot:slot>
<x-slot:less><span></span></x-slot:less>
</x-slot:wrapper>
</x-rapidez::readmore>
```
--}}
@slots(['more', 'less'])
<div {{ $attributes->twMerge('read-more-component group') }}>
<div {{ $slot->attributes->twMerge('content line-clamp-5 group-has-[:checked]:line-clamp-none mb-2') }}>
{{ $slot }}
@slots(['more', 'less', 'wrapper'])
<div {{ $attributes->twMerge('read-more-component') }}>
<div {{ $wrapper->attributes->twMerge('contents') }}>
<div {{ $slot->attributes->twMerge('content line-clamp-5 mb-2') }}>
{{ $slot }}
</div>
@slotdefault('more')
<span
class="invisible min-w-24 h-6 flex cursor-pointer items-center gap-1 whitespace-nowrap text-primary hover:underline"
data-read-more
data-text-more="@lang('Read more')"
>
<x-heroicon-o-chevron-down class="size-3.5 mt-px" stroke-width="2" />
</span>
@endslotdefault

@slotdefault('less')
<span
class="hidden invisible cursor-pointer items-center gap-1 whitespace-nowrap text-primary hover:underline"
data-read-less
data-text-less="@lang('Read less')"
>
<x-heroicon-o-chevron-up class="size-3.5 mt-px" stroke-width="2" />
</span>
@endslotdefault
</div>
<label class="invisible">
<input type="checkbox" class="hidden peer">
<span {{ $more->attributes->twMerge('inline-flex peer-checked:hidden') }}>
@slotdefault('more')
<span class="hover:underline cursor-pointer flex items-center gap-1 text-primary">
@lang('Read more')
<x-heroicon-o-chevron-down class="size-3.5 mt-px" stroke-width="2" />
</span>
@endslotdefault
</span>
<span {{ $less->attributes->twMerge('hidden peer-checked:inline-flex') }}>
@slotdefault('less')
<span class="hover:underline cursor-pointer flex items-center gap-1 text-primary">
@lang('Read less')
<x-heroicon-o-chevron-up class="size-3.5 mt-px" stroke-width="2" />
</span>
@endslotdefault
</span>
</label>
</div>

@pushOnce('foot')
<script>
function checkReadMore() {
document.querySelectorAll('.read-more-component').forEach(container => {
const content = container.querySelector('.content');
const label = container.querySelector('label');
label.classList.toggle('invisible', content.scrollHeight <= content.clientHeight);
const readMoreBtn = container.querySelector('[data-read-more]');
const readLessBtn = container.querySelector('[data-read-less]');
const needsReadMore = content.scrollHeight > content.clientHeight;

if (!readMoreBtn.textContent.trim()) {
readMoreBtn.prepend(readMoreBtn.dataset.textMore + ' ');
}
if (!readLessBtn.textContent.trim()) {
readLessBtn.prepend(readLessBtn.dataset.textLess + ' ');
}

if (!content.dataset.originalClasses) {
const lineClampMatch = content.className.match(/line-clamp-\d+/);
content.dataset.originalClasses = lineClampMatch ? lineClampMatch[0] : 'line-clamp-5';
}

readMoreBtn.classList.toggle('invisible', !needsReadMore);
readLessBtn.classList.add('invisible');

readMoreBtn.addEventListener("click", () => {
content.className = content.className.replace(/line-clamp-\d+/g, '');
readMoreBtn.style.display = "none";
readLessBtn.classList.remove('invisible')
readLessBtn.style.display = "inline-flex";
});

readLessBtn.addEventListener("click", () => {
content.classList.add(content.dataset.originalClasses);
readMoreBtn.style.display = "inline-flex";
readLessBtn.style.display = "none";
});
});
}

Expand Down
Loading