trendyol / baklava Goto Github PK
View Code? Open in Web Editor NEWBaklava is a design system provided by Trendyol to create a consistent UI/UX for app users.
Home Page: https://baklava.design/
License: MIT License
Baklava is a design system provided by Trendyol to create a consistent UI/UX for app users.
Home Page: https://baklava.design/
License: MIT License
General usage example:
<bl-pagination current-page=1 total-items=200 items-per-page=5 ></bl-pagination>
bl-pagination
componentPagination component is for listing the pages to the users and redirecting them between pages.
Attribute | Description | Default Value |
---|---|---|
current-page (number ) |
Sets the current page | 1 |
total-items (number ) |
Total number of data to be paginated | - |
items-per-page (number ) |
Sets the number of items per page | 100 |
has-jumper (boolean ) |
Adds a jumper input to the pagination | false |
has-select (boolean ) |
Adds select component to let users choose the result per page | false |
jumper-label (string ) |
Sets the jumper label | Go To |
select-label (string ) |
Sets select label | Show |
option-text (string ) |
Sets the option texts of the select element | Items |
Event | Description | Data |
---|---|---|
bl-change |
Fires everytime user selects a page | ( {selectedPage,prevPage}) |
It makes sense to be able to play with CSS property values of the components in Storybook as well as regular component properties. Apparently, there is already a plugin for that: https://storybook.js.org/addons/@ljcl/storybook-addon-cssprops Let's try it.
Currently, our main file in CDN fetches and registers all of the components immediately. It's also possible to hand pick components by users to only download and use them like:
<script type="module" src="https://cdn.jsdelivr.net/npm/@trendyol/[email protected]/dist/components/button/bl-button.js"></script>
But the idea in this issue is to check the possibility and feasibility of lazy loading components dynamically once they are used in the DOM. In this case, user will just include the main file (or another main file for the lazy loading approach) as always. But this time, instead of downloading and registering all of the components, the library will register a placeholder component for all of our components. And this placeholder component will load the actual one in its connectedCallback
method. In theory, this will prevent downloading most part of the library on landing pages since, most of the time, a single page use a small part of the all components.
But there are some points we need to consider here:
General usage example:
<bl-checkbox checked disabled>single checkbox</bl-checkbox>
Indeterminate
state can be use with a single checkbox.bl-checkbox
CSS properties. Like<style>
.checkbox-new {
--bl-color-primary: rebeccapurple;
}
</style>
<bl-checkbox class="checkbox-new">new label</bl-checkbox>
bl-checkbox
componentCheckbox component handles interaction to change checked/unchecked states.
Attribute | Description | Default Value |
---|---|---|
checked (boolean ) |
Sets checkbox checked. By default checkbox is unchecked | false |
disabled (boolean ) |
Sets checkbox disabled | - |
indeterminate (boolean ) |
Sets checkbox indeterminate | - |
Name | Description | Default Content |
---|---|---|
default slot |
label | - |
Event | Description |
---|---|
bl-checkbox-change |
Will be triggered when checkbox clicked ( event.target.checked ) |
bl-notification
ImplementationGeneral usage example:
<bl-notification
no-animation
duration="7"
></bl-notification>
<script>
const el = document.querySelector("bl-notification");
const addedNotification = el.addNotification({
caption: "Notification Caption",
description: "This is a notification",
variant: "warning",
icon: "academy",
primaryAction: {
label: "Action",
onClick: notification => {
notification.remove();
},
},
secondaryAction: {
label: "Action",
onClick: async notification => {
await notification.remove();
first.remove();
},
},
});
// some actions
addedNotification.remove();
// or
el.removeNotification(addedNotification.id);
</script>
duration
attribute sets the default duration of notifications when not provided.no-animation
attribute disables animation of notifications. Animations will respect the user's preferences regardless of this property.Notification component acts as an interface that will manage notifications. It has two methods to add and remove notifications.
Attribute | Description | Default Value |
---|---|---|
duration (number ) |
Sets the default duration of notifications in seconds when not provided | 7 |
no-animation (boolean ) |
Disables animation of notifications | false |
Method | Description | Parameters | Return Value |
---|---|---|---|
addNotification |
Adds a notification to the notification list | BlNotificationCard Props | The added notification object with remove method |
removeNotification |
Async method that removes a notification from the notification list after the animation is finished | Notification ID | A promise that resolves when the animation is finished |
bl-notification-card
ImplementationGeneral usage example:
<bl-notification-card
caption="Caption"
icon
variant="error"
permanent
duration="7"
closed
@bl-notification-card-request-close
@bl-notification-card-close
>
Lorem ipsum dolor sit amet consectetur adipisicing elit.
<bl-button slot="primary-action">Action</bl-button>
<bl-button slot="secondary-action">Secondary Action</bl-button>
</bl-notification-card
duration
attribute sets the duration of the notification in seconds. When the duration is over, the notification will be dismissed automatically.permanent
attribute makes the notification permanent and it will not be dismissed automatically. User can still dismiss it manually.closed
attribute makes the notification closed and it will not be displayed.caption
attribute sets the caption of the notification.icon
attribute sets the icon of the notification. Either boolean or icon name can be provided. True value will use bl-alert
default.variant
attribute sets the variant of the notification. Possible values are info
, success
, warning
, error
.primary-action
slot will be displayed as a primary action button.secondary-action
slot will be displayed as a secondary action button.bl-notification-card-request-close
event will be fired when the notification is requested to be closed. If default prevented, the notification will not be closed.bl-notification-card-close
event will be fired when the notification is closed.Notification card component is a component that will be used to display notifications.
Attribute | Description | Default Value |
---|---|---|
duration (number ) |
Sets the duration of the notification in seconds | 7 |
permanent (boolean ) |
Makes the notification permanent and it will not be dismissed automatically | false |
closed (boolean ) |
Makes the notification closed and it will not be displayed | false |
caption (string ) |
Sets the caption of the notification | "" |
icon (string ) |
Sets the icon of the notification | "" |
variant (string ) |
Sets the variant of the notification | "" |
Slot | Description |
---|---|
default |
Will be displayed as the description of the notification |
primary-action |
Will be displayed as a primary action button |
secondary-action |
Will be displayed as a secondary action button |
Event | Description | Detail |
---|---|---|
bl-notification-card-request-close |
Fired when the notification is requested to be closed | { source: "duration-ended" / "close-button" } |
bl-notification-card-close |
Fired when the notification is closed | { source: "duration-ended" / "close-button" } |
We are using npm ci
to install all the dependencies. It uses only package lock file, so npm can skip the first steps (you can find more detailed information here). It does clean install, in other words deletes node_modules
. However, we can cache ~/.npm
to prevent redownloading all this stuff.
We'll use commitlint with contenional commit format.
This is an epic issue for tracking the roadmap to the first stable version of Baklava (previously named as Grace).
After using Grace as one of the UI libraries inside Trendyol, now we decided having some major changes in next version because of some new requirements:
Project evolved from a UI library to a Design System to cover more generic use-cases then some specific areas inside Trendyol.
Grace V2 will be a "web component" library written with Lit. The main motivation behind this decision is that we (in Trendyol) want to use the same UI library and design guidelines in both Vue and React projects.
We want to maintain Grace project with regular open-source principles, fully managed in GitHub. So contribution guidelines, documentation, release pipelines will be more transparent and clear.
One of the main purposes of Baklava Design System is to provide fully accessible UI elements. This will help to improve A11y all of our projects in Trendyol without repeating work.
We'll focus on automating releases, tests, documentation generation, PR workflows, and so on, so we'll allow getting more contributions without blocking anyone because of a lack of human resources.
We are using next
branch for the development of version 2. We'll fully re-write components with a refreshed design in this branch, then we'll release the first stable release of V2. On the road, we'll be able to start using alpha/beta releases.
After creating core parts of the new version, we'll expect contributions to finish implementing all of the needed components in the new version.
We'll publish the library to CDN(s) as well as the NPM registry. We plan to promote consuming Grace V2 via CDN since this will give so much benefit for our users to cache the library on the browser.
Here is the list of tasks that needs to be done for having the first stable release of V2.
You are very welcome to be part of this initiative. You can pick some tasks from the list and create a PR request by starting and targeting next
branch. Please don't miss to check our new Contribution Guideline.
This issue covers creating basic structure of grace next.
CONTRIBUTE.md
README.md
and storybookFont family, size, weight rules will be defined as CSS variables in our default.css
files and we'll stick to those options inside every components for all of the texts.
General usage example:
<bl-select label="Select country" required>
<bl-select-option value="tr" selected>Turkey</bl-select-option>
<bl-select-option value="nl">The Netherlands</bl-select-option>
</bl-select>
bl-select
componentSelect component is for getting input from users to select one or multiple options from a given list.
Attribute | Description | Default Value |
---|---|---|
label (string ) |
Label for the input | - |
value (string ) |
Value for the input | - |
required (boolean ) |
Sets select input required | - |
disabled (boolean ) |
Sets select input disabled | - |
multiple (boolean ) |
Allows for multi selection | - |
Name | Description | Default Content |
---|---|---|
default slot |
List of bl-select-option components |
- |
Event | Description |
---|---|
bl-select |
Will be triggered once user make a selection |
bl-select-option
componentAttribute | Description | Default Value |
---|---|---|
value (string ) |
Value for the option | - |
disabled (boolean ) |
Sets option disabled | - |
selected (boolean ) |
Sets option selected | - |
Name | Description | Default Content |
---|---|---|
default slot |
Label for the option | - |
67
Figma
General usage example:
<bl-alert
variant="error"
caption="Default Caption"
description="Default Description"
icon="close_fill"
closable
>
<span slot="caption">
Awesome Caption!
</span>
Some important description.
<bl-button slot="action">
Click me!
</bl-button>
</bl-alert>
closable
attribute displays a close button in alert component. Emits an event named bl-close
and component will hide itself via css property.icon
to use default icons according to variants or icon="calendar"
to customize icon.action
slot will only accept bl-button
component (else will cause an error) and will override some attributes of the slotted button (variant
will be secondary
and kind
will be text
, icon
will not be allowed).bl-button
component which can be used in action
slot will convert itself to icon-only bl-button
.bl-alert
componentAlert component displays an informational message to users with additional features if desired.
Attribute | Description | Default Value |
---|---|---|
variant (string ) |
Decides variants of alert box ( info , success , warning , error ) |
"info" |
caption (string ) |
Sets alert caption | - |
description (string ) |
Sets alert description | - |
icon (string, boolean ) |
Allows to customize alert icon | false |
closable (boolean ) |
Displays a close button when used | false |
Event | Description |
---|---|
caption slot |
Will fill alert caption |
default slot |
Will fill alert description |
action slot |
Will fill alert action slot and will accept only bl-button component or it will throw an error |
Event | Description |
---|---|
bl-close |
Will be triggered each time close button is clicked |
v-model
with our input components.tslint, eslint, prettier, csslint, postcss should be considered in this issue.
Our main expectations from those linters are;
Hello Might be I can contribute in something in this repository, so I can help you improve that project!
Storybook documentation should be automatically deployed to a different URL for each PRs and also for the main branch. Storybook URL of PR should be automatically mentioned in PR once it's deployed. So visual reviews can be done by checking the published version.
General usage example:
<bl-radio-group label="Payment Type" name="payment-type" value="cc">
<bl-radio value="cc">Credit Card</bl-radio>
<bl-radio value="ideal">iDeal</bl-radio>
</bl-radio-group>
bl-radio-group
componentThis component is the wrapper component of the radio options. Field value will be set/red via this component.
Attribute | Description | Default Value |
---|---|---|
label (string ) |
Label of the form field. This is needed for accessibility needs. | - |
name (string ) |
Name of the form field | - |
value (string ) |
Default value of the input | - |
required (boolean ) |
Sets form field required | false |
Event | Description | Event Data |
---|---|---|
bl-radio-change |
Will be triggered once radio selection changed | new value as string |
Property | Description | Default Value |
---|---|---|
--bl-radio-direction |
Can be used for showing radio options as columns instead of rows. Options are row or column |
row |
bl-radio
componentThis component defines options for the radio input.
Attribute | Description | Default Value |
---|---|---|
value (string ) |
Value of the option | - |
disabled (boolean ) |
Sets option disabled | false |
Name | Description | Default Content |
---|---|---|
default slot |
Label of the option | - |
Event | Description | Event Data |
---|---|---|
bl-checked |
Will be triggered once this option is selected | - |
bl-focus |
Will be triggered once this option is focused | - |
bl-blur |
Will be triggered once this option is blurred | - |
Lit
doesn't have any builtin solutions for handling slot changes
, component specific slots
etc. that we need or will need for our components.
Additionally, slots
will be used by many of our components. It will prevent code duplication.
In this issue, I will close those:
General usage example:
<bl-dialog caption='Dialog Title'>
<p> Dialog Content </p>
<bl-button slot="primary-action">Save Message</bl-button>
<bl-button slot="secondary-action" kind="danger">Delete Message</bl-button>
<bl-button slot="tertiary-action">Dismiss</bl-button>
</bl-dialog>
Attribute | Description | Default Value |
---|---|---|
caption (string ) |
Title of the dialog | - |
open (boolean ) |
Sets dialog open-close status. By default, the dialog is closed. | false |
Name | Description | Default Content |
---|---|---|
default slot |
Content of dialog | - |
actions slot |
Dialog actions (action buttons) of dialog | - |
Event | Description |
---|---|
bl-dialog-open |
Will be triggered every time the dialog is opened |
bl-dialog-close |
Will be triggered every time the dialog is closed |
General usage example:
<bl-tab-group>
<bl-tab
name="content" caption="content info" slot="tab" selected>Tab item 1</bl-tab>
<bl-tab-panel tab="content">
<p>
Content item 1.
</p>
</bl-tab-panel>
<bl-tab name="detail" slot="tab" help-text="Some information will be showed in tooltip" notify>Tab item 2</bl-tab>
<bl-tab-panel tab="detail">
<p>
Content item 2.
</p>
</bl-tab-panel>
<bl-tab slot="tab" disabled badge="Coming soon">New feature</bl-tab>
</bl-tab-group>
bl-tab
components) will stay in single line even if it doesn't fit the screen. Horizontal scrolling will be possible if tabs doesn't fit the screen.help-text
we'll use bl-tooltip
component (its work in progress).badge
component will be possible via bl-badge
CSS properties. Like<style>
.tab-badge-new {
--bl-badge-color: var(--bl-color-primary-background);
--bl-badge-bg-color: var(--bl-color-danger);
}
</style>
<bl-tab class="tab-badge-new" badge="New">Payment Options</bl-tab>
bl-tab
componentTab component handles interaction to show/hide tab panes.
Attribute | Description | Default Value |
---|---|---|
name (string ) |
Name of the tab | - |
selected (boolean ) |
Sets tab selected. By default first tab becomes selected | - |
disabled (boolean ) |
Sets tab disabled | - |
caption (string ) |
Caption text of tab. Will stay as single line, so it should not be a long text | - |
icon (string ) |
Name of the icon that will be shown next to the tab title | - |
help-text (string ) |
Text content to show in a tooltip that will be triggered with an icon button (info icon) inside the tab |
- |
notify (boolean ) |
Points a notification dot next to tab title | - |
badge (string ) |
Adds a badge next to the title with the content of this text | - |
Name | Description | Default Content |
---|---|---|
default slot |
Title of tab. Will stay as single line, so it should not be a long text | - |
Event | Description |
---|---|
bl-tab-show |
Will be triggered once this tab panel shown |
bl-tab-hide |
Will be triggered once this tab panel hidden |
bl-tab-panel
componentContainer for the tab contents.
Attribute | Description | Default Value |
---|---|---|
name (string ) |
Name of the panel | - |
Name | Description | Default Content |
---|---|---|
default slot |
Content of the panel | - |
Event | Description |
---|---|
bl-tab-panel-show |
Will be triggered once this tab panel shown |
bl-tab-panel-hide |
Will be triggered once this tab panel hidden |
bl-tab-group
componentContainer for bl-tab
and bl-tab-panel
components.
Name | Description | Default Content |
---|---|---|
default slot |
bl-tab-panel components will come to this slot |
- |
tab slot |
bl-tab components will come to this slot |
- |
Event | Description |
---|---|
bl-tab-change |
Will be triggered once a tab changed. Event data will contain the name of the new tab opened |
Currently -and commonly- Lit component styles are defined in TS code with css
literal function. We consider to use regular CSS files instead. Using CSS files will be more familiar for developers and easier to lint/check. For achieving this there seems 2 options:
lit-css is a package to convert CSS files to TS codes in bundling time. This looks like a simple solution but needs to be checked together with Storybook.
There is an API proposal (and chrome already supports it) for importing CSS files dynamically for web component in runtime like:
import sheet from 'https://site.com/sheet.css' assert { type: 'css' };
es-module-shims is a pollyfill that makes this possible in every browser. This can be a more future-proof solution.
In this issue, we'll try to implement best solution for us.
component.story.ts
)Lit doesn't provide any convention for defining and publishing component events but it seems logical to at least create our own. So events of the component will be more visible and we'll avoid code duplication for firing multiple events from many components.
class GrIcon extends LitElement {
....
@event('gr-load') load: EventEmitter<string>;
So for me, requirements are:
bubbles
, cancellable
).General usage example:
<bl-badge>In Progress</bl-badge>
Default background color is --bl-color-accent-primary-background
and default color is --bl-color-primary
. But any color can be set like this:
<style>
.danger-badge {
--bl-badge-bg-color:var(--bl-color-danger-background);
--bl-badge-color:var(--bl-color-danger);
}
</style>
<bl-badge class="danger-badge">Denied</bl-badge>
The icon can be set like this:
<bl-badge icon="waiting">In Progress</bl-badge>
The size can be set like this:
<bl-badge size="large">In Progress</bl-badge>
Attribute | Description | Default Value |
---|---|---|
size (string ) |
Size of badge(small,medium,large) | medium |
icon (string ) |
Name of the icon that will be shown in badge | - |
A default theme uses Rubik font and by-detault we use it directly from Google Fonts. This is not very nice for a copule of reasons as explained in Fontsource project page. In this issue, we'll consider using fontsource to bundling Rubik font together with Grace.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.