From 71c52f35a5f8ade6f8525503c23512cc07f498d1 Mon Sep 17 00:00:00 2001 From: Luiz Gomes Date: Fri, 7 Aug 2026 06:50:58 -0300 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20feat(web):=20add=20featured=20a?= =?UTF-8?q?rticles=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds /docs/featured/articles as the written-content counterpart to the YouTube page: an aggregator of community articles about Zard UI, with the original cover image of each post and a submission section pointing to the same address used for video submissions. Seeded with the two dev.to articles currently available. Adding a new one is a single entry in featured-articles.ts. --- apps/web/prerender-routes.txt | 1 + apps/web/public/docs/featured/articles.md | 23 ++++ .../featured/articles/articles.page.html | 90 ++++++++++++++ .../featured/articles/articles.page.spec.ts | 111 ++++++++++++++++++ .../pages/featured/articles/articles.page.ts | 104 ++++++++++++++++ .../pages/featured/data/featured-articles.ts | 65 ++++++++++ .../domain/pages/featured/featured.routes.ts | 4 + .../app/shared/constants/routes.constant.ts | 2 +- 8 files changed, 399 insertions(+), 1 deletion(-) create mode 100644 apps/web/public/docs/featured/articles.md create mode 100644 apps/web/src/app/domain/pages/featured/articles/articles.page.html create mode 100644 apps/web/src/app/domain/pages/featured/articles/articles.page.spec.ts create mode 100644 apps/web/src/app/domain/pages/featured/articles/articles.page.ts create mode 100644 apps/web/src/app/domain/pages/featured/data/featured-articles.ts diff --git a/apps/web/prerender-routes.txt b/apps/web/prerender-routes.txt index e21417191..019c7aa68 100644 --- a/apps/web/prerender-routes.txt +++ b/apps/web/prerender-routes.txt @@ -19,6 +19,7 @@ /docs/version-support /docs/about /docs/featured/youtube +/docs/featured/articles /docs/components/accordion /docs/components/alert /docs/components/alert-dialog diff --git a/apps/web/public/docs/featured/articles.md b/apps/web/public/docs/featured/articles.md new file mode 100644 index 000000000..9665f8d7c --- /dev/null +++ b/apps/web/public/docs/featured/articles.md @@ -0,0 +1,23 @@ +--- +title: Articles +description: Blog posts, tutorials and write-ups the community published about Zard UI, gathered in one place. +--- + +# Articles + +Blog posts, tutorials and write-ups the community published about Zard UI, gathered in one place. + +Made by the community + +Every article below was written by someone outside the core team. Each card opens the original post on the platform where it was published, so the author keeps the traffic and the credit. + +## English + +- [Building fast in Angular with Zard UI, Tailwind CSS and Signals](https://dev.to/hassantayyab/building-fast-in-angular-with-zard-ui-tailwind-css-and-signals-cj5) +- [ZardUI Beta: Bringing shadcn/ui's Philosophy to Angular - Where You Own Every Line of Code](https://dev.to/samuelrizzondev/zardui-beta-bringing-shadcnuis-philosophy-to-angular-where-you-own-every-line-of-code-2a79) + +## Contribute + +Wrote an article about Zard UI? + +Send the link to [hello@luizgomes.dev](mailto:hello@luizgomes.dev?subject=Zard%20UI%20article%20submission) and we will add it to this page. Submissions go through a review before being published, so it may take a while until your article shows up here. Content in any language is welcome. diff --git a/apps/web/src/app/domain/pages/featured/articles/articles.page.html b/apps/web/src/app/domain/pages/featured/articles/articles.page.html new file mode 100644 index 000000000..de8420229 --- /dev/null +++ b/apps/web/src/app/domain/pages/featured/articles/articles.page.html @@ -0,0 +1,90 @@ + + + + + + @for (group of groups(); track group.id) { +
+

+ {{ group.label }} +

+ + +
+ } + +
+

Contribute

+ + + + +

+ Send the link to + hello@luizgomes.dev + and we will add it to this page. Submissions go through a review before being published, so it may take a while + until your article shows up here. Content in any language is welcome. +

+
+
+
diff --git a/apps/web/src/app/domain/pages/featured/articles/articles.page.spec.ts b/apps/web/src/app/domain/pages/featured/articles/articles.page.spec.ts new file mode 100644 index 000000000..d81bdaf58 --- /dev/null +++ b/apps/web/src/app/domain/pages/featured/articles/articles.page.spec.ts @@ -0,0 +1,111 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { By } from '@angular/platform-browser'; +import { provideRouter } from '@angular/router'; + +import { ScrollSpyItemDirective } from '@doc/domain/directives/scroll-spy-item.directive'; + +import { ArticlesPage } from './articles.page'; +import { FEATURED_ARTICLES } from '../data/featured-articles'; + +describe('ArticlesPage', () => { + let component: ArticlesPage; + let fixture: ComponentFixture; + + const cards = () => fixture.debugElement.queryAll(By.css('a[target="_blank"][rel="noopener noreferrer"]')); + + const imageSources = () => + fixture.debugElement.queryAll(By.css('img')).map(el => (el.nativeElement as HTMLImageElement).getAttribute('src')); + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ArticlesPage], + providers: [provideRouter([])], + }).compileComponents(); + + fixture = TestBed.createComponent(ArticlesPage); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('creates', () => { + expect(component).toBeTruthy(); + }); + + describe('article cards', () => { + it('renders one card per article', () => { + expect(cards()).toHaveLength(FEATURED_ARTICLES.length); + }); + + it('links every card to the original post in a new tab', () => { + const hrefs = cards().map(card => (card.nativeElement as HTMLAnchorElement).getAttribute('href')); + + for (const article of FEATURED_ARTICLES) { + expect(hrefs).toContain(article.url); + } + }); + + it('shows the author, the publication date and the reading time', () => { + const text = (fixture.nativeElement as HTMLElement).textContent ?? ''; + + expect(text).toContain('Samuel Rizzon'); + expect(text).toContain('Aug 19, 2025'); + expect(text).toContain('4 min read'); + }); + }); + + describe('navigation', () => { + // Bound as `[scrollSpyItem]`/`[id]` on the language sections, so the directive — not the + // attribute selector — is what finds every spied section. + const sectionIds = () => + fixture.debugElement + .queryAll(By.directive(ScrollSpyItemDirective)) + .map(el => (el.nativeElement as HTMLElement).id); + + it('has a navigation entry for every section in the template', () => { + const configured = component['navigationConfig']().items.map(item => item.id); + + for (const id of sectionIds()) { + expect(configured).toContain(id); + } + }); + + it('has a section in the template for every navigation entry', () => { + const rendered = sectionIds(); + + for (const item of component['navigationConfig']().items) { + expect(rendered).toContain(item.id); + } + }); + + it('skips languages that have no article yet', () => { + const configured = component['navigationConfig']().items.map(item => item.id); + + expect(configured).not.toContain('portuguese'); + }); + }); + + describe('contribute section', () => { + it('points to the submission address', () => { + const link = fixture.debugElement.query(By.css('section#contribute a[href^="mailto:"]')); + + expect((link.nativeElement as HTMLAnchorElement).getAttribute('href')).toBe( + 'mailto:hello@luizgomes.dev?subject=Zard%20UI%20article%20submission', + ); + }); + }); + + describe('cover fallback', () => { + it('drops the remote image when the cover fails to load', () => { + const article = FEATURED_ARTICLES[0]; + + expect(imageSources()).toContain(article.cover); + expect(imageSources()).not.toContain('/images/zard.svg'); + + component['onCoverError'](article.id); + fixture.detectChanges(); + + expect(imageSources()).not.toContain(article.cover); + expect(imageSources()).toContain('/images/zard.svg'); + }); + }); +}); diff --git a/apps/web/src/app/domain/pages/featured/articles/articles.page.ts b/apps/web/src/app/domain/pages/featured/articles/articles.page.ts new file mode 100644 index 000000000..e82eea738 --- /dev/null +++ b/apps/web/src/app/domain/pages/featured/articles/articles.page.ts @@ -0,0 +1,104 @@ +import { DatePipe } from '@angular/common'; +import { ChangeDetectionStrategy, Component, computed, inject, OnInit, signal } from '@angular/core'; + +import { NgIcon, provideIcons } from '@ng-icons/core'; +import { lucideArrowUpRight } from '@ng-icons/lucide'; + +import { DocContentComponent } from '@doc/domain/components/doc-content/doc-content.component'; +import { DocHeadingComponent } from '@doc/domain/components/doc-heading/doc-heading.component'; +import { NavigationConfig } from '@doc/domain/components/dynamic-anchor/dynamic-anchor.component'; +import { ScrollSpyItemDirective } from '@doc/domain/directives/scroll-spy-item.directive'; +import { ScrollSpyDirective } from '@doc/domain/directives/scroll-spy.directive'; +import { SeoService } from '@doc/shared/services/seo.service'; + +import { ZardAlertComponent } from '@zard/components/alert/alert.component'; +import { ZardBadgeComponent } from '@zard/components/badge/badge.component'; + +import { FEATURED_ARTICLES, type FeaturedArticle, type FeaturedArticleLanguage } from '../data/featured-articles'; + +interface ArticleCard extends FeaturedArticle { + /** Whether the remote cover failed to load and the card must render the placeholder instead. */ + coverFailed: boolean; +} + +interface ArticleGroup { + id: string; + label: string; + articles: ArticleCard[]; +} + +const LANGUAGE_GROUPS: ReadonlyArray<{ id: string; label: string; language: FeaturedArticleLanguage }> = [ + { id: 'portuguese', label: 'Portuguese 🇧🇷', language: 'pt-BR' }, + { id: 'english', label: 'English', language: 'en' }, +]; + +@Component({ + selector: 'z-articles', + standalone: true, + changeDetection: ChangeDetectionStrategy.OnPush, + templateUrl: './articles.page.html', + imports: [ + DatePipe, + DocContentComponent, + DocHeadingComponent, + NgIcon, + ZardAlertComponent, + ZardBadgeComponent, + ScrollSpyDirective, + ScrollSpyItemDirective, + ], + viewProviders: [provideIcons({ lucideArrowUpRight })], +}) +export class ArticlesPage implements OnInit { + private readonly seoService = inject(SeoService); + activeAnchor?: string; + + /** + * Seeded synchronously, unlike the YouTube page: the anchor list is derived from this data, and + * filling it in after the first render leaves the server-rendered anchors and the client out of + * sync — the hydrated `@for` ends up moving the language anchor past `Contribute`. The list still + * stays out of the initial bundle because the whole route is lazy-loaded. + */ + private readonly articles = signal(FEATURED_ARTICLES); + /** IDs whose cover could not be fetched (CDN down, hotlink blocked, article unpublished). */ + private readonly degradedCovers = signal>(new Set()); + + protected readonly groups = computed(() => { + const articles = this.articles(); + const degraded = this.degradedCovers(); + + return LANGUAGE_GROUPS.map(group => ({ + id: group.id, + label: group.label, + articles: articles + .filter(article => article.language === group.language) + // Copy before sorting: the source array is readonly and must never be mutated. + .slice() + .sort((a, b) => b.publishedAt.localeCompare(a.publishedAt)) + .map(article => ({ ...article, coverFailed: degraded.has(article.id) })), + })).filter(group => group.articles.length > 0); + }); + + /** Derived from the rendered groups so an empty language never leaves a dangling anchor. */ + protected readonly navigationConfig = computed(() => ({ + items: [ + { id: 'overview', label: 'Overview', type: 'core' }, + ...this.groups().map(group => ({ id: group.id, label: group.label, type: 'custom' as const })), + { id: 'contribute', label: 'Contribute', type: 'custom' }, + ], + })); + + ngOnInit(): void { + this.seoService.setDocsSeo( + 'Articles', + 'Blog posts, tutorials and write-ups the community published about Zard UI, gathered in one place.', + '/docs/featured/articles', + 'og-featured-articles.jpg', + ); + } + + /** Covers are hotlinked from the publisher's CDN, so a broken URL must degrade to the placeholder. */ + protected onCoverError(id: string): void { + this.degradedCovers.update(current => (current.has(id) ? current : new Set(current).add(id))); + } +} diff --git a/apps/web/src/app/domain/pages/featured/data/featured-articles.ts b/apps/web/src/app/domain/pages/featured/data/featured-articles.ts new file mode 100644 index 000000000..6328481f5 --- /dev/null +++ b/apps/web/src/app/domain/pages/featured/data/featured-articles.ts @@ -0,0 +1,65 @@ +export type FeaturedArticleLanguage = 'pt-BR' | 'en'; + +export interface FeaturedArticle { + /** Stable slug — used as the `@for` track and as the key of the degraded cover state. */ + id: string; + title: string; + /** Author of the article, so the writer gets the credit on the card. */ + author: string; + /** Canonical article URL — the whole card links here. */ + url: string; + /** Cover image served by the publisher's CDN. See the note about `cover_image` vs `social_image`. */ + cover: string; + /** Publication date in ISO (`YYYY-MM-DD`) — formatted in the view. */ + publishedAt: string; + /** Reading time in minutes, as reported by the publisher. */ + readingTime: number; + /** Where the article was published, rendered as a badge over the cover. */ + source: string; + tags: readonly string[]; + language: FeaturedArticleLanguage; +} + +/** + * Articles featured on `/docs/featured/articles`. + * + * Adding a new one is a single entry here and nothing else: the page derives the card, + * the language grouping and the ordering from these fields. + * + * Metadata was read from dev.to's public article endpoint + * (`https://dev.to/api/articles/{username}/{slug}`), which needs no API key. + * + * About the covers: dev.to exposes both `cover_image` and `social_image`. When an author never + * uploads a dedicated cover, `cover_image` comes back `null` while `social_image` still holds the + * image dev.to actually renders on the article — that is the case of the ZardUI Beta post below. + * Always keep the remote CDN URL here; covers are never copied into the repository. + */ +export const FEATURED_ARTICLES: readonly FeaturedArticle[] = [ + { + id: 'zardui-beta-bringing-shadcnuis-philosophy-to-angular-where-you-own-every-line-of-code', + title: "ZardUI Beta: Bringing shadcn/ui's Philosophy to Angular - Where You Own Every Line of Code", + author: 'Samuel Rizzon', + url: 'https://dev.to/samuelrizzondev/zardui-beta-bringing-shadcnuis-philosophy-to-angular-where-you-own-every-line-of-code-2a79', + // `cover_image` is null on this one, so this is the `social_image` returned by the API. + cover: + 'https://media2.dev.to/dynamic/image/width=1000,height=500,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frusyrcfgg8m3axncu03f.png', + publishedAt: '2025-08-19', + readingTime: 4, + source: 'dev.to', + tags: ['webdev', 'angular', 'shadcn', 'opensource'], + language: 'en', + }, + { + id: 'building-fast-in-angular-with-zard-ui-tailwind-css-and-signals', + title: 'Building fast in Angular with Zard UI, Tailwind CSS and Signals', + author: 'hassantayyab', + url: 'https://dev.to/hassantayyab/building-fast-in-angular-with-zard-ui-tailwind-css-and-signals-cj5', + cover: + 'https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3pu9rhupvijjnc87n38n.png', + publishedAt: '2025-11-24', + readingTime: 4, + source: 'dev.to', + tags: ['webdev', 'angular', 'tailwindcss', 'typescript'], + language: 'en', + }, +]; diff --git a/apps/web/src/app/domain/pages/featured/featured.routes.ts b/apps/web/src/app/domain/pages/featured/featured.routes.ts index be9eefd24..79e903e51 100644 --- a/apps/web/src/app/domain/pages/featured/featured.routes.ts +++ b/apps/web/src/app/domain/pages/featured/featured.routes.ts @@ -10,4 +10,8 @@ export const FEATURED_ROUTES: Routes = [ path: 'youtube', loadComponent: () => import('./youtube/youtube.page').then(c => c.YoutubePage), }, + { + path: 'articles', + loadComponent: () => import('./articles/articles.page').then(c => c.ArticlesPage), + }, ]; diff --git a/apps/web/src/app/shared/constants/routes.constant.ts b/apps/web/src/app/shared/constants/routes.constant.ts index 9af3be9c4..a34f36c64 100644 --- a/apps/web/src/app/shared/constants/routes.constant.ts +++ b/apps/web/src/app/shared/constants/routes.constant.ts @@ -76,7 +76,7 @@ export const FEATURED_PATH: NavSection = { title: 'Featured', data: [ { name: 'YouTube', path: '/docs/featured/youtube', available: true }, - { name: 'Articles', path: '/docs/featured/articles', available: false }, + { name: 'Articles', path: '/docs/featured/articles', available: true }, ], }; From 6baa26a172fb8168dd672b87c72d0b005e80cf9c Mon Sep 17 00:00:00 2001 From: Luiz Gomes Date: Fri, 7 Aug 2026 19:23:33 -0300 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=92=84=20style(web):=20move=20Feature?= =?UTF-8?q?d=20to=20the=20end=20of=20the=20sidebar?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Featured lists community content, not API reference, so sitting between Get Started and Components broke the reading order of the sidebar. It now comes last, after Contribute. SIDEBAR_PATHS backs the sidebar, the mobile menu, the command palette and the sitemap, so all four follow the new order. Prerendered routes are unaffected. --- .../app/shared/constants/routes.constant.ts | 2 +- carousel-upgrade.md | 441 ------------------ 2 files changed, 1 insertion(+), 442 deletions(-) delete mode 100644 carousel-upgrade.md diff --git a/apps/web/src/app/shared/constants/routes.constant.ts b/apps/web/src/app/shared/constants/routes.constant.ts index a34f36c64..5270793e3 100644 --- a/apps/web/src/app/shared/constants/routes.constant.ts +++ b/apps/web/src/app/shared/constants/routes.constant.ts @@ -151,4 +151,4 @@ export const CONTRIBUTE_PATH: NavSection = { ], }; -export const SIDEBAR_PATHS: NavSection[] = [SECTIONS, DOCS_PATH, FEATURED_PATH, COMPONENTS_PATH, CONTRIBUTE_PATH]; +export const SIDEBAR_PATHS: NavSection[] = [SECTIONS, DOCS_PATH, COMPONENTS_PATH, CONTRIBUTE_PATH, FEATURED_PATH]; diff --git a/carousel-upgrade.md b/carousel-upgrade.md deleted file mode 100644 index 5f3a7b6e0..000000000 --- a/carousel-upgrade.md +++ /dev/null @@ -1,441 +0,0 @@ -eu necessito no momento atualizar o componente de carousel do zard/ui, a ideia seria atualizar ele utilizando o design atual do componente "original" do shadcn/ui, -a ideia nao e apenas atualizar o componente mas tambem atualizar seus exemplos e api table, para que se encaixe com o padrao completo do projeto ja que realizamos -diversas mudancas, a ideia aqui e conseguir seguir de forma completa por tanto voce devera inicialmente analisar o componente atual do zard e depois da uma olhada aqui -no codigo adicionado para que seja mais claro para voce como seguir passo a passo. - -primeiramente o caminho do arquivo completo para o gerenciamento do carousel.ts seria esse aqui: -C:\Users\ReckD\OneDrive\Documentos\GitHub\pessoal\zardui\libs\zard\src\lib\shared\components\carousel\demo\carousel.ts - -no carousel.ts voce tem titulo, descricao e etc a ideia e garantir uma facilidade minima no desenvolvimento de novas coisas, agora a lista de solicitacoes para esse update: - -1. comparar o componente atual com a sua versao "original" do shadcn/ui, a pricipio o principal aqui e comparar as classes do tailwind, pois algumas sao bem necessarias serem atualizadas, segue abaixo o codigo fonte do componente do shadcn/ui: - -``` -"use client" - -import * as React from "react" -import useEmblaCarousel, { - type UseEmblaCarouselType, -} from "embla-carousel-react" -import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react" - -import { cn } from "@/lib/utils" -import { Button } from "@/components/ui/button" - -type CarouselApi = UseEmblaCarouselType[1] -type UseCarouselParameters = Parameters -type CarouselOptions = UseCarouselParameters[0] -type CarouselPlugin = UseCarouselParameters[1] - -type CarouselProps = { - opts?: CarouselOptions - plugins?: CarouselPlugin - orientation?: "horizontal" | "vertical" - setApi?: (api: CarouselApi) => void -} - -type CarouselContextProps = { - carouselRef: ReturnType[0] - api: ReturnType[1] - scrollPrev: () => void - scrollNext: () => void - canScrollPrev: boolean - canScrollNext: boolean -} & CarouselProps - -const CarouselContext = React.createContext(null) - -function useCarousel() { - const context = React.useContext(CarouselContext) - - if (!context) { - throw new Error("useCarousel must be used within a ") - } - - return context -} - -function Carousel({ - orientation = "horizontal", - opts, - setApi, - plugins, - className, - children, - ...props -}: React.ComponentProps<"div"> & CarouselProps) { - const [carouselRef, api] = useEmblaCarousel( - { - ...opts, - axis: orientation === "horizontal" ? "x" : "y", - }, - plugins - ) - const [canScrollPrev, setCanScrollPrev] = React.useState(false) - const [canScrollNext, setCanScrollNext] = React.useState(false) - - const onSelect = React.useCallback((api: CarouselApi) => { - if (!api) return - setCanScrollPrev(api.canScrollPrev()) - setCanScrollNext(api.canScrollNext()) - }, []) - - const scrollPrev = React.useCallback(() => { - api?.scrollPrev() - }, [api]) - - const scrollNext = React.useCallback(() => { - api?.scrollNext() - }, [api]) - - const handleKeyDown = React.useCallback( - (event: React.KeyboardEvent) => { - if (event.key === "ArrowLeft") { - event.preventDefault() - scrollPrev() - } else if (event.key === "ArrowRight") { - event.preventDefault() - scrollNext() - } - }, - [scrollPrev, scrollNext] - ) - - React.useEffect(() => { - if (!api || !setApi) return - setApi(api) - }, [api, setApi]) - - React.useEffect(() => { - if (!api) return - onSelect(api) - api.on("reInit", onSelect) - api.on("select", onSelect) - - return () => { - api?.off("select", onSelect) - } - }, [api, onSelect]) - - return ( - -
- {children} -
-
- ) -} - -function CarouselContent({ className, ...props }: React.ComponentProps<"div">) { - const { carouselRef, orientation } = useCarousel() - - return ( -
-
-
- ) -} - -function CarouselItem({ className, ...props }: React.ComponentProps<"div">) { - const { orientation } = useCarousel() - - return ( -
- ) -} - -function CarouselPrevious({ - className, - variant = "outline", - size = "icon-sm", - ...props -}: React.ComponentProps) { - const { orientation, scrollPrev, canScrollPrev } = useCarousel() - - return ( - - ) -} - -function CarouselNext({ - className, - variant = "outline", - size = "icon-sm", - ...props -}: React.ComponentProps) { - const { orientation, scrollNext, canScrollNext } = useCarousel() - - return ( - - ) -} - -export { - type CarouselApi, - Carousel, - CarouselContent, - CarouselItem, - CarouselPrevious, - CarouselNext, - useCarousel, -} -``` - -2. atualizar a descricao da tela, para agora ser: "A carousel with motion and swipe built using Embla." -3. adicionar o exemplo preview, que vai seguir essa estrutura que ja esta na tipagem do projeto: - -``` - preview: { - name: 'preview', - component: ZardDemoCarouselPreviewComponent, - column: false, - codeData: Carousel_DEMO_PREVIEW, - }, -``` - -e dai o exemplo deve ser portado desse daqui do shadcn/ui: - -``` -import * as React from "react" - -import { Card, CardContent } from "@/components/ui/card" -import { - Carousel, - CarouselContent, - CarouselItem, - CarouselNext, - CarouselPrevious, -} from "@/components/ui/carousel" - -export function CarouselDemo() { - return ( - - - {Array.from({ length: 5 }).map((_, index) => ( - -
- - - {index + 1} - - -
-
- ))} -
- - -
- ) -} -``` - -o componente de card ja existe e seria esse aqui: C:\Users\ReckD\OneDrive\Documentos\GitHub\pessoal\zardui\libs\zard\src\lib\shared\components\card - -4.exemplo inicial vai ser o sizes: - -``` -import * as React from "react" - -import { Card, CardContent } from "@/components/ui/card" -import { - Carousel, - CarouselContent, - CarouselItem, - CarouselNext, - CarouselPrevious, -} from "@/components/ui/carousel" - -export function CarouselSize() { - return ( - - - {Array.from({ length: 5 }).map((_, index) => ( - -
- - - {index + 1} - - -
-
- ))} -
- - -
- ) -} -``` - -com a descricao: To set the size of the items, you can use the basis utility class on the . (obviamente adaptada ao contexto do zard) - -5. adicionar o exemplo do spacing: - -``` -import * as React from "react" - -import { Card, CardContent } from "@/components/ui/card" -import { - Carousel, - CarouselContent, - CarouselItem, - CarouselNext, - CarouselPrevious, -} from "@/components/ui/carousel" - -export function CarouselSpacing() { - return ( - - - {Array.from({ length: 5 }).map((_, index) => ( - -
- - - {index + 1} - - -
-
- ))} -
- - -
- ) -} -``` - -com a descricao: To set the spacing between the items, we use a pl-[VALUE] utility on the and a negative -ml-[VALUE] on the . - -6. adicionar o Orientation - -``` -import * as React from "react" - -import { Card, CardContent } from "@/components/ui/card" -import { - Carousel, - CarouselContent, - CarouselItem, - CarouselNext, - CarouselPrevious, -} from "@/components/ui/carousel" - -export function CarouselOrientation() { - return ( - - - {Array.from({ length: 5 }).map((_, index) => ( - -
- - - {index + 1} - - -
-
- ))} -
- - -
- ) -} -``` - -com a descricao: Use the orientation prop to set the orientation of the carousel. - -7. eu quero adicionar uma coisa no component page que vai ser mais uma propriedade chamada code after e code before, onde eu terei um block, um titulo e um description totalmente opcional e conforme eu passo os parametros eles vao aparecendo apos o item que existiver na ordem da listagem dos exemplos, dai o code after fica abaixo do exemplo e o code before fica antes do exemplo, mas com o code before ele de ver acima do exemplo porem abaixo da descricao do exemplo, beleza? dai esses blocks eles podem ter highlight de linha e etc. - -8. a opcao de adicionar um exemplo de apenas um code block mas sem codigo rodando, basicamente usar o code block para conseguir exibir um codigo com titulo e descricao que faça parte da estrutura da tela, mas que ainda seja possivel não usar o code block que renderiza o componente, pois essa ideia e apenas para exibir coisas muito especificas. - -9. adicionar a opcao de about que vai ser literalmente um titulo chamado about e uma descricao abaixo onde eu vou conseguir escrever um textinho e um link para que eu possa referenciar a lib no projeto, ok? pois alguns componentes utilizam bibliotecas externas.