DS Prototype Template uses the Ankorstore Design System (v28) as its exclusive component library. This guide covers component usage, design tokens, styling patterns, and responsive design.
All interactive UI elements must use Ak* prefixed components from @ankorstore/design-system. Components are globally registered; no imports needed.
- AkInput — Text input field
- AkSelect — Dropdown selection
- AkCheckbox — Checkbox toggle
- AkRadio — Radio button group
- AkToggle — Boolean toggle switch
- AkButton — Primary action button
- AkLink — Navigation link (looks like text)
- AkIcon — Icon display (from DS icon library)
- AkTable — Tabular data with columns
- AkBadge — Status/tag indicator
- AkPill — Rounded tag label
- AkBreadcrumb — Navigation breadcrumb trail
- AkAlert — Informational message
- AkBanner — Page-level announcement
- AkModal — Dialog modal
- AkPagination — Page control
- AkSkeleton — Loading placeholder
- AkLogoAKS — Full logo
- AkLogoAKSSymbol — Icon/symbol only
<!-- Primary action -->
<AkButton color="primary" size="md" @click="handleSave">Save</AkButton>
<!-- Secondary action -->
<AkButton outlined color="primary" size="md">Cancel</AkButton>
<!-- Success action -->
<AkButton color="success" size="lg">Confirm</AkButton>
<!-- Error action -->
<AkButton color="error" size="lg">Delete</AkButton>
<!-- Icon only -->
<AkButton onlyIcon symbol="edit" size="md" color="white" />
<!-- Loading state -->
<AkButton loading color="primary">Processing...</AkButton>
<!-- Disabled -->
<AkButton disabled color="primary">Disabled</AkButton>Available Props:
color—primary|error|white|success|success-alt|orderpaysize—md|lg|xloutlined— BooleanonlyIcon— Boolean (icon-only button)loading— Booleandisabled— Booleansymbol— Icon name (see icon reference below)
Event: @click
<!-- Basic text input -->
<AkInput v-model="name" label="Full Name" placeholder="Enter your name..." />
<!-- Email input -->
<AkInput v-model="email" label="Email" type="email" placeholder="you@example.com" />
<!-- Password input -->
<AkInput v-model="password" label="Password" type="password" />
<!-- Search with icon -->
<AkInput v-model="search" placeholder="Search..." iconLeft="search" />
<!-- Disabled -->
<AkInput disabled label="Read Only" value="Cannot edit" />
<!-- With error state -->
<AkInput v-model="input" label="Field" error="This field is required" />Available Props:
type—text|email|number|password|search|tel|url|datelabel— Field labelplaceholder— Placeholder texticonLeft— Icon before inputdisabled— Booleanerror— Error message string (shows error state)required— Boolean
Event: v-model (two-way binding)
<AkSelect
v-model="selectedStatus"
:options="[
{ label: 'Pending', value: 'pending' },
{ label: 'Confirmed', value: 'confirmed' },
{ label: 'Shipped', value: 'shipped' },
]"
label="Order Status"
placeholder="Choose status..."
@change="onStatusChange"
/>Available Props:
options— Array of{ label: string, value: any }label— Field labelplaceholder— Placeholder textdisabled— Booleanmultiple— Boolean (allow multiple selections)
Event: @change | v-model
<AkTable
:columns="[
{ name: 'reference', label: 'Reference', width: '150px', align: 'left' },
{ name: 'brand', label: 'Brand', width: '200px' },
{ name: 'status', label: 'Status', width: '100px', align: 'center' },
{ name: 'total', label: 'Total', width: '100px', align: 'right' },
]"
:data="orders"
:border="true"
:rowStyles="['hover']"
@rowClick="selectOrder"
>
<!-- Custom cell template -->
<template #item.status="{ item }">
<AkBadge :content="item.status" :color="statusColors[item.status]" size="sm" />
</template>
<!-- Custom header template -->
<template #column.reference>
<span style="font-weight: 600;">Order Ref</span>
</template>
</AkTable>Available Props:
columns— Array of column config:{ name: string, label: string, width?: string, align?: 'left'|'center'|'right' }data— Array of row objectsborder— Boolean (show borders)rowStyles— Array of styles:['hover'],['striped']
Slots:
#item.[columnName]="{ item }"— Custom cell content#column.[columnName]— Custom header content
Event: @rowClick="handler" → receives row object
<!-- Status badge -->
<AkBadge content="Active" color="green" size="sm" />
<!-- Badge with icon -->
<AkBadge content="Warning" color="orange-full" size="xs" symbol="clock" />
<!-- Red badge (error) -->
<AkBadge content="Cancelled" color="red" size="md" />Available Props:
content— Badge textcolor—blue|green|grey|orange|purple|red(add-fullfor solid variants)size—xs|sm|md|lgsymbol— Optional icon name
<!-- Info alert -->
<AkAlert type="info" title="Note">This is informational content.</AkAlert>
<!-- Success alert -->
<AkAlert type="success" title="Done" closable @close="onClose">Your order has been saved!</AkAlert>
<!-- Warning alert -->
<AkAlert type="warning" title="Attention">Please review before proceeding.</AkAlert>
<!-- Error alert -->
<AkAlert type="error" title="Error">Something went wrong. Please try again.</AkAlert>Available Props:
type—info|success|warning|error|discount|neutraltitle— Alert titleclosable— Boolean (show close button)
Event: @close (when user closes)
<AkPagination
:currentPage="page"
:lastPage="totalPages"
@change="page = $event"
/>Available Props:
currentPage— Current page number (1-based)lastPage— Total number of pages
Event: @change="handler" → receives new page number
<!-- Confirmation modal -->
<AkButton @click="$refs.confirmModal.openModal()">Delete</AkButton>
<AkModal
ref="confirmModal"
size="md"
titleContent="Confirm Delete"
validateButtonText="Delete"
validateButtonColor="error"
cancelButtonText="Cancel"
@validated="onDelete"
@cancel="onCancel"
>
<p>This action cannot be undone.</p>
</AkModal>Available Props:
size—sm|md|lg|xl|fulltitleContent— Modal titlevalidateButtonText— Confirm button textvalidateButtonColor— Button colorcancelButtonText— Cancel button text
Methods:
openModal()— Show modalcloseModal()— Hide modal
Events: @validated | @cancel
<!-- Small icon -->
<AkIcon symbol="home" size="sm" />
<!-- Medium icon -->
<AkIcon symbol="search" size="md" />
<!-- Large icon -->
<AkIcon symbol="edit" size="lg" />Available Props:
symbol— Icon name (see icon reference below)size—sm|md|lg
- Navigation:
home,list,grid,search,settings - Actions:
plus,edit,trash,download,upload,share - Status:
check,close,clock,alert,info - Navigation:
chevron-left,chevron-right,chevron-up,chevron-down - Commerce:
cart,shop-window,graph-up,bell,heart
See src/llms-component-catalog.md for complete icon list.
/* 1rem = 16px (browser default) */
--space-0: 0rem /* 0px */
--space-0-5: 0.125rem /* 2px */
--space-1: 0.25rem /* 4px */
--space-2: 0.5rem /* 8px */
--space-3: 0.75rem /* 12px */
--space-4: 1rem /* 16px */ ← Most common
--space-5: 1.5rem /* 24px */ ← Common for sections
--space-6: 2rem /* 32px */
--space-8: 4rem /* 64px */Usage:
<!-- Padding -->
<div style="padding: var(--space-4);">Content</div>
<!-- Margin -->
<div style="margin-bottom: var(--space-5);">Section</div>
<!-- Gap (flexbox) -->
<div style="display: flex; gap: var(--space-3);">Items</div>/* Font sizes with line heights */
--text-xs: 0.75rem /* 12px */
--text-sm: 0.875rem /* 14px */
--text-base: 1rem /* 16px */ ← Default
--text-lg: 1.125rem /* 18px */
--text-xl: 1.25rem /* 20px */
--text-2xl: 1.5rem /* 24px */
--text-3xl: 1.75rem /* 28px */
--text-4xl: 2.25rem /* 36px */
--text-5xl: 2.5rem /* 40px */
/* Line heights follow TypeScript convention */
--leading-xs: 1rem
--leading-sm: 1.25rem
--leading-base: 1.5rem
--leading-lg: 1.5rem
--leading-xl: 1.75rem
--leading-2xl: 2remUsage:
<style scoped>
h1 {
font-size: var(--text-3xl);
line-height: var(--leading-3xl);
}
p {
font-size: var(--text-base);
line-height: var(--leading-base);
}
.small-text {
font-size: var(--text-sm);
line-height: var(--leading-sm);
}
</style>--radius-xs: 3px
--radius-sm: 4px
--radius-md: 8px ← Most common
--radius-lg: 16px
--radius-xl: 32px
--radius-2xl: 48pxUsage:
<style scoped>
.card {
border-radius: var(--radius-md);
}
.button {
border-radius: var(--radius-sm);
}
.avatar {
border-radius: 50%; /* Circle */
}
</style>--font-family: 'Poppins', sans-serifUsage:
<style scoped>
* {
font-family: var(--font-family); /* Already applied globally */
}
</style>Colors are auto-loaded from @ankorstore/design-system/dist/design-system.css
Primary Brand Colors:
--color-primary: #14060A(dark purple/black)--color-white: #FFFFFF
Neutral Scale:
--color-neutral-100: #F9F9F9(very light gray, backgrounds)--color-neutral-200: #F0F0F0(light gray, dividers)--color-neutral-700: #808080(dark gray, text)--color-neutral-900: #4D4D4D(very dark gray, headings)
Status Colors:
--color-error-700: #DE043C(red)--color-success-700: #557566(green)--color-info-700: #0B00F4(blue)
Usage:
<style scoped>
.error {
color: var(--color-error-700);
}
.success {
color: var(--color-success-700);
}
.card {
background-color: var(--color-neutral-100);
}
</style><div style="display: flex; flex-direction: column; gap: var(--space-4);">
<h2>Title</h2>
<p>Paragraph</p>
<AkButton>Action</AkButton>
</div><div style="display: flex; align-items: center; gap: var(--space-3);">
<AkIcon symbol="check" />
<span>Success message</span>
</div><div style="
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: var(--space-4);
">
<div class="card">Item 1</div>
<div class="card">Item 2</div>
<div class="card">Item 3</div>
</div><div style="
background-color: var(--color-neutral-100);
border-radius: var(--radius-md);
padding: var(--space-5);
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
">
<h3>Card Title</h3>
<p>Card content</p>
</div><div style="
display: flex;
gap: var(--space-3);
align-items: flex-end;
margin-bottom: var(--space-5);
">
<AkInput
v-model="search"
placeholder="Search..."
iconLeft="search"
style="flex: 1;"
/>
<AkSelect v-model="status" :options="statusOptions" />
<AkButton outlined>Reset</AkButton>
</div><AkTable :columns="columns" :data="items">
<template #item.status="{ item }">
<AkBadge
:content="item.status"
:color="statusColors[item.status]"
size="sm"
/>
</template>
</AkTable><div style="
display: flex;
flex-direction: column;
gap: var(--space-4);
max-width: 500px;
">
<AkInput v-model="name" label="Name" required />
<AkInput v-model="email" label="Email" type="email" required />
<AkSelect v-model="role" label="Role" :options="roleOptions" />
<div style="display: flex; gap: var(--space-3);">
<AkButton color="primary">Save</AkButton>
<AkButton outlined>Cancel</AkButton>
</div>
</div>| Name | Width | Use Case |
|---|---|---|
xs |
480px | Mobile (phones) |
sm |
640px | Mobile (large phones) |
md |
768px | Tablets |
lg |
1024px | Laptops |
xl |
1280px | Desktops |
2xl |
1600px | Large displays |
<style scoped>
/* Default: mobile (xs) */
.grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-4);
}
/* Tablets and up */
@media (min-width: 768px) {
.grid {
grid-template-columns: 1fr 1fr;
}
}
/* Laptops and up */
@media (min-width: 1024px) {
.grid {
grid-template-columns: 1fr 1fr 1fr;
}
}
</style><!-- Scrollable on mobile -->
<div style="overflow-x: auto;">
<AkTable :columns="columns" :data="items" />
</div>
<style scoped>
@media (max-width: 768px) {
/* Stack columns vertically on mobile */
/* (Note: requires custom component wrapper) */
}
</style>- Design System components meet WCAG 2.1 Level AA
- Don't rely on color alone; use icons + labels
- Test with contrast checker if adding custom colors
- All Ak* components support keyboard navigation
- Ensure tab order is logical
- Focus styles provided by DS
- Use AkButton for actions (not divs)
- Use AkLink for navigation (not divs)
- Use AkInput for text input (not divs)
- Use AkTable for tabular data (not divs)
- Use
labelprop on AkInput and AkSelect - AkTable columns have accessible headers
- Modal titles via
titleContentprop
DS v28 does not include built-in dark mode. If needed in future:
- Add CSS custom properties for dark color scheme
- Toggle via
prefers-color-schememedia query - Or add manual theme toggle
<!-- WRONG -->
<button @click="save">Save</button>
<input v-model="search" />
<table><!-- data --></table>
<!-- CORRECT -->
<AkButton @click="save">Save</AkButton>
<AkInput v-model="search" />
<AkTable :data="items" :columns="cols" /><!-- WRONG -->
<style scoped>
.card {
padding: 16px;
margin: 24px 0;
border-radius: 8px;
}
</style>
<!-- CORRECT -->
<style scoped>
.card {
padding: var(--space-4);
margin: var(--space-5) 0;
border-radius: var(--radius-md);
}
</style><!-- WRONG (Tailwind removed) -->
<style scoped>
.card {
@apply p-4 m-5 rounded-md;
}
</style>
<!-- CORRECT -->
<style scoped>
.card {
padding: var(--space-4);
margin: var(--space-5);
border-radius: var(--radius-md);
}
</style>// WRONG
// src/styles/global.css
body {
padding: 20px; // Will affect all pages
}
// CORRECT: Use scoped styles or design-tokens.css
// scoped in AppLayout.vue insteadLast Updated: 2026-03-27 Design System: Ankorstore v28 Component Registration: Global (no imports needed)