Skip to main content

Content blocks

Aris comes with many content blocks (or designed blocks) which helps you to present your data/information in pages, blog post or any places you want to.

Alert

Type declaration
type AlertProps = {
alertType?: AlertTagColor
alignment?: "left" | "right"
className?: string
hasShadow?: boolean
children: React.ReactNode
/**
* make your alert looks `art` when skew to the left or to the right
*/
art?: "right" | "left"
}

type AlertTagColor = number | "gray" | "blue" | "red" | "yellow" | "green" | "random" | "info" | "success" | "warning" | "error"
import Alert from "~/components/Alert"

<Alert alertType="warning">
Lorem ipsum dolor sit amet, consectetur adip locales justifying information
</Alert>

Align

Type declaration
type AlignProps = {
alignment?: "left" | "right" | "2Columns" | "expanded"
className?: string
children: React.ReactNode
}
import Align from "~/components/Align"

<Align alignment="2Columns">
Occaecat commodo ullamco nisi exercitation magna dolore et. Aliqua proident nisi ea fugiat et velit cupidatat. Fugiat incididunt aute eu cillum in in amet cupidatat laborum. Minim reprehenderit esse irure culpa. Officia anim pariatur tempor irure.

Amet dolore cillum dolore officia sit eiusmod aliqua Lorem sit excepteur ullamco ea. Eu velit id in Lorem labore voluptate ea non deserunt sit in labore. Dolor cillum nostrud exercitation adipisicing irure..
</Align>

Facts

Type declaration
type FactsProps = {
facts: FactsGroup
langTable: LangTable
}

type FactsGroup = {
title?: string
description?: string
facts: FactItem[]
}

type FactItem = {
quantity: number,
title: string
imageUrl?: string
}
import Facts from "~/components/Facts"

<Facts
facts={factsInAbout}
langTable={factsLangTable}
/>

FaqsBlock

Type declaration
type FaqsBlockProps = {
faqs: FAQs[],
langTable: LangTable
/**
* if FaqsBlock is `standalone`, it only display list of questions and answers
* without `title` and `description`
*/
standalone?: boolean
}

type FAQs = {
question: string
answer: string
expanded?: boolean
additional?: {
question?: string[]
answer?: string[]
}
}
import FaqsBlock from "~/components/Faqs"

<FaqsBlock
langTable={faqsServicesLangTable}
faqs={faqsServices}
/>

Features

Features.Simplicity

Type declaration
type FeaturesSimplicityProps = {
features: TFeatures
langTable: LangTable
}
import Features from "~/components/Features"

<Features.Simplicity
features={mySkills}
langTable={skillsLangTable}
/>

Features.Blocks

Type declaration
type FeaturesBlocksProps = {
features: TFeatures
langTable: LangTable
}
import Features from "~/components/Features"

<Features.Blocks
features={mySkills}
langTable={skillsLangTable}
/>

Features.Picture

Type declaration
type FeaturesPictureProps = {
features: TFeatures
langTable: LangTable
/**
* swap `left to right` and `right to left`
*/
reverse?: boolean
}
import Features from "~/components/Features"

<Features.Picture
features={mySkills}
langTable={skillsLangTable}
/>

Features.Art

Type declaration
type FeaturesArtProps = {
features: TFeatures
langTable: LangTable
/**
* swap
*/
reverse?: boolean
}
import Features from "~/components/Features"

<Features.Art
features={mySkills}
langTable={skillsLangTable}
/>

Highlight

Type declaration
type HighlightProps = {
/**
* background color
*/
color?: string,
/**
* text color
*/
text?: string,
children: React.ReactNode
}
import Highlight from "~/components/Highlight"

<Highlight>3rd article</Highlight>

<Highlight color="blue" text="white">
3rd article
</Highlight>
Sed ut perspiciatis <Highlight>3rd article</Highlight> unde omnis iste natus error sit voluptatem <Highlight color="blue" text="white">doloremque</Highlight> doloremque laudantium, totam rem aperiam, eaque ipsa quae ab illo <Highlight color="yellow" text="black">explicabo</Highlight> veritatis et quasi architecto beatae vitae dicta sunt explicabo.

Image

Display a image based on screen size. mobile for screen size >= 640px. desktop for screen size > 640px.

Type declaration
type ImageProps = JSX.IntrinsicElements["img"] & {
srcList: ImgSrcSet,
rounded?: "sm" | "md" | "lg" | "xl" | "2xl"
wfull?: boolean,
hfull?: boolean
}

type ImgSrcSet = {
mobile: string
desktop?: string
description?: string
}
import Image from "~/components/Image"

<Image
srcList={image}
className="bg-slate-100 w-full"
alt=""
/>

LatestBlogPosts

Type declaration
type LatestBlogPostsProps = {
showTitle?: boolean
display?: Display
/**
* max is 6
*/
limit?: number,
showAsColumn?: boolean
}
import LatestBlogPosts from "~/components/LatestBlogPosts"

<LatestBlogPosts
display={["image", "description"]}
limit={2}
showAsColumn
/>

LatestContent

You can extract and display latest update by block or by link

Type declaration
/**
* LatestContent.Note
* LatestContent.Update
* LatestContent.Announcement
*/
type LatestBlockProps = { alignment?: "left" | "right" }

/**
* LatestContent.NotesLink
* LatestContent.UpdateLink
* LatestContent.AnnouncementLink
*/
type LatestLinkProps = {/* empty */}
import LatestContent from "~/components/LatestContent"

<LatestContent.Note />
<LatestContent.Update />
<LatestContent.Announcement />

<LatestContent.NotesLink />
<LatestContent.AnnouncementLink />
<LatestContent.UpdateLink />
View latest announcement <LatestContent.AnnouncementLink /> for details.

LatestPortfolio {#latest-portfolio}}

Type declaration
type LatestPortfolioProps = {
showTitle?: boolean
display?: Display
limit?: number
}
import LatestPortfolio from "~/components/LatestPortfolio"

<LatestPortfolio
display={["image", "description"]}
limit={2}
/>

If you want a link, let you use Link component. Or if the target is internal links, you must use this component, or multi-language feature not working.

Type declaration
type LinkProps = {
to: string
className?: string
children: string
}
import Link from "~/components/Link"

<Link to="/blog">Blog</Link>
Type declaration
type LinksGridProps = {
links: LinkMeta[]
className?: string
}

type LinkMeta = {
/**
* if you set a type for a link
* we will show an icon for the link (default icon)
* if you don't set imageUrl.
*/
type?: LinkMetaType
title: string,
description?: string
slug: string,
iconPicture?: string,
decoration?: {
/**
* we will fill gradient the background
* 1st & 2nd is background gradient
* 3rd is text-color
*/
backgroundColor?: [string, string, string]
isTextCenter?: boolean
isBold?: boolean
isItalic?: boolean
isDownloadable?: boolean
}
}
imort LinksGrid from "~/components/LinksGrid"

<LinksGrid links={linksGrid} />
Type declaration
type LinksListProps = {
links: LinkMeta[]
className?: string
}

type LinkMeta = {
/**
* if you set a type for a link
* we will show an icon for the link (default icon)
* if you don't set imageUrl.
*/
type?: LinkMetaType
title: string,
description?: string
slug: string,
iconPicture?: string,
decoration?: {
/**
* we will fill gradient the background
* 1st & 2nd is background gradient
* 3rd is text-color
*/
backgroundColor?: [string, string, string]
isTextCenter?: boolean
isBold?: boolean
isItalic?: boolean
isDownloadable?: boolean
}
}
import LinksList from "~/components/LinksList"

<LinksList links={linksList}/>

Map

Map component allows you to show a map and you can also add many custom marker. When hovering over a marker, it information would be display on the top right of the map.

Type declaration
type MapProps = {
markers: TMarker[]
/**
* zoom is from `4` to `18`
*/
defaultZoom?: number
defaultCenter?: Point
hasPadding?: boolean
alignment?: "left" | "right" | "expanded"
}

export type TMarker = {
width?: number
color?: string
anchor: Point
slug?: string
title?: string
description?: string
/**
* title and description would be displayed
* as if the marker is on hover if `isDefault` is true
* Tip: only set 1 marker with `isDefault = true`
*/
isDefault?: boolean
}

/**
* [latitude, longitude]
*/
export type Point = [number, number]
import Map from "~/components/Map"

<Map
alignment="expanded"
defaultCenter={[10.8161863, 106.7782831]}
defaultZoom={16}
hasPadding={true}
markers={myMarkers}
/>

Markdown

Type declaration
type MarkdownProps = {
maxWidth?: "md" | "lg" | "xl"
textSize?: "md" | "lg" | "xl"
/**
* by the fault, the spacing between h1, h2 & h3 is big
* some cases, we need to decrease the spacing for
* some inner block of text
*/
compact?: boolean
/**
* split the text into 2 columns
*/
twoColumns?: boolean,
}
import Markdown from "~/components/Markdown"

<Markdown markdown={`
# H1

**Lorem** ipsum dolor \`sit\` amet, consectetur adipisicing elit, sed do **eiusmod** tempor incididunt ut labore.

| |ASCII |HTML |
|----------------|-------------------------------|-----------------------------|
|Single backticks|\`'Isn't this fun?'\` |'Isn't this fun?' |
|Quotes |\`"Isn't this fun?"\` |"Isn't this fun?" |
|Dashes |\`-- is en-dash, --- is em-dash\`|-- is en-dash, --- is em-dash|

`}
/>

Picture

Display a single picture

Type declaration
type PictureProps = {
className?: string
alt?: string
src: string
alignment?: "left" | "right" | "expanded"
rounded?: "sm" | "md" | "lg" | "xl" | "2xl"
/**
* By the default, when alignment is left or right, the width would be 1/2
* Some cases, you want it to be smaller, which is 1/3
*/
oneThird?: boolean
}
import Picture from "~/components/Picture"

<Picture
src="/img/background/placeholder.svg"
alt="image's description"
expand
/>

PricingTable

Type declaration is the same for all PriceTable components PricingTable.List, PricingTable.TwoColumn and PricingTable.ThreeColumn

PricingTable.List

Type declaration
type PricingTableListProps = {
pricingData: PricingData,
langTable: LangTable
}

type PricingData = {
title: string
description: string
defaultPriceType: PricingType
packages: PricingPackage[]
/**
* if this data is provided, the pricing table would have
* a list of features listed on the left
* by this time, the size of `featuresHeading` must equal to `packages.features`
*/
featuresHeadering?: string[]
currencyConversion: {
[key in Language]: {
ratio: number
rounding: number
}
}
}

type PricingType = "fixed" | "monthly" | "yearly" | "lifetime"

type PricingPackage = {
name: string
pricing: { type: PricingType, value: number }[]
features: { featureName: string, bulletType: BulletType, quantity?: number }[]
isPopular?: boolean
buttonText?: string
link: string
}

type BulletType = "none" | "available" | "unavailable"
import PricingTable from "~/components/PricingTable"

<PricingTable.List
pricingData={pricingList}
langTable={servicesLangTable}
/>

PricingTable.TwoColumn

Type declaration
/* The same with `PricingTable.List` */
import PricingTable from "~/components/PricingTable"

<PricingTable.TwoColumn
pricingData={pricing2Column}
langTable={servicesLangTable}
/>

PricingTable.ThreeColumn

Type declaration
/* The same with `PricingTable.List` */
import PricingTable from "~/components/PricingTable"

<PricingTable.ThreeColumn
pricingData={pricing3Column}
langTable={servicesLangTable}
/>

Resume

Resume.Experience

Type declaration
type ResumeExperienceProps = {
resume: ResumeExperience
langTable: LangTable
}

type ResumeExperience = {
title: string
description?: string
items: {
logoUrl: string
jobTitle: string
companyName: string
location: string
contractType: ContractType
startDate: string
endDate: string
description: MarkdownText
}[]
}

export type ContractType = "full-time" | "part-time" | "freelance"

/**
* Why don't we set it as `string` type but `MarkdownText = string`
* That's because we want to indicate that.. we can use markdown text
* in this field.
*/
export type MarkdownText = string
import Resume from "~/components/Resume"

<Resume.Experience
resume={experiences}
langTable={resumeLangTable}
/>

Resume.Education

Type declaration
type ResumeEducationProps = {
resume: ResumeEducation
langTable: LangTable
}

type ResumeEducation = {
title: string
description?: string
items: {
logoUrl: string
major: string
schoolName: string
location: string
startDate: string
endDate: string
}[]
}
import Resume from "~/components/Resume"

<Resume.Education
resume={education}
langTable={resumeLangTable}
/>

Slider

Type declaration
type SliderProps = {
images: ImgSrcSet[]
autoPlay?: boolean
showThumbs?: boolean
alignment?: "left" | "right" | "expanded"
}

type ImgSrcSet = {
mobile: string
desktop?: string
description?: string
}
import Slider from "~/components/Slider"

<Slider
alignment="expanded"
images={mySlides}
/>

Testimonials

Type declaration
type TestimonialsProps = {
testimonials: TestimonialsGroup,
langTable: LangTable
}

type TestimonialsGroup = {
title?: string
description?: string
testimonials: TestimonialItem[]
}

type TestimonialItem = {
name: string
title: string
imageUrl?: string
content: MarkdownText
}
import Testimonials from "~/components/Testimonials"

<Testimonials
testimonials={testimonials}
langTable={testimonialsLangTable}
/>

Translate

Type declaration
type TranslateProps = {
lang: Language
children: React.ReactNode
}
//this block only display when current selected language is `en`
<Translate lang="en">
Hello world
</Translate>

//this block only display when current selected language is `vi`
<Translate lang="vi">
Xin chào!
</Translate>

Video

Video.Youtube

Embed youtube video.

Type declaration
type VideoYoutubeProps = {
/**
* `id` of the video or playlist
* eg: https://www.youtube.com/watch?v=8kV8KVWZYaw&list=PLCzpHpwST0xx8IxDzF82Va_rhIEcpbgW5
* you can use `8kV8KVWZYaw` or `PLCzpHpwST0xx8IxDzF82Va_rhIEcpbgW5`
*/
id: string
params?: string
/**
* `id` of any video within the playlist, to get the cover
*/
playlistCoverId?: string
/**
* title of the video
*/
title: string
alignment?: "left" | "right" | "expanded"
}
import Video from "~/components/Video"

<Video.Youtube
id="PLCzpHpwST0xx8IxDzF82Va_rhIEcpbgW5"
playlistCoverId="F90ozD7peX0"
title="Phương Ý"
alignment="expanded"
/>

Video.Local

Play your local video files.

Type declaration
type VideoLocalProps = {
src: string
autoPlay?: boolean
loop?: boolean
muted?: boolean
aspectRatio?: string
className?: string
}
import Video from "~/components/Video"

<Video.Local
src="video.mp4"
autoPlay
loop
/>